diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/DexFileFactory.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/DexFileFactory.java index 5987d7ce..8b2237be 100644 --- a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/DexFileFactory.java +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/DexFileFactory.java @@ -46,16 +46,21 @@ import java.util.zip.ZipFile; public final class DexFileFactory { @Nonnull public static DexBackedDexFile loadDexFile(String path, int api) throws IOException { - return loadDexFile(new File(path), new Opcodes(api)); + return loadDexFile(new File(path), "classes.dex", new Opcodes(api)); } @Nonnull public static DexBackedDexFile loadDexFile(File dexFile, int api) throws IOException { - return loadDexFile(dexFile, new Opcodes(api)); + return loadDexFile(dexFile, "classes.dex", new Opcodes(api)); } @Nonnull - public static DexBackedDexFile loadDexFile(File dexFile, @Nonnull Opcodes opcodes) throws IOException { + public static DexBackedDexFile loadDexFile(File dexFile, String dexEntry, int api) throws IOException { + return loadDexFile(dexFile, dexEntry, new Opcodes(api)); + } + + @Nonnull + public static DexBackedDexFile loadDexFile(File dexFile, String filename, @Nonnull Opcodes opcodes) throws IOException { ZipFile zipFile = null; boolean isZipFile = false; try { @@ -63,16 +68,16 @@ public final class DexFileFactory { // if we get here, it's safe to assume we have a zip file isZipFile = true; - ZipEntry zipEntry = zipFile.getEntry("classes.dex"); + ZipEntry zipEntry = zipFile.getEntry(filename); if (zipEntry == null) { throw new NoClassesDexException("zip file %s does not contain a classes.dex file", dexFile.getName()); } long fileLength = zipEntry.getSize(); if (fileLength < 40) { throw new ExceptionWithContext( - "The classes.dex file in %s is too small to be a valid dex file", dexFile.getName()); + "The " + filename + " file in %s is too small to be a valid dex file", dexFile.getName()); } else if (fileLength > Integer.MAX_VALUE) { - throw new ExceptionWithContext("The classes.dex file in %s is too large to read in", dexFile.getName()); + throw new ExceptionWithContext("The " + filename + " file in %s is too large to read in", dexFile.getName()); } byte[] dexBytes = new byte[(int)fileLength]; ByteStreams.readFully(zipFile.getInputStream(zipEntry), dexBytes); diff --git a/brut.apktool/apktool-cli/src/main/java/brut/apktool/Main.java b/brut.apktool/apktool-cli/src/main/java/brut/apktool/Main.java index 234a44dc..6a3ad6d1 100644 --- a/brut.apktool/apktool-cli/src/main/java/brut/apktool/Main.java +++ b/brut.apktool/apktool-cli/src/main/java/brut/apktool/Main.java @@ -30,6 +30,7 @@ import java.io.IOException; import java.util.HashMap; import java.util.logging.*; +import brut.directory.DirectoryException; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.HelpFormatter; @@ -187,6 +188,9 @@ public class Main { } catch (IOException ex) { System.err.println("Could not modify file. Please ensure you have permission."); System.exit(1); + } catch (DirectoryException ex) { + System.err.println("Could not modify internal dex files. Please ensure you have permission."); + System.exit(1); } } 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 2ab94739..cc9ad696 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 @@ -48,7 +48,8 @@ public class Androlib { private final AndrolibResources mAndRes = new AndrolibResources(); protected final ResUnknownFiles mResUnknownFiles = new ResUnknownFiles(); - public ResTable getResTable(ExtFile apkFile) throws AndrolibException { + public ResTable getResTable(ExtFile apkFile) + throws AndrolibException { return mAndRes.getResTable(apkFile, true); } @@ -57,25 +58,24 @@ public class Androlib { return mAndRes.getResTable(apkFile, loadMainPkg); } - public void decodeSourcesRaw(ExtFile apkFile, File outDir, boolean debug) + public void decodeSourcesRaw(ExtFile apkFile, File outDir, String filename) throws AndrolibException { try { - Directory apk = apkFile.getDirectory(); LOGGER.info("Copying raw classes.dex file..."); - apkFile.getDirectory().copyToDir(outDir, "classes.dex"); + apkFile.getDirectory().copyToDir(outDir, filename); } catch (DirectoryException ex) { throw new AndrolibException(ex); } } - public void decodeSourcesSmali(File apkFile, File outDir, boolean debug, String debugLinePrefix, + public void decodeSourcesSmali(File apkFile, File outDir, String filename, boolean debug, String debugLinePrefix, boolean bakdeb, int api) throws AndrolibException { try { - File smaliDir = new File(outDir, SMALI_DIRNAME); + File smaliDir = new File(outDir, SMALI_DIRNAME + "_" + filename.substring(0, filename.indexOf("."))); OS.rmdir(smaliDir); smaliDir.mkdirs(); - LOGGER.info("Baksmaling..."); - SmaliDecoder.decode(apkFile, smaliDir, debug, debugLinePrefix, bakdeb, api); + LOGGER.info("Baksmaling " + filename + "..."); + SmaliDecoder.decode(apkFile, smaliDir, filename, debug, debugLinePrefix, bakdeb, api); } catch (BrutException ex) { throw new AndrolibException(ex); } @@ -98,15 +98,14 @@ public class Androlib { } } - public void decodeManifestFull(ExtFile apkFile, File outDir, - ResTable resTable) throws AndrolibException { + public void decodeManifestFull(ExtFile apkFile, File outDir, ResTable resTable) + throws AndrolibException { mAndRes.decodeManifest(resTable, apkFile, outDir); } public void decodeResourcesRaw(ExtFile apkFile, File outDir) throws AndrolibException { try { - // Directory apk = apkFile.getDirectory(); LOGGER.info("Copying raw resources..."); apkFile.getDirectory().copyToDir(outDir, APK_RESOURCES_FILENAMES); } catch (DirectoryException ex) { @@ -114,8 +113,8 @@ public class Androlib { } } - public void decodeResourcesFull(ExtFile apkFile, File outDir, - ResTable resTable) throws AndrolibException { + public void decodeResourcesFull(ExtFile apkFile, File outDir, ResTable resTable) + throws AndrolibException { mAndRes.decode(resTable, apkFile, outDir); } @@ -162,15 +161,15 @@ public class Androlib { // loop all items in container recursively, ignoring any that are pre-defined by aapt Set files = unk.getFiles(true); for (String file : files) { - if (!isAPKFileNames(file)) { + if (!isAPKFileNames(file) && !file.endsWith(".dex")) { // copy file out of archive into special "unknown" folder // to be re-included on build - unk.copyToDir(unknownOut,file); + unk.copyToDir(unknownOut, file); try { // ignore encryption - apkZipFile.getEntry(file.toString()).getGeneralPurposeBit().useEncryption(false); - invZipFile = apkZipFile.getEntry(file.toString()); + apkZipFile.getEntry(file).getGeneralPurposeBit().useEncryption(false); + invZipFile = apkZipFile.getEntry(file); // lets record the name of the file, and its compression type // so that we may re-include it the same way @@ -256,24 +255,23 @@ public class Androlib { } } - public void build(File appDir, File outFile, - HashMap flags, String aaptPath) + public void build(File appDir, File outFile, HashMap flags, String aaptPath) throws BrutException { build(new ExtFile(appDir), outFile, flags, aaptPath); } - public void build(ExtFile appDir, File outFile, - HashMap flags, String aaptPath) + public void build(ExtFile appDir, File outFile, HashMap flags, String aaptPath) throws BrutException { - LOGGER.info("Using Apktool " + Androlib.getVersion() + " on " + appDir.getName()); mAaptPath = aaptPath; Map meta = readMetaFile(appDir); Object t1 = meta.get("isFrameworkApk"); flags.put("framework", t1 == null ? false : (Boolean) t1); - flags.put("compression", meta.get("compressionType") == null ? false + flags.put("compression", meta.get("compressionType") == null + ? false : Boolean.valueOf(meta.get("compressionType").toString())); + mAndRes.setSdkInfo((Map) meta.get("sdkInfo")); mAndRes.setPackageId((Map) meta.get("packageInfo")); mAndRes.setPackageInfo((Map) meta.get("packageInfo")); @@ -287,57 +285,74 @@ public class Androlib { new File(appDir, APK_DIRNAME).mkdirs(); buildSources(appDir, flags); - buildResources(appDir, flags, - (Map) meta.get("usesFramework")); + buildNonDefaultSources(appDir, flags); + buildResources(appDir, flags, (Map) meta.get("usesFramework")); buildLib(appDir, flags); buildCopyOriginalFiles(appDir, flags); buildApk(appDir, outFile, flags); // we must go after the Apk is built, and copy the files in via Zip // this is because Aapt won't add files it doesn't know (ex unknown files) - buildUnknownFiles(appDir,outFile,meta); + buildUnknownFiles(appDir, outFile, meta); } public void buildSources(File appDir, HashMap flags) throws AndrolibException { - if (!buildSourcesRaw(appDir, flags) - && !buildSourcesSmali(appDir, flags) - && !buildSourcesJava(appDir, flags)) { + if (!buildSourcesRaw(appDir, "classes.dex", flags) && !buildSourcesSmali(appDir, "smali", "classes.dex", flags) && !buildSourcesJava(appDir, flags)) { LOGGER.warning("Could not find sources"); } } - public boolean buildSourcesRaw(File appDir, HashMap flags) + public void buildNonDefaultSources(ExtFile appDir, HashMap flags) throws AndrolibException { try { - File working = new File(appDir, "classes.dex"); - if (!working.exists()) { - return false; + Map dirs = appDir.getDirectory().getDirs(); + for (Map.Entry directory : dirs.entrySet()) { + String name = directory.getKey(); + if (name.startsWith("smali_")) { + String filename = name.substring(name.indexOf("_") + 1) + ".dex"; + + if (!buildSourcesRaw(appDir, filename, flags) && !buildSourcesSmali(appDir, name, filename, flags) && !buildSourcesJava(appDir, flags)) { + LOGGER.warning("Could not find sources"); + } + } } - File stored = new File(appDir, APK_DIRNAME + "/classes.dex"); - if (flags.get("forceBuildAll") || isModified(working, stored)) { - LOGGER.info("Copying classes.dex file..."); - BrutIO.copyAndClose(new FileInputStream(working), - new FileOutputStream(stored)); - } - return true; - } catch (IOException ex) { + } catch(DirectoryException ex) { throw new AndrolibException(ex); } } - public boolean buildSourcesSmali(File appDir, HashMap flags) + public boolean buildSourcesRaw(File appDir, String filename, HashMap flags) throws AndrolibException { - ExtFile smaliDir = new ExtFile(appDir, "smali"); + File working = new File(appDir, filename); + if (!working.exists()) { + return false; + } + File stored = new File(appDir, APK_DIRNAME + "/" + filename); + if (flags.get("forceBuildAll") || isModified(working, stored)) { + LOGGER.info("Copying " + appDir.toString() + " " + filename + " file..."); + try { + BrutIO.copyAndClose(new FileInputStream(working), new FileOutputStream(stored)); + return true; + } catch (IOException ex) { + throw new AndrolibException(ex); + } + } + return true; + } + + public boolean buildSourcesSmali(File appDir, String folder, String filename, HashMap flags) + throws AndrolibException { + ExtFile smaliDir = new ExtFile(appDir, folder); if (!smaliDir.exists()) { return false; } - File dex = new File(appDir, APK_DIRNAME + "/classes.dex"); + File dex = new File(appDir, APK_DIRNAME + "/" + filename); if (!flags.get("forceBuildAll")) { LOGGER.info("Checking whether sources has changed..."); } if (flags.get("forceBuildAll") || isModified(smaliDir, dex)) { - LOGGER.info("Smaling..."); + LOGGER.info("Smaling " + folder + " folder into " + filename +"..."); dex.delete(); SmaliBuilder.build(smaliDir, dex, flags); } @@ -362,17 +377,16 @@ public class Androlib { return true; } - public void buildResources(ExtFile appDir, HashMap flags, - Map usesFramework) throws BrutException { - if (!buildResourcesRaw(appDir, flags) - && !buildResourcesFull(appDir, flags, usesFramework) + public void buildResources(ExtFile appDir, HashMap flags, Map usesFramework) + throws BrutException { + if (!buildResourcesRaw(appDir, flags) && !buildResourcesFull(appDir, flags, usesFramework) && !buildManifest(appDir, flags, usesFramework)) { LOGGER.warning("Could not find resources"); } } - public boolean buildResourcesRaw(ExtFile appDir, - HashMap flags) throws AndrolibException { + public boolean buildResourcesRaw(ExtFile appDir, HashMap flags) + throws AndrolibException { try { if (!new File(appDir, "resources.arsc").exists()) { return false; @@ -394,8 +408,7 @@ public class Androlib { } } - public boolean buildResourcesFull(File appDir, - HashMap flags, Map usesFramework) + public boolean buildResourcesFull(File appDir, HashMap flags, Map usesFramework) throws AndrolibException { try { if (!new File(appDir, "res").exists()) { @@ -440,8 +453,8 @@ public class Androlib { } } - public boolean buildManifestRaw(ExtFile appDir, - HashMap flags) throws AndrolibException { + public boolean buildManifestRaw(ExtFile appDir, HashMap flags) + throws AndrolibException { try { File apkDir = new File(appDir, APK_DIRNAME); LOGGER.info("Copying raw AndroidManifest.xml..."); @@ -452,8 +465,7 @@ public class Androlib { } } - public boolean buildManifest(ExtFile appDir, - HashMap flags, Map usesFramework) + public boolean buildManifest(ExtFile appDir, HashMap flags, Map usesFramework) throws BrutException { try { if (!new File(appDir, "AndroidManifest.xml").exists()) { @@ -519,8 +531,8 @@ public class Androlib { } } - public void buildCopyOriginalFiles(File appDir, - HashMap flags) throws AndrolibException { + public void buildCopyOriginalFiles(File appDir, HashMap flags) + throws AndrolibException { if (flags.get("copyOriginal")) { File originalDir = new File(appDir, "original"); if(originalDir.exists()) { @@ -708,8 +720,7 @@ public class Androlib { private String mAaptPath = null; private Path mPath = null; - private final static Logger LOGGER = Logger.getLogger(Androlib.class - .getName()); + private final static Logger LOGGER = Logger.getLogger(Androlib.class.getName()); private final static String SMALI_DIRNAME = "smali"; private final static String APK_DIRNAME = "build/apk"; @@ -723,5 +734,5 @@ public class Androlib { private final static String[] APK_MANIFEST_FILENAMES = new String[] { "AndroidManifest.xml" }; private final static String[] APK_STANDARD_ALL_FILENAMES = new String[] { - "classes.dex", "AndroidManifest.xml", "resources.arsc","res","lib", "libs","assets","META-INF" }; + "classes.dex", "AndroidManifest.xml", "resources.arsc", "res", "lib", "libs", "assets", "META-INF" }; } 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 b69bcaab..78485723 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 @@ -69,7 +69,7 @@ public class ApkDecoder { mApi = api; } - public void decode() throws AndrolibException, IOException { + public void decode() throws AndrolibException, IOException, DirectoryException { File outDir = getOutDir(); if (!mForceDelete && outDir.exists()) { @@ -134,10 +134,10 @@ public class ApkDecoder { if (hasSources()) { switch (mDecodeSources) { case DECODE_SOURCES_NONE: - mAndrolib.decodeSourcesRaw(mApkFile, outDir, mDebug); + mAndrolib.decodeSourcesRaw(mApkFile, outDir, "classes.dex"); break; case DECODE_SOURCES_SMALI: - mAndrolib.decodeSourcesSmali(mApkFile, outDir, mDebug, mDebugLinePrefix, mBakDeb, mApi); + mAndrolib.decodeSourcesSmali(mApkFile, outDir, "classes.dex", mDebug, mDebugLinePrefix, mBakDeb, mApi); break; case DECODE_SOURCES_JAVA: mAndrolib.decodeSourcesJava(mApkFile, outDir, mDebug); @@ -145,6 +145,28 @@ public class ApkDecoder { } } + if (hasMultipleSources()) { + // foreach unknown dex file in root, lets disassemble it + Set files = mApkFile.getDirectory().getFiles(true); + for (String file : files) { + if (file.endsWith(".dex")) { + if (! file.equalsIgnoreCase("classes.dex")) { + switch(mDecodeSources) { + case DECODE_SOURCES_NONE: + mAndrolib.decodeSourcesRaw(mApkFile, outDir, file); + break; + case DECODE_SOURCES_SMALI: + mAndrolib.decodeSourcesSmali(mApkFile, outDir, file, mDebug, mDebugLinePrefix, mBakDeb, mApi); + break; + case DECODE_SOURCES_JAVA: + mAndrolib.decodeSourcesJava(mApkFile, outDir, mDebug); + break; + } + } + } + } + } + mAndrolib.decodeRawFiles(mApkFile, outDir); mAndrolib.decodeUnknownFiles(mApkFile, outDir, mResTable); mAndrolib.writeOriginalFiles(mApkFile, outDir); @@ -233,6 +255,23 @@ public class ApkDecoder { } } + public boolean hasMultipleSources() throws AndrolibException { + try { + Set files = mApkFile.getDirectory().getFiles(true); + for (String file : files) { + if (file.endsWith(".dex")) { + if ( ! file.equalsIgnoreCase("classes.dex")) { + return true; + } + } + } + + return false; + } catch (DirectoryException ex) { + throw new AndrolibException(ex); + } + } + public boolean hasManifest() throws AndrolibException { try { return mApkFile.getDirectory().containsFile("AndroidManifest.xml"); @@ -268,10 +307,8 @@ public class ApkDecoder { meta.put("version", Androlib.getVersion()); meta.put("apkFileName", mApkFile.getName()); - if (mDecodeResources != DECODE_RESOURCES_NONE - && (hasManifest() || hasResources())) { - meta.put("isFrameworkApk", - Boolean.valueOf(mAndrolib.isFrameworkApk(getResTable()))); + if (mDecodeResources != DECODE_RESOURCES_NONE && (hasManifest() || hasResources())) { + meta.put("isFrameworkApk", mAndrolib.isFrameworkApk(getResTable())); putUsesFramework(meta); putSdkInfo(meta); putPackageInfo(meta); diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/src/SmaliBuilder.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/src/SmaliBuilder.java index 29bac1be..e5735b78 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/src/SmaliBuilder.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/src/SmaliBuilder.java @@ -36,13 +36,12 @@ import org.jf.dexlib2.writer.io.FileDataStore; */ public class SmaliBuilder { - public static void build(ExtFile smaliDir, File dexFile, - HashMap flags) throws AndrolibException { + public static void build(ExtFile smaliDir, File dexFile, HashMap flags) + throws AndrolibException { new SmaliBuilder(smaliDir, dexFile, flags).build(); } - private SmaliBuilder(ExtFile smaliDir, File dexFile, - HashMap flags) { + private SmaliBuilder(ExtFile smaliDir, File dexFile, HashMap flags) { mSmaliDir = smaliDir; mDexFile = dexFile; mFlags = flags; @@ -61,8 +60,8 @@ public class SmaliBuilder { } } - private void buildFile(String fileName, DexBuilder dexBuilder) throws AndrolibException, - IOException { + private void buildFile(String fileName, DexBuilder dexBuilder) + throws AndrolibException, IOException { File inFile = new File(mSmaliDir, fileName); InputStream inStream = new FileInputStream(inFile); @@ -96,8 +95,7 @@ public class SmaliBuilder { out.append(".source \"").append(inFile.getName()).append("\"\n"); while (it.hasNext()) { String line = it.next().split("//", 2)[1].trim(); - if (line.isEmpty() || line.charAt(0) == '#' - || line.startsWith(".source")) { + if (line.isEmpty() || line.charAt(0) == '#' || line.startsWith(".source")) { continue; } if (line.startsWith(".method ")) { @@ -123,6 +121,5 @@ public class SmaliBuilder { private final File mDexFile; private final HashMap mFlags; - private final static Logger LOGGER = Logger.getLogger(SmaliBuilder.class - .getName()); + private final static Logger LOGGER = Logger.getLogger(SmaliBuilder.class.getName()); } diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/src/SmaliDecoder.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/src/SmaliDecoder.java index af43f723..35ac419c 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/src/SmaliDecoder.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/src/SmaliDecoder.java @@ -41,15 +41,16 @@ import java.nio.file.attribute.BasicFileAttributes; */ public class SmaliDecoder { - public static void decode(File apkFile, File outDir, boolean debug, String debugLinePrefix, + public static void decode(File apkFile, File outDir, String dexName, boolean debug, String debugLinePrefix, boolean bakdeb, int api) throws AndrolibException { - new SmaliDecoder(apkFile, outDir, debug, debugLinePrefix, bakdeb, api).decode(); + new SmaliDecoder(apkFile, outDir, dexName, debug, debugLinePrefix, bakdeb, api).decode(); } - private SmaliDecoder(File apkFile, File outDir, boolean debug, String debugLinePrefix, + private SmaliDecoder(File apkFile, File outDir, String dexName, boolean debug, String debugLinePrefix, boolean bakdeb, int api) { mApkFile = apkFile; mOutDir = outDir.toPath(); + mDexFile = dexName; mDebug = debug; mDebugLinePrefix = debugLinePrefix; mBakDeb = bakdeb; @@ -90,7 +91,7 @@ public class SmaliDecoder { } // create the dex - DexBackedDexFile dexFile = DexFileFactory.loadDexFile(mApkFile, mApi); + DexBackedDexFile dexFile = DexFileFactory.loadDexFile(mApkFile, mDexFile, mApi); if (dexFile.isOdexFile()) { throw new AndrolibException("Warning: You are disassembling an odex file without deodexing it."); @@ -115,10 +116,10 @@ public class SmaliDecoder { private final Path mOutDir; private final boolean mDebug; private final String mDebugLinePrefix; + private final String mDexFile; private final boolean mBakDeb; private final int mApi; - private class SmaliFileVisitor extends SimpleFileVisitor { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/BuildAndDecodeTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/BuildAndDecodeTest.java index 6ebca78c..2a8cb034 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/BuildAndDecodeTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/BuildAndDecodeTest.java @@ -40,13 +40,11 @@ public class BuildAndDecodeTest { sTestOrigDir = new ExtFile(sTmpDir, "testapp-orig"); sTestNewDir = new ExtFile(sTmpDir, "testapp-new"); LOGGER.info("Unpacking testapp..."); - TestUtils.copyResourceDir(BuildAndDecodeTest.class, - "brut/apktool/testapp/", sTestOrigDir); + TestUtils.copyResourceDir(BuildAndDecodeTest.class, "brut/apktool/testapp/", sTestOrigDir); LOGGER.info("Building testapp.apk..."); File testApk = new File(sTmpDir, "testapp.apk"); - new Androlib().build(sTestOrigDir, testApk, - TestUtils.returnStockHashMap(),""); + new Androlib().build(sTestOrigDir, testApk, TestUtils.returnStockHashMap(),""); LOGGER.info("Decoding testapp.apk..."); ApkDecoder apkDecoder = new ApkDecoder(testApk); @@ -219,8 +217,19 @@ public class BuildAndDecodeTest { compareUnknownFiles(); } + @Test + public void multipleDexTest() throws BrutException, IOException { + compareBinaryFolder("/smali_classes2", false); + } + + @Test + public void singleDexTest() throws BrutException, IOException { + compareBinaryFolder("/smali", false); + } + @SuppressWarnings("unchecked") - private void compareUnknownFiles() throws BrutException, IOException { + private void compareUnknownFiles() + throws BrutException, IOException { Map control = new Androlib().readMetaFile(sTestOrigDir); Map test = new Androlib().readMetaFile(sTestNewDir); assertTrue(control.containsKey("unknownFiles")); @@ -231,8 +240,8 @@ public class BuildAndDecodeTest { assertTrue(control_files.size() == test_files.size()); } - private boolean compareBinaryFolder(String path, boolean res) throws BrutException, IOException { - + private boolean compareBinaryFolder(String path, boolean res) + throws BrutException, IOException { String tmp = ""; if (res) { tmp = File.separatorChar + "res" + File.separatorChar; @@ -265,8 +274,7 @@ public class BuildAndDecodeTest { } private void compareValuesFiles(String path) throws BrutException { - compareXmlFiles("res/" + path, new ElementNameAndAttributeQualifier( - "name")); + compareXmlFiles("res/" + path, new ElementNameAndAttributeQualifier("name")); } private void compareXmlFiles(String path) throws BrutException { @@ -291,14 +299,12 @@ public class BuildAndDecodeTest { diff.overrideElementQualifier(qualifier); } - assertTrue(path + ": " + diff.getAllDifferences().toString(), - diff.similar()); + assertTrue(path + ": " + diff.getAllDifferences().toString(), diff.similar()); } private static ExtFile sTmpDir; private static ExtFile sTestOrigDir; private static ExtFile sTestNewDir; - private final static Logger LOGGER = Logger - .getLogger(BuildAndDecodeTest.class.getName()); + private final static Logger LOGGER = Logger.getLogger(BuildAndDecodeTest.class.getName()); } diff --git a/brut.apktool/apktool-lib/src/test/resources/brut/apktool/testapp/smali_classes2/HelloDualDexSupport.smali b/brut.apktool/apktool-lib/src/test/resources/brut/apktool/testapp/smali_classes2/HelloDualDexSupport.smali new file mode 100644 index 00000000..e9613981 --- /dev/null +++ b/brut.apktool/apktool-lib/src/test/resources/brut/apktool/testapp/smali_classes2/HelloDualDexSupport.smali @@ -0,0 +1,15 @@ +.class public LHelloDualDexSupport; + +.super Ljava/lang/Object; + +.method public static main([Ljava/lang/String;)V + .registers 2 + + sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream; + + const/high16 v1, 0x7f020000 + + invoke-virtual {v0, v1}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V + + return-void +.end method \ No newline at end of file