Android App Penetration Testing & Frida Hooks

Frida Cookbook: Essential Recipes for Android API Interception and Data Faking

Google AdSense Native Placement - Horizontal Top-Post banner

Introduction to Android API Interception with Frida

Frida is an unparalleled dynamic instrumentation toolkit that allows developers, security researchers, and penetration testers to inject custom scripts into running processes. Its ability to hook into functions, inspect and modify arguments, and even alter return values at runtime makes it an indispensable tool for understanding and manipulating Android applications. This ‘Frida Cookbook’ will guide you through essential recipes for intercepting and faking data for Android APIs, with a specific focus on the critical startActivity method.

In Android app penetration testing, runtime manipulation is key. Often, static analysis can reveal potential vulnerabilities, but dynamic analysis with Frida can confirm them, bypass security controls, and even discover new attack vectors by observing app behavior under manipulated conditions. By intercepting startActivity, we can monitor application flow, prevent sensitive activities from launching, or inject malicious data into intents to test an app’s robustness.

Setting Up Your Frida Environment (Briefly)

Before diving into the recipes, ensure you have a working Frida environment. This typically involves:

  • A rooted Android device or an emulator.
  • frida-server running on the Android device, matching your host’s Frida version and device architecture.
  • frida-tools installed on your host machine (e.g., pip install frida-tools).

To start frida-server on your device, push it and execute:

adb push /path/to/frida-server /data/local/tmp/frida-server
adb shell "chmod 755 /data/local/tmp/frida-server"
adb shell "/data/local/tmp/frida-server &"

Recipe 1: Monitoring startActivity Calls

Monitoring when and how an application launches new activities provides crucial insights into its navigation logic and potential entry points for deep linking or intent manipulation. We’ll hook the startActivity method to log the details of the Intent being passed.

Frida Script for Monitoring startActivity

This script uses Java.perform to ensure our code runs within the app’s Java context. We then use Java.use to get a reference to the android.app.Activity class and its startActivity method. Since startActivity has multiple overloads, we specify the one that takes an android.content.Intent as an argument.

Java.perform(function () {
    console.log("[+] Frida script loaded: Monitoring startActivity calls");

    var Activity = Java.use("android.app.Activity");

    // Hooking startActivity(Intent intent)
    Activity.startActivity.overload('android.content.Intent').implementation = function (intent) {
        console.log("n[+] startActivity called:");
        console.log("    Action: " + intent.getAction());
        console.log("    Component: " + intent.getComponent());

        var extras = intent.getExtras();
        if (extras) {
            // Use a new Bundle to get a readable string representation of extras
            var bundle = Java.use("android.os.Bundle").$new();
            bundle.putAll(extras);
            console.log("    Extras: " + bundle.toString());
        }

        // Call the original method to ensure the activity actually starts
        this.startActivity(intent);
    };

    console.log("[+] Hooked android.app.Activity.startActivity(android.content.Intent)");
});

Executing the Script

Save the above code as monitor_startactivity.js. To attach to a running application (replace com.example.app with your target package name):

frida -U -l monitor_startactivity.js com.example.app

Now, whenever your target application calls startActivity, you’ll see detailed logs in your terminal.

Recipe 2: Preventing or Redirecting Activity Launches

In penetration testing, you might want to prevent sensitive activities from launching (e.g., payment screens, admin panels) or redirect them to a different, less privileged activity to observe app behavior or bypass certain flows.

Frida Script for Preventing/Redirecting startActivity

Java.perform(function () {
    console.log("[+] Frida script loaded: Preventing/Redirecting startActivity");

    var Activity = Java.use("android.app.Activity");

    Activity.startActivity.overload('android.content.Intent').implementation = function (intent) {
        var component = intent.getComponent();
        if (component) {
            var targetActivity = component.getClassName();
            console.log("[+] Attempting to launch: " + targetActivity);

            // Example 1: Prevent a specific activity from launching
            if (targetActivity.includes("SensitiveActivity")) { // e.g., com.example.app.SensitiveActivity
                console.warn("[!!!] Blocking launch of SensitiveActivity!");
                // Just return, do not call the original startActivity
                return;
            }

            // Example 2: Redirect a specific activity to a harmless one
            if (targetActivity.includes("AdminPanelActivity")) { // e.g., com.example.app.AdminPanelActivity
                console.warn("[!!!] Redirecting AdminPanelActivity to MainActivity!");
                var newIntent = Java.use("android.content.Intent").$new();
                // Replace with a known safe activity in the target app
                newIntent.setClassName("com.example.app", "com.example.app.MainActivity");
                this.startActivity(newIntent); // Call original with modified intent
                return;
            }
        }

        // If no conditions met, call the original method
        this.startActivity(intent);
    };

    console.log("[+] Hooked android.app.Activity.startActivity(android.content.Intent) for control.");
});

Execution and Observation

Save this as control_startactivity.js and run it with Frida as before:

frida -U -l control_startactivity.js com.example.app

Interact with the app and try to trigger the activities you’ve targeted for prevention or redirection. Observe the console output and the application’s behavior.

Recipe 3: Faking Data in Intent Extras

Many Android apps pass critical data between activities using Intent extras (Bundles). By intercepting startActivity, we can inspect and even modify these extras before the target activity receives them. This is powerful for bypassing client-side checks, escalating privileges, or triggering unexpected application logic.

Frida Script for Faking Intent Extras

Java.perform(function () {
    console.log("[+] Frida script loaded: Faking data in Intent extras");

    var Activity = Java.use("android.app.Activity");
    var Intent = Java.use("android.content.Intent");
    var Bundle = Java.use("android.os.Bundle");

    Activity.startActivity.overload('android.content.Intent').implementation = function (intent) {
        var component = intent.getComponent();
        if (component) {
            var targetActivity = component.getClassName();
            console.log("[+] Original startActivity for: " + targetActivity);

            // Target a specific activity that processes data from extras
            if (targetActivity.includes("DataProcessingActivity")) { // e.g., com.example.app.DataProcessingActivity
                console.warn("[!!!] Intercepting DataProcessingActivity intent to fake data.");

                var originalExtras = intent.getExtras();
                var modifiedBundle = Bundle.$new();
                if (originalExtras) {
                    modifiedBundle.putAll(originalExtras); // Copy existing extras
                }

                // Example: Modify an existing key's value
                if (modifiedBundle.containsKey("user_role")) {
                    var originalRole = modifiedBundle.getString("user_role");
                    modifiedBundle.putString("user_role", "admin"); // Elevate role
                    console.log("    Modified 'user_role' from '" + originalRole + "' to 'admin'");
                }

                // Example: Add a new key-value pair
                if (!modifiedBundle.containsKey("is_privileged")) {
                    modifiedBundle.putBoolean("is_privileged", true);
                    console.log("    Added 'is_privileged' set to true");
                }

                // Create a new Intent with the modified Bundle
                var modifiedIntent = Intent.$new(intent); // Copy original intent
                modifiedIntent.putExtras(modifiedBundle); // Set the modified bundle

                // Call the original startActivity with the modified intent
                this.startActivity(modifiedIntent);
                return; // Prevent original intent from being used
            }
        }

        // For all other activities, proceed normally
        this.startActivity(intent);
    };

    console.log("[+] Hooked android.app.Activity.startActivity(android.content.Intent) for data faking.");
});

Verification Steps

Save as fake_intent_data.js and execute:

frida -U -l fake_intent_data.js com.example.app

Trigger the DataProcessingActivity in your target app. The Frida console will log the modification, and if the app relies on the `user_role` or `is_privileged` flag for authorization, you might observe elevated access or different behavior within the `DataProcessingActivity`.

Conclusion

The recipes presented here for Android’s startActivity method barely scratch the surface of what’s possible with Frida. From simply monitoring application flow to actively preventing activity launches and faking critical data, Frida empowers you with unparalleled control over an app’s runtime behavior. Mastering these techniques is fundamental for any serious Android penetration tester or security researcher, enabling deep insights and effective exploitation of client-side vulnerabilities.

Remember to use Frida responsibly and only on applications you have explicit permission to test. Its power lies in its ability to dynamically alter execution, making it a double-edged sword that requires ethical considerations.

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