Skip to content
LaurieWired edited this page Mar 28, 2023 · 6 revisions

JADXecute Overview

JADXecute is a plugin integrated into the latest version of JADX. To use, simply download the release from this repository and execute it as usual. Once JADX is open, locate the coffee cup icon in the top left corner and click it.

image

Upon clicking, the JADXecute dialog will appear:

image

Executing Code with JADXecute

Once you've written your code, hit run and you should either see successful console output or the list of code compilation errors that Java encountered when compiling your jadx-scripting code.

Scripting Code Structure

In order for JADXecute to be able to execute your dynamic code, you must declare your class with:

public static String userCodeMain(MainWindow mainWindow)

Also, don't forget to include any imports you need as you normally would in Java code!

Console Output

To print values to the console window, you must append them to the string value that is returned by the "userCodeMain" function in the JADXecute window. In the sample code, this string is named jadxecuteOutput. After your code has successfully run, the console displays the final value of this string. Optionally, you could also create a logger object for the class if you would prefer to print values to the JADX Log Viewer.

Handling Errors

If your code has a compiler error, the console will display the Java error message: image

Additionally, if your program fails during execution, the stack trace is printed to the console.

Importing a Java File

Alternatively, JADXecute allows you to import your own Java file. To do so, click the "Browse" button and select the desired Java file. The code in the "Java Input" section will update accordingly. Remember to click "Run" once you are ready to execute your script.

Basic Template

If you are already familiar with the JADX API, start with the following template and add code as you normally would to call JADX API methods:

import jadx.gui.ui.MainWindow;

public class UserCodeClass {
    public static String userCodeMain(MainWindow mainWindow) {
        String jadxScriptingOutput = "";
        
        // Your code goes here!

        return jadxScriptingOutput;
    }
}

Code Examples

Utilize the examples below as a starting point for your JADXecute coding. Look for comments labeled "Update here" in the code to identify locations where you should edit the code to match your method or class names. All these examples can be modified and expanded upon.

JadxWrapper example

Find many more examples inside jadx.gui.JadxWrapper or in the JADX API classes! Use the following code as an example for initializing and using the JadxWrapper class:

import jadx.gui.ui.MainWindow;
import jadx.gui.JadxWrapper;
import jadx.api.JavaClass;

public class UserCodeClass {
    public static String userCodeMain(MainWindow mainWindow) {
        String jadxecuteOutput = "Example output...";

        JadxWrapper wrapper = mainWindow.getWrapper();
        
        // Here's an example of using the wrapper object. Update here!
        for (JavaClass cls : wrapper.getClasses()) {
            jadxecuteOutput += cls.getName() + "\n";
        }

        return jadxecuteOutput;
    }
}

Print all class names

import jadx.gui.ui.MainWindow;
import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.nodes.RootNode;
import java.util.List;

public class UserCodeClass {
    public static String userCodeMain(MainWindow mainWindow) {
        String jadxecuteOutput = "";
        
        // Add all strings to the jadxecute output to be printed
        RootNode root = mainWindow.getWrapper().getDecompiler().getRoot();
        List<ClassNode> classes = root.getClasses();
        for (ClassNode cls : classes) {
            jadxecuteOutput += cls.getFullName() + "\n";
        }

        return jadxecuteOutput;
    }
}

Print all method names

import jadx.gui.ui.MainWindow;
import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.nodes.MethodNode;
import jadx.core.dex.nodes.RootNode;
import java.util.List;

public class UserCodeClass {
    public static String userCodeMain(MainWindow mainWindow) {
        String jadxecuteOutput = "";
        ClassNode selectedClassNode = null;
        String searchClassName = "exampleClassName"; // Update this
        
        // Add all strings to the jadxecute output to be printed
        RootNode root = mainWindow.getWrapper().getDecompiler().getRoot();
        List<ClassNode> classes = root.getClasses();
        for (ClassNode cls : classes) {
            if (cls.getFullName().contains(searchClassName)) {
                jadxecuteOutput += "Found class: " + cls.getFullName() + "\n";
                selectedClassNode = cls;
            }
        }
        
        if (selectedClassNode != null) {
            jadxecuteOutput += "Methods:\n";
            
            // Print all methods in the selected class
            for (MethodNode method : selectedClassNode.getMethods()) {
                jadxecuteOutput += method.getAlias() + "\n"; // Use the alias since this includes user updates
            }
        } else {
            jadxecuteOutput += "Could not find class " + searchClassName;
        }

        return jadxecuteOutput;
    }
}

Print all field names

import jadx.gui.ui.MainWindow;
import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.nodes.FieldNode;
import jadx.core.dex.nodes.RootNode;
import java.util.List;

public class UserCodeClass {
    public static String userCodeMain(MainWindow mainWindow) {
        String jadxecuteOutput = "";
        ClassNode selectedClassNode = null;
        String searchClassName = "exampleClassName"; // Update this
        
        // Add all strings to the jadxecute output to be printed
        RootNode root = mainWindow.getWrapper().getDecompiler().getRoot();
        List<ClassNode> classes = root.getClasses();
        for (ClassNode cls : classes) {
            if (cls.getFullName().contains(searchClassName)) {
                jadxecuteOutput += "Found class: " + cls.getFullName() + "\n";
                selectedClassNode = cls;
            }
        }
        
        if (selectedClassNode != null) {
            jadxecuteOutput += "Fields:\n";
            
            // Print all field in the selected class
            for (FieldNode field : selectedClassNode.getFields()) {
                jadxecuteOutput += field.getAlias() + "\n"; // Use the alias since this includes user updates
            }
        } else {
            jadxecuteOutput += "Could not find class " + searchClassName;
        }

        return jadxecuteOutput;
    }
}

Print classes inheriting from class

import jadx.gui.ui.MainWindow;
import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.nodes.RootNode;
import java.util.List;
import jadx.core.dex.instructions.args.ArgType;

public class UserCodeClass {
    public static String userCodeMain(MainWindow mainWindow) {
        String jadxecuteOutput = "";
        String searchClassName = "IntentService"; // Update this
        ArgType superClassType = null;
        
        // Add all strings to the jadxecute output to be printed
        RootNode root = mainWindow.getWrapper().getDecompiler().getRoot();
        List<ClassNode> classes = root.getClasses();
        
        jadxecuteOutput += "Classes extending " + searchClassName + ":\n";
        
        for (ClassNode cls : classes) {     
            superClassType = cls.getSuperClass();
            
            if (superClassType != null && superClassType.toString().contains(searchClassName)) {
                jadxecuteOutput += cls.getFullName() + "\n";
            }
        }

        return jadxecuteOutput;
    }
}

Print classes containing substring

import jadx.gui.ui.MainWindow;
import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.nodes.RootNode;
import java.util.List;

public class UserCodeClass {
    public static String userCodeMain(MainWindow mainWindow) {
        String jadxecuteOutput = "";
        String searchClassName = "exampleClassName"; // Update this
        
        // Loop through all classes and add desired name to return output
        RootNode root = mainWindow.getWrapper().getDecompiler().getRoot();
        List<ClassNode> classes = root.getClasses();
        for (ClassNode cls : classes) {

            // Example: finds all user-renamed classes renamed like "mw_MyClassA"
            if (cls.getFullName().contains(searchClassName)) {
                jadxecuteOutput += cls.getFullName() + "\n";
            }
        }

        return jadxecuteOutput;
    }
}

Rename a class

import jadx.gui.ui.MainWindow;
import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.nodes.RootNode;
import java.util.List;
import jadx.gui.treemodel.JClass;
import jadx.api.JavaClass;
import jadx.gui.plugins.jadxecute.RenameObjectHelper;

public class UserCodeClass {
    public static String userCodeMain(MainWindow mainWindow) {
        String jadxecuteOutput = "";
        String searchClassName = "exampleClassName"; // Update this
        
        // Find desired class
        RootNode root = mainWindow.getWrapper().getDecompiler().getRoot();
        List<ClassNode> classes = root.getClasses();
        for (ClassNode cls : classes) {
            if (cls.getFullName().contains(searchClassName)) {
                RenameObjectHelper renameObjectHelper = new RenameObjectHelper();
                JClass jclass = new JClass(cls.getJavaNode());

                // Rename found class to desired name
                jadxecuteOutput += renameObjectHelper.renameObject(mainWindow, jclass, "newClassName");
                
                // Optionally return here or you could add functionality to change all 
                //  matched objects to different names and return out of the loop
                return jadxecuteOutput;
            }
        }

        return jadxecuteOutput;
    }
}

Print Java code in a class

import jadx.gui.ui.MainWindow;
import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.nodes.RootNode;
import java.util.List;
import jadx.gui.treemodel.JClass;
import jadx.api.JavaClass;
import jadx.gui.plugins.jadxecute.RenameObjectHelper;

public class UserCodeClass {
    public static String userCodeMain(MainWindow mainWindow) {
        String jadxecuteOutput = "";
        String searchClassName = "exampleClassName"; // Update this
        
        // Find desired class
        RootNode root = mainWindow.getWrapper().getDecompiler().getRoot();
        List<ClassNode> classes = root.getClasses();
        for (ClassNode cls : classes) {
            if (cls.getFullName().contains(searchClassName)) {
                RenameObjectHelper renameObjectHelper = new RenameObjectHelper();
                
                jadxecuteOutput += "Found class " + searchClassName + ":\n\n";
                jadxecuteOutput += cls.getJavaNode().getCodeInfo().toString();
                
                return jadxecuteOutput;
            }
        }

        return jadxecuteOutput;
    }
}

Insert a new instruction comment

Note: This is based on the smali index of the instruction, but will appear in the Java code. The smali index for the method starts from 0 as the first instruction. Select a blank line in the smali code within your corresponding Java line number to have the comment appear in the decompilation.

import jadx.gui.ui.MainWindow;
import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.nodes.MethodNode;
import jadx.core.dex.nodes.RootNode;
import java.util.List;
import jadx.gui.plugins.jadxecute.AddCommentHelper;

public class UserCodeClass {
	public static String userCodeMain(MainWindow mainWindow) {
		String jadxecuteOutput = "";
		ClassNode selectedClassNode = null;
		MethodNode selectedMethodNode = null;
		String searchClassName = "exampleClassName"; // Update this
		String searchMethodName = "exampleMethodName"; // Update this
		String commentToAdd = "This is a new comment!"; // Update this
		int smaliInstructionIndex = 0; // Update this
		
		// Add all strings to the jadxecute output to be printed
		RootNode root = mainWindow.getWrapper().getDecompiler().getRoot();
		List<ClassNode> classes = root.getClasses();
		for (ClassNode cls : classes) {
			if (cls.getFullName().contains(searchClassName)) {
				jadxecuteOutput += "Found class: " + cls.getFullName() + "\n";
				selectedClassNode = cls;
			}
		}
		
		if (selectedClassNode != null) {
			for (MethodNode method : selectedClassNode.getMethods()) {
				if (method.getAlias().contains(searchMethodName)) {
					jadxecuteOutput += "Found method: " + method.getAlias() + "\n";
					selectedMethodNode = method;
				}
			}
			
			// Add the comment if the method was found
			if (selectedMethodNode != null) {
				AddCommentHelper addCommentHelper = new AddCommentHelper(mainWindow, selectedMethodNode.getJavaNode());
				jadxecuteOutput += addCommentHelper.addInstructionComment(commentToAdd, smaliInstructionIndex);
			}
			
		} else {
			jadxecuteOutput += "Could not find class " + searchClassName;
		}

		return jadxecuteOutput;
	}
}