14: Add JADX decompiler

This commit is contained in:
Bartłomiej Pluta
2019-04-11 14:06:02 +02:00
parent 9b2dd2817a
commit 7e3715708a
7 changed files with 95 additions and 25 deletions

View File

@@ -3,7 +3,7 @@ package com.bartek.esa.analyser.apk;
import com.bartek.esa.analyser.core.Analyser;
import com.bartek.esa.core.archetype.Plugin;
import com.bartek.esa.core.executor.PluginExecutor;
import com.bartek.esa.decompiler.decompiler.Decompiler;
import com.bartek.esa.decompiler.archetype.Decompiler;
import com.bartek.esa.error.EsaException;
import com.bartek.esa.file.cleaner.FileCleaner;
import com.bartek.esa.file.matcher.GlobMatcher;
@@ -12,11 +12,9 @@ import com.bartek.esa.file.provider.FileProvider;
import java.io.File;
import java.util.Set;
public class ApkAnalyser extends Analyser {
private static final String ANDROID_MANIFEST_GLOB = "**/" + Decompiler.XML_FILES_DIR + "/AndroidManifest.xml";
private static final String JAVA_GLOB = "**/" + Decompiler.JAVA_FILES_DIR + "/**/*.java";
private static final String LAYOUT_GLOB = "**/" + Decompiler.XML_FILES_DIR + "/**/layout*/*.xml";
import static java.lang.String.format;
public class ApkAnalyser extends Analyser {
private final Decompiler decompiler;
private final FileCleaner fileCleaner;
private final GlobMatcher globMatcher;
@@ -43,17 +41,17 @@ public class ApkAnalyser extends Analyser {
@Override
protected String getAndroidManifestGlob() {
return ANDROID_MANIFEST_GLOB;
return format("**/%s/AndroidManifest.xml", decompiler.getAndroidManifestFolder());
}
@Override
protected String getJavaGlob() {
return JAVA_GLOB;
return format("**/%s/**/*.java", decompiler.getJavaSourcesFolder());
}
@Override
protected String getLayoutGlob() {
return LAYOUT_GLOB;
return format("**/%s/layout*/*.xml", decompiler.getResFolder());
}
@Override

View File

@@ -4,7 +4,7 @@ import com.bartek.esa.analyser.apk.ApkAnalyser;
import com.bartek.esa.analyser.source.SourceAnalyser;
import com.bartek.esa.core.archetype.Plugin;
import com.bartek.esa.core.executor.PluginExecutor;
import com.bartek.esa.decompiler.decompiler.Decompiler;
import com.bartek.esa.decompiler.archetype.Decompiler;
import com.bartek.esa.file.cleaner.FileCleaner;
import com.bartek.esa.file.matcher.GlobMatcher;
import com.bartek.esa.file.provider.FileProvider;

View File

@@ -0,0 +1,10 @@
package com.bartek.esa.decompiler.archetype;
import java.io.File;
public interface Decompiler {
File decompile(File inputApk, boolean debug);
String getAndroidManifestFolder();
String getResFolder();
String getJavaSourcesFolder();
}

View File

@@ -1,5 +1,6 @@
package com.bartek.esa.decompiler.decompiler;
import com.bartek.esa.decompiler.archetype.Decompiler;
import com.bartek.esa.decompiler.process.ProcessExecutor;
import com.bartek.esa.file.cleaner.FileCleaner;
import com.bartek.esa.file.provider.FileProvider;
@@ -10,9 +11,9 @@ import javax.inject.Inject;
import java.io.File;
import java.util.Set;
public class Decompiler {
public static final String XML_FILES_DIR = "xml";
public static final String JAVA_FILES_DIR = "java";
public class CfrDecompiler implements Decompiler {
private static final String XML_FILES_DIR = "xml";
private static final String JAVA_FILES_DIR = "java";
private static final String APK_UNZIPPED_DIR = "apk_unzipped";
private static final String JAR_FILES_DIR = "jar";
@@ -23,13 +24,14 @@ public class Decompiler {
private final FileCleaner fileCleaner;
@Inject
public Decompiler(FileProvider fileProvider, ProcessExecutor processExecutor1, ZipTool zipTool, FileCleaner fileCleaner) {
public CfrDecompiler(FileProvider fileProvider, ProcessExecutor processExecutor1, ZipTool zipTool, FileCleaner fileCleaner) {
this.fileProvider = fileProvider;
this.processExecutor = processExecutor1;
this.zipTool = zipTool;
this.fileCleaner = fileCleaner;
}
@Override
public File decompile(File inputApk, boolean debug) {
File tmp = fileProvider.createTemporaryDirectory();
File javaDirectory = new File(tmp, JAVA_FILES_DIR);
@@ -41,6 +43,21 @@ public class Decompiler {
return tmp;
}
@Override
public String getAndroidManifestFolder() {
return "";
}
@Override
public String getResFolder() {
return XML_FILES_DIR;
}
@Override
public String getJavaSourcesFolder() {
return JAVA_FILES_DIR;
}
private void decompileJavaFiles(File inputApk, File tmp, File javaDirectory, boolean debug) {
File unzippedApkDirectory = new File(tmp, APK_UNZIPPED_DIR);
File jarDirectory = new File(tmp, JAR_FILES_DIR);

View File

@@ -0,0 +1,53 @@
package com.bartek.esa.decompiler.decompiler;
import com.bartek.esa.decompiler.archetype.Decompiler;
import com.bartek.esa.decompiler.process.ProcessExecutor;
import com.bartek.esa.file.provider.FileProvider;
import javax.inject.Inject;
import java.io.File;
public class JadxDecompiler implements Decompiler {
private static final String RESOURCES_FILES_DIR = "resources";
private static final String JAVA_FILES_DIR = "sources";
private final FileProvider fileProvider;
private final ProcessExecutor processExecutor;
@Inject
public JadxDecompiler(FileProvider fileProvider, ProcessExecutor processExecutor) {
this.fileProvider = fileProvider;
this.processExecutor = processExecutor;
}
@Override
public File decompile(File inputApk, boolean debug) {
File tmp = fileProvider.createTemporaryDirectory();
runJadx(inputApk, tmp, debug);
return tmp;
}
private void runJadx(File inputApk, File tmp, boolean debug) {
String[] cmd = {
"jadx", inputApk.getAbsolutePath(),
"-ds", new File(tmp, JAVA_FILES_DIR).getAbsolutePath(),
"-dr", new File(tmp, RESOURCES_FILES_DIR).getAbsolutePath()
};
processExecutor.execute(cmd, debug);
}
@Override
public String getAndroidManifestFolder() {
return RESOURCES_FILES_DIR;
}
@Override
public String getResFolder() {
return RESOURCES_FILES_DIR + "/res";
}
@Override
public String getJavaSourcesFolder() {
return JAVA_FILES_DIR;
}
}

View File

@@ -1,10 +1,9 @@
package com.bartek.esa.decompiler.di;
import com.bartek.esa.decompiler.decompiler.Decompiler;
import com.bartek.esa.decompiler.archetype.Decompiler;
import com.bartek.esa.decompiler.decompiler.JadxDecompiler;
import com.bartek.esa.decompiler.process.ProcessExecutor;
import com.bartek.esa.file.cleaner.FileCleaner;
import com.bartek.esa.file.provider.FileProvider;
import com.bartek.esa.file.zip.ZipTool;
import dagger.Module;
import dagger.Provides;
@@ -17,7 +16,7 @@ public class DecompilerModule {
}
@Provides
public Decompiler decompiler(FileProvider fileProvider, ProcessExecutor processExecutor, ZipTool zipTool, FileCleaner fileCleaner) {
return new Decompiler(fileProvider, processExecutor, zipTool, fileCleaner);
public Decompiler decompiler(FileProvider fileProvider, ProcessExecutor processExecutor) {
return new JadxDecompiler(fileProvider, processExecutor);
}
}

View File

@@ -21,7 +21,6 @@ public class ProcessExecutor {
.getOrElseThrow(EsaException::new);
printStdOutAndStdErrFromProcess(debug, process);
waitForProcess(process);
checkExitValue(process, command[0]);
}
private void printCommandLine(String[] command, boolean debug) {
@@ -55,10 +54,4 @@ public class ProcessExecutor {
private void waitForProcess(Process process) {
Try.run(process::waitFor).getOrElseThrow(EsaException::new);
}
private void checkExitValue(Process process, String commandName) {
if (process.exitValue() != 0) {
throw new EsaException("'" + commandName + "' process has finished with non-zero code. Interrupting...");
}
}
}