Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,51 @@ If you need the early-boot details for MediaTek devices, review:

Also note that **public tooling such as [MTKClient](https://github.com/bkerler/mtkclient)** makes several MediaTek Boot ROM / download-mode workflows practical on affected chipsets.

### Biometric TA AuthToken forgery: root-to-CE bypass without patching Gatekeeper

A second reusable pattern is to **abuse biometric Trusted Applications (fingerprint / face TAs) that share the same AuthToken HMAC trust domain as Gatekeeper and Keymaster / KeyMint**. On Android, a successful authenticator returns a signed **`hw_auth_token_t`** proving who authenticated, by which method, and when. If a biometric TA can be tricked into **signing attacker-controlled data** or **leaking the shared per-boot HMAC key**, Android root can be upgraded into **PIN recovery** and sometimes **BFU CE decryption**.

Relevant AuthToken properties:

- `hw_auth_token_t` is a fixed **69-byte** structure with fields such as `challenge`, `user_sid`, `authenticator_id`, `authenticator_type`, `timestamp`, and a trailing **32-byte HMAC-SHA256** computed with a **per-boot shared secret**.
- `authenticator_type = 1` is the important value for **Gatekeeper / PIN** tokens.
- Keymaster / KeyMint validates the HMAC, freshness, SID binding, and expected authenticator type before releasing authentication-bound key operations.

Common exploitation patterns seen in vendor biometric TAs:

1. **Signing oracle (`GET_AUTH_OBJ`-style bugs)**: a TA command accepts an arbitrary 69-byte buffer and simply HMAC-signs it, without checking that a fingerprint/face match actually happened.
2. **Biometric result oracle + verifier confusion**: a TA emits a valid **type-2** biometric token without a real match, and Keymaster incorrectly accepts it for operations that should require **type-1** Gatekeeper authentication.
3. **Error-path secret leakage**: HMAC verification failures print or return the shared **32-byte per-boot AuthToken HMAC key** via TrustZone logs, shared memory, or even `dmesg`-reachable secure logs.
4. **TA memory disclosure / corruption**: out-of-bounds reads or arbitrary-read primitives leak plaintext per-boot HMAC keys from heap / stack / BSS after defeating weak TA ASLR.

Once the attacker can mint a valid **type-1** token (or a verifier incorrectly accepts **type-2**), the remaining CE attack looks very similar to the early-boot TEE-patching chain, but **without** modifying Gatekeeper itself:

1. Obtain **Android root / kernel EL1 R/W**.
2. Invoke the biometric TA directly with **`libTEEC`** or an equivalent TEE client.
3. Forge or request a signed **Gatekeeper-typed AuthToken**.
4. Pass that token to **Keymaster / KeyMint** to decrypt the first-stage **Synthetic Password** blob.
5. Brute-force the real PIN **offline** using the AES-GCM tag as a correctness oracle.

Minimal attacker view:

```python
at = forge_gatekeeper_authtoken() # type = 1, HMAC valid
spblob = read('/data/system_de/<uid>/spblob/...')
intermediate = keymaster_decrypt(at, spblob)

for pin in range(1_000_000):
key = derive_synthetic_pw(intermediate, pin)
if aes_gcm_decrypt(intermediate, key):
return pin
```

Operational notes:

- **BFU impact** usually requires a forged **type-1 / Gatekeeper** token that Keymaster accepts before first unlock.
- **AFU-only** cases can still exist if the device incorrectly accepts biometric **type-2** tokens after first unlock.
- Multiple dormant fingerprint TAs in one firmware image increase attack surface because **each TA may hold the same per-boot AuthToken HMAC material**.
- **StrongBox / Weaver-backed** designs reduce the usefulness of this chain because recovering the Keymaster-gated intermediate is not always enough to obtain an offline brute-force oracle.

### StrongBox / Weaver changes the brute-force model

If the device uses **Weaver** backed by a separate Secure Element / StrongBox, compromising Android or even the TEE is usually **not enough** to obtain an offline brute-force primitive:
Expand Down Expand Up @@ -88,8 +133,12 @@ For defenders and app testers, the important lesson is simple: **if the target d
## References

- [Demystifying phone unlocking tools: A technical overview](https://osservatorionessuno.org/blog/2026/05/demystifying-phone-unlocking-tools-a-technical-overview/)
- [Android Open Source Project - Authentication](https://source.android.com/docs/security/features/authentication)
- [Android Open Source Project - Gatekeeper](https://source.android.com/docs/security/features/authentication/gatekeeper)
- [Android Open Source Project - Weaver](https://source.android.com/docs/security/features/authentication/weaver)
- [Android Open Source Project - KeyMint implementer reference](https://source.android.com/docs/security/features/keystore/implementer-ref)
- [MTKClient](https://github.com/bkerler/mtkclient)
- [The Biometric AuthToken Heist: Forging Android AuthTokens from Biometric Trusted Applications](https://darknavy.org/blog/the_biometric_authtoken_heist)
- [First analysis of Apple's USB Restricted Mode bypass (CVE-2025-24200)](https://blog.quarkslab.com/first-analysis-of-apples-usb-restricted-mode-bypass-cve-2025-24200.html)

{{#include ../../banners/hacktricks-training.md}}