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 e5b22039e..beefc7826 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 @@ -20,6 +20,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.android.dex.Dex; +import com.android.dex.DexException; import jadx.core.utils.AsmUtils; import jadx.core.utils.exceptions.DecodeException; @@ -52,7 +53,7 @@ public class InputFile { String fileName = file.getName(); if (fileName.endsWith(".dex")) { - addDexFile(fileName, new Dex(file), file.toPath()); + addDexFile(fileName, file.toPath()); return; } if (fileName.endsWith(".smali")) { @@ -60,12 +61,12 @@ public class InputFile { SmaliOptions options = new SmaliOptions(); options.outputDexFile = output.toAbsolutePath().toString(); Smali.assemble(options, file.getAbsolutePath()); - addDexFile("", new Dex(output.toFile()), output); + addDexFile(fileName, output); return; } if (fileName.endsWith(".class")) { for (Path path : loadFromClassFile(file)) { - addDexFile(path); + addDexFile(fileName, path); } return; } @@ -80,7 +81,7 @@ public class InputFile { } if (fileName.endsWith(".jar")) { for (Path path : loadFromJar(file.toPath())) { - addDexFile(path); + addDexFile(fileName, path); } return; } @@ -96,18 +97,6 @@ public class InputFile { LOG.warn("No dex files found in {}", file); } - private void addDexFile(Path path) throws IOException { - addDexFile(path.getFileName().toString(), path); - } - - private void addDexFile(String fileName, Path path) throws IOException { - addDexFile(fileName, new Dex(Files.readAllBytes(path)), path); - } - - private void addDexFile(String fileName, Dex dexBuf, Path path) { - dexFiles.add(new DexFile(this, fileName, dexBuf, path)); - } - private boolean loadFromZip(String ext) throws IOException, DecodeException { int index = 0; try (ZipFile zf = new ZipFile(file)) { @@ -127,9 +116,8 @@ public class InputFile { || entryName.endsWith(instantRunDexSuffix)) { switch (ext) { case ".dex": - Path path = makeDexBuf(entryName, inputStream); - if (path != null) { - addDexFile(entryName, path); + Path path = copyToTmpDex(entryName, inputStream); + if (addDexFile(entryName, path)) { index++; } break; @@ -163,8 +151,32 @@ public class InputFile { return index > 0; } + private boolean addDexFile(String entryName, @Nullable Path filePath) { + if (filePath == null) { + return false; + } + Dex dexBuf = loadDexBufFromPath(filePath, entryName); + if (dexBuf == null) { + return false; + } + dexFiles.add(new DexFile(this, entryName, dexBuf, filePath)); + return true; + } + @Nullable - private Path makeDexBuf(String entryName, InputStream inputStream) { + private Dex loadDexBufFromPath(Path path, String entryName) { + try { + return new Dex(Files.readAllBytes(path)); + } catch (DexException e) { + LOG.error("Failed to load dex file: {}, error: {}", entryName, e.getMessage()); + } catch (Exception e) { + LOG.error("Failed to load dex file: {}, error: {}", entryName, e.getMessage(), e); + } + return null; + } + + @Nullable + private Path copyToTmpDex(String entryName, InputStream inputStream) { try { Path path = FileUtils.createTempFile(".dex"); Files.copy(inputStream, path, StandardCopyOption.REPLACE_EXISTING); diff --git a/jadx-core/src/test/java/jadx/core/utils/files/InputFileTest.java b/jadx-core/src/test/java/jadx/core/utils/files/InputFileTest.java new file mode 100644 index 000000000..7f4f60fa5 --- /dev/null +++ b/jadx-core/src/test/java/jadx/core/utils/files/InputFileTest.java @@ -0,0 +1,37 @@ +package jadx.core.utils.files; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +import org.junit.jupiter.api.Test; + +import jadx.core.utils.exceptions.DecodeException; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.notNullValue; + +class InputFileTest { + private static final String TEST_SAMPLES_DIR = "test-samples/"; + + @Test + public void testApkWithFakeDex() throws IOException, DecodeException { + File sample = getFileFromSampleDir("app-with-fake-dex.apk"); + + List list = new ArrayList<>(); + InputFile.addFilesFrom(sample, list, false); + assertThat(list, hasSize(1)); + InputFile inputFile = list.get(0); + assertThat(inputFile.getDexFiles(), hasSize(1)); + } + + private static File getFileFromSampleDir(String fileName) { + URL resource = InputFileTest.class.getClassLoader().getResource(TEST_SAMPLES_DIR + fileName); + assertThat(resource, notNullValue()); + String pathStr = resource.getFile(); + return new File(pathStr); + } +} diff --git a/jadx-core/src/test/resources/test-samples/app-with-fake-dex.apk b/jadx-core/src/test/resources/test-samples/app-with-fake-dex.apk new file mode 100644 index 000000000..0a6969ad6 Binary files /dev/null and b/jadx-core/src/test/resources/test-samples/app-with-fake-dex.apk differ