Android Software Reverse Engineering & Decompilation

Your First JEB Python Script: A Step-by-Step Guide to Android App Static Analysis

Google AdSense Native Placement - Horizontal Top-Post banner

Introduction to JEB Python Scripting for Android Analysis

JEB Decompiler is a powerful tool for reverse engineering and analyzing Android applications, native binaries, and more. While its interactive GUI offers a rich set of features, the true power of JEB for advanced users and security researchers often lies in its Python scripting API. This API allows for automation of repetitive tasks, large-scale analysis, and custom vulnerability detection, transforming JEB from a manual tool into a programmatic analysis platform.

This tutorial will guide you through creating your first Python script for JEB, focusing on a practical application: identifying hardcoded string literals within an Android application’s DEX files. This foundational skill is crucial for tasks like extracting API keys, URLs, or other sensitive information often embedded directly in an application’s code.

Setting Up Your JEB Scripting Environment

Before diving into code, ensure you have JEB installed and running. JEB comes with an embedded Python interpreter, so you typically don’t need to configure a separate Python environment. Scripts are executed directly within JEB’s context, giving them access to the loaded project and its associated units.

To start, simply create a .py file in your preferred text editor. A basic JEB script always extends the IScript interface and implements the run method. This method receives a JebContext object, which serves as the entry point to JEB’s API.

# my_first_script.py
from jeb.api import IScript

class MyFirstScript(IScript):
    def run(self, ctx):
        print('Hello from JEB! The context is ready.')
        # Your analysis logic will go here

Save this file. We’ll run it later once we’ve built our full script.

Understanding JEB’s Core API Concepts

Interacting with JEB programmatically involves understanding a few core concepts:

The IRuntime Interface (JebContext)

The ctx object passed to your run method is an instance of IRuntime (or JebContext in newer versions, which extends IRuntime). It’s your gateway to the entire JEB application. Through ctx, you can access the currently loaded project, create new units, interact with the UI, and log messages.

# Example: Getting the current project
project = ctx.get_project()
if project:
    print(f"Current project: {project.get_name()}")
else:
    print("No project currently loaded.")

IUnit and Unit Types

In JEB, an IUnit represents a high-level component of your analyzed file. For an Android APK, common unit types include:

  • DEX Units: Represent compiled Android bytecode (.dex files). This is where our string analysis will focus.
  • APK Units: The top-level container for an Android package.
  • Native Units: For shared libraries (.so files) containing ARM, x86, etc., machine code.
  • XML Units: For AndroidManifest.xml, layouts, etc.

Each unit type has specific interfaces that expose its unique properties and methods. To work with a DEX unit, you’ll cast a generic IUnit to a Dex unit using unit.as_unit(Dex.UNIT_TYPE).

Practical Example: Locating Hardcoded Strings in a DEX Unit

Our objective is to write a script that enumerates all hardcoded string literals within an Android application’s DEX files. This is a common first step in static analysis, often revealing API keys, URLs, sensitive messages, or configuration values.

Step-by-Step Script Development

Step 1: Accessing the Current Project and DEX Units

First, we need to ensure a project is loaded and then iterate through its units to find all DEX units.

from jeb.api import IScript
from jeb.api.dex import Dex # Import the Dex unit type

class HardcodedStringFinder(IScript):
    def run(self, ctx):
        print("Starting Hardcoded String Finder script...")
        project = ctx.get_project()
        if not project:
            print("No project open. Please open an Android APK first.")
            return

        found_strings_count = 0
        # Iterate through all units in the project
        for unit in project.get_units():
            # Check if the unit is a DEX unit
            if unit.is_a(Dex.UNIT_TYPE):
                dex_unit = unit.as_unit(Dex.UNIT_TYPE)
                print(f"Analyzing DEX unit: {dex_unit.get_name()}")
                # ... further analysis will go here ...
        print("Script finished initial scan.")

Step 2: Iterating Through Classes and Methods

Inside each DEX unit, we’ll traverse its classes, and within each class, its methods. This forms the structure of an Android application’s bytecode.

# ... (inside the if unit.is_a(Dex.UNIT_TYPE) block)
                for cls in dex_unit.get_classes():
                    # Each class has methods
                    for method in cls.get_methods():
                        # Methods contain bytecode instructions; we need their bodies
                        body = method.get_body()
                        if body:
                            # Now we can iterate through instructions
                            # ... (next step will go here) ...

Step 3: Extracting String Literals from Instructions

Dalvik bytecode instructions that load string literals into registers are typically const-string or const-string/jumbo. We can check the instruction’s mnemonic and then retrieve the string reference.

# ... (inside the if body: block)
                            for insn in body.get_instructions():
                                # Check if it's a const-string instruction
                                if insn.get_mnemonic().startswith('const-string'):
                                    # Get the string reference object
                                    string_ref = insn.get_string_ref()
                                    if string_ref:
                                        string_value = string_ref.get_value()
                                        print(f"  [+] Method: {method.get_signature()} -> String: '{string_value}'")
                                        found_strings_count += 1

Complete Hardcoded String Finder Script

Combining all steps, here is the full script:

from jeb.api import IScript
from jeb.api.dex import Dex

class HardcodedStringFinder(IScript):
    def run(self, ctx):
        print("Starting Hardcoded String Finder script...")
        project = ctx.get_project()
        if not project:
            print("No project open. Please open an Android APK first.")
            return

        found_strings_count = 0
        for unit in project.get_units():
            if unit.is_a(Dex.UNIT_TYPE):
                dex_unit = unit.as_unit(Dex.UNIT_TYPE)
                print(f"Analyzing DEX unit: {dex_unit.get_name()}")

                for cls in dex_unit.get_classes():
                    for method in cls.get_methods():
                        body = method.get_body()
                        if body:
                            for insn in body.get_instructions():
                                # Check for 'const-string' or 'const-string/jumbo' instructions
                                if insn.get_mnemonic().startswith('const-string'):
                                    string_ref = insn.get_string_ref()
                                    if string_ref:
                                        string_value = string_ref.get_value()
                                        print(f"  [+] Method: {method.get_signature()} -> String: '{string_value}'")
                                        found_strings_count += 1

        print(f"Script finished. Total hardcoded strings found: {found_strings_count}")
        if found_strings_count == 0:
            print("No hardcoded strings detected in the current project (or no DEX units found). This may indicate obfuscation or a simple application).")

Executing Your Script in JEB

With your .py file saved, follow these steps to run it in JEB:

  1. Open an Android APK: In JEB, open any Android application (File -> Open...) so there’s a project to analyze.
  2. Access Scripting Menu: Go to File -> Scripting -> Execute script... in the JEB menu bar.
  3. Select Your Script: A file dialog will appear. Navigate to where you saved HardcodedStringFinder.py and select it.
  4. Observe Output: JEB will execute the script. Any print() statements from your script will appear in JEB’s Log pane, typically at the bottom of the JEB window.

You should see output similar to:

Starting Hardcoded String Finder script...
Analyzing DEX unit: com.example.app-1.dex
  [+] Method: com.example.app.MainActivity->onCreate(Landroid/os/Bundle;)V -> String: 'Hello, JEB Scripting!'
  [+] Method: com.example.app.network.ApiHelper->getApiKey()Ljava/lang/String; -> String: 'sk_live_YOUR_SECRET_KEY'
...
Script finished. Total hardcoded strings found: 123

Beyond Hardcoded Strings: Expanding Your Scripting Capabilities

This basic string finder is just the beginning. JEB’s Python API offers extensive capabilities for deeper analysis:

  • Automating Renaming: Identify obfuscated method/class names based on analysis patterns (e.g., cross-references, known library calls) and rename them programmatically.
  • Call Graph Analysis: Build or visualize call graphs for specific functions or classes to understand execution flow.
  • Vulnerability Detection: Scan for common insecure coding patterns, such as insecure crypto implementations, weak random number generation, or improper handling of sensitive data.
  • Data Flow Analysis: Trace the flow of data from sources (e.g., user input, sensor data) to sinks (e.g., network transmissions, file writes) to identify potential privacy leaks or injection vulnerabilities.
  • Signature Matching: Implement custom YARA-like rules or other signature-based detection for malware families.

Explore the official JEB API documentation (often available via Help -> API Documentation in JEB) for a comprehensive list of classes and methods you can leverage.

Conclusion

You’ve successfully written and executed your first JEB Python script, taking a significant step towards automating and enhancing your Android application static analysis workflow. By leveraging JEB’s powerful API, you can move beyond manual inspection, develop custom analysis tools, and greatly improve your efficiency in reverse engineering tasks. The ability to programmatically interact with an application’s structure and bytecode is an invaluable skill for any serious security researcher or reverse engineer.

Android Mobile Specs & Compare Directory

Are you researching mobile hardware properties, processor SoCs, GPU chipsets, or RAM configurations? Access our complete specs catalog to compare up to 5 devices side-by-side!

Compare Devices Specs →
Google AdSense Inline Placement - Content Footer banner