diff --git a/plugins/java/XposedGenerator.java b/plugins/java/XposedGenerator.java index a291dafe..5d869cf7 100644 --- a/plugins/java/XposedGenerator.java +++ b/plugins/java/XposedGenerator.java @@ -11,6 +11,7 @@ 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.api.*; @@ -18,27 +19,27 @@ import the.bytecode.club.bytecodeviewer.decompilers.impl.FernFlowerDecompiler; import the.bytecode.club.bytecodeviewer.gui.resourceviewer.viewer.ResourceViewer; /** - ** This is an Xposed Generator Plugin, used to aid Reverse-Engineering. - ** - ** @author jowasp + * * This is an Xposed Generator Plugin, used to aid Reverse-Engineering. + * * + * * @author jowasp **/ -public class XposedGenerator extends Plugin { - +public class XposedGenerator extends Plugin +{ + private static final List methodsNames = new ArrayList<>(); private static final List cleanMethodsNames = new ArrayList<>(); private static String foundPckg; - public XposedGenerator() { - } - @Override - public void execute(List classNodeList) { + public void execute(List classNodeList) + { //Get actual file class content ResourceViewer viewer = BytecodeViewer.getActiveResource(); - if (viewer == null) { - BytecodeViewer.showMessage("Open A Class First"); + if (viewer == null) + { + BytecodeViewer.showMessage("Open A Classfile First"); return; } @@ -49,8 +50,10 @@ public class XposedGenerator extends Plugin { ParseChosenFileContent(className, classnode); } - public static void ParseChosenFileContent(String classname, ClassNode classNode) { - try { + public static void ParseChosenFileContent(String classname, ClassNode classNode) + { + try + { //Parse content - Extract methods after APK /JAR has been extracted byte[] cont = ASMUtil.nodeToBytes(classNode); @@ -61,8 +64,7 @@ public class XposedGenerator extends Plugin { //Decompile using Fern String decomp = decompilefern.decompileClassNode(classNode, cont); String[] xposedTemplateTypes = {"Empty", "Parameters", "Helper"}; - @SuppressWarnings({"unchecked", "rawtypes"}) - JComboBox xposedTemplateList = new JComboBox(xposedTemplateTypes); + @SuppressWarnings({"unchecked", "rawtypes"}) JComboBox xposedTemplateList = new JComboBox(xposedTemplateTypes); //Set results of parsed methods into a list List methodsExtracted = ProcessContentExtractedClass(decomp); String packgExtracted = ProcessContentExtractedPackage(decomp); @@ -71,7 +73,8 @@ public class XposedGenerator extends Plugin { List cleanMethods; //clear list cleanMethods = ProcessCleanMethodsAll(methodsExtracted); - if (!cleanMethods.isEmpty()) { + if (!cleanMethods.isEmpty()) + { JComboBox cb = new JComboBox<>(cleanMethods.toArray(new String[0])); //Add Panel elements @@ -82,49 +85,57 @@ public class XposedGenerator extends Plugin { myPanel.add(cb); //output methods to pane box - int result = JOptionPane.showConfirmDialog(null, myPanel, - "Choose Template and Method for Xposed Module", JOptionPane.OK_CANCEL_OPTION); + int result = JOptionPane.showConfirmDialog(null, myPanel, "Choose Template and Method for Xposed Module", JOptionPane.OK_CANCEL_OPTION); - if (result == JOptionPane.OK_OPTION) { + if (result == JOptionPane.OK_OPTION) + { //Read Chosen Class Object cbItem = cb.getSelectedItem(); Object xPosedItem = xposedTemplateList.getSelectedItem(); System.out.println("SELECTED CLASS is" + cbItem); - if (cbItem != null && xPosedItem != null) { + if (cbItem != null && xPosedItem != null) + { String selectedClass = cbItem.toString(); String selectedXposedTemplate = xPosedItem.toString(); //WriteXposed Class with extracted data - try { + try + { WriteXposedModule(selectedClass, packgExtracted, classname, selectedXposedTemplate); - } catch (IllegalArgumentException e) { + } + catch (IllegalArgumentException e) + { e.printStackTrace(); JOptionPane.showMessageDialog(null, "Error" + e); } } } - } else { + } + else + { JOptionPane.showMessageDialog(null, "Class Not Suitable"); } - } catch (IllegalArgumentException e) { + } + catch (IllegalArgumentException e) + { e.printStackTrace(); JOptionPane.showMessageDialog(null, "Error" + e); } - } - public static void WriteXposedModule(String functionToHook, String packageName, String classToHook, - String template) { - if (template != null && !template.equals("Empty")) { - try { - + public static void WriteXposedModule(String functionToHook, String packageName, String classToHook, String template) + { + if (template != null && !template.equals("Empty")) + { + try + { //TODO: Prompt save dialog File file = new File("./XposedClassTest.java"); // 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 classToHookNameOnly = classToHook; @@ -133,41 +144,14 @@ public class XposedGenerator extends Plugin { String[] classClean = classToHookNameOnly.split("/"); String[] functionSplitValues = functionToHook.split("\\s+"); - + //select String onlyClass = classClean[classClean.length - 1]; String onlyFunction = CleanUpFunction(functionSplitValues); //Write Xposed Class - String XposedClassText = "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"; + String XposedClassText = "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"; FileWriter fw = new FileWriter(file.getAbsoluteFile()); BufferedWriter bw = new BufferedWriter(fw); bw.write(XposedClassText); @@ -175,68 +159,87 @@ public class XposedGenerator extends Plugin { bw.close(); JOptionPane.showMessageDialog(null, "Xposed Module Generated"); - } catch (IOException e) { + } + catch (IOException e) + { JOptionPane.showMessageDialog(null, "Error" + e); e.printStackTrace(); } - } else { + } + 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"; Pattern pattern = Pattern.compile(regexclass, Pattern.CASE_INSENSITIVE); - - while (scanner.hasNextLine()) { + + while (scanner.hasNextLine()) + { String line = scanner.nextLine(); - + // process the line Matcher matcher = pattern.matcher(line); - while (matcher.find()) { - if (matcher.group() != null) { + while (matcher.find()) + { + 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"); } } } - if (methodsNames.isEmpty()) { + if (methodsNames.isEmpty()) methodsNames.add("No methods found"); - } else { + else return methodsNames; - } + return methodsNames; - } finally { + } + 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("(")))) { + if (!m.contains("extends") && (!m.contains("implements") && (m.contains("(")))) + { cleanMethodsNames.add(m); } } - + return cleanMethodsNames; } - 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]; } @@ -245,49 +248,63 @@ public class XposedGenerator extends Plugin { return onlyFunc; } - private static String ProcessContentExtractedPackage(String contentFile) { + private static String ProcessContentExtractedPackage(String contentFile) + { Scanner scanner = null; - try { + try + { scanner = new Scanner(contentFile); String regexPkg = "package"; Pattern patternPkg = Pattern.compile(regexPkg, Pattern.CASE_INSENSITIVE); String line = scanner.nextLine(); - + // process the line Matcher matcher = patternPkg.matcher(line); - while (matcher.find()) { - if (matcher.group() != null) { + while (matcher.find()) + { + if (matcher.group() != null) + { System.out.println("find() found the pattern \"" + quote(line.trim())); foundPckg = quote(line.trim()); - } else { + } + else + { foundPckg = ""; } } - + try { 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 { + } + catch (NullPointerException e) + { + JOptionPane.showMessageDialog(null, "Error - no package was found in the selected class: " + e); + } + finally + { scanner.close(); } - } catch (IllegalArgumentException e) { + } + catch (IllegalArgumentException e) + { JOptionPane.showMessageDialog(null, "Error" + e); if (scanner != null) scanner.close(); - } finally { + } + finally + { if (scanner != null) scanner.close(); } - + return foundPckg; } - private static String quote(String aText) { + private static String quote(String aText) + { String QUOTE = "'"; return QUOTE + aText + QUOTE; }