/bypassing-root-jailbreak-detection
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
$ npx -y skills add trilwu/secskills --skill bypassing-root-jailbreak-detection --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/bypassing-root-jailbreak-detection
Context preview
The summary Claude sees to decide when to auto-load this skill.
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
SKILL.md
bypassing-root-jailbreak-detection.SKILL.mdname: 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.
| Layer | Signals | Response | | --- | --- | --- | | **Java/managed checks** | `RootBeer`, `File.exists("/system/xbin/su")`, package queries for Magisk | Hook at the Java layer (objection, Frida) | | **Native checks in `.so`** | `stat`/`access`/`fopen` on `su`, `/proc/self/maps` scans | Hook libc, or patch the `.so` | | **Instrumentation detection** | Dies only when Frida is attached; port 27042 probes; thread-name scans | Hide the agent, not the root | | **Hardware attestation** | Play Integrity, SafetyNet, DeviceCheck, App Attest | Cannot be hooked — see below |
# 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.
# 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:
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:
// 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`:
# 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.
| Check | Counter | | --- | --- | | TCP 27042 open, or the D-Bus handshake response | Run `frida-server` on a random port, or use Gadget instead of Server | | `/proc/self/maps` contains `frida-agent`, `gum` | Rename the agent; use a patched build | | Thread names `gmain`, `gum-js-loop`, `pool-frida` | Patched Frida builds rename these | | `/proc/self/task/*/stat` scanning | Same | | Named pipes and `re.frida.server` strings | Patched build | | Periodic re-check after launch | Attach *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
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
- `
Read more
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.
| Layer | Signals | Response | | --- | --- | --- | | **Java/managed checks** | `RootBeer`, `File.exists("/system/xbin/su")`, package queries for Magisk | Hook at the Java layer (objection, Frida) | | **Native checks in `.so`** | `stat`/`access`/`fopen` on `su`, `/proc/self/maps` scans | Hook libc, or patch the `.so` | | **Instrumentation detection** | Dies only when Frida is attached; port 27042 probes; thread-name scans | Hide the agent, not the root | | **Hardware attestation** | Play Integrity, SafetyNet, DeviceCheck, App Attest | Cannot be hooked — see below |
# 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.
# 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:
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:
// 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`:
# 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.
| Check | Counter | | --- | --- | | TCP 27042 open, or the D-Bus handshake response | Run `frida-server` on a random port, or use Gadget instead of Server | | `/proc/self/maps` contains `frida-agent`, `gum` | Rename the agent; use a patched build | | Thread names `gmain`, `gum-js-loop`, `pool-frida` | Patched Frida builds rename these | | `/proc/self/task/*/stat` scanning | Same | | Named pipes and `re.frida.server` strings | Patched build | | Periodic re-check after launch | Attach *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
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
- `
**Security skills for Claude Code that encode the judgment professionals bring, not another wrapper around a scanner.** Offense, defense, and the reverse-engineering and code-audit core both sides share. Every skill is fact-checked against primary sources.

