Android App Penetration Testing & Frida Hooks

Frida Scripting for Data Exfiltration: A Practical Walkthrough for Android APIs

Google AdSense Native Placement - Horizontal Top-Post banner

Introduction

Frida is a dynamic instrumentation toolkit that allows developers and security researchers to inject JavaScript into native apps on Android, iOS, Windows, macOS, and Linux. This capability makes it an invaluable tool for reverse engineering, security research, and penetration testing, particularly for Android applications. One of its most powerful applications is the ability to monitor and manipulate API calls at runtime, enabling data exfiltration from within the application’s process. This article provides a practical, expert-level walkthrough on using Frida to hook Android APIs to identify and exfiltrate sensitive data.

Setting Up Your Environment

Before diving into Frida scripting, ensure you have the necessary tools installed and configured.

Prerequisites:

  • An Android device or emulator with root access.
  • ADB (Android Debug Bridge) installed on your host machine.
  • Python 3 and pip installed on your host machine.
  • Frida-tools installed via pip:
pip install frida-tools

Next, download the appropriate Frida server for your Android device’s architecture (e.g., `arm64`, `x86_64`) from the Frida releases page. Push it to your device and make it executable:

adb push frida-server-<version>-android-<arch> /data/local/tmp/frida-server
adb shell "chmod 755 /data/local/tmp/frida-server"

Finally, start the Frida server on your device:

adb shell "/data/local/tmp/frida-server &"

Verify Frida is running by listing processes:

frida-ps -U

Identifying Target APIs for Exfiltration

The first step in data exfiltration is identifying which Android APIs handle or store sensitive data. Common targets include:

  • android.content.SharedPreferences: For locally stored key-value pairs.
  • android.util.Log: Debug logs often contain sensitive information inadvertently.
  • Network APIs (e.g., java.net.HttpURLConnection, okhttp3.OkHttpClient): For intercepting network requests/responses.
  • Cryptographic APIs (e.g., javax.crypto.Cipher): For observing encryption/decryption keys or plaintext data.
  • Content Providers or databases: For accessing structured data.

For this walkthrough, we will focus on android.content.SharedPreferences to demonstrate local data retrieval and android.util.Log to capture debug output.

Crafting the Frida Script for Data Exfiltration

We’ll create a single JavaScript file, `exfiltrate_data.js`, to target both SharedPreferences and Log APIs.

Frida Script Structure

All Frida scripts start with Java.perform(function() { ... }); to ensure the Java VM is ready for instrumentation.

Here’s the combined script:

Java.perform(function() {
    console.log("[*] Starting Frida script for Android API data exfiltration...");

    // --- Hooking SharedPreferences for read/write operations ---
    var SharedPreferencesEditor = Java.use("android.content.SharedPreferences$Editor");
    SharedPreferencesEditor.putString.overload('java.lang.String', 'java.lang.String').implementation = function(key, value) {
        console.log("[SharedPreferences Write] Key: '" + key + "', Value: '" + value + "'");
        return this.putString(key, value);
    };

    var SharedPreferences = Java.use("android.content.SharedPreferences");
    SharedPreferences.getString.overload('java.lang.String', 'java.lang.String').implementation = function(key, defValue) {
        var ret = this.getString(key, defValue);
        console.log("[SharedPreferences Read] Key: '" + key + "', Retrieved Value: '" + ret + "', Default Value: '" + defValue + "'");
        return ret;
    };

    // --- Hooking android.util.Log for all log levels ---
    var Log = Java.use("android.util.Log");

    var hookLogMethod = function(level, methodName) {
        // Overload for (String tag, String msg)
        Log[methodName].overload('java.lang.String', 'java.lang.String').implementation = function(tag, msg) {
            console.log("[Log " + level + "] Tag: '" + tag + "', Message: '" + msg + "'");
            return this[methodName](tag, msg);
        };
        // Overload for (String tag, String msg, Throwable tr)
        Log[methodName].overload('java.lang.String', 'java.lang.String', 'java.lang.Throwable').implementation = function(tag, msg, tr) {
            console.log("[Log " + level + "] Tag: '" + tag + "', Message: '" + msg + "', Exception: '" + tr + "'");
            return this[methodName](tag, msg, tr);
        };
    };

    hookLogMethod("DEBUG", "d");
    hookLogMethod("ERROR", "e");
    hookLogMethod("INFO", "i");
    hookLogMethod("VERBOSE", "v");
    hookLogMethod("WARN", "w");

    console.log("[*] Frida script loaded successfully.");
});

Explanation of the Script:

  1. Java.perform(function() { ... });: This is the entry point for all Java-related Frida interactions, ensuring the Java VM is initialized.

  2. Java.use("fully.qualified.ClassName"): This function obtains a wrapper for a Java class, allowing you to interact with its static and instance methods.

  3. .overload('arg1.Type', 'arg2.Type'): When a method has multiple signatures (overloads), you must specify the exact argument types for the overload you wish to hook. Use full class names for types (e.g., `java.lang.String`).

  4. .implementation = function(...) { ... }: This is where you define your custom logic. Inside this function:

    • this refers to the original Java object or class.
    • Calling this.originalMethod(...) (e.g., this.putString(key, value)) invokes the original method. It’s crucial to call the original method to ensure the app continues to function correctly unless you explicitly want to bypass or modify its behavior.
    • console.log(...): Used to print information to the Frida console, which is how we exfiltrate the data.
  5. SharedPreferences Hooks: We hook both `putString` on `SharedPreferences$Editor` to see data being written, and `getString` on `SharedPreferences` to see data being read. This gives a comprehensive view of sensitive data managed by SharedPreferences.

  6. Log Hooks: We define a helper function `hookLogMethod` to reduce code duplication and apply the hook to all common `android.util.Log` methods (debug, error, info, verbose, warn), capturing both simple messages and those with `Throwable` objects.

Running the Frida Script

Now, execute the script against your target Android application. First, find the package name of your target app (e.g., `com.example.app`).

frida-ps -Uai # Lists all installed apps with package names

Once you have the package name, run Frida with your script:

frida -U -f com.example.app -l exfiltrate_data.js --no-pause
  • -U: Attaches to a USB device.
  • -f com.example.app: Spawns the application specified by its package name.
  • -l exfiltrate_data.js: Loads your Frida script.
  • --no-pause: Prevents Frida from pausing the application at startup, allowing it to run immediately.

As the application runs and interacts with SharedPreferences or uses `android.util.Log`, you will see the exfiltrated data printed directly to your terminal. Interact with the app to trigger different code paths and data accesses.

Analyzing Exfiltrated Data

The output in your terminal will contain the data captured by your script. Carefully review this output for any sensitive information:

  • API keys or tokens
  • User credentials
  • Personally Identifiable Information (PII)
  • Confidential business logic details
  • Internal debugging messages not meant for production

For large amounts of data, consider piping the output to a file for easier analysis:

frida -U -f com.example.app -l exfiltrate_data.js --no-pause > exfiltrated_data.txt

Conclusion

Frida scripting provides an incredibly powerful and flexible way to perform dynamic analysis and data exfiltration from Android applications. By hooking critical APIs like SharedPreferences and android.util.Log, security researchers can gain deep insights into an application’s runtime behavior and uncover sensitive data that might otherwise be hidden. This practical walkthrough serves as a foundation; the true power of Frida lies in its adaptability to target specific functions and bypass various security controls, making it an indispensable tool in any mobile penetration tester’s arsenal.

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