Bypassing Root Detection Without Breaking the App
Richard · February 14, 2026
Every mobile pentest engagement eventually hits the same wall: the app detects root, throws up a dialog, and force-closes before you’ve done anything interesting. The tempting move is to grab a generic Frida bypass script off GitHub and hope it works. Sometimes it does. When it doesn’t, you need to know why — and copy-pasted scripts don’t teach you that.
Find the checks before you hook anything
Before touching Frida, decompile the APK and search for the usual fingerprints:
- References to
su,busybox,Superuser.apk,Magisk RootBeeror similar library importsFile.exists()calls against paths like/system/xbin/su- Build tag checks against
test-keys
Grepping the decompiled source for these tells you how many independent checks you’re dealing with — which matters, because a script built for an app with one check will silently fail against an app that has three different checks each triggering independently.
Hook at the right layer
Rather than trying to patch every individual check, it’s usually faster to hook the common low-level primitives every check ultimately routes through:
Java.perform(() => {
const File = Java.use('java.io.File');
File.exists.implementation = function () {
const path = this.getAbsolutePath();
if (path.includes('su') || path.includes('magisk')) {
return false;
}
return this.exists();
};
});
This catches most naive filesystem-based checks in one hook instead of chasing down every call site. But it won’t catch checks done over JNI in a native library, which is where a lot of the more defensive apps have moved their root detection specifically to make Java-layer hooking useless.
When the check is native
If strings on lib/arm64-v8a/*.so turns up nothing useful, the check is
likely obfuscated or computed rather than a literal string match. At that
point static analysis in Ghidra to locate the comparison logic, followed by
a targeted Frida hook on the specific native function, is the only reliable
path — there’s no generic script that reaches this.
The pattern to take away: generic bypass scripts solve the easy 80% of apps. The interesting engagements are the other 20%, and that’s where actually understanding what the checks are doing pays off.