# Attacking Titan M with Only One Byte

One-byte out-of-bounds write in Titan M Keymaster ImportKey allows stack pivot and ROP to leak StrongBox keys.

- Payout: $75,000
- Severity: critical
- Program: Google
- Credited: Damiano Melotti, Maxime Rossi Bellom
- Disclosed: 2022-08-11
- CVE: CVE-2022-20233
- Write-up quality: 9/10
- Original: https://blog.quarkslab.com/attacking-titan-m-with-only-one-byte.html
- Library page: https://bugbountylibrary.com/r/blog%3Ablog-quarkslab-com-attacking-titan-m-with-only-one-byte-html
- Tags: domain:mobile impact:data-leak impact:privesc kind:bounty platform:blog sev:critical tech:android technique:fuzzing technique:reverse-engineering technique:source-review vuln:memory-corruption

**Target:** Titan M security chip firmware (Keymaster task)
**Root cause:** ImportKey handler uses DIGEST parameter integer as offset into stack buffer without proper bounds check, allowing 1-byte write of 0x01 to attacker-chosen address.
**Steps:**
1. Send ImportKeyRequest with KeyParameters containing DIGEST tag (0x20005) and integer value 0xa204 to write 0x01 to address 0x1e21d (KEYMASTER_SPI_DATA).
2. This changes the pointer for incoming Keymaster requests from 0x192c8 to 0x101c8.
3. Send a large Keymaster command (e.g., DestroyAttestationIds) with payload such that after 556 bytes a return address is overwritten, redirecting execution to a gadget.
4. Use ROP chain with gadget `sub sp, #0x20; mov r4, r0; ldr r3, [r0]; add.w r5, r4, #0x70; ldr r3, [r3, #8]; blx r3;` to pivot stack and build read primitive.
5. Overwrite DestroyAttestationIds handler with trampoline gadget to pivot stack to controlled area.
6. Call memcpy with user-controlled arguments to copy arbitrary memory into SPI response buffer, leaking secrets.
**How found:** Emulation-based fuzzing of Keymaster task using AFL++ in Unicorn mode with libprotobuf-mutator; detected crash UC_ERR_WRITE_UNMAPPED on strb instruction during ImportKey processing.
**Exploitation:** Attacker with root or physical SPI access sends crafted ImportKey to corrupt request pointer, then sends large command to hijack control flow, uses ROP to read arbitrary memory including StrongBox keys.
**Escalation:** Leaked StrongBox-protected keys by first sending BeginOperation to decrypt key into memory, then using read primitive to exfiltrate plaintext key.
**Insight:** In static memory layouts without ASLR, even a single-byte write can corrupt critical pointers; focus on structures like request buffers that are used across commands.
