From cf68e4722aa0f41a0e2c34a7b4d2f134954c5a48 Mon Sep 17 00:00:00 2001 From: Nizam Moidu Date: Wed, 11 Nov 2015 12:22:47 +0400 Subject: [PATCH] multidex support for apk & zip --- .../main/java/jadx/api/JadxDecompiler.java | 7 ++++- .../java/jadx/core/clsp/ConvertToClsSet.java | 14 ++++++++-- .../java/jadx/core/utils/files/InputFile.java | 28 ++++++++++++++++--- 3 files changed, 42 insertions(+), 7 deletions(-) diff --git a/jadx-core/src/main/java/jadx/api/JadxDecompiler.java b/jadx-core/src/main/java/jadx/api/JadxDecompiler.java index b78aa9cdc..fc8b78d5a 100644 --- a/jadx-core/src/main/java/jadx/api/JadxDecompiler.java +++ b/jadx-core/src/main/java/jadx/api/JadxDecompiler.java @@ -116,7 +116,12 @@ public final class JadxDecompiler { inputFiles.clear(); for (File file : files) { try { - inputFiles.add(new InputFile(file)); + InputFile inputFile = new InputFile(file); + inputFiles.add(inputFile); + while (inputFile.nextDexIndex != -1) { + inputFile = new InputFile(file, inputFile.nextDexIndex); + inputFiles.add(inputFile); + } } catch (IOException e) { throw new JadxException("Error load file: " + file, e); } diff --git a/jadx-core/src/main/java/jadx/core/clsp/ConvertToClsSet.java b/jadx-core/src/main/java/jadx/core/clsp/ConvertToClsSet.java index 48df74fa7..07cd69fb3 100644 --- a/jadx-core/src/main/java/jadx/core/clsp/ConvertToClsSet.java +++ b/jadx-core/src/main/java/jadx/core/clsp/ConvertToClsSet.java @@ -36,7 +36,12 @@ public class ConvertToClsSet { if (f.isDirectory()) { addFilesFromDirectory(f, inputFiles); } else { - inputFiles.add(new InputFile(f)); + InputFile inputFile = new InputFile(f); + inputFiles.add(inputFile); + while (inputFile.nextDexIndex != -1) { + inputFile = new InputFile(f, inputFile.nextDexIndex); + inputFiles.add(inputFile); + } } } for (InputFile inputFile : inputFiles) { @@ -67,7 +72,12 @@ public class ConvertToClsSet { if (fileName.endsWith(".dex") || fileName.endsWith(".jar") || fileName.endsWith(".apk")) { - inputFiles.add(new InputFile(file)); + InputFile inputFile = new InputFile(file); + inputFiles.add(inputFile); + while (inputFile.nextDexIndex != -1) { + inputFile = new InputFile(file, inputFile.nextDexIndex); + inputFiles.add(inputFile); + } } } } diff --git a/jadx-core/src/main/java/jadx/core/utils/files/InputFile.java b/jadx-core/src/main/java/jadx/core/utils/files/InputFile.java index 2bf548abe..42edfb065 100644 --- a/jadx-core/src/main/java/jadx/core/utils/files/InputFile.java +++ b/jadx-core/src/main/java/jadx/core/utils/files/InputFile.java @@ -23,11 +23,18 @@ public class InputFile { private final File file; private final Dex dexBuf; + public int nextDexIndex = -1; + private final int dexIndex; public InputFile(File file) throws IOException, DecodeException { + this(file, 0); + } + + public InputFile(File file, int dexIndex) throws IOException, DecodeException { if (!file.exists()) { throw new IOException("File not found: " + file.getAbsolutePath()); } + this.dexIndex = dexIndex; this.file = file; this.dexBuf = loadDexBuffer(); } @@ -41,7 +48,7 @@ public class InputFile { return loadFromClassFile(file); } if (fileName.endsWith(".apk") || fileName.endsWith(".zip")) { - Dex dex = loadFromZip(file); + Dex dex = loadFromZip(this,file); if (dex == null) { throw new IOException("File 'classes.dex' not found in file: " + file); } @@ -49,7 +56,7 @@ public class InputFile { } if (fileName.endsWith(".jar")) { // check if jar contains 'classes.dex' - Dex dex = loadFromZip(file); + Dex dex = loadFromZip(this,file); if (dex != null) { return dex; } @@ -74,13 +81,26 @@ public class InputFile { } } - private static Dex loadFromZip(File file) throws IOException { + private static Dex loadFromZip(InputFile ipf, File file) throws IOException { ZipFile zf = new ZipFile(file); - ZipEntry dex = zf.getEntry("classes.dex"); + String dexName = "classes.dex"; + String futureDexName = "classes2.dex"; + if (ipf.dexIndex != 0) { + dexName = "classes" + ipf.dexIndex + ".dex"; + futureDexName = "classes" + (ipf.dexIndex + 1) + ".dex"; + } + ZipEntry dex = zf.getEntry(dexName); if (dex == null) { zf.close(); return null; } + try { + ZipEntry futureDex = zf.getEntry(futureDexName); + if (futureDex != null) { + ipf.nextDexIndex = ipf.dexIndex == 0 ? 2 : ipf.dexIndex + 1; + } + } catch (Exception ex) { + } ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(); InputStream in = null; try {