Signal catalogue¶
Every INTEL_XXXX code the SDK can emit. The wire carries only the code;
this page is what each one means and what it unlocks for whoever writes
backend policy. Source of truth:
tools/registry/signals-registry.json.
Attestation — hardware identity & verified boot¶
Hardware identity and verified boot: whether the device is what it claims to be.
| Code | detector | kind | Sev | Meaning | Reach — what it unlocks |
|---|---|---|---|---|---|
INTEL_0001 |
attestation | attestation_critical |
CRITICAL | TEE key-attestation cross-checks failed (keybox reuse / device-property honeypot / revoked keybox); the device's hardware-backed identity is untrustworthy. | Forged hardware identity — spoof Play Integrity DEVICE/STRONG, impersonate a genuine device, defeat hardware-key-bound checks. |
INTEL_0015 |
attestation | token_emitted_unsigned |
CRITICAL | No signing key was available at all — neither the attested session key nor a plain Keystore key — so the token carries an empty SIG binding. Its contents are unauthenticated and must never read as evidence of a clean device. | Unauthenticated token — anyone able to encrypt to the server key could have minted it naming any session. Its contents must never read as evidence of a clean device. |
INTEL_0016 |
attestation | keybox_cross_level_reuse |
CRITICAL | The StrongBox and TEE attestation chains were signed by the SAME batch key. Genuine hardware provisions physically-separate, distinct batch keys per security level; a single leaked keybox can only sign with one key, so identical batch keys across levels prove keybox injection. Live-confirmed: spoofed rig reused one TEE keybox for both levels (identical batch pubkey) while a genuine StrongBox device presented distinct O=StrongBox / O=TEE batch keys. | Injected leaked keybox — spoof hardware attestation end-to-end, defeat Play Integrity STRONG. |
INTEL_0019 |
attestation | patch_level_self_report_mismatch |
HIGH | Build.VERSION.SECURITY_PATCH, truncated to YYYY-MM, does not match the TEE-attested osPatchLevel. Both are the FRAMEWORK patch, which is the only apples-to-apples pair: vendorPatchLevel and bootPatchLevel are the SoC and bootloader patches and legitimately diverge on non-Pixel OEMs. A prop spoofer that fakes a current patch level to look healthy trips this, in the same family as INTEL_0055. Fails open: a missing or unparseable value on either side emits nothing. | Prop spoofer faking a current patch to look healthy — same family as INTEL_0055. |
INTEL_0023 |
attestation | scan_without_session |
CRITICAL | scan() ran with no session id prepared: setSession() was never called, failed, or named a different session. Nothing binds this scan to a session, so the token is degraded rather than suppressed. | Unbound token — no session binding at all, so the result cannot be attributed to a login and is replayable. Also fires on an integration that simply skipped setSession, so rule out a wiring fault before reading it as an attack. |
INTEL_0030 |
attestation | session_attestation_unavailable |
CRITICAL | setSession() could not produce a hardware-attested key — the TEE/StrongBox keygen failed or was hooked — so the scan carries no attestation chain and cannot be bound to the session. The token is emitted anyway, degraded, rather than suppressed. | Unbound token — nothing ties this scan to a session or to hardware, so it is replayable against another session. A hook engine that breaks keygen produces exactly this, which is why it is reported rather than met with silence. |
INTEL_0037 |
attestation | app_not_licensed |
HIGH | The self-reported and attested app identities agree, but the signing-certificate digest is not in the licensed set for this deployment. This is a LICENSING finding, not a tampering one: the app is what it claims to be, it is simply not entitled to enroll. Kept separate from INTEL_0046 so a stale licence table cannot be mistaken for an integrity compromise. | Licensing, not tampering — kept separate so a stale licence table can't read as a compromise. |
INTEL_0038 |
attestation | licence_rejected_at_scan |
HIGH | The licence blob parsed but was rejected at scan time (expired, or bound to a different package). Has a benign cause — a genuinely expired blob — as well as a hostile one, so it grades below the other degradation codes. | Licensing, or a rehosted SDK — an expired blob is benign; one bound to another package means this SDK is running in an app it was not issued to. Grades below the other degradation codes because the benign cause is common. |
INTEL_0045 |
attestation | strongbox_chain_unavailable |
VERY_LOW | No StrongBox attestation chain was produced even though StrongBox appears to be available, so the cross-level keybox-reuse defense (INTEL_0016) could not run (fail-closed). Two routes reach this: (a) the leaf claims StrongBox assurance but no StrongBox cross-level chain was produced; (b) the device reports StrongBox hardware (FEATURE_STRONGBOX_KEYSTORE) yet enrollment fell back to TEE. Route (b) applies ONLY to models absent from the StrongBox capability list — a capable model presenting TEE-only is the CRITICAL INTEL_0039 downgrade instead, regardless of what the device reports, because that self-report is app-visible and hookable. Lower confidence than INTEL_0016: a transient StrongBox attestation failure on a GENUINE device causes both routes, so this is a candidate for observe-only / retry rather than a hard block. | Cross-level keybox-reuse check (INTEL_0016) could not run — possible attestation-downgrade evasion (also fires transiently on genuine HW). |
INTEL_0046 |
attestation | app_identity_mismatch |
CRITICAL | The scan's self-reported package name or signing-certificate digest does not match the attestationApplicationId (tag 709) recorded from the hardware attestation at bootstrap. The self-report is app-visible and trivially patchable; the attested value is written by the platform keystore and signed over by the TEE. A disagreement means the running code is not the code the attested key was issued to - repackaging, a cloned or rehosted APK, or a patched core reporting a licensed identity it does not have. The self-report alone proves nothing: this signal is the CROSS-CHECK, and only the disagreement is evidence. Trustworthy exactly when the boot state is, since tag 709 lives in the softwareEnforced list. | Repackaged or rehosted APK — the running code is not what the attested key was issued to. |
INTEL_0050 |
attestation | security_patch_stale |
MEDIUM | The oldest of the TEE-attested osPatchLevel, vendorPatchLevel and bootPatchLevel is older than the backend's policy window (default 365 days), modelled on the recent-security-update requirement of Play Integrity's MEETS_STRONG_INTEGRITY. The threshold lives on the BACKEND, not the device: a device-side constant would be frozen at build time, would itself go stale, and could be patched out. Evaluated against the OLDEST of the three because a current framework patch on a two-year-old bootloader is still exposed. Note leaked keyboxes tend to originate from older handsets and the source handset's patch level rides along in the replayed certificate, so this partially correlates with INTEL_0016. | Unpatched device — known CVEs. Backend-computed, so the window retunes without an app release. |
INTEL_0055 |
attestation | verified_boot_prop_spoof |
CRITICAL | The device self-reports a clean, locked boot (ro.boot.verifiedbootstate=green with flash.locked=1 or vbmeta.device_state=locked) while its hardware attestation RootOfTrust says otherwise — a prop-spoofing Play-Integrity-Fix (e.g. IntegrityBox/TrickyStore) forcing the boot-state props while the TEE reports the truth. | Verified-boot / Play Integrity spoofing — a rooted device masquerades as a locked, uncompromised one. |
INTEL_0056 |
attestation | software_attested_environment |
CRITICAL | The attestation's KeyDescription explicitly reports securityLevel=Software(0): the key was generated by the AOSP software keystore, not a TEE or StrongBox, so this environment has NO hardware root of trust. Emulators (AVD, Genymotion, BlueStacks, cloud farms) and devices without a hardware keystore land here. Unlike environment probes — build properties, sensors, telephony, graphics libraries — this cannot be neutralised by an anti-emulation layer: evading it requires possessing a Google-signed hardware attestation key, i.e. actually being real hardware. Fires ONLY on an explicitly parsed securityLevel of 0; a missing or unparseable level grades to Assurance.SOFTWARE for the integrity gate but does NOT raise this signal, so the label never states more than the attestation proved. Note the precise claim is 'no hardware root of trust', not 'is an emulator' — a genuine device with a broken or non-Google keystore also lands here. | Emulator / software keystore — no TEE at all. |
Runtime instrumentation — hooks, debuggers, injected code¶
Hooks, debuggers and injected code: whether this process is being manipulated as it runs.
| Code | detector | kind | Sev | Meaning | Reach — what it unlocks |
|---|---|---|---|---|---|
INTEL_0000 |
dex | dex_foreign_loader |
HIGH | A dex was loaded from memory by a class loader whose parent chain does not include the app's own loader, so the app's classes are invisible to it. A legitimate dynamic-feature or DI loader is parented into the app loader precisely so its code can call back into the app; code that cannot see the app it was loaded into is not a feature module. | Injected code running in-process — an agent loaded its own classes without going through the app's loader, and can run arbitrary Java and reach whatever reflection reaches, while staying outside the app's class graph. |
INTEL_0002 |
environment | frida_server_port |
CRITICAL | A frida-server listening port was found. | Dynamic instrumentation — hook anything in the process, full code injection. |
INTEL_0003 |
environment | libc_inline_hook |
CRITICAL | A hot libc function's prologue is overwritten with a branch into injected foreign code (directly into a foreign .so, or via an anon trampoline that references a foreign module) — an inline hook (Dobby/ShadowHook/bytehook/whale). Unlike INTEL_0031 (GOT/function-pointer hijack), an inline hook leaves the GOT intact and patches the function body, so the pointer scan cannot see it; this decodes the first instruction of a fixed hot-set (openat/access/__system_property_get/ioctl/ptrace/fork/…) and flags one only when it is an unconditional branch (direct B, or LDR x16/x17 + BR absolute trampoline). False-positive-safe via the INTEL_0031 discipline: the branch target must resolve to injected code OUTSIDE the legit roots (a direct foreign .so, or an anon trampoline that references one), so a legitimately app-bundled inline hooker — whose trampoline routes to its own /data/app .so — is NOT flagged; a normal libc prologue (never an unconditional branch) and an intra-legit ifunc/tail branch are also ignored. Enriches with the hooked symbol and, via the anon-trampoline hop, the hooking module. | libc interception — hide root and lie to the app about files/properties/syscalls. |
INTEL_0004 |
native | libart_text_patched |
CRITICAL | libart.so's executable segment differs from the pristine on-disk file, i.e. code inside the ART runtime was rewritten after load. This is where Frida-Java's implementation= hook lands when the target method is already native: it patches ART's dispatch trampolines (art_quick_resolution_trampoline / art_quick_generic_jni_trampoline / art_quick_to_interpreter_bridge) and leaves the ArtMethod untouched, so the ART method registry cannot see it. Symbol-free and version-independent (bytes vs file; the art_quick_* stubs are hidden and absent from .dynsym, so no symbol-based check can reach them). The on-disk read uses raw syscalls, so a libc hook cannot serve a clean copy. CRITICAL requires an absolute-jump stub branching outside libart; any other drift is reported HIGH. |
Method interception no ART-level check can see — the hook lives in the runtime's dispatch path rather than the method registry, so INTEL_0012 cannot reach it. The stubs are hidden and absent from .dynsym, so no symbol-based check can either. |
INTEL_0007 |
environment | debugger_attached |
CRITICAL | A tracer/debugger is attached to the process (non-zero TracerPid / ptrace). | Live memory & key extraction, step-through dynamic tampering. |
INTEL_0008 |
environment | libc_inline_stub |
CRITICAL | A hot libc function's prologue is an absolute-jump trampoline stub (arm64 LDR x16/x17 + BR; x86_64 jmp rel32 / jmp [rip] / movabs+jmp / push+ret; arm LDR pc) that inline-hooking engines (Dobby/ShadowHook/bytehook/Frida Gum/Substrate) splice over a function entry. Detected by OPCODE SHAPE alone — no baseline, no baked hash, no on-disk comparison — so it is immune to per-device/per-version libc drift and fires even on a function hooked before JNI_OnLoad. Complements INTEL_0003 (which anchors on provenance: the branch must target injected foreign/anon code): INTEL_0008 catches the SAME inline hook when every file-backed trace has been scrubbed and the trampoline references only legit code (Shamiko-grade cleanup), because the stub must remain in place for the hook to function. False-positive-safe by construction: a legitimately-compiled prologue is stack setup or a BTI landing pad, never an absolute-jump stub, and benign code drift never produces one. Promoted to CRITICAL after clean-device FP validation on three OEMs (Pixel 6 Pro, Pixel 9 Pro, Xiaomi 2512BPNDAG); a legit app-bundled inline hooker also splices a stub, which is a policy call rather than a benign-drift false positive. | Inline libc hook that survives provenance cleanup (Shamiko/NeoZygisk-grade) — filesystem/syscall lies. |
INTEL_0009 |
environment | injected_executable_mapping |
HIGH | Executable mapping with no backing file (or memfd/deleted backing): covers zygisk-injected stub pools (anonymous RWX), Frida gadgets (memfd), and unloaded-but-mapped payloads ((deleted)). Kernel vdso/vvar/vectors (and vsyscall/uprobes) pages are excluded by name. Reads via raw syscall, so no libc hook can serve a doctored maps blob. The device reports, the backend decides. Fail-open on unreadable maps. | Native code injection without file provenance — code executing from mappings no clean loader produces, so path-based provenance checks (INTEL_0044) and the linker list (INTEL_0061) cannot see it. |
INTEL_0012 |
art | art_hook_critical |
CRITICAL | An ArtMethod entry point, JNIEnv table, inline prologue, or ACC_NATIVE bit was tampered (Xposed/LSPosed/frida-family hook engine). | Arbitrary Java/Kotlin method interception → in-app code injection — steal credentials, rewrite business logic, bypass in-app checks. |
INTEL_0018 |
native_integrity | watchdog_anomaly |
HIGH | A fork-exec'd watchdog child (plain /system/bin/sh, only async-signal-safe calls between fork and exec) re-reads the parent's /proc/ |
|
INTEL_0024 |
native | native_integrity_critical |
CRITICAL | Live in-memory .text of the native core diverged from the build-baked hash (patched or replaced native library). | Native code injection — the detector's own logic can be patched out. |
INTEL_0025 |
environment | hook_framework_present |
CRITICAL | A known hook-framework library (dobby/whale/yahfa/substrate/...) was mapped into the process. | Arbitrary function hooking → code injection. |
INTEL_0028 |
environment | sealed_exec_memfd |
CRITICAL | A sealed (F_SEAL_WRITE | F_SEAL_SEAL) EXECUTABLE memfd is mapped into the process. Root injectors (NeoZygisk / zygiskd) hand each Zygisk module .so to the app as a sealed read-only memfd received over a unix socket and dlopen it (DlopenMem) — so the module never appears at a /data/adb path that INTEL_0044's file provenance keys on. Detection reads /proc/self/fd for memfd symlinks, fcntl(F_GET_SEALS), and cross-checks /proc/self/maps for a matching executable /memfd: region. Name-independent: it keys on the SEAL BITS, so a module whose memfd is named 'jit-cache' to masquerade as ART's JIT cache is still caught — because ART's JIT memfd is executable but WRITABLE (never F_SEAL_WRITE). False-positive-safe: ordinary apps do not map sealed executable memfds. Complements INTEL_0061 (the anonymized loader) — together they cover both provenance-evasion mechanisms (anon loader + memfd modules) that a /data/adb-centric provenance scan misses. Validated: 0 on a clean app; caught a sealed exec memfd named 'jit-cache'. |
INTEL_0029 |
native_integrity | channel_sequence_anomaly |
CRITICAL | Every scan carries a session-key-MACed monotonic counter — a SHA-256 chain folded over (session_key | |
INTEL_0031 |
environment | got_ptr_hijack |
CRITICAL | A pointer inside a system/app library's data or GOT points into injected foreign executable code — a hooked function pointer. False-positive-free: no legitimate library ever references an injected module. Complements INTEL_0044; catches a hook whose module hides its .so but still redirects a GOT slot into foreign code. | Hooked function pointer — calls silently redirected into injected code. |
INTEL_0032 |
dex | dex_unaccounted_in_memory |
HIGH | /proc/self/maps shows more in-memory dex mappings than any reachable class loader claims. A detached loader — held by an injector and referenced by nothing in the app — leaves exactly this trace. Compared one-directionally: ART dedupes identical dex bytes, so the mapped count can under-report, which fails safe. | Hidden injected classes — code is loaded into the process that no reachable loader admits to, so enumerating class loaders or allow-listing them cannot see it. |
INTEL_0034 |
self_hook | native_function_hooked |
CRITICAL | A monitored native function's prologue was overwritten with a trampoline (inline hook). | Native function interception — redirect calls/syscalls into injected code. |
INTEL_0042 |
native_integrity | text_integrity_divergence |
CRITICAL | SHA-256 over the library's executable segment compared to the build-time digest baked at link time — catches inline hooks and stub overwrites in the SDK's own code. Per-page detail is reserved for the obfuscator pass. Fail-open: a zeroed build digest (no baseline yet) or an unreadable segment contributes nothing. | The detector itself patched while running — someone rewrote the code that reports, so every other signal from this process is suspect. Complements INTEL_0024 (build-baked APK fingerprint) with a self-contained baseline that needs no asset. |
INTEL_0044 |
environment | foreign_text_mapped |
HIGH | Executable code is mapped from outside the legitimate code roots (system/apex/vendor/product/app) — an injected native library such as a Zygisk/Magisk/KernelSU module. Provenance-based and name-independent: unlike the fixed hook-framework name-list (INTEL_0025), this catches ANY injected .so by where it came from. Live-verified catching hma/lsposed-vector/playintegrityfix/zygisksu + a custom module by /data/adb path alone. | Native code injection (Zygisk/Magisk/KernelSU module) by provenance, name-independent. |
INTEL_0051 |
dex | foreign_dex_loaded |
CRITICAL | A DEX was loaded from an attacker-writable path (runtime code injection). | Runtime Java/Kotlin code injection — load attacker classes into the app. |
INTEL_0052 |
environment | rwx_memory_mapping |
CRITICAL | A simultaneously writable+executable mapping was found — proof-positive on API >= 29 where W^X is enforced. Read-write-executable memory mapping detected. On API 28+ the loader and the ART JIT do not leave a persistent RWX page, so one is a strong hooker signature — but RWX alone is ambiguous (a JIT code cache is RWX too), so each region is characterized: a region whose trampoline stubs branch into legit system code or a foreign module (tramp=legit/foreign, hook_stub_regions>0) is a hook redirecting real code; a self-referential or empty region (tramp=self/none) is a benign cache. | Injected shellcode / self-modifying hook staging. |
INTEL_0053 |
environment | frida_memfd_jit_present |
CRITICAL | A frida memfd-backed JIT mapping was found. Frida 16+ Gum JIT signature: rwxp-mapped /memfd:jit-cache region(s) > 8 MB. ART legitimately maps the same path but only with r-xp/r--p perms; the rwxp combination is unambiguous on Android. | Instrumentation code injection, staged from a hidden memfd. |
INTEL_0054 |
environment | frida_worker_thread |
CRITICAL | A frida worker thread (pool-frida) was found in the process. | In-process Frida instrumentation → code injection. |
INTEL_0058 |
environment | property_divergence |
CRITICAL | A boot-state / root-indicator property (ro.boot.verifiedbootstate, ro.boot.flash.locked, ro.boot.vbmeta.device_state, ro.build.tags, ro.debuggable, ...) read via libc __system_property_get returns a DIFFERENT value than the same property read from the property area via __system_property_find + __system_property_read_callback. The only cause is a userspace hook on __system_property_get lying about the property — in-process boot-state / verified-boot spoofing (the behavioral, provenance-independent analog of INTEL_0055's attestation-vs-self-report check). Mechanism-independent: it survives injectors that hide their module's provenance (NeoZygisk-class) because it tests the RESULT of the property read, not the hook's origin. False-positive-free by construction: both entry points read the same property trie, so they agree on a clean device (boot-state properties are static); only a selective hook on the legacy __system_property_get entry point diverges. (A resetprop-style edit of the trie itself changes BOTH reads and is caught by the attestation layer, not here.) Complements INTEL_0059 (syscall divergence). | In-process boot-state / verified-boot spoofing at the property layer (the behavioral analog of INTEL_0055). |
INTEL_0059 |
environment | syscall_divergence |
CRITICAL | a libc file-query (faccessat or the stat family) reports an existing system file (e.g. /system/bin/sh, /apex/com.android.runtime) as absent while a raw svc faccessat syscall — which bypasses libc entirely — confirms it exists. The only cause is a userspace hook (inline / GOT / PLT / LD_PRELOAD) lying about the filesystem to hide root or tamper artifacts. Unlike INTEL_0031/0038/0039 which detect a hook STRUCTURALLY (GOT pointer / inline prologue stub), this is BEHAVIORAL and mechanism-independent: it catches any hooking method as long as the observable result diverges from kernel truth, including hooks those structural signals miss (a GOT hook with an intact prologue, a handler in anon-legit memory, a preload interposer). False-positive-free by construction: libc and the raw syscall issue the same call with the same args, so they agree on a clean device; only a kernel-confirmed existence (raw==0) is trusted as ground truth, and a failed/unavailable raw call is never flagged. Carries hooked_symbol=faccessat so the verdict can CORRELATE it with a structural hook on the same symbol (structural + behavioral agreement = definitive). Boundary: catches userspace hooks only; a kernel/seccomp-level filter intercepts the raw svc too and is covered by the proc-consistency signal instead. |
Filesystem cloaking — hide root binaries / tamper artifacts from the app (behavioral, mechanism-independent). |
INTEL_0061 |
environment | linker_maps_divergence |
CRITICAL | The dynamic linker (dl_iterate_phdr) names a loaded .so whose executable segment maps, in /proc/self/maps, to an ANONYMOUS empty-path VMA. This is the file->anon map spoof performed by NeoZygisk's spoof_virtual_maps() (and ZygiskNext-class cleanup): after modules unload it mremaps the injected loader's file-backed VMA into an anonymous region to erase the foreign-code provenance that INTEL_0044 keys on — but the linker's soinfo still names the object, so the two views split. This is the residue that survives the cleanup specifically designed to blind file-provenance detection. False-positive-free by construction: a legitimately loaded .so always has BOTH a linker record AND a file-backed VMA at its base; a memfd-loaded library keeps its /memfd: name (not empty), and JIT / trampoline anonymous code is never linker-tracked so it does not appear in dl_iterate_phdr. Complements INTEL_0044 (pre-cleanup file provenance) and INTEL_0059 (behavioral backstop). Validated: 0 divergences across 349 legitimate linker objects on a clean device; fires on a spoof_virtual_maps-style anonymization. | Stealth injected module with provenance erased (NeoZygisk spoof_virtual_maps-class hiding). |
Anti-analysis — syscall filtering¶
Syscall filtering: whether something is hiding what the process can observe.
| Code | detector | kind | Sev | Meaning | Reach — what it unlocks |
|---|---|---|---|---|---|
INTEL_0036 |
seccomp | seccomp_kill_filtered |
CRITICAL | A seccomp filter configured to kill the process on syscalls was detected (anti-instrumentation / sandbox tamper). | Anti-instrumentation — the process self-kills to evade analysis / sandboxing. |
INTEL_0040 |
seccomp | seccomp_user_notif_listener |
CRITICAL | The process holds a SECCOMP_RET_USER_NOTIF listener fd — an in-process syscall interceptor used to spoof /proc reads below libc (maps/status/mounts). A benign seccomp-bpf policy leaves no such fd. | In-process syscall interceptor — spoof /proc reads (maps/status/mounts) below libc, hiding root from even raw-syscall probes. |
Root & system integrity¶
Whether the operating system underneath the app is still trustworthy.
| Code | detector | kind | Sev | Meaning | Reach — what it unlocks |
|---|---|---|---|---|---|
INTEL_0005 |
root | su_binary_present |
CRITICAL | An su binary was found on PATH or a common location. | Root escalation available — unlocks essentially every tamper in this table. |
INTEL_0006 |
root | selinux_permissive |
CRITICAL | SELinux is not enforcing (enforce=0). | Sandbox boundary removed — cross-app data access, privilege escalation. |
INTEL_0010 |
root | magisk_in_init_mountinfo |
CRITICAL | Magisk mount traces were found in init's mountinfo. | Systemless root active → hidden module mounts overlaying system files. |
INTEL_0013 |
root | tls_trust_store_tampered |
CRITICAL | A tmpfs bind-mount was found over the conscrypt trust-store apex (TLS interception / MITM setup). | MITM / TLS interception — network credential and traffic theft. |
INTEL_0021 |
root | kernelsu_present |
CRITICAL | KernelSU (kernel-level root) was detected. | Kernel-level root — the strongest tamper; can defeat userspace detection and spoof almost anything. |
INTEL_0035 |
root | magisk_artifact_present |
CRITICAL | A Magisk file or artifact was found on the device. | Systemless root → module injection, Play-Integrity spoofing via modules. |
INTEL_0057 |
root | test_keys_build |
CRITICAL | The build is signed with Android test-keys (non-production / engineering build). | Non-production / pre-rooted image — weakened security posture. |
INTEL_0060 |
root | magisk_daemon_socket_present |
CRITICAL | The Magisk daemon (magiskd) abstract socket was found. | Live Magisk daemon → on-demand root grants to any app. |
INTEL_0063 |
root | su_binary_system_path |
CRITICAL | An su binary was found in a protected system path (strong root indicator). | Strong root → full device control. |
Package integrity — repackaging & tamper¶
Whether the running APK and its DEX are the ones that were signed.
| Code | detector | kind | Sev | Meaning | Reach — what it unlocks |
|---|---|---|---|---|---|
INTEL_0014 |
apk | apk_entry_added |
CRITICAL | An unexpected entry was added to the APK. | Injected payload/DEX smuggled into the package. |
INTEL_0017 |
apk | apk_entry_removed |
CRITICAL | An expected APK entry is missing. | Stripped security asset / disabled check. |
INTEL_0022 |
apk | apk_entry_modified |
CRITICAL | A protected APK entry's bytes differ from the baked fingerprint (tampered package). | Patched app logic / tampered resources or DEX. |
INTEL_0026 |
apk | installer_not_whitelisted |
MEDIUM | The installing package is not an approved app store. | Side-loaded outside a trusted store. |
INTEL_0041 |
apk | fingerprint_corrupt |
CRITICAL | The baked APK fingerprint asset could not be parsed or validated. | Integrity baseline damaged — self-check degraded. |
INTEL_0043 |
apk | fingerprint_bad_magic |
CRITICAL | The baked APK fingerprint asset has an invalid magic header (tampered asset). | Tampered integrity-baseline asset. |
INTEL_0049 |
apk | apk_source_dir_unexpected |
MEDIUM | The APK source directory is not the expected install location. | Side-loaded / hijacked install path. |
INTEL_0062 |
apk | apk_signer_mismatch |
CRITICAL | The running APK's signing certificate does not match the expected signer (repackaged / re-signed). | Repackaged / trojanized app — injected malware, credential harvesting inside a clone. |
Virtual environments — emulators & translation¶
Whether this device is real silicon or an emulated/translated environment.
| Code | detector | kind | Sev | Meaning | Reach — what it unlocks |
|---|---|---|---|---|---|
INTEL_0027 |
emulator | translated_environment |
CRITICAL | Definitional emulator signal, not a heuristic: the kernel's ISA (raw uname(2) syscall) does not match this process's compile-time ABI — an arm64 process on an x86 kernel (or the reverse) is executing under a binary-translation layer (libhoudini / libndk_translation), which is what LDPlayer / BlueStacks / Nox / MuMu ARM mode and Genymotion-on-x86 are; genuine silicon cannot produce this. Corroborating sub-facts: ro.dalvik.vm.native.bridge names a known translation bridge (no genuine phone ships one), or that bridge lib is mapped in /proc/self/maps (read via raw syscall, surviving a prop spoofer). All reads are raw syscalls — public emulator-bypass kits hook Build.* fields, __system_property_get and libc fopen/access, none the syscall layer. CRITICAL because the sub-facts are impossible on genuine silicon: the one sanctioned landing zone (ChromeOS/ARC ndk_translation) already trips INTEL_0056 software attestation and the pinned-root chain check, so it is no new blocking class, and CRITICAL is what keeps the on-device clean-device gate locked on an emulator — on an AVD where the attestation path degrades before the KeyDescription parse, this can be the only on-device finding. The device reports; the backend still decides. Fail-open on every input. | Scaled virtual devices — one host running hundreds of "devices": scripted automation, replay, credential stuffing and promo abuse at near-zero marginal cost. No hardware keys (corroborate with INTEL_0056), but full app-level control. |
INTEL_0033 |
emulator | hypervisor_cpu |
CRITICAL | x86_64 builds only: CPUID.1:ECX[31] (hypervisor present) is set and/or the CPUID.0x40000000 hypervisor vendor leaf answers. Detects emulators that hand guest code to the real CPU under hardware virtualization (QEMU/KVM) — no binary translation exists there, so INTEL_0027 correctly stays silent and this is the only in-process tell. A real phone CPU cannot set the architecturally reserved hypervisor leaf. Honest scope: x86_64 Android also runs on Chromebooks (ARCVM) and Windows Subsystem for Android, which set the same bit — genuine markets, so the backend may downweight per policy. A determined emulator can mask the leaf (KVM cpuid masking); default configs do not. Fail-open: without the bit or a known vendor string the probe contributes nothing. arm64 builds contribute nothing by construction. | Hardware-virtualized environment — the CPU itself is the emulator; scaled farms run these for free, and properties are the only spoofable layer (KVM can mask the leaf; default configs do not). |
INTEL_0047 |
emulator | cpu_rerouting_anomaly |
CRITICAL | Behavioural companion to INTEL_0027: catches a translation layer that renamed itself out of the provenance keys. Two sub-facts, each architecturally impossible on genuine silicon. (1) Counter coherence: CNTVCT_EL0 must advance at exactly CNTFRQ_EL0 (a fixed always-on clock domain that does not track DVFS; measured error 0.0000 on real devices) — a bridge has no guest timer and serves the counter from the host clock (measured 23,000x divergence on libndk_translation). (2) Synchronous-fault fidelity: an undefined instruction executed by the process always reports SIGILL si_code=ILL_ILLOPC on a genuine AArch64 kernel; a bridge replays the fault from its own metadata as si_code=SI_USER, the code of a user-sent signal. Fail-open: every unreadable register, short window, or missing measurement contributes nothing. Supporting spike probes (syscall toll, cold-vs-warm) deliberately do not gate — see docs/spikes/cpu-rerouting.md. | Hidden translation layer — a CPU-virtualizing bridge that renamed itself and scrubbed its provenance, defeating INTEL_0027's name/provenance keys; same reach: scaled virtual devices with full app-level control. |
INTEL_0048 |
emulator | arm64_vm_platform |
CRITICAL | arm64 builds only: the device-tree model or compatible blob carries hypervisor-platform markers (qemu, dummy-virt, crosvm, cuttlefish, goldfish/ranchu), and/or /dev/qemu_pipe opens read-write. Catches full-system emulators and ARM VMs that run ARM app code natively inside an emulated ARM system — the guest ISA matches the app, so INTEL_0027 sees no divergence and INTEL_0033 (x86 CPUID) does not apply. Real devices report their SoC board and have no qemu_pipe node. Fails open on unreadable files; markers classified by a pure, host-tested header. Evasion note: a hypervisor that fabricates a plausible device-tree defeats this — fabrication cost is the deterrent, and the signals feed backend cross-checks against the claimed device model. | ARM VM / full-system emulator — the arm64 counterpart of INTEL_0033 for the class TCG/ranchu farms and cuttlefish-style VMs; fails open on unreadable files, and a fabricated device-tree defeats it (fabrication cost is the deterrent). |