| name | android-frida-pentest |
| description | Use this skill whenever you need to perform dynamic analysis, hooking, or instrumentation on Android applications using Frida. Trigger this for any Android app security testing, reverse engineering, DEX dumping, anti-debugging bypass, runtime manipulation, or mobile pentesting tasks. Make sure to use this skill when the user mentions Android app analysis, Frida, dynamic instrumentation, hooking Java methods, DEX dumping, FLAG_SECURE bypass, or any mobile security testing. |
Android Frida Pentesting Skill
A comprehensive guide for dynamic Android application analysis using Frida instrumentation.
Quick Start
Install Frida Tools
pip install frida-tools
pip install frida
Setup Frida Server on Android
Rooted device (one-liner):
adb root; adb connect localhost:6000; sleep 1; adb push frida-server /data/local/tmp/; adb shell "chmod 755 /data/local/tmp/frida-server"; adb shell "/data/local/tmp/frida-server &"
Verify installation:
frida-ps -U
frida-ps -U | grep -i <package_name>
Basic Hooking Commands
frida -U --no-pause -l script.js -f com.example.app
frida -U -n com.example.app -l script.js
frida-ps -Uai
Frida Gadget (No-Root Option)
When you don't have root access, bundle Frida Gadget inside the APK:
Manual Gadget Integration
- Unpack APK:
apktool d app.apk -o app_modified
- Add Gadget files:
- Place
libfrida-gadget.so in lib/<abi>/ (e.g., lib/arm64-v8a/)
- Create
assets/frida-gadget.config:
{
"interaction": { "type": "script", "path": "/sdcard/hook.js" },
"runtime": { "logFile": "/sdcard/frida-gadget.log" }
}
- Repack and sign:
apktool b app_modified -o app_gadget.apk
uber-apk-signer -a app_gadget.apk -o out_signed
adb install -r out_signed/app_gadget-aligned-debugSigned.apk
Automated with Objection
objection patchapk -s app.apk \
-c gadget-config.json \
-l agent.js \
--use-aapt2
Common Hooking Patterns
Hook Functions Without Parameters
Java.perform(function () {
var targetClass = Java.use("com.example.ClassName");
targetClass.methodName.overload().implementation = function () {
console.log("[+] methodName called");
return false;
};
});
Hook Functions With Parameters
Java.perform(function () {
var targetClass = Java.use("com.example.ClassName");
targetClass.methodName.overload("java.lang.String", "int").implementation = function (arg1, arg2) {
console.log("[+] Input arg1: " + arg1);
console.log("[+] Input arg2: " + arg2);
var result = this.methodName(arg1, arg2);
console.log("[+] Output: " + result);
return result;
};
});
Hook Activity Lifecycle Methods
Java.perform(function () {
var MainActivity = Java.use("com.example.MainActivity");
MainActivity.onCreate.overload("android.os.Bundle").implementation = function (bundle) {
console.log("[+] MainActivity.onCreate() called");
return this.onCreate(bundle);
};
MainActivity.onStart.overload().implementation = function () {
console.log("[+] MainActivity.onStart() called");
return this.onStart();
};
});
Intercept Decryption Functions
function bytesToString(data) {
var result = "";
for (var i = 0; i < data.length; i++) {
result += String.fromCharCode(data[i]);
}
return result;
}
Java.perform(function () {
var cryptoClass = Java.use("com.example.Crypto");
cryptoClass.decrypt.overload("[B", "[B").implementation = function (key, encrypted) {
console.log("[+] Key: " + bytesToString(key));
console.log("[+] Encrypted: " + bytesToString(encrypted));
var decrypted = this.decrypt(key, encrypted);
console.log("[+] Decrypted: " + bytesToString(decrypted));
return decrypted;
};
});
Find and Inspect Object Instances
Java.choose("com.example.ClassName", {
onMatch: function (instance) {
console.log("[+] Found instance: " + instance);
console.log("[+] Private field: " + instance.privateMethod());
},
onComplete: function () {
console.log("[+] Search complete");
}
});
Prevent App Exit
Java.perform(function () {
var System = Java.use("java.lang.System");
System.exit.overload("int").implementation = function (code) {
console.log("[!] App tried to exit with code: " + code);
return;
};
});
Anti-Debugging Bypass
Disable Root Detection
Java.perform(function () {
var Build = Java.use("android.os.Build");
var SystemProperties = Java.use("android.os.SystemProperties");
Build.FINGERPRINT.get = function() { return "generic/generic/generic"; };
Build.HARDWARE.get = function() { return "generic"; };
Build.MODEL.get = function() { return "Android SDK built for x86"; };
Build.MANUFACTURER.get = function() { return "Google"; };
SystemProperties.get.overload("java.lang.String").implementation = function (key) {
if (key.contains() || key.()) {
;
}
.(key);
};
});
Block SIGSEGV Handlers
Interceptor.attach(Module.findExportByName("libc.so", "sigaction"), {
onEnter: function (args) {
if (args[1] !== null) {
console.log("[+] sigaction called - blocking anti-debug");
args[1] = null;
}
}
});
DEX Dumping with clsdumper
pip install clsdumper
clsdumper com.example.app
clsdumper com.example.app --spawn
clsdumper com.example.app --strategies fart_dump,oat_extract,memory_scan
clsdumper com.example.app --deep-scan
clsdumper com.example.app --extract-classes
JDWP Injection (Debuggable Apps, No Root)
For apps with android:debuggable="true":
python frida-jdwp-loader.py frida -n com.example.app
python frida-jdwp-loader.py frida -n com.example.app -s
python frida-jdwp-loader.py frida -n com.example.app -i script -l hook.js
Useful Scripts
See the scripts/ directory for ready-to-use Frida scripts:
clear-flag-secure.js - Remove FLAG_SECURE to enable screenshots
basic-hook-template.js - Template for common hooking patterns
setup-frida-server.sh - Automated frida-server deployment
Best Practices
-
Spawn vs Attach: Use --spawn (-f) to hook before onCreate() for early initialization hooks. Use attach for running apps.
-
Multi-strategy DEX dumping: Hardened apps load code from multiple sources. Use clsdumper with default strategies plus --spawn for maximum coverage.
-
Frida 17+ Java Bridge: If your agent hooks Java, include the Java bridge:
npm install frida-java-bridge
npm run build
-
Stealth: For Gadget on hardened apps, use obfuscated names and conditional loading to avoid detection.
-
UI Thread Hooks: For window manipulation, schedule on main thread to avoid flicker:
Java.scheduleOnMainThread(function () {
});
References