How to Use Frida for Dynamic Instrumentation of Android Apps with Static Analysis
Combine the static analysis output from the android-reverse-engineering-skill repository with Frida to identify critical methods and hook them at runtime for comprehensive dynamic instrumentation.
The android-reverse-engineering-skill repository by SimoneAvogadro provides a complete static analysis pipeline for decompiling APK files and extracting API calls, but it does not ship with native Frida integration. By pairing its automated decompilation scripts with Frida's dynamic instrumentation capabilities, you can trace runtime behavior, intercept network calls, and bypass obfuscation that static analysis alone cannot reveal.
Prerequisites and Tool Setup
Before instrumenting Android apps, install the static analysis dependencies from the repository and configure Frida on both your host machine and target device.
First, verify that jadx, dex2jar, and fernflower are installed using the repository's dependency checker:
bash plugins/android-reverse-engineering/skills/android-reverse-engineering/scripts/check-deps.sh
Install Frida on your host system via pip:
pip install frida-tools
Deploy frida-server to your Android device or emulator. Push the binary and execute it with root privileges:
adb push frida-server /data/local/tmp/
adb shell "chmod 755 /data/local/tmp/frida-server"
adb shell "/data/local/tmp/frida-server &"
Step 1 – Static Analysis with the Android Reverse Engineering Skill
The first phase involves extracting the application's structure and identifying precise hook targets using the skill's automation scripts.
Decompiling the APK
Use the decompile.sh script to generate Java sources from the target APK. This script orchestrates jadx or fernflower depending on the file type and outputs a structured source tree:
bash plugins/android-reverse-engineering/skills/android-reverse-engineering/scripts/decompile.sh myapp.apk
The script outputs sources to output/myapp-decompiled/sources/, preserving the package hierarchy. The print_structure function within the script helps navigate large codebases by displaying top-level packages.
Extracting API Calls and Method Signatures
Once decompiled, use find-api-calls.sh to locate HTTP-related methods, hard-coded URLs, and authentication logic. This script detects Retrofit interfaces, OkHttp usage, and WebView JavaScript bridges:
bash plugins/android-reverse-engineering/skills/android-reverse-engineering/scripts/find-api-calls.sh output/myapp-decompiled/sources/ --retrofit
The output provides fully-qualified class names like com.example.app.network.ApiService and exact method signatures such as login(String, String). These identifiers are critical for writing precise Frida hooks.
Step 2 – Preparing Frida for Dynamic Instrumentation
With target methods identified from the static analysis output, configure Frida to attach to the application process. You can target the app by its package name or process ID.
List running processes to verify the target is active:
frida-ps -U
For applications with anti-debugging mechanisms, use the --no-pause flag to prevent Frida from suspending the process during startup. This allows you to hook early initialization routines before anti-tampering checks execute.
Step 3 – Writing and Injecting Frida Hooks
Create a JavaScript file containing your instrumentation logic, referencing the exact class names and method signatures discovered during static analysis.
The following example hooks a Retrofit-style login method identified by find-api-calls.sh:
// hook.js
Java.perform(function () {
// Target class from static analysis output
var ApiService = Java.use('com.example.app.network.ApiService');
// Hook the specific overload matching the signature
ApiService.login.overload('java.lang.String', 'java.lang.String').implementation = function (username, password) {
console.log('[Frida] Hook intercepted login call');
console.log('[Frida] Username: ' + username);
console.log('[Frida] Password: ' + password);
// Invoke original method
var result = this.login(username, password);
console.log('[Frida] Login result: ' + result);
return result; // Modify here if needed
};
});
Launch the instrumentation session:
frida -U -f com.example.app -l hook.js --no-pause
The -U flag specifies USB device connection, -f spawns the application, and -l loads your script. The --no-pause option ensures hooks are active during application startup.
Step 4 – Runtime Observation and Iteration
Once Frida attaches, exercise the application through its UI or automated testing tools. The JavaScript console outputs intercepted arguments and return values in real-time, revealing dynamic behavior that static decompilation cannot capture.
If initial hooks miss critical execution paths, return to the static analysis output. Use the print_structure functionality in decompile.sh to locate alternative classes, then add additional hooks to your hook.js file. This iterative workflow—static discovery followed by dynamic verification—allows you to bypass obfuscation and uncover hidden logic.
Summary
Combining the android-reverse-engineering-skill repository with Frida creates a comprehensive reverse-engineering workflow:
- Static analysis via
scripts/decompile.shandscripts/find-api-calls.shextracts class names, method signatures, and API endpoints from APK files. - Target identification uses the repository's output to pinpoint specific methods for instrumentation, such as authentication or network routines.
- Dynamic instrumentation with Frida attaches to the live application, intercepts method calls using the exact signatures discovered earlier, and logs or modifies runtime behavior.
- Iterative refinement allows you to return to static analysis when hooks miss targets, creating a feedback loop that defeats obfuscation.
Frequently Asked Questions
Do I need to root my Android device to use Frida for dynamic instrumentation?
Not necessarily for all scenarios, but generally yes. Frida-server requires root privileges to attach to most target processes on Android. However, you can use Frida gadget mode or patch the APK to include the Frida library without root access, though this modifies the application package and requires repackaging.
How do I find the exact method signature to use in my Frida hook?
Use the find-api-calls.sh script from the android-reverse-engineering-skill repository to extract fully-qualified class names and method signatures from the decompiled sources. For overloaded methods, use Frida's .overload() method with the specific parameter types (e.g., .overload('java.lang.String', 'java.lang.String')) to target the correct variant.
Can Frida bypass SSL pinning or other anti-debugging mechanisms in Android apps?
Yes, Frida can bypass SSL pinning by hooking the specific methods that validate certificates, such as those in X509TrustManager or OkHttp certificate pinner classes. Use the static analysis output to locate these validation methods, then write Frida hooks that return true or dummy values to bypass checks. The --no-pause flag helps bypass early anti-debugging traps that detect Frida during startup.
What is the difference between static analysis with jadx and dynamic instrumentation with Frida?
Static analysis decompiles the APK into readable Java/Kotlin source code without executing the application, revealing the app's structure, hardcoded strings, and logic flow. Dynamic instrumentation attaches to a running app to observe actual runtime behavior, encrypted network traffic, user input processing, and anti-tampering responses. The android-reverse-engineering-skill repository provides static analysis tools that feed directly into Frida's dynamic instrumentation workflow, creating a complete reverse-engineering solution.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →