Android App Penetration Testing & Frida Hooks

Beyond the Basics: Dynamic Data Exfiltration & Manipulation in Android Apps with Frida

Google AdSense Native Placement - Horizontal Top-Post banner

Introduction

In the realm of Android application penetration testing, static analysis often falls short when dealing with obfuscated code, dynamically loaded components, or runtime decision-making. This is where dynamic instrumentation frameworks like Frida shine. Frida allows security researchers and developers to inject JavaScript code into target processes, hooking into native and Java APIs at runtime, effectively enabling powerful data exfiltration and manipulation capabilities. This expert-level guide will delve into advanced techniques for using Frida to identify, capture, and modify sensitive data flows within Android applications.

Setting the Stage: Your Frida Environment

Before we embark on our data exfiltration journey, ensure your Frida environment is properly configured. You’ll need a rooted Android device or emulator, ADB, Python, and Frida-tools installed on your host machine.

Prerequisites:

  • A rooted Android device or emulator (e.g., AVD, Genymotion, NoxPlayer)
  • ADB (Android Debug Bridge) installed and configured
  • Python 3.x installed
  • Frida-tools installed via pip:
pip install frida-tools

Installing Frida Server on Android:

Download the appropriate frida-server binary for your device’s architecture from Frida’s GitHub releases (e.g., frida-server-*-android-arm64 for a 64-bit ARM device). Push it to the device and set permissions:

adb push frida-server-*-android-arm64 /data/local/tmp/frida-serveradb shell"chmod 755 /data/local/tmp/frida-server"adb shell"/data/local/tmp/frida-server &"

Verify Frida is running by listing processes:

frida-ps -U

The Power of Dynamic Instrumentation

Frida operates by injecting a JavaScript engine (V8) into the target process. This allows you to interact with the application’s memory, call arbitrary functions, and intercept method invocations. For data exfiltration, we’re primarily interested in two key capabilities:

  1. Hooking API calls: Intercepting methods from Android SDK, third-party libraries, or the application’s own classes.
  2. Modifying arguments and return values: Changing data as it passes through methods, or altering the outcome of method calls.

Identifying Targets for Data Exfiltration

Effective data exfiltration requires understanding where sensitive data might be processed or stored. Common targets include:

  • Shared Preferences: Often used for storing user settings, session tokens, or other sensitive key-value pairs.
  • SQLite Databases: Local databases frequently hold user data, chat histories, or application-specific information.
  • File I/O: Reading/writing to internal or external storage.
  • Network Communication: Sending/receiving data over HTTP/HTTPS, custom protocols.
  • Crypto APIs: Encryption/decryption operations revealing keys or plaintexts.
  • System APIs: Methods interacting with SMS, contacts, location, etc.

Frida Basics: Hooking a Method

Let’s start with a simple hook to understand the mechanics. We’ll hook the android.util.Log.d method to demonstrate capturing arguments.

// my_basic_hook.jsJava.perform(function () {    console.log("[+] Script loaded successfully");    var Log = Java.use("android.util.Log");    Log.d.overload("java.lang.String", "java.lang.String").implementation = function (tag, msg) {        console.log("[Frida-Logd] Tag: " + tag + ", Message: " + msg);        return this.d(tag, msg);    };    console.log("[+] Hooked android.util.Log.d");});

To inject this script into an app (e.g., com.example.app), use:

frida -U -f com.example.app -l my_basic_hook.js --no-pause

Any calls to Log.d within the application will now be printed to your Frida console.

Advanced Data Exfiltration: Capturing SharedPreferences

SharedPreferences is a common target for storing sensitive data. We’ll hook methods in android.content.SharedPreferences$Editor to intercept key-value pairs before they are committed.

Scenario: Exfiltrating Saved User Credentials

// frida_prefs_exfil.jsJava.perform(function () {    console.log("[+] SharedPreferences Exfiltration Script Loaded");    var SharedPreferencesEditor = Java.use("android.content.SharedPreferences$Editor");    // Hook putString    SharedPreferencesEditor.putString.implementation = function (key, value) {        console.log("n[SharedPreferences.putString] Key: '" + key + "'nValue: '" + value + "'");        return this.putString(key, value);    };    // Hook putInt    SharedPreferencesEditor.putInt.implementation = function (key, value) {        console.log("n[SharedPreferences.putInt] Key: '" + key + "'nValue: '" + value + "'");        return this.putInt(key, value);    };    // Add hooks for other types like putBoolean, putFloat, putLong, putStringSet as needed    // Hook apply/commit to confirm write operations    var apply = SharedPreferencesEditor.apply;    apply.implementation = function () {        console.log("n[SharedPreferences.apply] Data committed!");        return apply.call(this);    };    var commit = SharedPreferencesEditor.commit;    commit.implementation = function () {        console.log("n[SharedPreferences.commit] Data committed!");        return commit.call(this);    };    console.log("[+] Hooked SharedPreferences.Editor methods.");});

When the target application writes to its SharedPreferences, you’ll see the keys and values logged in your console.

Beyond Exfiltration: Dynamic Data Manipulation

Frida’s power isn’t limited to just observing; you can actively modify data. This opens up possibilities for bypassing client-side checks, altering application logic, or even injecting malicious payloads.

Scenario: Manipulating SharedPreferences Data to Change App Behavior

Let’s say an app stores a boolean isAdmin in SharedPreferences. We can force it to true:

// frida_prefs_manip.jsJava.perform(function () {    console.log("[+] SharedPreferences Manipulation Script Loaded");    var SharedPreferencesEditor = Java.use("android.content.SharedPreferences$Editor");    SharedPreferencesEditor.putBoolean.implementation = function (key, value) {        if (key.equals("isAdmin") && value === false) {            console.log("n[SharedPreferences.putBoolean] Original: isAdmin=false. Forcing to true!");            return this.putBoolean(key, true); // Manipulate the value        }        console.log("n[SharedPreferences.putBoolean] Key: '" + key + "', Value: '" + value + "'");        return this.putBoolean(key, value);    };    SharedPreferencesEditor.apply.implementation = function () {        console.log("n[SharedPreferences.apply] Data committed (possibly manipulated)!");        return this.apply();    };    SharedPreferencesEditor.commit.implementation = function () {        console.log("n[SharedPreferences.commit] Data committed (possibly manipulated)!");        return this.commit();    };    console.log("[+] Hooked SharedPreferences.Editor for manipulation.");});

Inject this script, and if the app attempts to set isAdmin to false, Frida will intercept and change it to true before it’s written. This can bypass client-side permission checks or unlock hidden features.

Exfiltrating Network Traffic (HTTP/S)

Intercepting network traffic at the API level can be challenging, especially with SSL pinning. However, for non-pinned or custom HTTP clients, you can hook into methods that send or receive data. For instance, hooking okhttp3.Request.Builder.url or java.net.HttpURLConnection.connect() can reveal endpoints and request details.

Example: Capturing HTTPURLConnection Details

// frida_http_hook.jsJava.perform(function () {    console.log("[+] HTTPURLConnection Hook Script Loaded");    var HttpURLConnection = Java.use("java.net.HttpURLConnection");    HttpURLConnection.connect.implementation = function () {        console.log("n[HTTPURLConnection.connect] Connecting to: " + this.getURL().toString());        var method = this.getRequestMethod();        if (method) {            console.log("[HTTPURLConnection.connect] Method: " + method);        }        // You can also try to get request headers or body here, but it's more complex.        return this.connect();    };    console.log("[+] Hooked java.net.HttpURLConnection.connect.");});

This script will log the URL whenever HttpURLConnection.connect() is called. For more advanced network interception, you’d combine this with hooks on input/output streams or dedicated network libraries like OkHttp or Apache HttpClient.

Conclusion

Frida is an indispensable tool for advanced Android app penetration testing. Its dynamic instrumentation capabilities empower security researchers to move beyond static analysis, providing deep insights into runtime behavior, sensitive data flows, and potential manipulation points. By mastering the techniques of API hooking, data exfiltration, and argument/return value manipulation, you can uncover critical vulnerabilities that are otherwise hidden, significantly enhancing the depth and effectiveness of your security assessments.

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