YinkoShield

Knowledge Center / Mobile runtime attacks / mobile runtime attacks · 2026·02

Hook-detection bypass and counter-detection

Hook-detection has been an arms race for as long as the toolchains have existed. Each technique an app uses to detect Frida, Xposed, or method-table rewrites has documented counter-techniques in the security-research community; each counter-technique invites a follow-on detection. The ladder rarely closes. The substrate's position is structurally different: sign what was observed and let the operator's verifier reason about the result, rather than depend on any one detection technique winning the local race.

[ hook detection — the arms race ] detect: scan /proc/self/maps for frida-agent.so simple readlines, fast, easy to deploy bypass: rename agent .so to look-alike path also: hook open() to filter the maps file detect: read /proc/self/maps via direct syscall avoids libc, sees the unfiltered list bypass: hook the SVC instruction at libc level filter /proc/self/maps content in SVC handler detect: prologue-hash check on critical methods sees ART method-table rewrites directly bypass: hook the prologue-hash check itself return expected-hash regardless of real bytes detect: remote attestation of the prologue hashes sign + send to a backend that has the truth bypass: hook the signing call · attack the key chain requires more sophistication; not closed // the substrate's position sign what was observed — whether or not detection succeeded — and let the verifier reason offline
Detection and bypass alternate. Each rung's existence makes the next rung more expensive but rarely closes the ladder. The substrate's posture is to sign the observation, not to depend on the detection winning.

1. The detection rungs

Real-world hook detection is not a single check; it is a stack of complementary checks at different layers, each more expensive to bypass than the last:

  • Maps scan. Read /proc/self/maps, look for known agent names (frida-agent, LSPosed module paths). Cheap, defeated by renaming and by hooking open(2) to filter the file.
  • Syscall-level scan. Read the maps file via a direct syscall, bypassing libc. Defeated by SVC-instruction hooks installed by sophisticated agents.
  • Prologue-hash check. Read the first instructions of critical methods in memory, hash them, compare against the hash from the dex / shared object. Defeated by hooking the hash-check method itself.
  • Remote attestation of prologue hashes. Sign the hashes on-device and forward to a backend that holds the truth. Harder to defeat — requires hooking the signing call and attacking the key chain.

Each technique narrows the surface; none closes it.

2. The bypass rungs

OWASP MASTG [3] documents this dynamic in detail under the Resilience Against Reverse Engineering sections. Frida’s Stalker [1] is the canonical code-tracing engine the framework exposes; the broader anti-anti-debug practice lives across the Frida CodeShare community (separate from Stalker proper) and in published research write-ups. LSPosed’s documentation [2] describes what a module can and cannot hide from a careful host (LSPosed’s GitHub wiki is intermittently maintained; the Riru / Zygisk integration paths are documented in the repository itself). The ecosystem is explicit about this being an evolving game.

The point is structural: any detection technique that runs inside a process the attacker has compromised can, in principle, be hooked. The detection’s truth has to escape the compromised process to be reliable.

3. Which checkpoints it bypasses

Hook detection bypass does not bypass any standard checkpoint on its own — it bypasses the app’s own detection logic. But it composes with the other attacks in this catalogue: a successful bypass means library injection, accessibility-service abuse, IME compromise, parameter tampering, and memory manipulation can all run with the host app’s detection logic silenced.

4. Which signals make it observable

runtime.environment. The Trusted Runtime Primitive runs multiple complementary detection probes — at different layers, with different expected results — and signs the full set of observations into the Evidence Token. Even when individual probes are bypassed, divergence between probes (e.g. libc-level maps look clean but kernel-level maps via direct syscall show agent libraries) is itself a signal.

The substrate also signs probes whose result is clean on a healthy device but suspicious under a known bypass — the absence of expected signals is informative.

5. Evidence Token shape when observed

The following example is illustrative; field names, type values, and schema are defined in YEI-001 §4 (available through the spec-access process).

{
  "ev": [{
    "ts":   "2026-06-15T10:23:14Z",
    "class": "runtime.environment",
    "type":  "hook_probe.suite_result",
    "data": {
      "maps_libc":           "clean",
      "maps_direct_syscall": "frida_agent_present",
      "method_prologue":     "drift_detected",
      "remote_attestation":  "signed_ok",
      "divergence":          true
    }
  }]
}

The divergence: true is the load-bearing field: probes that should agree disagree. Execution Evidence Infrastructure (EEI) — the device-identity infrastructure layer for banking and payments — signs the multi-probe set so the operator’s verifier reads them together, with hardware-key-bound signing as the substrate that prevents the same compromise from also forging the divergence record.

6. Cross-references

7. External references

[1] Frida. Stalker — code-tracing engine (canonical Frida documentation). frida.re/docs/stalker. Cited 2026-02-01.

[2] LSPosed. Module API (README + source). github.com/LSPosed/LSPosed. Cited 2026-02-01.

[3] OWASP MASTG. Resilience Against Reverse Engineering. mas.owasp.org/MASTG/Android/0x05j-Testing-Resiliency-Against-Reverse-Engineering/. Cited 2026-02-01.