diff --git a/README.md b/README.md index 3bb128d..d4da3f8 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ # AndroidProjectCreator Convert an APK to an Android Studio Project using multiple open-source tools. Tools that are unavailable are mirrored using repositories on my own Github account (copyright remains with the original creators, those repositories only serve as a mirror). -For more information, refer to [this](https://maxkersten.nl/projects/androidprojectcreator/) page on my website. If you've got any questions, please contact me on Twitter [@LibraAnalysis](https://twitter.com/LibraAnalysis)! +For more information, refer to [this](https://maxkersten.nl/projects/androidprojectcreator/) page on my website. If you've got any questions, please contact me on Twitter [@Libranalysis](https://twitter.com/Libranalysis)! diff --git a/pom.xml b/pom.xml index 169837d..1ddc45a 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 libra AndroidProjectCreator - 1.4-stable + 1.5-stable jar UTF-8 @@ -47,6 +47,21 @@ zip4j 1.3.2 + + org.apache.logging.log4j + log4j-api + 2.13.3 + + + org.apache.logging.log4j + log4j-core + 2.13.3 + + + org.apache.logging.log4j + log4j-slf4j-impl + 2.13.3 + @@ -65,4 +80,4 @@ - \ No newline at end of file + diff --git a/src/main/java/apc/AndroidProjectCreator.java b/src/main/java/apc/AndroidProjectCreator.java index e937d6f..b0982ea 100644 --- a/src/main/java/apc/AndroidProjectCreator.java +++ b/src/main/java/apc/AndroidProjectCreator.java @@ -47,9 +47,9 @@ public static void main(String[] args) { */ boolean debugging = false; if (debugging) { - //installTest(); + installTest(); //updateTest(); - decompileTest(DecompilerType.FERNFLOWER); + //decompileTest(DecompilerType.FERNFLOWER); System.exit(0); } diff --git a/src/main/java/apc/ArgumentManager.java b/src/main/java/apc/ArgumentManager.java index 8c734c3..8868d31 100644 --- a/src/main/java/apc/ArgumentManager.java +++ b/src/main/java/apc/ArgumentManager.java @@ -173,9 +173,9 @@ private void showError(Exception ex) { * Display the version information */ public void showVersion() { - String versionNumber = "1.4-stable"; + String versionNumber = "1.5-stable"; StringBuilder version = new StringBuilder(); - version.append("[+]AndroidProjectCreator " + versionNumber + " [developed by Max 'Libra' Kersten or @LibraAnalysis on Twitter]\n"); + version.append("[+]AndroidProjectCreator " + versionNumber + " [developed by Max 'Libra' Kersten or @Libranalysis on Twitter]\n"); System.out.println(version.toString()); } } diff --git a/src/main/java/command/CompactInstaller.java b/src/main/java/command/CompactInstaller.java index 25c490f..279cf94 100644 --- a/src/main/java/command/CompactInstaller.java +++ b/src/main/java/command/CompactInstaller.java @@ -41,10 +41,10 @@ public void install() throws IOException, InterruptedException, Exception { RepositoryManager repositoryManager = new RepositoryManager(); System.out.println("[+]Starting cloning the repositories"); List repository = new ArrayList<>(); - String name = "CompactInstall version 1.0 (dated 28-07-2020)"; + String name = "CompactInstall version 1.1 (dated 11-05-2021)"; String url = "https://github.com/thisislibra/apc-compact.git"; File directory = new File(Constants.LIBRARY_FOLDER); - String branch = "28-07-2020"; + String branch = "11-05-2021"; repository.add(new Repository(name, url, directory, branch)); repositoryManager.cloneRepositories(repository); System.out.println("[+]Cloning finished"); diff --git a/src/main/java/command/Decompiler.java b/src/main/java/command/Decompiler.java index 9fd9d2f..04e41e6 100644 --- a/src/main/java/command/Decompiler.java +++ b/src/main/java/command/Decompiler.java @@ -120,28 +120,34 @@ public void decompile() throws IOException, InterruptedException, ZipException { //TODO before the combine functionality is added, add a temporary "copy all classes[n].dex files to the template project's assets folder" method //TODO Combine classes[N].dex files into classes.dex to decompile every part of the binary, should be optional since it can exceed 64k functions. Use /Users/[name]/Library/Android/sdk/build-tools/28.0.2/lib/dx.jar com.android.dx.merge.DexMerger output.dex part1.dex part2.dex //Source for code: https://stackoverflow.com/questions/11257378/is-there-a-way-to-merge-two-or-more-dex-files-into-one-dex-file-using-scala - //Convert the classes.dex to a JAR file for later use /** - * Convert the classes.dex to a JAR (use the "sh" in front since the - * script is not executable by default) - * - * The '-n' is used to ignore exceptions that are thrown by dex2jar - * - * The '-f' is used to forcefully overwrite existing files on the - * destination location - * - * The '-o' is used to define the output location + * JADX can decompile an APK directly, therefore its more efficient to + * skip this step if the JADX decompiler has been selected. */ - if (isWindows) { - command = "d2j-dex2jar.bat"; - } else { - //Add extra shell here to avoid the need to chmod +x the shell script - command = "sh ./d2j-dex2jar.sh"; + if (argumentPackage.getDecompilerType().equals(DecompilerType.JADX) == false) { + //Convert the classes.dex to a JAR file for later use + /** + * Convert the classes.dex to a JAR (use the "sh" in front since the + * script is not executable by default) + * + * The '-n' is used to ignore exceptions that are thrown by dex2jar + * + * The '-f' is used to forcefully overwrite existing files on the + * destination location + * + * The '-o' is used to define the output location + */ + if (isWindows) { + command = "d2j-dex2jar.bat"; + } else { + //Add extra shell here to avoid the need to chmod +x the shell script + command = "sh ./d2j-dex2jar.sh"; + } + //Append the flags and the file paths to the commands. These are the same on any platform due to the Java runtime + command += " -n -f -o " + encapsulate(new File(Constants.TEMP_CONVERTED_JAR).getAbsolutePath()) + " " + encapsulate(new File(Constants.TEMP_LIBRARY_FOLDER + "/apktool/classes.dex").getAbsolutePath()); + workingDirectory = new File(Constants.DEX2JAR_LIBRARY_FOLDER); + executeCommand(DecompilerType.DEX2JAR, command, workingDirectory); } - //Append the flags and the file paths to the commands. These are the same on any platform due to the Java runtime - command += " -n -f -o " + encapsulate(new File(Constants.TEMP_CONVERTED_JAR).getAbsolutePath()) + " " + encapsulate(new File(Constants.TEMP_LIBRARY_FOLDER + "/apktool/classes.dex").getAbsolutePath()); - workingDirectory = new File(Constants.DEX2JAR_LIBRARY_FOLDER); - executeCommand(DecompilerType.DEX2JAR, command, workingDirectory); //Ensure that the output directory for the source code exists new File(Constants.TEMP_SOURCES_FOLDER).mkdir(); @@ -164,7 +170,7 @@ public void decompile() throws IOException, InterruptedException, ZipException { /** * -d sets output dir * - * -r avoids resources (got these with APKTool alraedy + * -r avoids resources (got these with APKTool already) * * --escape-unicode to escape unicode characters * @@ -182,7 +188,7 @@ public void decompile() throws IOException, InterruptedException, ZipException { command = "sh ./jadx"; } //Append the flags and the file paths to the commands. These are the same on any platform due to the Java runtime - command += " -r --escape-unicode -d " + encapsulate(new File(Constants.TEMP_LIBRARY_FOLDER).getAbsolutePath()) + " " + encapsulate(new File(Constants.TEMP_CONVERTED_JAR).getAbsolutePath()); + command += " -r --escape-unicode -d " + encapsulate(new File(Constants.TEMP_LIBRARY_FOLDER).getAbsolutePath()) + " " + encapsulate(argumentPackage.getApk().getAbsolutePath()); workingDirectory = new File(Constants.JADX_LIBRARY_FOLDER); break; case JDCMD: @@ -286,26 +292,43 @@ public void decompile() throws IOException, InterruptedException, ZipException { */ private void executeCommand(DecompilerType name, String commandString, File workingDirectory) throws IOException, InterruptedException, ZipException { Command command = new Command(commandString, workingDirectory); + FileManager fileManager = new FileManager(); System.out.println("[+]Decompling JAR with " + name); try { command.execute(); - if (name.equals(DecompilerType.FERNFLOWER)) { - new FileManager().extractArchive(new File(Constants.TEMP_SOURCES_FOLDER + "/output.jar").getAbsolutePath(), new File(Constants.TEMP_SOURCES_FOLDER).getAbsolutePath()); - new FileManager().delete(new File(Constants.TEMP_SOURCES_FOLDER + "/output.jar")); - } else if (name.equals(DecompilerType.JEB3)) { - /** - * If the JEB3 output folder exists, copy the contents to the - * TEMP_SOURCES_FOLDER and remove the JEB3 output folder. This - * way, the rest file handling can stay the same. - */ - File sourceLocation = new File(Constants.TEMP_SOURCES_FOLDER); - File jeb3Output = new File(sourceLocation.getAbsolutePath() + "/Bytecode_decompiled"); - if (jeb3Output.exists() && jeb3Output.isDirectory()) { - for (File currentFileObject : sourceLocation.listFiles()) { - new FileManager().copyFolder(currentFileObject, sourceLocation); + switch (name) { + case FERNFLOWER: + fileManager.extractArchive(new File(Constants.TEMP_SOURCES_FOLDER + "/output.jar").getAbsolutePath(), new File(Constants.TEMP_SOURCES_FOLDER).getAbsolutePath()); + fileManager.delete(new File(Constants.TEMP_SOURCES_FOLDER + "/output.jar")); + break; + case JEB3: + /** + * If the JEB3 output folder exists, copy the contents to + * the TEMP_SOURCES_FOLDER and remove the JEB3 output + * folder. This way, the rest file handling can stay the + * same. + */ + File sourceLocation = new File(Constants.TEMP_SOURCES_FOLDER); + File jeb3Output = new File(sourceLocation.getAbsolutePath() + "/Bytecode_decompiled"); + if (jeb3Output.exists() && jeb3Output.isDirectory()) { + for (File currentFileObject : sourceLocation.listFiles()) { + fileManager.copyFolder(currentFileObject, sourceLocation); + } + fileManager.delete(jeb3Output); } - new FileManager().delete(jeb3Output); - } + break; + case JADX: + File source = new File(Constants.TEMP_SOURCES_FOLDER); + File jadxOutput = new File(source.getAbsolutePath() + "/sources"); + if (jadxOutput.exists() && jadxOutput.isDirectory()) { + for (File currentFileObject : source.listFiles()) { + fileManager.copyFolder(currentFileObject, source); + } + fileManager.delete(jadxOutput); + } + break; + default: + break; } System.out.println("[+]Decompilation finished"); } catch (IOException ex) { diff --git a/src/main/java/library/Repositories.java b/src/main/java/library/Repositories.java index 5980013..12b01f7 100644 --- a/src/main/java/library/Repositories.java +++ b/src/main/java/library/Repositories.java @@ -89,7 +89,7 @@ public static Repository getJdCmd() { //String url = "https://github.com/kwart/jd-cmd.git"; String url = "https://github.com/ThisIsLibra/jdcmd.git"; File directory = new File(Constants.JDCMD_REPOSITORY_FOLDER); - String branch = "master"; + String branch = "main"; return new Repository(name, url, directory, branch); } @@ -129,7 +129,7 @@ public static Repository getAndroidProject() { //String name = "androidstudioproject"; String url = "https://github.com/ThisIsLibra/AndroidStudioProject.git"; File directory = new File(Constants.ANDROIDPROJECT_REPOSITORY_FOLDER); - String branch = "master"; + String branch = "main"; return new Repository(name, url, directory, branch); } @@ -168,7 +168,7 @@ public static Repository getJeb3AndroidDecompilerScript() { String name = DecompilerType.JEB3.toString().toLowerCase(); String url = "https://github.com/ThisIsLibra/jeb3-cli-android-decompiler.git"; File directory = new File(Constants.JEB3_CLI_ANDROID_SCRIPT_REPOSITORY_FOLDER); - String branch = "master"; + String branch = "main"; return new Repository(name, url, directory, branch); } } diff --git a/target/AndroidProjectCreator-1.4-stable-jar-with-dependencies.jar b/target/AndroidProjectCreator-1.5-stable-jar-with-dependencies.jar similarity index 59% rename from target/AndroidProjectCreator-1.4-stable-jar-with-dependencies.jar rename to target/AndroidProjectCreator-1.5-stable-jar-with-dependencies.jar index 51c5523..300015b 100644 Binary files a/target/AndroidProjectCreator-1.4-stable-jar-with-dependencies.jar and b/target/AndroidProjectCreator-1.5-stable-jar-with-dependencies.jar differ