Skip to content

Commit

Permalink
fix: ignore incorrect dex files in apk (#700)
Browse files Browse the repository at this point in the history
  • Loading branch information
skylot committed Jul 8, 2019
1 parent 3eee83c commit c3f7a04
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 20 deletions.
52 changes: 32 additions & 20 deletions jadx-core/src/main/java/jadx/core/utils/files/InputFile.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
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;
Expand Down Expand Up @@ -52,20 +53,20 @@ private void searchDexFiles(boolean skipSources) throws IOException, DecodeExcep
String fileName = file.getName();

if (fileName.endsWith(".dex")) {
addDexFile(fileName, new Dex(file), file.toPath());
addDexFile(fileName, file.toPath());
return;
}
if (fileName.endsWith(".smali")) {
Path output = FileUtils.createTempFile(".dex");
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;
}
Expand All @@ -80,7 +81,7 @@ private void searchDexFiles(boolean skipSources) throws IOException, DecodeExcep
}
if (fileName.endsWith(".jar")) {
for (Path path : loadFromJar(file.toPath())) {
addDexFile(path);
addDexFile(fileName, path);
}
return;
}
Expand All @@ -96,18 +97,6 @@ private void searchDexFiles(boolean skipSources) throws IOException, DecodeExcep
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)) {
Expand All @@ -127,9 +116,8 @@ private boolean loadFromZip(String ext) throws IOException, DecodeException {
|| 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;
Expand Down Expand Up @@ -163,8 +151,32 @@ private boolean loadFromZip(String ext) throws IOException, DecodeException {
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 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 makeDexBuf(String entryName, InputStream inputStream) {
private Path copyToTmpDex(String entryName, InputStream inputStream) {
try {
Path path = FileUtils.createTempFile(".dex");
Files.copy(inputStream, path, StandardCopyOption.REPLACE_EXISTING);
Expand Down
37 changes: 37 additions & 0 deletions jadx-core/src/test/java/jadx/core/utils/files/InputFileTest.java
Original file line number Diff line number Diff line change
@@ -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<InputFile> 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);
}
}
Binary file not shown.

0 comments on commit c3f7a04

Please sign in to comment.