skip to main content
hacking.communityplay in the sandbox.
← news & articles
tutorial ai-assistedreviewed by Prakash Shinde

Your First Frida Hook: Bypass Root Detection in 8 Lines

For mobile security beginners who want to learn dynamic instrumentation by writing a simple Frida script to hook and modify Android app behavior at runtime.

Prakash Shinde·8/29/2026·30 views·
Your First Frida Hook: Bypass Root Detection in 8 Lines — hacking.community
0

What You'll Learn

Frida is a dynamic instrumentation toolkit that lets you inject JavaScript into native apps to observe and modify their behavior. We'll hook a simple root detection function and force it to always return "not rooted" — a perfect first Frida script that teaches the fundamentals.

Prerequisites

  • Android device or emulator (rooted preferred, but not required)
  • ADB installed: sudo apt install adb or brew install android-platform-tools
  • Python 3.7+
  • A test app with root detection (we'll use a sample APK)

Step 1: Install Frida

Install Frida tools on your computer:

bash
pip3 install frida-tools

Verify installation:

bash
frida --version

You should see something like 16.1.4.

Step 2: Install Frida Server on Android

Download the appropriate Frida server for your device architecture:

bash
# Check your device's architecture adb shell getprop ro.product.cpu.abi # Output example: arm64-v8a # Download frida-server (replace version and arch as needed) wget https://github.com/frida/frida/releases/download/16.1.4/frida-server-16.1.4-android-arm64.xz unxz frida-server-16.1.4-android-arm64.xz

Push to device and start:

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

Verify it's running:

bash
frida-ps -U

You should see a list of running processes on your device.

Step 3: Find the Target Function

Install a test app with root detection. For this tutorial, we'll use a generic pattern. Most root detection checks look like this in Java:

java
public boolean isRooted() { // Checks for su binary, Magisk, etc. return true; // Device is rooted }

We need to find this function. Use jadx-gui or apktool to decompile the APK and search for strings like "su", "rooted", or "root".

Let's say we found: com.example.app.SecurityCheck.isRooted()

Step 4: Write Your First Hook

Create a file called bypass-root.js:

javascript
Java.perform(function() { console.log("[*] Starting root detection bypass..."); var SecurityCheck = Java.use("com.example.app.SecurityCheck"); SecurityCheck.isRooted.implementation = function() { console.log("[*] isRooted() called - returning false"); return false; }; console.log("[*] Hook installed successfully!"); });

What each line does:

  • Java.perform(): Waits for the Java VM to be ready
  • Java.use(): Gets a reference to the target class
  • .implementation: Replaces the original function
  • return false: Our modified return value (not rooted)

Step 5: Run the Hook

Launch the app with Frida:

bash
frida -U -l bypass-root.js -f com.example.app --no-pause

Flags explained:

  • -U: Use USB device
  • -l: Load script file
  • -f: Spawn the app
  • --no-pause: Don't pause at startup

You should see:

code
[*] Starting root detection bypass... [*] Hook installed successfully!

When you trigger the root check in the app, you'll see:

[*] isRooted() called - returning false

The app now thinks it's running on a non-rooted device!

Step 6: Hook Apps Already Running

If the app is already open:

bash
# List running apps frida-ps -U | grep example # Attach to running process frida -U -l bypass-root.js com.example.app

Step 7: Inspect Arguments and Return Values

Let's enhance our hook to see what the original function would have returned:

javascript
Java.perform(function() { var SecurityCheck = Java.use("com.example.app.SecurityCheck"); SecurityCheck.isRooted.implementation = function() { var originalResult = this.isRooted.call(this); console.log("[*] Original result: " + originalResult); console.log("[*] Returning: false"); return false; }; });

Now you can see both the real and spoofed values.

Step 8: Handle Overloaded Methods

If isRooted() has multiple versions (overloads):

javascript
Java.perform(function() { var SecurityCheck = Java.use("com.example.app.SecurityCheck"); // Hook the version that takes no arguments SecurityCheck.isRooted.overload().implementation = function() { return false; }; // Hook the version that takes a boolean SecurityCheck.isRooted.overload('boolean').implementation = function(checkDeep) { console.log("[*] checkDeep parameter: " + checkDeep); return false; }; });

Where to Go Next

  • Hook multiple functions to bypass certificate pinning
  • Use Java.choose() to find and modify existing class instances
  • Intercept native (C/C++) functions with Interceptor.attach()
  • Write Frida scripts in Python for automation
  • Explore frida-trace for automatic API tracing
  • Try objection, a higher-level framework built on Frida

You've just written your first dynamic instrumentation! This same pattern works for bypassing SSL pinning, defeating anti-debugging, and modifying any app behavior. The key is finding the right class and method, then replacing its implementation with your own logic.

Comments (0)

Sign in to join the discussion.

// go deeper

// install app

Install hacking.community for fast access, offline reading, and push notifications. No app store needed.