From e254cec64865e2fa6e6ea0039a267f2caffc69fc Mon Sep 17 00:00:00 2001 From: Connor Tumbleson Date: Tue, 7 Jan 2014 10:59:37 -0600 Subject: [PATCH] rework manifest renaming Issue #526, correctly handles apks where a renamed package is required, by comparing the package name present in AndroidManifest.xml and resources.arsc. If different, we take the package name present in resources.arsc (original) and replace it in the tag of AndroidManifest.xml. The previous value in AndroidManifest.xml (renamed) becomes the value to be passed to aapt on rebuild via --rename-manifest-package Both these values along with the package id of the original are stored in apktool.yml, for use during the rebuild --- .../src/main/java/brut/androlib/Androlib.java | 1 + .../main/java/brut/androlib/ApkDecoder.java | 13 +++-- .../brut/androlib/res/AndrolibResources.java | 33 ++++++------ .../java/brut/androlib/res/data/ResTable.java | 50 ++++++++++++++----- .../androlib/res/decoder/ARSCDecoder.java | 6 --- .../res/decoder/XmlPullStreamDecoder.java | 7 ++- 6 files changed, 70 insertions(+), 40 deletions(-) diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/Androlib.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/Androlib.java index 5460bae1..6b736328 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/Androlib.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/Androlib.java @@ -272,6 +272,7 @@ public class Androlib { : Boolean.valueOf(meta.get("compressionType").toString())); mAndRes.setSdkInfo((Map) meta.get("sdkInfo")); mAndRes.setPackageId((Map) meta.get("packageInfo")); + mAndRes.setPackageInfo((Map) meta.get("packageInfo")); mAndRes.setVersionInfo((Map) meta.get("versionInfo")); if (outFile == null) { diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkDecoder.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkDecoder.java index 93ac42b0..bfec1e89 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkDecoder.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkDecoder.java @@ -317,10 +317,15 @@ public class ApkDecoder { private void putPackageInfo(Map meta) throws AndrolibException { - Map info = getResTable().getPackageInfo(); - if (info.size() > 0) { - meta.put("packageInfo", info); - } + String renamed = getResTable().getPackageRenamed(); + String original = getResTable().getPackageOriginal(); + int id = getResTable().getPackageId(); + + HashMap packages = new HashMap(); + packages.put("renamed", renamed); + packages.put("original", original); + packages.put("original_id", String.valueOf(id)); + meta.put("packageInfo", packages); } private void putVersionInfo(Map meta) diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/AndrolibResources.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/AndrolibResources.java index 22742062..5ae94b60 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/AndrolibResources.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/AndrolibResources.java @@ -176,13 +176,17 @@ final public class AndrolibResources { public void adjust_package_manifest(ResTable resTable, String filePath) throws AndrolibException { - // check if packages different, and that package is not equal to "android" - Map packageInfo = resTable.getPackageInfo(); - String currentPackage = packageInfo.get("cur_package"); - String originalPackage = packageInfo.get("orig_package"); + // compare resources.arsc package name to the one present in AndroidManifest + ResPackage resPackage = resTable.getHighestSpecPackage(); + mPackageOriginal = resPackage.getName(); + mPackageRenamed = resTable.getPackageRenamed(); - if (currentPackage.equalsIgnoreCase(originalPackage) || "android".equalsIgnoreCase(currentPackage) - || "com.htc".equalsIgnoreCase(currentPackage)) { + + resTable.setPackageId(resPackage.getId()); + resTable.setPackageOriginal(mPackageOriginal); + + if (mPackageOriginal.equalsIgnoreCase(mPackageRenamed) || "android".equalsIgnoreCase(mPackageRenamed) + || "com.htc".equalsIgnoreCase(mPackageRenamed)) { LOGGER.info("Regular manifest package..."); } else { try { @@ -196,9 +200,7 @@ final public class AndrolibResources { // update package attribute NamedNodeMap attr = manifest.getAttributes(); Node nodeAttr = attr.getNamedItem("package"); - mPackageRenamed = nodeAttr.getNodeValue(); - nodeAttr.setNodeValue(currentPackage); - + nodeAttr.setNodeValue(mPackageOriginal); saveDocument(filePath, doc); } catch (SAXException | ParserConfigurationException | IOException | TransformerException ignored) { @@ -284,6 +286,7 @@ final public class AndrolibResources { // it will be passed as a parameter to aapt like "--min-sdk-version" via apktool.yml adjust_package_manifest(resTable, outDir.getAbsolutePath() + File.separator + "AndroidManifest.xml"); remove_manifest_versions(outDir.getAbsolutePath() + File.separator + "AndroidManifest.xml"); + mPackageId = String.valueOf(resTable.getPackageId()); } if (inApk.containsDir("res")) { in = inApk.getDir("res"); @@ -332,13 +335,14 @@ final public class AndrolibResources { public void setPackageInfo(Map map) { if (map != null) { - mPackageRenamed = map.get("package"); + mPackageRenamed = map.get("renamed"); + mPackageOriginal = map.get("original"); } } public void setPackageId(Map map) { if (map != null) { - mPackageId = map.get("cur_package_id"); + mPackageId = map.get("original_id"); } } @@ -359,8 +363,7 @@ final public class AndrolibResources { customAapt = true; if (flags.get("verbose")) { - LOGGER.info(aaptFile.getPath() - + " being used as aapt location."); + LOGGER.info(aaptFile.getPath() + " being used as aapt location."); } } else { LOGGER.warning("aapt location could not be found. Defaulting back to default"); @@ -838,7 +841,6 @@ final public class AndrolibResources { private final static Logger LOGGER = Logger .getLogger(AndrolibResources.class.getName()); - private String mPackageId = null; private String mMinSdkVersion = null; private String mMaxSdkVersion = null; private String mTargetSdkVersion = null; @@ -846,6 +848,9 @@ final public class AndrolibResources { private String mVersionName = null; private String mPackageRenamed = null; + private String mPackageOriginal = null; + private String mPackageId = null; + private File mAaptBinary = null; } diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResTable.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResTable.java index f55c3937..c851ac63 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResTable.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResTable.java @@ -34,10 +34,12 @@ public class ResTable { private final Set mFramePackages = new LinkedHashSet(); private String mFrameTag; + private String mPackageRenamed; + private String mPackageOriginal; + private int mPackageId; private boolean mAnalysisMode = false; private Map mSdkInfo = new LinkedHashMap(); - private Map mPackageInfo = new LinkedHashMap(); private Map mVersionInfo = new LinkedHashMap(); private Map mUnknownFiles = new LinkedHashMap(); @@ -76,6 +78,18 @@ public class ResTable { throw new UndefinedResObject(String.format("package: id=%d", id)); } + public ResPackage getHighestSpecPackage() throws AndrolibException { + int id = 0; + int value = 0; + for(ResPackage resPackage : mPackagesById.values()) { + if(resPackage.getResSpecCount() > value && !resPackage.getName().equalsIgnoreCase("android")) { + value = resPackage.getResSpecCount(); + id = resPackage.getId(); + } + } + return getPackage(id); + } + public ResPackage getPackage(String name) throws AndrolibException { ResPackage pkg = mPackagesByName.get(name); if (pkg == null) { @@ -126,6 +140,18 @@ public class ResTable { public void setAnalysisMode(boolean mode) { mAnalysisMode = mode; } + + public void setPackageRenamed(String pkg) { + mPackageRenamed = pkg; + } + + public void setPackageOriginal(String pkg) { + mPackageOriginal = pkg; + } + + public void setPackageId(int id) { + mPackageId = id; + } public void clearSdkInfo() { mSdkInfo.clear(); @@ -139,18 +165,10 @@ public class ResTable { mVersionInfo.put(key, value); } - public void addPackageInfo(String key, String value) { - mPackageInfo.put(key, value); - } - public void addUnknownFileInfo(String file, String value) { mUnknownFiles.put(file,value); } - public Map getPackageInfo() { - return mPackageInfo; - } - public Map getVersionInfo() { return mVersionInfo; } @@ -167,7 +185,15 @@ public class ResTable { return mUnknownFiles; } - public boolean isPackageInfoValueSet(String key) { - return (mPackageInfo.containsKey(key)); - } + public String getPackageRenamed() { + return mPackageRenamed; + } + + public String getPackageOriginal() { + return mPackageOriginal; + } + + public int getPackageId() { + return mPackageId; + } } diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ARSCDecoder.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ARSCDecoder.java index 1805de4d..93f1b8f2 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ARSCDecoder.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ARSCDecoder.java @@ -80,12 +80,6 @@ public class ARSCDecoder { for (int i = 0; i < packageCount; i++) { packages[i] = readPackage(); } - - // store package - if (this.mResTable.isPackageInfoValueSet("cur_package") != true) { - this.mResTable.addPackageInfo("cur_package", packages[0].getName()); - this.mResTable.addPackageInfo("cur_package_id", String.valueOf(packages[0].getId())); - } return packages; } diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/XmlPullStreamDecoder.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/XmlPullStreamDecoder.java index c71ab702..e6774ccc 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/XmlPullStreamDecoder.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/XmlPullStreamDecoder.java @@ -89,16 +89,15 @@ public class XmlPullStreamDecoder implements ResStreamDecoder { private boolean parseManifest(XmlPullParser pp) throws AndrolibException { - ResTable restable = resTable; // read for package: for (int i = 0; i < pp.getAttributeCount(); i++) { if (pp.getAttributeName(i).equalsIgnoreCase(("package"))) { - restable.addPackageInfo("orig_package",pp.getAttributeValue(i)); + resTable.setPackageRenamed(pp.getAttributeValue(i)); } else if (pp.getAttributeName(i).equalsIgnoreCase("versionCode")) { - restable.addVersionInfo("versionCode", pp.getAttributeValue(i).toString()); + resTable.addVersionInfo("versionCode", pp.getAttributeValue(i)); } else if (pp.getAttributeName(i).equalsIgnoreCase("versionName")) { - restable.addVersionInfo("versionName", pp.getAttributeValue(i).toString()); + resTable.addVersionInfo("versionName", pp.getAttributeValue(i)); } } return true;