diff --git a/plugins/Skeleton.gy b/plugins/Skeleton.gy index 7c540020..1008aea3 100644 --- a/plugins/Skeleton.gy +++ b/plugins/Skeleton.gy @@ -1,6 +1,5 @@ import org.objectweb.asm.tree.ClassNode -import the.bytecode.club.bytecodeviewer.api.Plugin -import the.bytecode.club.bytecodeviewer.api.PluginConsole +import the.bytecode.club.bytecodeviewer.api.* class Skeleton extends Plugin { diff --git a/plugins/Skeleton.java b/plugins/Skeleton.java index b3e8d3b8..0b1a0416 100644 --- a/plugins/Skeleton.java +++ b/plugins/Skeleton.java @@ -1,13 +1,14 @@ -import the.bytecode.club.bytecodeviewer.api.*; -import java.util.ArrayList; +import java.util.List; import org.objectweb.asm.tree.ClassNode; +import the.bytecode.club.bytecodeviewer.api.*; public class Skeleton extends Plugin { - @Override - public void execute(ArrayList classNodesList) { - PluginConsole gui = new PluginConsole("Skeleton"); - gui.setVisible(true); - gui.appendText("executed skeleton"); - } -} \ No newline at end of file + @Override + public void execute(List classNodesList) { + PluginConsole gui = new PluginConsole("Skeleton"); + gui.setVisible(true); + gui.appendText("executed skeleton"); + } + +} diff --git a/plugins/Skeleton.js b/plugins/Skeleton.js index 72850aa8..777fa3ca 100644 --- a/plugins/Skeleton.js +++ b/plugins/Skeleton.js @@ -1,7 +1,6 @@ -function execute(classNodeList) -{ +function execute(classNodeList) { var PluginConsole = Java.type("the.bytecode.club.bytecodeviewer.api.PluginConsole"); var gui = new PluginConsole("Skeleton"); gui.setVisible(true); gui.appendText("executed skeleton"); -} \ No newline at end of file +} diff --git a/plugins/Skeleton.rb b/plugins/Skeleton.rb index 1bfdf47c..8e0449d8 100644 --- a/plugins/Skeleton.rb +++ b/plugins/Skeleton.rb @@ -12,4 +12,4 @@ class Skeleton < Plugin gui.setVisible(true) gui.appendText("executed skeleton") end -end \ No newline at end of file +end diff --git a/plugins/XposedGenerator.java b/plugins/XposedGenerator.java index 216a2239..9661487c 100644 --- a/plugins/XposedGenerator.java +++ b/plugins/XposedGenerator.java @@ -1,4 +1,3 @@ -import java.awt.*; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; @@ -12,10 +11,8 @@ import javax.swing.Box; import javax.swing.JComboBox; import javax.swing.JOptionPane; import javax.swing.JPanel; - import org.objectweb.asm.tree.ClassNode; import the.bytecode.club.bytecodeviewer.*; -import the.bytecode.club.bytecodeviewer.util.*; import the.bytecode.club.bytecodeviewer.api.*; import the.bytecode.club.bytecodeviewer.decompilers.impl.FernFlowerDecompiler; import the.bytecode.club.bytecodeviewer.gui.resourceviewer.viewer.ResourceViewer; @@ -23,63 +20,58 @@ import the.bytecode.club.bytecodeviewer.gui.resourceviewer.viewer.ResourceViewer /** * @author jowasp */ -public class XposedGenerator extends Plugin -{ +public class XposedGenerator extends Plugin { //PRIVATE - private static List methodsNames = new ArrayList(); - private static List cleanMethodsNames = new ArrayList(); - private static String foundpckg; - - public XposedGenerator() {} - - @Override - public void execute(ArrayList classNodeList) - { - //Get actual file class content - ResourceViewer viewer = BytecodeViewer.getActiveResource(); - - if(viewer == null) - { - BytecodeViewer.showMessage("Open A Class First"); - return; - } - - String className = viewer.getName(); - String containerName = viewer.name; - ClassNode classnode = BytecodeViewer.getCurrentlyOpenedClassNode(); - - //Call XposedGenerator class - ParseChosenFileContent(className,containerName,classnode); + private static final List methodsNames = new ArrayList<>(); + private static final List cleanMethodsNames = new ArrayList<>(); + private static String foundPckg; + + public XposedGenerator() { } - public static void ParseChosenFileContent(String classname, String containerName, ClassNode classNode) - { - try - { + @Override + public void execute(List classNodeList) { + //Get actual file class content + ResourceViewer viewer = BytecodeViewer.getActiveResource(); + + if (viewer == null) { + BytecodeViewer.showMessage("Open A Class First"); + return; + } + + String className = viewer.getName(); + //String containerName = viewer.getName(); + ClassNode classnode = BytecodeViewer.getCurrentlyOpenedClassNode(); + + //Call XposedGenerator class + ParseChosenFileContent(className, classnode); + } + + public static void ParseChosenFileContent(String classname, ClassNode classNode) { + try { //Parse content - Extract methods after APK /JAR has been extracted byte[] cont = ASMUtil.nodeToBytes(classNode); - + //Use one of the decompilers //TODO:Allow users to select other decompilers? FernFlowerDecompiler decompilefern = new FernFlowerDecompiler(); //Decompile using Fern - String decomp = decompilefern.decompileClassNode(classNode, cont); - String[] xposedTemplateTypes = {"Empty","Parameters","Helper"}; - @SuppressWarnings({ "unchecked", "rawtypes" }) + String decomp = decompilefern.decompileClassNode(classNode, cont); + String[] xposedTemplateTypes = {"Empty", "Parameters", "Helper"}; + @SuppressWarnings({"unchecked", "rawtypes"}) JComboBox xposedTemplateList = new JComboBox(xposedTemplateTypes); - //Set results of parsed methods into an a list + //Set results of parsed methods into a list List methodsExtracted = ProcessContentExtractedClass(decomp); String packgExtracted = ProcessContentExtractedPackage(decomp); - System.out.println("PACKAGE NAME: " +packgExtracted); + System.out.println("PACKAGE NAME: " + packgExtracted); //Get a clean list - List cleanMethods = null; + List cleanMethods; //clear list cleanMethods = ProcessCleanMethodsAll(methodsExtracted); - if (!cleanMethods.isEmpty()) - { - JComboBox cb = new JComboBox<>(cleanMethods.toArray(new String[cleanMethods.size()])); + if (!cleanMethods.isEmpty()) { + JComboBox cb = new JComboBox<>(cleanMethods.toArray(new String[0])); //Add Panel elements //Start Panel @@ -94,56 +86,54 @@ public class XposedGenerator extends Plugin if (result == JOptionPane.OK_OPTION) { //Read Chosen Class - System.out.println("SELECTED CLASS is" + cb.getSelectedItem()); - String selectedClass = cb.getSelectedItem().toString(); - String selectedXposedTemplate = xposedTemplateList.getSelectedItem().toString(); + Object cbItem = cb.getSelectedItem(); + Object xPosedItem = xposedTemplateList.getSelectedItem(); + System.out.println("SELECTED CLASS is" + cbItem); + if (cbItem != null && xPosedItem != null) { + String selectedClass = cbItem.toString(); + String selectedXposedTemplate = xPosedItem.toString(); - //WriteXposed Class with extracted data - try{ - WriteXposedModule(selectedClass, packgExtracted, classname, selectedXposedTemplate); - } - catch(IllegalArgumentException e) - { - e.printStackTrace(); - JOptionPane.showMessageDialog(null,"Error" + e.toString()); + //WriteXposed Class with extracted data + try { + WriteXposedModule(selectedClass, packgExtracted, classname, selectedXposedTemplate); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + JOptionPane.showMessageDialog(null, "Error" + e); + } } } + } else { + JOptionPane.showMessageDialog(null, "Class Not Suitable"); } - else - { - JOptionPane.showMessageDialog(null,"Class Not Suitable"); - } - } - catch (IllegalArgumentException e) - { + } catch (IllegalArgumentException e) { e.printStackTrace(); - JOptionPane.showMessageDialog(null,"Error" + e.toString()); + JOptionPane.showMessageDialog(null, "Error" + e); } } - public static void WriteXposedModule(String functionToHook, String packageName, String classToHook, String template) { - System.out.println("TEMPLATE: " + template); - if (template != null && !template.equals("Empty")) - { + public static void WriteXposedModule(String functionToHook, String packageName, String classToHook, + String template) { + System.out.println("TEMPLATE: " + template); + if (template != null && !template.equals("Empty")) { try { //TODO: Prompt save dialog File file = new File("./XposedClassTest.java"); - // if file doesn't exists, then create it + // if file doesn't exist, then create it if (!file.exists()) { file.createNewFile(); } //Extract the package name only - String packageNameOnly = packageName.substring(8,packageName.length() - 2 ).trim(); + String packageNameOnly = packageName.substring(8, packageName.length() - 2).trim(); String classToHookNameOnly = classToHook; - if(classToHookNameOnly.endsWith(".class")) + if (classToHookNameOnly.endsWith(".class")) classToHookNameOnly = classToHook.substring(0, classToHookNameOnly.length() - 6); - - String[] classClean = classToHookNameOnly.split("\\/"); + + String[] classClean = classToHookNameOnly.split("/"); String[] functionSplitValues = functionToHook.split("\\s+"); //select - String onlyClass = classClean[classClean.length-1]; + String onlyClass = classClean[classClean.length - 1]; //String onlyFunctionParateses = functionSplitValues[functionSplitValues.length-2]; String onlyFunction = CleanUpFunction(functionSplitValues); @@ -153,30 +143,34 @@ public class XposedGenerator extends Plugin //Write Xposed Class String XposedClassText = - "package androidpentesting.com.xposedmodule;"+ "\r\n" + + "package androidpentesting.com.xposedmodule;" + "\r\n" + "import de.robv.android.xposed.IXposedHookLoadPackage;" + "\r\n" + "\r\n" + - "import de.robv.android.xposed.XC_MethodHook;" +"\r\n" + - "import de.robv.android.xposed.XposedBridge;" +"\r\n" + - "import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;"+"\r\n" + - "import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;"+"\r\n" +"\r\n" + - "public class XposedClassTest implements IXposedHookLoadPackage {"+"\r\n" +"\r\n" + - " public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable {" + "\r\n" +"\r\n" + - " String classToHook = " + "\"" + packageNameOnly + "." + onlyClass + "\";" + "\r\n" + - " String functionToHook = "+"\""+ onlyFunction+"\";"+"\r\n" + - " if (lpparam.packageName.equals("+"\""+packageNameOnly+ "\""+")){"+ "\r\n" + - " XposedBridge.log(" + "\" Loaded app: \" " + " + lpparam.packageName);"+ "\r\n" +"\r\n" + - " findAndHookMethod("+"\""+onlyClass+"\"" + ", lpparam.classLoader, "+" \"" +onlyFunction + "\""+", int.class,"+ "\r\n" + - " new XC_MethodHook() {"+ "\r\n" + - " @Override"+ "\r\n" + - " protected void beforeHookedMethod(MethodHookParam param) throws Throwable {"+ "\r\n" + - " //TO BE FILLED BY ANALYST"+ "\r\n" + - " }"+ "\r\n" + - " });"+"\r\n" + - " }"+ "\r\n" + - " }"+ "\r\n" + - "}"+ "\r\n" - ; + "import de.robv.android.xposed.XC_MethodHook;" + "\r\n" + + "import de.robv.android.xposed.XposedBridge;" + "\r\n" + + "import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;" + "\r\n" + + "import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;" + "\r\n" + + "\r\n" + + "public class XposedClassTest implements IXposedHookLoadPackage {" + "\r\n" + "\r\n" + + " public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable {" + "\r\n" + "\r\n" + + " String classToHook = " + "\"" + packageNameOnly + "." + onlyClass + "\";" + + "\r\n" + + " String functionToHook = " + "\"" + onlyFunction + "\";" + "\r\n" + + " if (lpparam.packageName.equals(" + "\"" + packageNameOnly + "\"" + ")){" + "\r" + + "\n" + + " XposedBridge.log(" + "\" Loaded app: \" " + " + lpparam.packageName);" + + "\r\n" + "\r\n" + + " findAndHookMethod(" + "\"" + onlyClass + "\"" + ", lpparam.classLoader, " + " \"" + onlyFunction + "\"" + ", int.class," + "\r\n" + + " new XC_MethodHook() {" + "\r\n" + + " @Override" + "\r\n" + + " protected void beforeHookedMethod(MethodHookParam param) throws " + + "Throwable {" + "\r\n" + + " //TO BE FILLED BY ANALYST" + "\r\n" + + " }" + "\r\n" + + " });" + "\r\n" + + " }" + "\r\n" + + " }" + "\r\n" + + "}" + "\r\n"; FileWriter fw = new FileWriter(file.getAbsoluteFile()); BufferedWriter bw = new BufferedWriter(fw); bw.write(XposedClassText); @@ -184,21 +178,19 @@ public class XposedGenerator extends Plugin bw.close(); System.out.println("Done"); - JOptionPane.showMessageDialog(null,"Xposed Module Generated"); + JOptionPane.showMessageDialog(null, "Xposed Module Generated"); } catch (IOException e) { - JOptionPane.showMessageDialog(null,"Error" + e.toString()); + JOptionPane.showMessageDialog(null, "Error" + e); e.printStackTrace(); } + } else { + JOptionPane.showMessageDialog(null, "Empty Template Chosen, Did Not Generate"); } - else - { - JOptionPane.showMessageDialog(null,"Empty Template Chosen, Did Not Generate"); - } } - private static List ProcessContentExtractedClass(String contentFile){ + private static List ProcessContentExtractedClass(String contentFile) { Scanner scanner = null; - try{ + try { scanner = new Scanner(contentFile); //@TODO : Improve patterns to match other excepts 'public' String regexclass = "public"; @@ -212,16 +204,13 @@ public class XposedGenerator extends Plugin String line = scanner.nextLine(); // process the line Matcher matcher = pattern.matcher(line); - while (matcher.find()){ + while (matcher.find()) { - if (matcher.group() != null) - { + if (matcher.group() != null) { System.out.println("find() found the pattern \"" + quote(line.trim())); System.out.println("Function: " + CleanUpFunction(line.trim().split("\\s+"))); methodsNames.add(quote(line.trim())); - } - else - { + } else { methodsNames.add("No methods found"); } @@ -229,34 +218,23 @@ public class XposedGenerator extends Plugin } - if (methodsNames.isEmpty()) - { + if (methodsNames.isEmpty()) { methodsNames.add("No methods found"); - } - else - { + } else { return methodsNames; } return methodsNames; - } - finally { - if (scanner!=null) + } finally { + if (scanner != null) scanner.close(); } } - private static List ProcessCleanMethodsAll(List rawMethods) - { - for (String m:rawMethods) - { + private static List ProcessCleanMethodsAll(List rawMethods) { + for (String m : rawMethods) { //Exclude class declaration //TODO:add a list containing all possible types - if (m.contains("extends") || (m.contains("implements") || (!m.contains("(")))) - { - continue; - } - else - { + if (!m.contains("extends") && (!m.contains("implements") && (m.contains("(")))) { cleanMethodsNames.add(m); } @@ -266,19 +244,12 @@ public class XposedGenerator extends Plugin } - private static String CleanUpFunction(String[] rawFunction) - { + private static String CleanUpFunction(String[] rawFunction) { String onlyFunc = "functiondummy"; - for (String m:rawFunction) - { - if(m.contains("(")) - { + for (String m : rawFunction) { + if (m.contains("(")) { String[] split = m.split("\\(")[0].split(" "); - return split[split.length-1]; - } - else - { - continue; + return split[split.length - 1]; } } @@ -286,61 +257,50 @@ public class XposedGenerator extends Plugin } - private static String ProcessContentExtractedPackage(String contentFile){ + private static String ProcessContentExtractedPackage(String contentFile) { Scanner scanner = null; try { scanner = new Scanner(contentFile); String regexPkg = "package"; - Pattern patternPkg = Pattern.compile(regexPkg , Pattern.CASE_INSENSITIVE); + Pattern patternPkg = Pattern.compile(regexPkg, Pattern.CASE_INSENSITIVE); String line = scanner.nextLine(); // process the line Matcher matcher = patternPkg.matcher(line); - while (matcher.find()){ + while (matcher.find()) { - if (matcher.group() != null) - { - System.out.println("find() found the pattern \"" + quote(line.trim())) ; - foundpckg = quote(line.trim()); + if (matcher.group() != null) { + System.out.println("find() found the pattern \"" + quote(line.trim())); + foundPckg = quote(line.trim()); - } - else - { - foundpckg = ""; + } else { + foundPckg = ""; } } try // { - if (foundpckg == null || foundpckg.isEmpty()) - foundpckg = "No Package Found"; + if (foundPckg == null || foundPckg.isEmpty()) + foundPckg = "No Package Found"; + } catch (NullPointerException e) { + JOptionPane.showMessageDialog(null, + "Error - no package was found in the selected class: " + e); + } finally { + scanner.close(); } - catch(NullPointerException e) - { - JOptionPane.showMessageDialog(null,"Error - no package was found in the selected class: " + e.toString()); - } - finally - { - if(scanner != null) - scanner.close(); - } - } - catch(IllegalArgumentException e) - { - JOptionPane.showMessageDialog(null,"Error" + e.toString()); - if(scanner != null) + } catch (IllegalArgumentException e) { + JOptionPane.showMessageDialog(null, "Error" + e); + if (scanner != null) + scanner.close(); + } finally { + if (scanner != null) scanner.close(); } - finally - { - if(scanner != null) - scanner.close(); - } - return foundpckg; + return foundPckg; } - private static String quote(String aText){ + private static String quote(String aText) { String QUOTE = "'"; return QUOTE + aText + QUOTE; } diff --git a/plugins/example/ExamplePrintClassesPlugin.js b/plugins/example/ExamplePrintClassesPlugin.js index 7bfb6e56..c9e7ca36 100644 --- a/plugins/example/ExamplePrintClassesPlugin.js +++ b/plugins/example/ExamplePrintClassesPlugin.js @@ -6,13 +6,11 @@ var PluginConsole = Java.type("the.bytecode.club.bytecodeviewer.api.PluginConsol var gui = new PluginConsole("Example Plugin Print Loaded Classes"); -function execute(classNodeList) -{ - for (index = 0; index < classNodeList.length; index++) - { +function execute(classNodeList) { + for (index = 0; index < classNodeList.length; index++) { var cn = classNodeList[index]; gui.appendText("Resource: " + cn.name + ".class"); } gui.setVisible(true); -} \ No newline at end of file +} diff --git a/plugins/example/ExampleStringDecrypter.gy b/plugins/example/ExampleStringDecrypter.gy index 086cbc83..b66103cc 100644 --- a/plugins/example/ExampleStringDecrypter.gy +++ b/plugins/example/ExampleStringDecrypter.gy @@ -23,30 +23,25 @@ class ExampleStringDecrypter extends Plugin { + nl + "for each class. IF THE FILE YOU'RE LOADING IS MALICIOUS, DO NOT CONTINUE.", new String[]{"Continue", "Cancel"}) - if(dialog.promptChoice() == 0) - { - for(ClassNode cn : classNodesList) - { + if (dialog.promptChoice() == 0) { + for (ClassNode cn : classNodesList) { BCV.getClassNodeLoader().addClass(cn) - for(Object o : cn.fields.toArray()) - { + for (Object o : cn.fields.toArray()) { FieldNode f = (FieldNode) o - if(f.name == "z") {// && f.desc.equals("([Ljava/lang/String;)V")) { - try - { - for(Field f2 : BCV.getClassNodeLoader().nodeToClass(cn).getFields()) - { + if (f.name == "z") {// && f.desc.equals("([Ljava/lang/String;)V")) { + try { + for (Field f2 : BCV.getClassNodeLoader().nodeToClass(cn).getFields()) { String s = f2.get(null) - if(s != null && !s.empty) + if (s != null && !s.empty) gui.appendText(cn + ":" + s) } - } catch(Exception | StackOverflowError ignored) {} + } catch (Exception | StackOverflowError ignored) { + } } } } - gui.setVisible(true) } } diff --git a/plugins/example/ExampleStringDecrypter.java b/plugins/example/ExampleStringDecrypter.java index 756dd3d5..a99185e3 100644 --- a/plugins/example/ExampleStringDecrypter.java +++ b/plugins/example/ExampleStringDecrypter.java @@ -1,10 +1,9 @@ -import the.bytecode.club.bytecodeviewer.api.* -import the.bytecode.club.bytecodeviewer.gui.components.MultipleChoiceDialog; - -import java.util.ArrayList; import java.lang.reflect.Field; +import java.util.List; import org.objectweb.asm.tree.ClassNode; -import org.objectweb.asm.tree.FieldNode +import org.objectweb.asm.tree.FieldNode; +import the.bytecode.club.bytecodeviewer.api.*; +import the.bytecode.club.bytecodeviewer.gui.components.MultipleChoiceDialog; import static the.bytecode.club.bytecodeviewer.Constants.nl; @@ -14,7 +13,7 @@ import static the.bytecode.club.bytecodeviewer.Constants.nl; public class ExampleStringDecrypter extends Plugin { @Override - public void execute(ArrayList classNodesList) { + public void execute(List classNodesList) { PluginConsole gui = new PluginConsole("Example String Decrypter"); MultipleChoiceDialog dialog = new MultipleChoiceDialog("Bytecode Viewer - WARNING", @@ -22,25 +21,21 @@ public class ExampleStringDecrypter extends Plugin { + nl + "for each class. IF THE FILE YOU'RE LOADING IS MALICIOUS, DO NOT CONTINUE.", new String[]{"Continue", "Cancel"}); - if(dialog.promptChoice() == 0) - { - for(ClassNode cn : classNodesList) - { - the.bytecode.club.bytecodeviewer.api.BCV.getClassNodeLoader().addClass(cn); + if (dialog.promptChoice() == 0) { + for (ClassNode cn : classNodesList) { + BCV.getClassNodeLoader().addClass(cn); - for(Object o : cn.fields.toArray()) - { + for (Object o : cn.fields.toArray()) { FieldNode f = (FieldNode) o; - if(f.name.equals("z")) {// && f.desc.equals("([Ljava/lang/String;)V")) { - try - { - for(Field f2 : the.bytecode.club.bytecodeviewer.api.BCV.getClassNodeLoader().nodeToClass(cn).getFields()) - { - String s = f2.get(null); - if(s != null && !s.empty()) - gui.appendText(cn+":"+s); + if (f.name.equals("z")) {// && f.desc.equals("([Ljava/lang/String;)V")) { + try { + for (Field f2 : BCV.getClassNodeLoader().nodeToClass(cn).getFields()) { + String s = (String) f2.get(null); + if (s != null && !s.isEmpty()) + gui.appendText(cn + ":" + s); } - } catch(Exception | StackOverflowError e) {} + } catch (Exception ignored) { + } } } @@ -49,4 +44,5 @@ public class ExampleStringDecrypter extends Plugin { gui.setVisible(true); } } -} \ No newline at end of file + +} diff --git a/plugins/example/ExampleStringDecrypter.js b/plugins/example/ExampleStringDecrypter.js index 1e5cb2ab..74c9a6dc 100644 --- a/plugins/example/ExampleStringDecrypter.js +++ b/plugins/example/ExampleStringDecrypter.js @@ -7,69 +7,60 @@ var MultipleChoiceDialog = Java.type("the.bytecode.club.bytecodeviewer.gui.compo var BytecodeViewer = Java.type("the.bytecode.club.bytecodeviewer.api.BCV") var dialog = new MultipleChoiceDialog("Bytecode Viewer - WARNING", - "WARNING: This will load the classes into the JVM and execute the initialize function" - + "\nfor each class. IF THE FILE YOU'RE LOADING IS MALICIOUS, DO NOT CONTINUE.", - ["Continue", "Cancel"]); + "WARNING: This will load the classes into the JVM and execute the initialize function" + + "\nfor each class. IF THE FILE YOU'RE LOADING IS MALICIOUS, DO NOT CONTINUE.", + ["Continue", "Cancel"]); var gui; -function execute(classNodeList) -{ +function execute(classNodeList) { gui = new PluginConsole("Skeleton"); - if(dialog.promptChoice() == 0) - { + if (dialog.promptChoice() == 0) { var needsWarning = false; - for (cnIndex = 0; cnIndex < classNodeList.length; cnIndex++) - { - try - { + for (cnIndex = 0; cnIndex < classNodeList.length; cnIndex++) { + try { var cn = classNodeList[cnIndex]; - var fields = cn.fields.toArray(); //load the class node into the classloader - BytecodeViewer.loadClassIntoClassLoader(cn); + BytecodeViewer.getClassNodeLoader().addClass(cn); - for (fieldIndex = 0; fieldIndex < fields.length; fieldIndex++) - { + var fields = cn.fields.toArray(); + for (fieldIndex = 0; fieldIndex < fields.length; fieldIndex++) { var field = fields[fieldIndex]; //if the class contains the field z, get the class object from the class node //then print out the value of the fields inside the class //if the strings get decrypted on init, this allows you to dump the current values - if(field.name.equals("z")) {// && f.desc.equals("([Ljava/lang/String;)V")) { - try - { + if (field.name.equals("z")) {// && f.desc.equals("([Ljava/lang/String;)V")) { + try { var loadedClass = BytecodeViewer.getClassNodeLoader().nodeToClass(cn); var reflectedFields = loadedClass.getFields(); - for (reflectedFieldIndex = 0; reflectedFieldIndex < reflectedFields.length; reflectedFieldIndex++) - { + for (reflectedFieldIndex = 0; reflectedFieldIndex < reflectedFields.length; reflectedFieldIndex++) { var reflectedField = reflectedFields[fieldIndex]; var s = reflectedField.get(null); - if(s != null && !s.empty()) + if (s != null && !s.empty()) gui.appendText(cn + "->" + s); } - } catch(e) {} + } catch (e) { + } } } - } - catch(e) - { - gui.appendText("Failed loading class " + cn.getName()); + } catch (e) { + gui.appendText("Failed loading class " + cn.name); e.printStackTrace(); needsWarning = true; } } - if (needsWarning) - { - BytecodeViewer.showMessage("Some classes failed to decrypt, if you'd like to decrypt all of them" - + nl + "makes sure you include ALL the libraries it requires."); + if (needsWarning) { + BytecodeViewer.showMessage("Some classes failed to decrypt, if you'd like to decrypt all of them\n" + + "makes sure you include ALL the libraries it requires."); } gui.setVisible(true); } -} \ No newline at end of file +} diff --git a/plugins/skeleton.py b/plugins/skeleton.py index 99c3a3a6..227870aa 100644 --- a/plugins/skeleton.py +++ b/plugins/skeleton.py @@ -10,4 +10,4 @@ class skeleton(Plugin): def execute(classNodeList, poop): #for some reason it requires a second arg gui = PluginConsole("Skeleton") gui.setVisible(Boolean.TRUE) - gui.appendText("exceuted skeleton") \ No newline at end of file + gui.appendText("exceuted skeleton") diff --git a/pom.xml b/pom.xml index 2792599f..71100183 100644 --- a/pom.xml +++ b/pom.xml @@ -31,7 +31,7 @@ 2.7.3 0.3.4 5.2.1.Final - v41 + v42 eda981d 2.8.9 31.0.1-jre @@ -44,7 +44,9 @@ 3.2 0.2.0 0.5.36 - 3.1.5 + + 10b32a4 + 3.1.6 2.1.1 1.7.32 2.5.2 @@ -237,6 +239,7 @@ paged_data ${paged-data.version} + + + com.github.mstrobel.procyon + procyon-compilertools + ${procyon-snapshot.version} + + + com.github.mstrobel.procyon + procyon-core + ${procyon-snapshot.version} + + + com.github.mstrobel.procyon + procyon-expressions + ${procyon-snapshot.version} + + + com.github.mstrobel.procyon + procyon-reflection + ${procyon-snapshot.version} + com.fifesoft rsyntaxtextarea @@ -379,8 +403,8 @@ maven-compiler-plugin 3.8.1 - ${java.version} - ${java.version} + ${maven.compiler.source} + ${maven.compiler.target} true @@ -389,7 +413,7 @@ maven-javadoc-plugin 3.3.1 - ${java.version} + ${maven.compiler.source} diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/api/Plugin.java b/src/main/java/the/bytecode/club/bytecodeviewer/api/Plugin.java index 3831ff72..fb7d3610 100644 --- a/src/main/java/the/bytecode/club/bytecodeviewer/api/Plugin.java +++ b/src/main/java/the/bytecode/club/bytecodeviewer/api/Plugin.java @@ -93,7 +93,7 @@ public abstract class Plugin extends Thread * On plugin start each resource container is iterated through, * then this is called with the resource container classes * - * @param classNodeList all of the loaded classes for easy access. + * @param classNodeList all the loaded classes for easy access. */ public abstract void execute(List classNodeList); } diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/gui/components/HTMLPane.java b/src/main/java/the/bytecode/club/bytecodeviewer/gui/components/HTMLPane.java index 7ac91dac..396b81dc 100644 --- a/src/main/java/the/bytecode/club/bytecodeviewer/gui/components/HTMLPane.java +++ b/src/main/java/the/bytecode/club/bytecodeviewer/gui/components/HTMLPane.java @@ -83,7 +83,7 @@ public class HTMLPane extends JEditorPane if (is == null) return null; try (InputStream stream = is; - Scanner s = new Scanner(stream).useDelimiter("\\A")) { + Scanner s = new Scanner(stream, "UTF-8").useDelimiter("\\A")) { return s.hasNext() ? s.next() : ""; } } diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/util/ZipUtils.java b/src/main/java/the/bytecode/club/bytecodeviewer/util/ZipUtils.java index 499fc662..9b28af92 100644 --- a/src/main/java/the/bytecode/club/bytecodeviewer/util/ZipUtils.java +++ b/src/main/java/the/bytecode/club/bytecodeviewer/util/ZipUtils.java @@ -35,6 +35,7 @@ import java.util.zip.ZipOutputStream; */ public final class ZipUtils { + // TODO: Maybe migrate to org.apache.commons.compress.archivers.examples.Expander? /** * Unzip files to path. * @@ -43,6 +44,11 @@ public final class ZipUtils { * @throws IOException Signals that an I/O exception has occurred. */ public static void unzipFilesToPath(String jarPath, String destinationDir) throws IOException { + String canonicalDestDir = new File(destinationDir).getCanonicalPath(); + if (!canonicalDestDir.endsWith(File.separator)) { + canonicalDestDir += File.separator; + } + File file = new File(jarPath); try (JarFile jar = new JarFile(file)) { @@ -67,6 +73,11 @@ public final class ZipUtils { String fileName = destinationDir + File.separator + entry.getName(); File f = new File(fileName); + if (!f.getCanonicalPath().startsWith(canonicalDestDir)) { + System.out.println("Zip Slip exploit detected. Skipping entry " + entry.getName()); + continue; + } + File parent = f.getParentFile(); if (!parent.exists()) { parent.mkdirs(); @@ -106,7 +117,7 @@ public final class ZipUtils { public static void zipFolder(String srcFolder, String destZipFile, String ignore) throws Exception { try (FileOutputStream fileWriter = new FileOutputStream(destZipFile); - ZipOutputStream zip = new ZipOutputStream(fileWriter)){ + ZipOutputStream zip = new ZipOutputStream(fileWriter)) { addFolderToZip("", srcFolder, zip, ignore); zip.flush(); } @@ -114,7 +125,7 @@ public final class ZipUtils { public static void zipFolderAPKTool(String srcFolder, String destZipFile) throws Exception { try (FileOutputStream fileWriter = new FileOutputStream(destZipFile); - ZipOutputStream zip = new ZipOutputStream(fileWriter)){ + ZipOutputStream zip = new ZipOutputStream(fileWriter)) { addFolderToZipAPKTool("", srcFolder, zip); zip.flush(); } @@ -199,4 +210,4 @@ public final class ZipUtils { } } } -} \ No newline at end of file +} diff --git a/src/main/resources/templates/Template_Plugin.java b/src/main/resources/templates/Template_Plugin.java index 94d7359d..2a99b101 100644 --- a/src/main/resources/templates/Template_Plugin.java +++ b/src/main/resources/templates/Template_Plugin.java @@ -1,45 +1,43 @@ -import the.bytecode.club.bytecodeviewer.api.*; -import java.util.ArrayList; +import java.util.List; import org.objectweb.asm.tree.ClassNode; +import the.bytecode.club.bytecodeviewer.api.*; + +public class Template extends Plugin { -public class Template extends Plugin -{ PluginConsole gui; - + /** * Main function */ @Override - public void execute(ArrayList classNodeList) - { - //create console + public void execute(List classNodeList) { + // Create console gui = new PluginConsole("Java Template"); - gui.setVisible(true); //show the console - - //debug text + gui.setVisible(true); // Show the console + + // Debug text out("Class Nodes: " + classNodeList.size()); - - //iterate through each class node - for(ClassNode cn : classNodeList) + + // Iterate through each class node + for (ClassNode cn : classNodeList) process(cn); - - BCV.hideFrame(gui, 10000); //hides the console after 10 seconds + + BCV.hideFrame(gui, 10000); // Hides the console after 10 seconds } - + /** * Process each class node */ - public void process(ClassNode cn) - { + public void process(ClassNode cn) { out("Node: " + cn.name + ".class"); - //TODO developer plugin code goes here + // TODO developer plugin code goes here } - + /** * Print to console */ - public void out(String text) - { + public void out(String text) { gui.appendText(text); } -} \ No newline at end of file + +}