<< All versions

Skill v1.0.0

currentAutomated scan100/100
trilwu/secskills/bypassing-root-jailbreak-detection
──Details
PublishedSeptember 29, 2026 at 05:58 PM
Content Hashsha256:81ec6e79e45796dd...
Git SHAca53957bcd8e
──Files
Files (1 file, 9.3 KB)
SKILL.md9.3 KBactive
SKILL.md · 211 lines · 9.3 KB

version: "1.0.0" name: bypassing-root-jailbreak-detection description: Defeat root, jailbreak, emulator, debugger, and Frida detection in mobile apps using Magisk DenyList, Zygisk modules, objection, and targeted Frida hooks, and understand where hardware-backed attestation like Play Integrity cannot be hooked. Use when an app exits, shows "device not secure", or silently fails on a rooted device or emulator, or when Frida attaches and the app immediately dies. verified: 2026-07-27


Bypassing Root and Jailbreak Detection

Detection is almost never one check. It is a dozen cheap checks scattered across the app, plus — increasingly — one hardware-backed attestation that no hook can touch. Hooking checks one at a time is whack-a-mole; the work is finding the layer the app actually depends on.

Use only against apps you are authorized to test.

When to Use

  • The app exits on launch, shows "rooted device detected", or degrades silently
  • The app works on a stock device but not on your test device or emulator
  • Frida attaches and the process dies immediately, or frida-ps shows nothing
  • objection fails to explore, or hooks stop firing after a few seconds
  • You need a stable instrumentation environment before any other testing

When NOT to Use

  • TLS interception failures — use bypassing-mobile-pinning; a proxy error

is a different problem, though detection can masquerade as one

  • The wider assessment — use testing-mobile-applications
  • Framework-specific reversing — use the relevant reversing-* skill
  • Defeating DRM or licensing to pirate an app — out of scope

Identify the Layer First

Detection lives at four layers, and each needs a different response. Working out which one is firing saves the most time.

LayerSignalsResponse
Java/managed checksRootBeer, File.exists("/system/xbin/su"), package queries for MagiskHook at the Java layer (objection, Frida)
Native checks in `.so`stat/access/fopen on su, /proc/self/maps scansHook libc, or patch the .so
Instrumentation detectionDies only when Frida is attached; port 27042 probes; thread-name scansHide the agent, not the root
Hardware attestationPlay Integrity, SafetyNet, DeviceCheck, App AttestCannot be hooked — see below
bash
# What does the app reference? Decompile and look before hooking.
apktool d target.apk -o out
rg -n 'RootBeer|isRooted|su\b|magisk|superuser|test-keys|/system/xbin|busybox|xposed|frida' -i out/smali* out/res 2>/dev/null | head -30
rg -n 'SafetyNet|PlayIntegrity|IntegrityManager|attest|DeviceCheck' -i out/ | head
# Native side
unzip -j target.apk 'lib/arm64-v8a/*' -d libs
rg -a -o 'su|/system/bin/su|magisk|frida|gum-js-loop|gmain' libs/*.so | sort -u | head -20

The strings you find in the native libraries tell you what the app looks for, which is far more efficient than hooking blind and waiting for it to die.

Android

Start with environment hiding, not hooking. A well-hidden root defeats most detection without a single hook, and it does not break when the app updates.

bash
# Magisk: DenyList the target so the root is invisible to it
# Settings → Zygisk ON, Enforce DenyList ON, select the target package
# Shamiko (Zygisk module) hides more thoroughly than DenyList alone
# Play Integrity Fix (PIF) module for the attestation layer — see limits below
# Verify what the app can see
adb shell "pm list packages | grep -i magisk" # should return nothing to the app

Then hook what remains:

bash
objection -g com.target.app explore
# then: android root disable
frida -U -f com.target.app -l anti-root-bypass.js --no-pause

Common Java hook points, in the order they usually appear:

javascript
// File existence checks — the single most common family
Java.use('java.io.File').exists.implementation = function () {
const p = this.getAbsolutePath();
if (/su$|magisk|superuser|busybox|xposed/i.test(p)) return false;
return this.exists();
};
// Runtime.exec("su") and ProcessBuilder
// Build.TAGS containing "test-keys"
// PackageManager.getPackageInfo for known root packages
// System properties: ro.debuggable, ro.secure, ro.build.selinux

Native checks need native hooks. When Java hooks are in place and the app still exits, the check is in a .so:

bash
# See which syscall is finding the evidence
frida-trace -U -f com.target.app -i 'stat*' -i 'access' -i 'fopen' -i 'open'
# then edit the generated handlers to lie about the paths it probes

Frida Detection Is a Separate Problem

If the app runs fine rooted but dies the moment you attach, you are fighting instrumentation detection, and hiding root will not help.

CheckCounter
TCP 27042 open, or the D-Bus handshake responseRun frida-server on a random port, or use Gadget instead of Server
/proc/self/maps contains frida-agent, gumRename the agent; use a patched build
Thread names gmain, gum-js-loop, pool-fridaPatched Frida builds rename these
/proc/self/task/*/stat scanningSame
Named pipes and re.frida.server stringsPatched build
Periodic re-check after launchAttach after the check window, or hook the timer

The practical answer is a patched Frida (community builds exist specifically for this) plus Gadget injection rather than a listening server. If detection still wins, fall back to static analysis plus targeted APK patching — you lose interactivity but keep progress.

iOS

bash
objection -g com.target.app explore
# then: ios jailbreak disable
# Tweak-based, system-wide: Liberty Lite, A-Bypass, Shadow (rootless jailbreaks)

What iOS apps check, and what to hide:

  • Existence of /Applications/Cydia.app, /bin/bash, /usr/sbin/sshd,

/etc/apt, /private/var/lib/apt

  • Writability outside the sandbox (fopen("/private/jailbreak.txt", "w"))
  • fork() succeeding, which it should not in a sandboxed app
  • dyld image list containing MobileSubstrate / substitute
  • URL scheme cydia:// being openable
  • NSFileManager checks, which are easier to hook than raw stat

Hook stat, access, fopen, getenv("DYLD_INSERT_LIBRARIES"), and _dyld_get_image_name for the native layer; hook NSFileManager methods for the Objective-C layer. On non-jailbroken devices, repackage with the Frida gadget (objection patchipa) — and expect that to trip attestation.

What You Cannot Hook

Hardware-backed attestation is the hard boundary. Play Integrity's MEETS_STRONG_INTEGRITY, key attestation via the TEE/StrongBox, and Apple's App Attest are signed by hardware keys and verified on the vendor's servers. A client-side hook can change what the app reads, but it cannot forge a signature the server validates.

What this means in practice:

  • Magisk plus a Play Integrity Fix module can often reach BASIC and

DEVICE integrity. STRONG requires an unmodified bootloader.

  • If the app fails closed on strong integrity, the honest options are a

non-rooted device with a repackaged app (which itself fails signature checks), a device with a stock ROM plus network-layer testing only, or agreeing an attestation exemption with the client for the test window.

  • Ask for the exemption. A test build with attestation disabled is a normal

engagement request and is far cheaper than days spent losing to a TEE.

Say this in the report rather than quietly reducing scope: "dynamic instrumentation was not possible against production builds due to hardware attestation; testing covered X and not Y" is a finding about your coverage, and hiding it is worse than the limitation.

Detection Quality Is Itself a Finding

While bypassing, record how good the detection was — clients ask, and it belongs in the report:

  • Does it fail closed (exit) or fail open (log and continue)?
  • Is the check result sent to the server, or trusted locally? Local-only checks

are advisory at best.

  • Is it one central function (trivially hooked) or distributed and re-checked?
  • Is hardware attestation used, or only filesystem heuristics?

An app whose entire root defense is File.exists("/system/xbin/su") deserves a low-severity note; one that uses server-verified attestation deserves credit.

Rationalizations to Reject

  • "objection's bypass didn't work, the detection is too strong." It covers

the common Java checks. Look at the native layer next.

  • "I hid root, so it should work." If it dies only under Frida, you are

fighting instrumentation detection, not root detection.

  • "Play Integrity can be bypassed with Frida." Not the hardware-backed

verdicts. Hooks change what the app reads, not what the TEE signs.

  • "I'll patch every check I find." Distributed checks re-run. Find the

central decision point, or hide the environment instead.

  • "Root detection is a vulnerability." It is a control, and a weak one. Its

absence is a low-severity note, not a headline finding.

  • "I couldn't instrument it, so there's nothing to report." Report the

coverage limitation explicitly.

References

  • testing-mobile-applications — the assessment this unblocks
  • bypassing-mobile-pinning — the other reason a mobile app "just fails"
  • analyzing-binaries — patching native detection routines
  • reporting-security-findings — how to state a coverage limitation honestly
  • Magisk + Zygisk, Shamiko, objection, Frida (and patched builds), Liberty Lite, Shadow
All versions