Files
CellGuard/common/docs/anti-forensics-hardening.md
sssnake 9a3e3a0501 CellGuard: LTE/5G-NR lock + IMSI-catcher detection KSU module
- cgcap.ko: cpif CP-frame capture via kprobe/kallsyms, stock-GKI build
- ratlock.sh: hold modem to LTE+NR(5G), block 2G/3G downgrade
- cgdetect.sh: always-on behavioral cell-site-simulator detection
- cgctl.sh + WebUI: block/detect toggles, status + alerts
- build-stock-gki.sh: reproducible stock-GKI module build pipeline
2026-07-12 09:21:54 -07:00

11 KiB
Raw Permalink Blame History

Rango Anti-Forensics Hardening — Case Write-Up

Scope: Owner-authorized security hardening and research on a personally-owned device. Goal: raise the cost of physical forensic extraction (Cellebrite UFED, GrayKey, XRY, Oxygen) and make the shell / low-level flash interfaces inaccessible without owner authorization.

This document is a defensive engineering plan for the device owner's own hardware. The research track (§8) is authorized vulnerability research on that same device; its purpose is to understand and mitigate the attack surface, not to produce a distributable exploit.


1. Objective

  • Resist forensic extraction by a physical-access adversary.
  • Deny an attacker useful access to adb, fastboot, fastbootd, recovery, and the USB data surface — gated behind owner authentication.
  • Keep the device usable (and rooted, for the CellGuard modem work) without giving that up as the price of hardening.

2. Device baseline (as-found)

Item Value
Device Pixel 10 Pro Fold (rango), Tensor G5, Shannon 5400 modem
Kernel stock GKI 6.6.102-android15-8-g6eb5b2a8c46b-ab14739656-4k
Kernel hardening RANDSTRUCT_NONE, CFI_CLANG (strict), MODVERSIONS, LTO_NONE, MODULE_SIG_PROTECT, MODULE_SIG_FORCE off
Root KernelSU LKM
Bootloader unlocked (props spoofed to locked/green to pass Play Integrity)
adb USB + wireless both enabled; ro.adb.secure=1; 1 authorized host key

3. Threat model

  • Adversary: forensic extraction appliance with physical possession.
  • Primary vectors:
    1. USB attack surface — adb, fastboot (ABL), fastbootd (userspace), the USB gadget/MTP stack. The port is the appliance's front door.
    2. Lockscreen brute force — throttled by Titan M2, but exploits + time erode a short PIN.
    3. AFU key residency — After First Unlock, disk-encryption keys are in RAM and the secure element has seen the credential → extraction is far easier than the Before-First-Unlock (BFU) state.
    4. Unlocked bootloader — while unlocked, fastboot boot <img> runs an attacker image instead of the owner OS, bypassing any in-OS defense.

4. Boot chain & trust anchors — what the owner can and cannot control

bootrom (fused OEM key)  →  bl1 → bl2 → bl31 (EL3)  →  pbl  →  ABL (fastboot)
      →  boot / init_boot (kernel + ramdisk)  →  Android userspace
Stage Owner-controllable? How
bootrom, bl1/bl2/bl31, pbl, ABL/fastboot bootrom-anchored to the OEM key; cannot be re-signed
boot / init_boot / vendor_boot / recovery / vbmeta custom AVB key (avb_custom_key) makes the owner the root of trust for these
Android userspace (adb, settings) root / WRITE_SECURE_SETTINGS

Key consequence: you can become the verified-boot root of trust for everything from boot upward, but not for the bootloader itself. So a legitimately-signed, password-patched fastboot is impossible — the only way to run modified ABL code is an exploit (see §5, §8).

5. Cryptographic reality (for the record)

  • RSA-2048/4096 and ECDSA P-256 are not broken by any known classical attack. Bootloader signing keys are in this range → not forgeable.
  • What is real: factored weak RSA (≤829-bit, academic), ECDSA nonce reuse / bad RNG (PS3, Bitcoin — implementation, not algorithm), side-channel / fault-injection bypasses of the verification path, and future quantum (Shor's — no cryptographically-relevant quantum computer exists yet; NIST PQC migration is pre-emptive).
  • Therefore: defeating verified boot means attacking the check (glitch / memory-corruption bug in the verifier or command parser), not breaking the key. This is the premise of the research track (§8).

6. Defensive architecture — achievable, layered

Ordered so each layer builds on the one below it.

  • L0 — Foundation: custom AVB root of trust + re-lock. Generate an owner AVB key; build a KSU-integrated GKI boot image (baked in, not LKM, so root survives lock); build a custom recovery; sign boot/init_boot/vendor_boot/recovery/vbmeta with the owner key; fastboot flash avb_custom_key; flash; prove it boots; then fastboot flashing lock. Delivers: locked verified boot with root; ABL fastboot becomes crypto-inert (refuses flash/boot/erase/unlock); recovery cannot be swapped. This is the linchpin — every other layer depends on it.

  • L1 — Password-gated recovery. Compile a secret gate into the signed recovery ramdisk for the pre-decryption actions: fastbootd, ADB sideload, factory reset. (fastbootd is "fastboot from inside recovery" — the piece the owner actually controls.)

  • L2 — USB-when-locked cutoff + adb hard-off. Deny USB data/enumeration (charge-only) whenever the screen is locked — the single most Cellebrite- relevant control (GrapheneOS's headline feature). Implement as a kernel module (reuses the CellGuard build pipeline) or a root daemon on keyguard state. adb defaults off; enabling is biometric/PIN-gated with an auto-off timeout.

  • L3 — Auto-reboot to BFU. Root/KSU daemon reboots after N minutes locked, evicting in-RAM keys → forces the hard BFU state, defeating AFU extraction.

  • L4 — Duress / honeypot. Only meaningful once L0 is locked (else the attacker boots their own image and skips it). Options:

    • Non-destructive decoy — a duress credential boots a sterile decoy user while the real user's keys stay underived.
    • Destructive — duress credential (or repeated failures) evicts/wipes the real keys.
    • Boot-context branchinit inspects androidboot.bootreason/mode and presents the decoy on abnormal boot.
    • Limit: true deniability is weak on Android — FBE metadata reveals that multiple users/volumes exist. Destructive duress is more reliable than a deniable-hidden-volume approach.
  • L5 — Strong passphrase (owner action). Converts lockscreen brute force from "time + exploit" into a non-starter.

7. Honest limits (what will NOT work, and why)

  • Patching/signing ABL — bootrom-anchored to the OEM key; a modified bootloader can't be signed and won't boot. Only an exploit runs it (§8).
  • Hiding/redirecting the ABL fastboot key-combo — the key combo is read by the signed bootloader before any OS/recovery code; recovery can't intercept it. The "TWRP forces you through recovery" trick (e.g., on the S20) relies on a more malleable bootloader and the fact that Samsung has no fastboot (Download/Odin + Knox instead). Not reproducible on Tensor.
  • Deniable hidden volumes — FBE leaks the existence of multiple data sets.
  • Current unlocked bootloader — negates most in-OS defenses until L0 re-lock, because an attacker can just boot their own image.

8. Research track — ABL vulnerability research (authorized, own device)

Parallel to the defensive build. Premise (§5): attack the verification, not the key. Assets already on hand: the rango factory image in ~/PixelFlasher/dist/ (contains bootloader-rango-*.img) and existing Ghidra projects under seteclabs/rango-wifi-monitor.

  1. Unpack bootloader-rango-*.img → split the pack into stages (bl1/bl2/bl31/pbl/ABL; Tensor uses a Samsung-style chain).
  2. Load ABL into Ghidra; locate the fastboot dispatch (strings: getvar, download:, flash:, boot, oem , reboot-bootloader).
  3. Audit the parser for classic wins: unchecked lengths in download/sparse-image handling, oem vendor commands (least-audited surface), integer overflows in partition sizing.
  4. Firmware diffing across bootloader versions — patched bugs point at the interesting code and sometimes yield n-days.
  5. Hardware surface (if pursued): identify UART/JTAG test points; assess the voltage/EM glitch surface on the signature-check path (ChipWhisperer-class).

Strategic note: an ABL exploit is the attacker's own primitive and is fragile (breaks/needs rework each firmware update). It should not gate the defensive build — ship L0L3 for protection now, run the RE track in parallel.

9. Safety rig / escape hatch (mandatory before anything irreversible)

  • Keep the factory image flash-all ready (~/PixelFlasher/dist/).
  • Keep the bootloader unlocked and OEM-unlocking enabled until the signed chain is proven to boot cleanly.
  • Dry-run the full sign → flash → boot cycle unlocked first; confirm avbtool verify passes against the owner key before ever typing fastboot flashing lock.
  • flashing lock is the last step; disable OEM-unlocking only after the locked chain is proven stable.
  • Prefer proving the sign/lock/escape-hatch loop on a spare device before the daily driver.

10. Risk register

Risk Mitigation
Re-lock with a non-verifying image → hard brick dry-run unlocked; avbtool verify; keep OEM-unlock until proven
OTA breaks the owner-signed chain re-sign after each update; hold OTAs until pipeline is scripted
KSU integration regressions under lock validate root + boot on unlocked build first
Duress deniability weaker than hoped prefer destructive duress; document the limit
Losing the working session over wireless adb when disabling adb attach USB fallback before testing the "off" path

11. Roadmap / next actions

  • Phase 0: prove the escape hatch (spare device and/or verified factory flash).
  • Phase 1 (reversible): L0 foundation — AVB key + KSU-integrated signed boot; flash and boot unlocked to validate; do not lock yet.
  • Phase 2: L1 recovery gate + L2 USB-when-locked / adb hard-off.
  • Phase 3: L3 auto-reboot-to-BFU + L4 duress/honeypot; then L0 flashing lock.
  • Parallel: §8 ABL RE track (unpack bootloader-rango-*.img → Ghidra).

Appendix A — current-state levers (verified this session)

settings get global adb_enabled            -> 1   (USB debugging)
settings get global adb_wifi_enabled       -> 1   (wireless debugging; current link)
getprop ro.adb.secure                      -> 1   (RSA host-key auth enforced)
/data/misc/adb/adb_keys                    -> 1 authorized host key

adb kill switch: settings put global adb_enabled 0; settings put global adb_wifi_enabled 0; setprop ctl.stop adbd.

  • common/kmod/cellguard.c — kernel module; demonstrates the GKI build + load path (protected-symbol resolution via kallsyms) reused by L2.
  • common/kmod/build-stock-gki.sh — stock-GKI module build pipeline; the basis for building the L0 KSU-integrated signed boot image.