commit
81e9e444be
15 changed files with 266 additions and 294 deletions
|
@ -1,6 +1,5 @@
|
||||||
import org.objectweb.asm.tree.ClassNode
|
import org.objectweb.asm.tree.ClassNode
|
||||||
import the.bytecode.club.bytecodeviewer.api.Plugin
|
import the.bytecode.club.bytecodeviewer.api.*
|
||||||
import the.bytecode.club.bytecodeviewer.api.PluginConsole
|
|
||||||
|
|
||||||
class Skeleton extends Plugin {
|
class Skeleton extends Plugin {
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
import the.bytecode.club.bytecodeviewer.api.*;
|
import java.util.List;
|
||||||
import java.util.ArrayList;
|
|
||||||
import org.objectweb.asm.tree.ClassNode;
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
|
import the.bytecode.club.bytecodeviewer.api.*;
|
||||||
|
|
||||||
public class Skeleton extends Plugin {
|
public class Skeleton extends Plugin {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(ArrayList<ClassNode> classNodesList) {
|
public void execute(List<ClassNode> classNodesList) {
|
||||||
PluginConsole gui = new PluginConsole("Skeleton");
|
PluginConsole gui = new PluginConsole("Skeleton");
|
||||||
gui.setVisible(true);
|
gui.setVisible(true);
|
||||||
gui.appendText("executed skeleton");
|
gui.appendText("executed skeleton");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,5 +1,4 @@
|
||||||
function execute(classNodeList)
|
function execute(classNodeList) {
|
||||||
{
|
|
||||||
var PluginConsole = Java.type("the.bytecode.club.bytecodeviewer.api.PluginConsole");
|
var PluginConsole = Java.type("the.bytecode.club.bytecodeviewer.api.PluginConsole");
|
||||||
var gui = new PluginConsole("Skeleton");
|
var gui = new PluginConsole("Skeleton");
|
||||||
gui.setVisible(true);
|
gui.setVisible(true);
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import java.awt.*;
|
|
||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileWriter;
|
import java.io.FileWriter;
|
||||||
|
@ -12,10 +11,8 @@ import javax.swing.Box;
|
||||||
import javax.swing.JComboBox;
|
import javax.swing.JComboBox;
|
||||||
import javax.swing.JOptionPane;
|
import javax.swing.JOptionPane;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
|
|
||||||
import org.objectweb.asm.tree.ClassNode;
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
import the.bytecode.club.bytecodeviewer.*;
|
import the.bytecode.club.bytecodeviewer.*;
|
||||||
import the.bytecode.club.bytecodeviewer.util.*;
|
|
||||||
import the.bytecode.club.bytecodeviewer.api.*;
|
import the.bytecode.club.bytecodeviewer.api.*;
|
||||||
import the.bytecode.club.bytecodeviewer.decompilers.impl.FernFlowerDecompiler;
|
import the.bytecode.club.bytecodeviewer.decompilers.impl.FernFlowerDecompiler;
|
||||||
import the.bytecode.club.bytecodeviewer.gui.resourceviewer.viewer.ResourceViewer;
|
import the.bytecode.club.bytecodeviewer.gui.resourceviewer.viewer.ResourceViewer;
|
||||||
|
@ -23,39 +20,35 @@ import the.bytecode.club.bytecodeviewer.gui.resourceviewer.viewer.ResourceViewer
|
||||||
/**
|
/**
|
||||||
* @author jowasp
|
* @author jowasp
|
||||||
*/
|
*/
|
||||||
public class XposedGenerator extends Plugin
|
public class XposedGenerator extends Plugin {
|
||||||
{
|
|
||||||
//PRIVATE
|
//PRIVATE
|
||||||
private static List<String> methodsNames = new ArrayList<String>();
|
private static final List<String> methodsNames = new ArrayList<>();
|
||||||
private static List<String> cleanMethodsNames = new ArrayList<String>();
|
private static final List<String> cleanMethodsNames = new ArrayList<>();
|
||||||
private static String foundpckg;
|
private static String foundPckg;
|
||||||
|
|
||||||
public XposedGenerator() {}
|
public XposedGenerator() {
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(ArrayList<ClassNode> classNodeList)
|
public void execute(List<ClassNode> classNodeList) {
|
||||||
{
|
|
||||||
//Get actual file class content
|
//Get actual file class content
|
||||||
ResourceViewer viewer = BytecodeViewer.getActiveResource();
|
ResourceViewer viewer = BytecodeViewer.getActiveResource();
|
||||||
|
|
||||||
if(viewer == null)
|
if (viewer == null) {
|
||||||
{
|
BytecodeViewer.showMessage("Open A Class First");
|
||||||
BytecodeViewer.showMessage("Open A Class First");
|
return;
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
String className = viewer.getName();
|
String className = viewer.getName();
|
||||||
String containerName = viewer.name;
|
//String containerName = viewer.getName();
|
||||||
ClassNode classnode = BytecodeViewer.getCurrentlyOpenedClassNode();
|
ClassNode classnode = BytecodeViewer.getCurrentlyOpenedClassNode();
|
||||||
|
|
||||||
//Call XposedGenerator class
|
//Call XposedGenerator class
|
||||||
ParseChosenFileContent(className,containerName,classnode);
|
ParseChosenFileContent(className, classnode);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ParseChosenFileContent(String classname, String containerName, ClassNode classNode)
|
public static void ParseChosenFileContent(String classname, ClassNode classNode) {
|
||||||
{
|
try {
|
||||||
try
|
|
||||||
{
|
|
||||||
//Parse content - Extract methods after APK /JAR has been extracted
|
//Parse content - Extract methods after APK /JAR has been extracted
|
||||||
byte[] cont = ASMUtil.nodeToBytes(classNode);
|
byte[] cont = ASMUtil.nodeToBytes(classNode);
|
||||||
|
|
||||||
|
@ -64,22 +57,21 @@ public class XposedGenerator extends Plugin
|
||||||
FernFlowerDecompiler decompilefern = new FernFlowerDecompiler();
|
FernFlowerDecompiler decompilefern = new FernFlowerDecompiler();
|
||||||
|
|
||||||
//Decompile using Fern
|
//Decompile using Fern
|
||||||
String decomp = decompilefern.decompileClassNode(classNode, cont);
|
String decomp = decompilefern.decompileClassNode(classNode, cont);
|
||||||
String[] xposedTemplateTypes = {"Empty","Parameters","Helper"};
|
String[] xposedTemplateTypes = {"Empty", "Parameters", "Helper"};
|
||||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||||
JComboBox xposedTemplateList = new JComboBox(xposedTemplateTypes);
|
JComboBox xposedTemplateList = new JComboBox(xposedTemplateTypes);
|
||||||
//Set results of parsed methods into an a list
|
//Set results of parsed methods into a list
|
||||||
List<String> methodsExtracted = ProcessContentExtractedClass(decomp);
|
List<String> methodsExtracted = ProcessContentExtractedClass(decomp);
|
||||||
String packgExtracted = ProcessContentExtractedPackage(decomp);
|
String packgExtracted = ProcessContentExtractedPackage(decomp);
|
||||||
System.out.println("PACKAGE NAME: " +packgExtracted);
|
System.out.println("PACKAGE NAME: " + packgExtracted);
|
||||||
|
|
||||||
//Get a clean list
|
//Get a clean list
|
||||||
List<String> cleanMethods = null;
|
List<String> cleanMethods;
|
||||||
//clear list
|
//clear list
|
||||||
cleanMethods = ProcessCleanMethodsAll(methodsExtracted);
|
cleanMethods = ProcessCleanMethodsAll(methodsExtracted);
|
||||||
if (!cleanMethods.isEmpty())
|
if (!cleanMethods.isEmpty()) {
|
||||||
{
|
JComboBox<String> cb = new JComboBox<>(cleanMethods.toArray(new String[0]));
|
||||||
JComboBox<String> cb = new JComboBox<>(cleanMethods.toArray(new String[cleanMethods.size()]));
|
|
||||||
|
|
||||||
//Add Panel elements
|
//Add Panel elements
|
||||||
//Start Panel
|
//Start Panel
|
||||||
|
@ -94,56 +86,54 @@ public class XposedGenerator extends Plugin
|
||||||
|
|
||||||
if (result == JOptionPane.OK_OPTION) {
|
if (result == JOptionPane.OK_OPTION) {
|
||||||
//Read Chosen Class
|
//Read Chosen Class
|
||||||
System.out.println("SELECTED CLASS is" + cb.getSelectedItem());
|
Object cbItem = cb.getSelectedItem();
|
||||||
String selectedClass = cb.getSelectedItem().toString();
|
Object xPosedItem = xposedTemplateList.getSelectedItem();
|
||||||
String selectedXposedTemplate = xposedTemplateList.getSelectedItem().toString();
|
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
|
//WriteXposed Class with extracted data
|
||||||
try{
|
try {
|
||||||
WriteXposedModule(selectedClass, packgExtracted, classname, selectedXposedTemplate);
|
WriteXposedModule(selectedClass, packgExtracted, classname, selectedXposedTemplate);
|
||||||
}
|
} catch (IllegalArgumentException e) {
|
||||||
catch(IllegalArgumentException e)
|
e.printStackTrace();
|
||||||
{
|
JOptionPane.showMessageDialog(null, "Error" + e);
|
||||||
e.printStackTrace();
|
}
|
||||||
JOptionPane.showMessageDialog(null,"Error" + e.toString());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
JOptionPane.showMessageDialog(null, "Class Not Suitable");
|
||||||
}
|
}
|
||||||
else
|
} catch (IllegalArgumentException e) {
|
||||||
{
|
|
||||||
JOptionPane.showMessageDialog(null,"Class Not Suitable");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (IllegalArgumentException e)
|
|
||||||
{
|
|
||||||
e.printStackTrace();
|
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) {
|
public static void WriteXposedModule(String functionToHook, String packageName, String classToHook,
|
||||||
System.out.println("TEMPLATE: " + template);
|
String template) {
|
||||||
if (template != null && !template.equals("Empty"))
|
System.out.println("TEMPLATE: " + template);
|
||||||
{
|
if (template != null && !template.equals("Empty")) {
|
||||||
try {
|
try {
|
||||||
//TODO: Prompt save dialog
|
//TODO: Prompt save dialog
|
||||||
File file = new File("./XposedClassTest.java");
|
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()) {
|
if (!file.exists()) {
|
||||||
file.createNewFile();
|
file.createNewFile();
|
||||||
}
|
}
|
||||||
//Extract the package name only
|
//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;
|
String classToHookNameOnly = classToHook;
|
||||||
if(classToHookNameOnly.endsWith(".class"))
|
if (classToHookNameOnly.endsWith(".class"))
|
||||||
classToHookNameOnly = classToHook.substring(0, classToHookNameOnly.length() - 6);
|
classToHookNameOnly = classToHook.substring(0, classToHookNameOnly.length() - 6);
|
||||||
|
|
||||||
String[] classClean = classToHookNameOnly.split("\\/");
|
String[] classClean = classToHookNameOnly.split("/");
|
||||||
String[] functionSplitValues = functionToHook.split("\\s+");
|
String[] functionSplitValues = functionToHook.split("\\s+");
|
||||||
//select
|
//select
|
||||||
String onlyClass = classClean[classClean.length-1];
|
String onlyClass = classClean[classClean.length - 1];
|
||||||
//String onlyFunctionParateses = functionSplitValues[functionSplitValues.length-2];
|
//String onlyFunctionParateses = functionSplitValues[functionSplitValues.length-2];
|
||||||
|
|
||||||
String onlyFunction = CleanUpFunction(functionSplitValues);
|
String onlyFunction = CleanUpFunction(functionSplitValues);
|
||||||
|
@ -153,30 +143,34 @@ public class XposedGenerator extends Plugin
|
||||||
|
|
||||||
//Write Xposed Class
|
//Write Xposed Class
|
||||||
String XposedClassText =
|
String XposedClassText =
|
||||||
"package androidpentesting.com.xposedmodule;"+ "\r\n" +
|
"package androidpentesting.com.xposedmodule;" + "\r\n" +
|
||||||
"import de.robv.android.xposed.IXposedHookLoadPackage;" + "\r\n" +
|
"import de.robv.android.xposed.IXposedHookLoadPackage;" + "\r\n" +
|
||||||
"\r\n" +
|
"\r\n" +
|
||||||
"import de.robv.android.xposed.XC_MethodHook;" +"\r\n" +
|
"import de.robv.android.xposed.XC_MethodHook;" + "\r\n" +
|
||||||
"import de.robv.android.xposed.XposedBridge;" +"\r\n" +
|
"import de.robv.android.xposed.XposedBridge;" + "\r\n" +
|
||||||
"import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;"+"\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" +
|
"import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;" + "\r\n" +
|
||||||
"public class XposedClassTest implements IXposedHookLoadPackage {"+"\r\n" +"\r\n" +
|
"\r\n" +
|
||||||
" public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable {" + "\r\n" +"\r\n" +
|
"public class XposedClassTest implements IXposedHookLoadPackage {" + "\r\n" + "\r\n" +
|
||||||
" String classToHook = " + "\"" + packageNameOnly + "." + onlyClass + "\";" + "\r\n" +
|
" public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable {" + "\r\n" + "\r\n" +
|
||||||
" String functionToHook = "+"\""+ onlyFunction+"\";"+"\r\n" +
|
" String classToHook = " + "\"" + packageNameOnly + "." + onlyClass + "\";" +
|
||||||
" if (lpparam.packageName.equals("+"\""+packageNameOnly+ "\""+")){"+ "\r\n" +
|
"\r\n" +
|
||||||
" XposedBridge.log(" + "\" Loaded app: \" " + " + lpparam.packageName);"+ "\r\n" +"\r\n" +
|
" String functionToHook = " + "\"" + onlyFunction + "\";" + "\r\n" +
|
||||||
" findAndHookMethod("+"\""+onlyClass+"\"" + ", lpparam.classLoader, "+" \"" +onlyFunction + "\""+", int.class,"+ "\r\n" +
|
" if (lpparam.packageName.equals(" + "\"" + packageNameOnly + "\"" + ")){" + "\r"
|
||||||
" new XC_MethodHook() {"+ "\r\n" +
|
+ "\n" +
|
||||||
" @Override"+ "\r\n" +
|
" XposedBridge.log(" + "\" Loaded app: \" " + " + lpparam.packageName);" +
|
||||||
" protected void beforeHookedMethod(MethodHookParam param) throws Throwable {"+ "\r\n" +
|
"\r\n" + "\r\n" +
|
||||||
" //TO BE FILLED BY ANALYST"+ "\r\n" +
|
" findAndHookMethod(" + "\"" + onlyClass + "\"" + ", lpparam.classLoader, " + " \"" + onlyFunction + "\"" + ", int.class," + "\r\n" +
|
||||||
" }"+ "\r\n" +
|
" new XC_MethodHook() {" + "\r\n" +
|
||||||
" });"+"\r\n" +
|
" @Override" + "\r\n" +
|
||||||
" }"+ "\r\n" +
|
" protected void beforeHookedMethod(MethodHookParam param) throws "
|
||||||
" }"+ "\r\n" +
|
+ "Throwable {" + "\r\n" +
|
||||||
"}"+ "\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());
|
FileWriter fw = new FileWriter(file.getAbsoluteFile());
|
||||||
BufferedWriter bw = new BufferedWriter(fw);
|
BufferedWriter bw = new BufferedWriter(fw);
|
||||||
bw.write(XposedClassText);
|
bw.write(XposedClassText);
|
||||||
|
@ -184,21 +178,19 @@ public class XposedGenerator extends Plugin
|
||||||
bw.close();
|
bw.close();
|
||||||
|
|
||||||
System.out.println("Done");
|
System.out.println("Done");
|
||||||
JOptionPane.showMessageDialog(null,"Xposed Module Generated");
|
JOptionPane.showMessageDialog(null, "Xposed Module Generated");
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
JOptionPane.showMessageDialog(null,"Error" + e.toString());
|
JOptionPane.showMessageDialog(null, "Error" + e);
|
||||||
e.printStackTrace();
|
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 <String> ProcessContentExtractedClass(String contentFile){
|
private static List<String> ProcessContentExtractedClass(String contentFile) {
|
||||||
Scanner scanner = null;
|
Scanner scanner = null;
|
||||||
try{
|
try {
|
||||||
scanner = new Scanner(contentFile);
|
scanner = new Scanner(contentFile);
|
||||||
//@TODO : Improve patterns to match other excepts 'public'
|
//@TODO : Improve patterns to match other excepts 'public'
|
||||||
String regexclass = "public";
|
String regexclass = "public";
|
||||||
|
@ -212,16 +204,13 @@ public class XposedGenerator extends Plugin
|
||||||
String line = scanner.nextLine();
|
String line = scanner.nextLine();
|
||||||
// process the line
|
// process the line
|
||||||
Matcher matcher = pattern.matcher(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("find() found the pattern \"" + quote(line.trim()));
|
||||||
System.out.println("Function: " + CleanUpFunction(line.trim().split("\\s+")));
|
System.out.println("Function: " + CleanUpFunction(line.trim().split("\\s+")));
|
||||||
methodsNames.add(quote(line.trim()));
|
methodsNames.add(quote(line.trim()));
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
methodsNames.add("No methods found");
|
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");
|
methodsNames.add("No methods found");
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return methodsNames;
|
return methodsNames;
|
||||||
}
|
}
|
||||||
return methodsNames;
|
return methodsNames;
|
||||||
}
|
} finally {
|
||||||
finally {
|
if (scanner != null)
|
||||||
if (scanner!=null)
|
|
||||||
scanner.close();
|
scanner.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List <String> ProcessCleanMethodsAll(List<String> rawMethods)
|
private static List<String> ProcessCleanMethodsAll(List<String> rawMethods) {
|
||||||
{
|
for (String m : rawMethods) {
|
||||||
for (String m:rawMethods)
|
|
||||||
{
|
|
||||||
//Exclude class declaration
|
//Exclude class declaration
|
||||||
//TODO:add a list containing all possible types
|
//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("(")))) {
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cleanMethodsNames.add(m);
|
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";
|
String onlyFunc = "functiondummy";
|
||||||
for (String m:rawFunction)
|
for (String m : rawFunction) {
|
||||||
{
|
if (m.contains("(")) {
|
||||||
if(m.contains("("))
|
|
||||||
{
|
|
||||||
String[] split = m.split("\\(")[0].split(" ");
|
String[] split = m.split("\\(")[0].split(" ");
|
||||||
return split[split.length-1];
|
return split[split.length - 1];
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,61 +257,50 @@ public class XposedGenerator extends Plugin
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String ProcessContentExtractedPackage(String contentFile){
|
private static String ProcessContentExtractedPackage(String contentFile) {
|
||||||
Scanner scanner = null;
|
Scanner scanner = null;
|
||||||
try {
|
try {
|
||||||
scanner = new Scanner(contentFile);
|
scanner = new Scanner(contentFile);
|
||||||
String regexPkg = "package";
|
String regexPkg = "package";
|
||||||
Pattern patternPkg = Pattern.compile(regexPkg , Pattern.CASE_INSENSITIVE);
|
Pattern patternPkg = Pattern.compile(regexPkg, Pattern.CASE_INSENSITIVE);
|
||||||
String line = scanner.nextLine();
|
String line = scanner.nextLine();
|
||||||
// process the line
|
// process the line
|
||||||
Matcher matcher = patternPkg.matcher(line);
|
Matcher matcher = patternPkg.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("find() found the pattern \"" + quote(line.trim())) ;
|
foundPckg = quote(line.trim());
|
||||||
foundpckg = quote(line.trim());
|
|
||||||
|
|
||||||
}
|
} else {
|
||||||
else
|
foundPckg = "";
|
||||||
{
|
|
||||||
foundpckg = "";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try
|
try
|
||||||
//
|
//
|
||||||
{
|
{
|
||||||
if (foundpckg == null || foundpckg.isEmpty())
|
if (foundPckg == null || foundPckg.isEmpty())
|
||||||
foundpckg = "No Package Found";
|
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)
|
} catch (IllegalArgumentException e) {
|
||||||
{
|
JOptionPane.showMessageDialog(null, "Error" + e);
|
||||||
JOptionPane.showMessageDialog(null,"Error - no package was found in the selected class: " + e.toString());
|
if (scanner != null)
|
||||||
}
|
scanner.close();
|
||||||
finally
|
} finally {
|
||||||
{
|
if (scanner != null)
|
||||||
if(scanner != null)
|
|
||||||
scanner.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(IllegalArgumentException e)
|
|
||||||
{
|
|
||||||
JOptionPane.showMessageDialog(null,"Error" + e.toString());
|
|
||||||
if(scanner != null)
|
|
||||||
scanner.close();
|
scanner.close();
|
||||||
}
|
}
|
||||||
finally
|
return foundPckg;
|
||||||
{
|
|
||||||
if(scanner != null)
|
|
||||||
scanner.close();
|
|
||||||
}
|
|
||||||
return foundpckg;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String quote(String aText){
|
private static String quote(String aText) {
|
||||||
String QUOTE = "'";
|
String QUOTE = "'";
|
||||||
return QUOTE + aText + QUOTE;
|
return QUOTE + aText + QUOTE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,10 +6,8 @@ var PluginConsole = Java.type("the.bytecode.club.bytecodeviewer.api.PluginConsol
|
||||||
|
|
||||||
var gui = new PluginConsole("Example Plugin Print Loaded Classes");
|
var gui = new PluginConsole("Example Plugin Print Loaded Classes");
|
||||||
|
|
||||||
function execute(classNodeList)
|
function execute(classNodeList) {
|
||||||
{
|
for (index = 0; index < classNodeList.length; index++) {
|
||||||
for (index = 0; index < classNodeList.length; index++)
|
|
||||||
{
|
|
||||||
var cn = classNodeList[index];
|
var cn = classNodeList[index];
|
||||||
gui.appendText("Resource: " + cn.name + ".class");
|
gui.appendText("Resource: " + cn.name + ".class");
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,30 +23,25 @@ class ExampleStringDecrypter extends Plugin {
|
||||||
+ nl + "for each class. IF THE FILE YOU'RE LOADING IS MALICIOUS, DO NOT CONTINUE.",
|
+ nl + "for each class. IF THE FILE YOU'RE LOADING IS MALICIOUS, DO NOT CONTINUE.",
|
||||||
new String[]{"Continue", "Cancel"})
|
new String[]{"Continue", "Cancel"})
|
||||||
|
|
||||||
if(dialog.promptChoice() == 0)
|
if (dialog.promptChoice() == 0) {
|
||||||
{
|
for (ClassNode cn : classNodesList) {
|
||||||
for(ClassNode cn : classNodesList)
|
|
||||||
{
|
|
||||||
BCV.getClassNodeLoader().addClass(cn)
|
BCV.getClassNodeLoader().addClass(cn)
|
||||||
|
|
||||||
for(Object o : cn.fields.toArray())
|
for (Object o : cn.fields.toArray()) {
|
||||||
{
|
|
||||||
FieldNode f = (FieldNode) o
|
FieldNode f = (FieldNode) o
|
||||||
if(f.name == "z") {// && f.desc.equals("([Ljava/lang/String;)V")) {
|
if (f.name == "z") {// && f.desc.equals("([Ljava/lang/String;)V")) {
|
||||||
try
|
try {
|
||||||
{
|
for (Field f2 : BCV.getClassNodeLoader().nodeToClass(cn).getFields()) {
|
||||||
for(Field f2 : BCV.getClassNodeLoader().nodeToClass(cn).getFields())
|
|
||||||
{
|
|
||||||
String s = f2.get(null)
|
String s = f2.get(null)
|
||||||
if(s != null && !s.empty)
|
if (s != null && !s.empty)
|
||||||
gui.appendText(cn + ":" + s)
|
gui.appendText(cn + ":" + s)
|
||||||
}
|
}
|
||||||
} catch(Exception | StackOverflowError ignored) {}
|
} catch (Exception | StackOverflowError ignored) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gui.setVisible(true)
|
gui.setVisible(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.lang.reflect.Field;
|
||||||
|
import java.util.List;
|
||||||
import org.objectweb.asm.tree.ClassNode;
|
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;
|
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 {
|
public class ExampleStringDecrypter extends Plugin {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(ArrayList<ClassNode> classNodesList) {
|
public void execute(List<ClassNode> classNodesList) {
|
||||||
PluginConsole gui = new PluginConsole("Example String Decrypter");
|
PluginConsole gui = new PluginConsole("Example String Decrypter");
|
||||||
|
|
||||||
MultipleChoiceDialog dialog = new MultipleChoiceDialog("Bytecode Viewer - WARNING",
|
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.",
|
+ nl + "for each class. IF THE FILE YOU'RE LOADING IS MALICIOUS, DO NOT CONTINUE.",
|
||||||
new String[]{"Continue", "Cancel"});
|
new String[]{"Continue", "Cancel"});
|
||||||
|
|
||||||
if(dialog.promptChoice() == 0)
|
if (dialog.promptChoice() == 0) {
|
||||||
{
|
for (ClassNode cn : classNodesList) {
|
||||||
for(ClassNode cn : classNodesList)
|
BCV.getClassNodeLoader().addClass(cn);
|
||||||
{
|
|
||||||
the.bytecode.club.bytecodeviewer.api.BCV.getClassNodeLoader().addClass(cn);
|
|
||||||
|
|
||||||
for(Object o : cn.fields.toArray())
|
for (Object o : cn.fields.toArray()) {
|
||||||
{
|
|
||||||
FieldNode f = (FieldNode) o;
|
FieldNode f = (FieldNode) o;
|
||||||
if(f.name.equals("z")) {// && f.desc.equals("([Ljava/lang/String;)V")) {
|
if (f.name.equals("z")) {// && f.desc.equals("([Ljava/lang/String;)V")) {
|
||||||
try
|
try {
|
||||||
{
|
for (Field f2 : BCV.getClassNodeLoader().nodeToClass(cn).getFields()) {
|
||||||
for(Field f2 : the.bytecode.club.bytecodeviewer.api.BCV.getClassNodeLoader().nodeToClass(cn).getFields())
|
String s = (String) f2.get(null);
|
||||||
{
|
if (s != null && !s.isEmpty())
|
||||||
String s = f2.get(null);
|
gui.appendText(cn + ":" + s);
|
||||||
if(s != null && !s.empty())
|
|
||||||
gui.appendText(cn+":"+s);
|
|
||||||
}
|
}
|
||||||
} catch(Exception | StackOverflowError e) {}
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,4 +44,5 @@ public class ExampleStringDecrypter extends Plugin {
|
||||||
gui.setVisible(true);
|
gui.setVisible(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -7,67 +7,58 @@ var MultipleChoiceDialog = Java.type("the.bytecode.club.bytecodeviewer.gui.compo
|
||||||
var BytecodeViewer = Java.type("the.bytecode.club.bytecodeviewer.api.BCV")
|
var BytecodeViewer = Java.type("the.bytecode.club.bytecodeviewer.api.BCV")
|
||||||
|
|
||||||
var dialog = new MultipleChoiceDialog("Bytecode Viewer - WARNING",
|
var dialog = new MultipleChoiceDialog("Bytecode Viewer - WARNING",
|
||||||
"WARNING: This will load the classes into the JVM and execute the initialize function"
|
"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.",
|
+ "\nfor each class. IF THE FILE YOU'RE LOADING IS MALICIOUS, DO NOT CONTINUE.",
|
||||||
["Continue", "Cancel"]);
|
["Continue", "Cancel"]);
|
||||||
var gui;
|
var gui;
|
||||||
|
|
||||||
function execute(classNodeList)
|
function execute(classNodeList) {
|
||||||
{
|
|
||||||
gui = new PluginConsole("Skeleton");
|
gui = new PluginConsole("Skeleton");
|
||||||
|
|
||||||
if(dialog.promptChoice() == 0)
|
if (dialog.promptChoice() == 0) {
|
||||||
{
|
|
||||||
var needsWarning = false;
|
var needsWarning = false;
|
||||||
|
|
||||||
for (cnIndex = 0; cnIndex < classNodeList.length; cnIndex++)
|
for (cnIndex = 0; cnIndex < classNodeList.length; cnIndex++) {
|
||||||
{
|
try {
|
||||||
try
|
|
||||||
{
|
|
||||||
var cn = classNodeList[cnIndex];
|
var cn = classNodeList[cnIndex];
|
||||||
var fields = cn.fields.toArray();
|
|
||||||
|
|
||||||
//load the class node into the classloader
|
//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];
|
var field = fields[fieldIndex];
|
||||||
|
|
||||||
//if the class contains the field z, get the class object from the class node
|
//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
|
//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 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")) {
|
if (field.name.equals("z")) {// && f.desc.equals("([Ljava/lang/String;)V")) {
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
var loadedClass = BytecodeViewer.getClassNodeLoader().nodeToClass(cn);
|
var loadedClass = BytecodeViewer.getClassNodeLoader().nodeToClass(cn);
|
||||||
var reflectedFields = loadedClass.getFields();
|
var reflectedFields = loadedClass.getFields();
|
||||||
|
|
||||||
for (reflectedFieldIndex = 0; reflectedFieldIndex < reflectedFields.length; reflectedFieldIndex++)
|
for (reflectedFieldIndex = 0; reflectedFieldIndex < reflectedFields.length; reflectedFieldIndex++) {
|
||||||
{
|
|
||||||
var reflectedField = reflectedFields[fieldIndex];
|
var reflectedField = reflectedFields[fieldIndex];
|
||||||
var s = reflectedField.get(null);
|
var s = reflectedField.get(null);
|
||||||
|
|
||||||
if(s != null && !s.empty())
|
if (s != null && !s.empty())
|
||||||
gui.appendText(cn + "->" + s);
|
gui.appendText(cn + "->" + s);
|
||||||
}
|
}
|
||||||
} catch(e) {}
|
} catch (e) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} catch (e) {
|
||||||
catch(e)
|
gui.appendText("Failed loading class " + cn.name);
|
||||||
{
|
|
||||||
gui.appendText("Failed loading class " + cn.getName());
|
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
needsWarning = true;
|
needsWarning = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (needsWarning)
|
if (needsWarning) {
|
||||||
{
|
BytecodeViewer.showMessage("Some classes failed to decrypt, if you'd like to decrypt all of them\n"
|
||||||
BytecodeViewer.showMessage("Some classes failed to decrypt, if you'd like to decrypt all of them"
|
+ "makes sure you include ALL the libraries it requires.");
|
||||||
+ nl + "makes sure you include ALL the libraries it requires.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gui.setVisible(true);
|
gui.setVisible(true);
|
||||||
|
|
34
pom.xml
34
pom.xml
|
@ -31,7 +31,7 @@
|
||||||
<darklaf.version>2.7.3</darklaf.version>
|
<darklaf.version>2.7.3</darklaf.version>
|
||||||
<darklaf-extensions-rsta.version>0.3.4</darklaf-extensions-rsta.version>
|
<darklaf-extensions-rsta.version>0.3.4</darklaf-extensions-rsta.version>
|
||||||
<decompiler-fernflower.version>5.2.1.Final</decompiler-fernflower.version>
|
<decompiler-fernflower.version>5.2.1.Final</decompiler-fernflower.version>
|
||||||
<dex2jar.version>v41</dex2jar.version>
|
<dex2jar.version>v42</dex2jar.version>
|
||||||
<fernflower.version>eda981d</fernflower.version>
|
<fernflower.version>eda981d</fernflower.version>
|
||||||
<gson.version>2.8.9</gson.version>
|
<gson.version>2.8.9</gson.version>
|
||||||
<guava.version>31.0.1-jre</guava.version>
|
<guava.version>31.0.1-jre</guava.version>
|
||||||
|
@ -44,7 +44,9 @@
|
||||||
<objenesis.version>3.2</objenesis.version>
|
<objenesis.version>3.2</objenesis.version>
|
||||||
<paged-data.version>0.2.0</paged-data.version>
|
<paged-data.version>0.2.0</paged-data.version>
|
||||||
<procyon.version>0.5.36</procyon.version>
|
<procyon.version>0.5.36</procyon.version>
|
||||||
<rsyntaxtextarea.version>3.1.5</rsyntaxtextarea.version>
|
<!-- TODO: Remove snapshot version when 0.6 stable is released -->
|
||||||
|
<procyon-snapshot.version>10b32a4</procyon-snapshot.version>
|
||||||
|
<rsyntaxtextarea.version>3.1.6</rsyntaxtextarea.version>
|
||||||
<semantic-version.version>2.1.1</semantic-version.version>
|
<semantic-version.version>2.1.1</semantic-version.version>
|
||||||
<slf4j.version>1.7.32</slf4j.version>
|
<slf4j.version>1.7.32</slf4j.version>
|
||||||
<smali.version>2.5.2</smali.version>
|
<smali.version>2.5.2</smali.version>
|
||||||
|
@ -237,6 +239,7 @@
|
||||||
<artifactId>paged_data</artifactId>
|
<artifactId>paged_data</artifactId>
|
||||||
<version>${paged-data.version}</version>
|
<version>${paged-data.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!-- TODO: Add back when 0.6 stable is released
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.bitbucket.mstrobel</groupId>
|
<groupId>org.bitbucket.mstrobel</groupId>
|
||||||
<artifactId>procyon-core</artifactId>
|
<artifactId>procyon-core</artifactId>
|
||||||
|
@ -257,6 +260,27 @@
|
||||||
<artifactId>procyon-compilertools</artifactId>
|
<artifactId>procyon-compilertools</artifactId>
|
||||||
<version>${procyon.version}</version>
|
<version>${procyon.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.mstrobel.procyon</groupId>
|
||||||
|
<artifactId>procyon-compilertools</artifactId>
|
||||||
|
<version>${procyon-snapshot.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.mstrobel.procyon</groupId>
|
||||||
|
<artifactId>procyon-core</artifactId>
|
||||||
|
<version>${procyon-snapshot.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.mstrobel.procyon</groupId>
|
||||||
|
<artifactId>procyon-expressions</artifactId>
|
||||||
|
<version>${procyon-snapshot.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.mstrobel.procyon</groupId>
|
||||||
|
<artifactId>procyon-reflection</artifactId>
|
||||||
|
<version>${procyon-snapshot.version}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.fifesoft</groupId>
|
<groupId>com.fifesoft</groupId>
|
||||||
<artifactId>rsyntaxtextarea</artifactId>
|
<artifactId>rsyntaxtextarea</artifactId>
|
||||||
|
@ -379,8 +403,8 @@
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
<version>3.8.1</version>
|
<version>3.8.1</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<source>${java.version}</source>
|
<source>${maven.compiler.source}</source>
|
||||||
<target>${java.version}</target>
|
<target>${maven.compiler.target}</target>
|
||||||
<showDeprecation>true</showDeprecation>
|
<showDeprecation>true</showDeprecation>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
@ -389,7 +413,7 @@
|
||||||
<artifactId>maven-javadoc-plugin</artifactId>
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
<version>3.3.1</version>
|
<version>3.3.1</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<source>${java.version}</source>
|
<source>${maven.compiler.source}</source>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
|
|
|
@ -93,7 +93,7 @@ public abstract class Plugin extends Thread
|
||||||
* On plugin start each resource container is iterated through,
|
* On plugin start each resource container is iterated through,
|
||||||
* then this is called with the resource container classes
|
* 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<ClassNode> classNodeList);
|
public abstract void execute(List<ClassNode> classNodeList);
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,7 +83,7 @@ public class HTMLPane extends JEditorPane
|
||||||
if (is == null)
|
if (is == null)
|
||||||
return null;
|
return null;
|
||||||
try (InputStream stream = is;
|
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() : "";
|
return s.hasNext() ? s.next() : "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ import java.util.zip.ZipOutputStream;
|
||||||
*/
|
*/
|
||||||
public final class ZipUtils {
|
public final class ZipUtils {
|
||||||
|
|
||||||
|
// TODO: Maybe migrate to org.apache.commons.compress.archivers.examples.Expander?
|
||||||
/**
|
/**
|
||||||
* Unzip files to path.
|
* Unzip files to path.
|
||||||
*
|
*
|
||||||
|
@ -43,6 +44,11 @@ public final class ZipUtils {
|
||||||
* @throws IOException Signals that an I/O exception has occurred.
|
* @throws IOException Signals that an I/O exception has occurred.
|
||||||
*/
|
*/
|
||||||
public static void unzipFilesToPath(String jarPath, String destinationDir) throws IOException {
|
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);
|
File file = new File(jarPath);
|
||||||
try (JarFile jar = new JarFile(file)) {
|
try (JarFile jar = new JarFile(file)) {
|
||||||
|
|
||||||
|
@ -67,6 +73,11 @@ public final class ZipUtils {
|
||||||
String fileName = destinationDir + File.separator + entry.getName();
|
String fileName = destinationDir + File.separator + entry.getName();
|
||||||
File f = new File(fileName);
|
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();
|
File parent = f.getParentFile();
|
||||||
if (!parent.exists()) {
|
if (!parent.exists()) {
|
||||||
parent.mkdirs();
|
parent.mkdirs();
|
||||||
|
@ -106,7 +117,7 @@ public final class ZipUtils {
|
||||||
|
|
||||||
public static void zipFolder(String srcFolder, String destZipFile, String ignore) throws Exception {
|
public static void zipFolder(String srcFolder, String destZipFile, String ignore) throws Exception {
|
||||||
try (FileOutputStream fileWriter = new FileOutputStream(destZipFile);
|
try (FileOutputStream fileWriter = new FileOutputStream(destZipFile);
|
||||||
ZipOutputStream zip = new ZipOutputStream(fileWriter)){
|
ZipOutputStream zip = new ZipOutputStream(fileWriter)) {
|
||||||
addFolderToZip("", srcFolder, zip, ignore);
|
addFolderToZip("", srcFolder, zip, ignore);
|
||||||
zip.flush();
|
zip.flush();
|
||||||
}
|
}
|
||||||
|
@ -114,7 +125,7 @@ public final class ZipUtils {
|
||||||
|
|
||||||
public static void zipFolderAPKTool(String srcFolder, String destZipFile) throws Exception {
|
public static void zipFolderAPKTool(String srcFolder, String destZipFile) throws Exception {
|
||||||
try (FileOutputStream fileWriter = new FileOutputStream(destZipFile);
|
try (FileOutputStream fileWriter = new FileOutputStream(destZipFile);
|
||||||
ZipOutputStream zip = new ZipOutputStream(fileWriter)){
|
ZipOutputStream zip = new ZipOutputStream(fileWriter)) {
|
||||||
addFolderToZipAPKTool("", srcFolder, zip);
|
addFolderToZipAPKTool("", srcFolder, zip);
|
||||||
zip.flush();
|
zip.flush();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,45 +1,43 @@
|
||||||
import the.bytecode.club.bytecodeviewer.api.*;
|
import java.util.List;
|
||||||
import java.util.ArrayList;
|
|
||||||
import org.objectweb.asm.tree.ClassNode;
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
|
import the.bytecode.club.bytecodeviewer.api.*;
|
||||||
|
|
||||||
|
public class Template extends Plugin {
|
||||||
|
|
||||||
public class Template extends Plugin
|
|
||||||
{
|
|
||||||
PluginConsole gui;
|
PluginConsole gui;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main function
|
* Main function
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void execute(ArrayList<ClassNode> classNodeList)
|
public void execute(List<ClassNode> classNodeList) {
|
||||||
{
|
// Create console
|
||||||
//create console
|
|
||||||
gui = new PluginConsole("Java Template");
|
gui = new PluginConsole("Java Template");
|
||||||
gui.setVisible(true); //show the console
|
gui.setVisible(true); // Show the console
|
||||||
|
|
||||||
//debug text
|
// Debug text
|
||||||
out("Class Nodes: " + classNodeList.size());
|
out("Class Nodes: " + classNodeList.size());
|
||||||
|
|
||||||
//iterate through each class node
|
// Iterate through each class node
|
||||||
for(ClassNode cn : classNodeList)
|
for (ClassNode cn : classNodeList)
|
||||||
process(cn);
|
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
|
* Process each class node
|
||||||
*/
|
*/
|
||||||
public void process(ClassNode cn)
|
public void process(ClassNode cn) {
|
||||||
{
|
|
||||||
out("Node: " + cn.name + ".class");
|
out("Node: " + cn.name + ".class");
|
||||||
//TODO developer plugin code goes here
|
// TODO developer plugin code goes here
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Print to console
|
* Print to console
|
||||||
*/
|
*/
|
||||||
public void out(String text)
|
public void out(String text) {
|
||||||
{
|
|
||||||
gui.appendText(text);
|
gui.appendText(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in a new issue