Bypassing Android Root Checks with Smali Patching — No Frida Required
A practical Android reverse-engineering guide based on static APK patching: finding root checks, modifying smali code, rebuilding the APK, and verifying the result in a lab environment.
This guide is based on my video about bypassing Android root checks using static Smali patching.
The idea is simple: instead of using Frida at runtime, we modify the APK itself. We decompile the app, find where it checks for root, patch the logic, rebuild the APK, sign it, and run it again.
This is useful for learning how Android apps protect themselves and how static analysis works in practice.
Use this only in a lab, on your own apps, intentionally vulnerable apps, or apps where you have permission to test. Do not patch or redistribute third-party apps.
What We Are Doing
Many Android apps try to detect root by checking things like:
subinary- Magisk-related files
- suspicious system paths
- root management packages
- dangerous system properties
- writable system directories
- custom native checks
In this guide, we focus on the static approach:
- Decompile the APK.
- Search through smali code.
- Find the root detection method.
- Change the return value.
- Rebuild and sign the APK.
- Install and test it.
Tools Needed
Install the basic tooling first:
sudo apt update
sudo apt install apktool jadx zipalign apksigner adb
You can also use Android Studio if you prefer a GUI for device management and logs.
Useful tools:
apktool— decompile and rebuild APKsjadx— read Java-like decompiled codeadb— install APK and read logsapksigner— sign rebuilt APKszipalign— align APK before signing
Step 1 — Decompile the APK
Create a working directory and decompile the APK:
mkdir android-root-check-lab
cd android-root-check-lab
apktool d app.apk -o app_src
After this, you will see files like:
app_src/
├── AndroidManifest.xml
├── smali/
├── smali_classes2/
├── res/
└── apktool.yml
The interesting part is usually inside smali/ or smali_classes*/.
Step 2 — Search for Root Detection Logic
Start with simple keyword searches:
grep -Rni "root" app_src/
grep -Rni "su" app_src/
grep -Rni "magisk" app_src/
grep -Rni "isDeviceRooted" app_src/
Common suspicious names:
isRooted
isDeviceRooted
checkRoot
detectRoot
checkSuExists
checkForBinary
checkForDangerousProps
If the app uses RootBeer or similar libraries, you may see method names that make the logic obvious.
Step 3 — Use JADX to Understand the Code
Open the APK in JADX:
jadx-gui app.apk
Look for classes related to security, root checks, startup logic, or login screens.
The Java-like code is easier to read than smali, but the actual patch will be done in smali.
Example Java-like logic:
public boolean isDeviceRooted() {
if (checkSuBinary()) {
return true;
}
if (checkMagisk()) {
return true;
}
return false;
}
In smali, this may become a method returning Z, which means boolean.
Step 4 — Understand Boolean Return Values in Smali
In smali:
.method public isDeviceRooted()Z
The Z means the method returns a boolean.
Boolean values are usually represented like this:
const/4 v0, 0x1
return v0
That means:
return true
And this:
const/4 v0, 0x0
return v0
Means:
return false
So if we find a method that returns whether the device is rooted, we can patch it to always return false.
Step 5 — Patch the Root Check
Example original method:
.method public isDeviceRooted()Z
.locals 1
invoke-static {}, Lcom/example/security/RootChecker;->checkSuBinary()Z
move-result v0
if-nez v0, :rooted
invoke-static {}, Lcom/example/security/RootChecker;->checkMagisk()Z
move-result v0
if-nez v0, :rooted
const/4 v0, 0x0
return v0
:rooted
const/4 v0, 0x1
return v0
.end method
Patched version:
.method public isDeviceRooted()Z
.locals 1
const/4 v0, 0x0
return v0
.end method
Now the method always returns false.
The app will think the device is not rooted.
Step 6 — Another Common Patch: Flip a Conditional Jump
Sometimes it is easier to change the condition instead of rewriting the whole method.
Example:
if-nez v0, :root_detected
This means:
if v0 is not zero, jump to root_detected
You can sometimes change it to:
if-eqz v0, :root_detected
But be careful. Flipping conditions without understanding the flow can break the app.
For beginners, patching the root-check method to return false is usually cleaner.
Step 7 — Rebuild the APK
After patching the smali file, rebuild the APK:
apktool b app_src -o app_patched_unsigned.apk
If you get an error, read the line number carefully. Common issues:
- broken smali syntax
- wrong register count
- missing label
- invalid method structure
- accidentally deleting
.end method
Step 8 — Align the APK
Before signing, align the APK:
zipalign -p -f 4 app_patched_unsigned.apk app_patched_aligned.apk
Step 9 — Sign the APK
Generate a debug keystore if you do not already have one:
keytool -genkeypair \
-v \
-keystore debug.keystore \
-alias androiddebugkey \
-keyalg RSA \
-keysize 2048 \
-validity 10000 \
-storepass android \
-keypass android
Sign the APK:
apksigner sign \
--ks debug.keystore \
--ks-key-alias androiddebugkey \
--ks-pass pass:android \
--key-pass pass:android \
--out app_patched.apk \
app_patched_aligned.apk
Verify the signature:
apksigner verify --verbose app_patched.apk
Step 10 — Install and Test
Uninstall the original app first if needed:
adb uninstall com.example.app
Install the patched APK:
adb install app_patched.apk
Run the app and check whether the root warning is gone.
You can also watch logs:
adb logcat | grep -i root
Or:
adb logcat | grep -i security
Common Problems
The App Does Not Install
Possible causes:
- original app is still installed with a different signature
- APK was not signed correctly
- APK was not aligned
- Android version blocks old SDK behavior
Try:
adb uninstall com.example.app
adb install app_patched.apk
The App Crashes After Launch
Possible causes:
- smali patch broke the method
- register count is wrong
- app has signature verification
- app checks APK integrity
- app has native root detection too
Check logs:
adb logcat | grep -i AndroidRuntime
Root Detection Still Works
Possible causes:
- there are multiple root checks
- root detection is inside native
.solibrary - app uses remote config
- app verifies app integrity
- root check happens before the method you patched
- detection result is cached
Search again:
grep -Rni "root" app_src/
grep -Rni "su" app_src/
grep -Rni "magisk" app_src/
grep -Rni "jail" app_src/
grep -Rni "tamper" app_src/
Smali Cheat Sheet
Boolean return:
const/4 v0, 0x0
return v0
Means:
return false
Boolean true:
const/4 v0, 0x1
return v0
Means:
return true
Method returning boolean:
.method public someMethod()Z
Method returning void:
.method public someMethod()V
Method returning string:
.method public someMethod()Ljava/lang/String;
Static Patching vs Frida
Frida is dynamic. It changes app behavior at runtime.
Smali patching is static. It changes the APK itself.
Frida is faster for experiments, but smali patching is great for understanding how the app works internally.
Frida approach
Good for:
- quick testing
- runtime hooks
- debugging behavior
- bypassing checks without rebuilding APK
Bad for:
- apps that detect Frida
- setups where runtime instrumentation is unstable
- beginners who need to understand the app structure
Smali patching approach
Good for:
- learning APK internals
- permanent lab patches
- understanding real control flow
- bypassing checks without running Frida
Bad for:
- apps with integrity checks
- apps with heavy obfuscation
- apps with native detection
- production apps with server-side validation
Final Thoughts
Root detection is not real security by itself. It is only one layer.
A serious Android security model should also include:
- server-side validation
- certificate pinning where appropriate
- secure storage
- proper session handling
- anti-tampering checks
- runtime integrity checks
- minimal trust in the client
But from a reverse-engineering perspective, root checks are a great first target. They are easy to understand, easy to test, and they teach the basics of smali patching very well.
If you are learning Android security, this is one of the best exercises to start with: simple enough to follow, but close enough to real-world mobile app protection techniques.
Video Topic
This article is based on the video:
How to Bypass Android Root Checks via Smali Patching — No Frida. Part 2
YouTube: https://youtu.be/WC_FdEfaFug