Nick Stephens presented an exploit chain that achieves complete compromise of a smartphone's trusted execution environment (TEE) from an untrusted app. The chain involves four steps: (1) exploiting vulnerabilities in the TEE driver to escalate from userland to kernel code execution, (2) exploiting parameter passing to escalate from kernel to a trustlet, (3) exploiting lack of pointer sanitization in system calls to escalate from the trustlet to the trusted core, and (4) reversing and patching the fingerprint authentication trustlet to disable fingerprint security. The talk provided technical details on vulnerabilities and exploitation techniques at each step of the chain to achieve the goal of trusted app and TEE compromise.
Alexey kurakin-what's new in adversarial machine learning
Nick Stephens-how does someone unlock your phone with nose
1. Behind the PWN of a TrustZone
from untrusted app to trustzone kernel code exec
Nick Stephens
2. Bio
- Nick from Shellphish
- Worked on the Cyber Grand Challenge and research papers
- Automated Bug Finding and Exploitation
- TrustZone and Android bugs
- Played a lot of CTF
- Submitted TrustZone research to GeekPwn 2016
3. The Goal
Complete compromise of a smartphone
From an untrusted app compromise the ‘TEE’
Trusted Execution Environment
Disable the Fingerprint Sensor the TEE controls
4. The exploit chain
Android TEE
EL0 - Userland
EL1 - Kernel
Secure EL0 - Trusted Apps
Secure EL1 - TEE OS
Secure Storage
Secure Payment
Biometric Sensors
Trusted UI
Trusted Core
Start executing
code here
Get code execution here
5. The modern mobile security architecture
Android TEE
EL0 - Userland
EL1 - Kernel
Secure EL0 - Trusted Apps
Secure EL1 - TEE OS
Secure Storage
Secure Payment
Biometric Sensors
Trusted UI
Trusted Core
6. Disclaimer - Chipset determines the TEE
- The TEE implementation is closely tied to the chipset of the phone
- Qualcomm, Samsung, etc have their own implementations
- All bugs discussed are tied to one chipset line in particular
7. TrustZone system architecture
Android App
teecd
tc_ns_client
TEE Connection Daemon
TEE Global Task
Secure Storage
Keymaster
ta_finger
Trusted
Core
ioctls to driver
smc to trustlets*
svc calls to trusted kernel
retrieve tc_ns_client fd
TEE kernel driver
Trustlets
8. Step 1 - Userland to Kernel
- Target the Trustzone driver
- ‘Logs in’ userland apps, maintains a form of session management
- Relies on teecd to perform the ‘log in’ before giving app control
- Proxy calls to trustlets from userland
- Manages messaging primitives for trustlet communication
- Support for passing ‘memory references’ and integer values
- Sanitizes parameters sent to trustlets
- Two vulnerabilities, CVE-2016-8762 and CVE-2016-8763
Android App
tc_ns_client
ioctls to driver
9. - The TrustZone kernel, known as the Trusted Core, has a virtual address space which is 1-to-1 with physical addresses
- Trustlets need to have these physical addresses translated for them as they exist in their own virtual address space (with
ASLR )
- But the normal kernel has no insight into where destination trustlets are mapped
Into CVE-2016-8762 - The TEE address space
Normal
World
Kernel
Destination Trustlet
Trusted
Core
Pass Parameters
expressed as
physical
addresses
Pass Parameters
as virtual
addresses
Translates and maps in pages from
the normal world to the destination’s
address space
10. - Occurs when preparing an app’s parameters for trustzone translation
- No sanitization on memref.offset parameter
CVE-2016-8762 - An OOB with a Twist
- shared_mem->kernel_addr + client_param->memref.offset
- We can pass the physical address of any page mapped in
12. - Find a Trustlet function which will write a value to the address we provide
Exploitation - Redirecting the fops table
GLOBAL_CMD_ID_NEED_LOAD_APP handler, writes a 32-bit 1 or 0
13. - Issue several calls, writing the a 32-bit 0x1 over the 64-bit fops pointer
Exploitation - Redirecting the fops table
0xff 0xff 0xff 0xc0 0x02 0x12 0xa1 0xc0
0x00 0x00 0x00 0x01 0x02 0x12 0xa1 0xc0
0x00 0x00 0x00 0x00 0x00 0x00 0x01 0xc0
0x00 0x00 0x00 0x00 0x01 0x00 0x01 0xc0
ext4_file_operations
userland memory
- Now overwrite cred struct members with arbitrary write, becoming root
14. - Target Secure File Storage Trustlet
- Only HiDisk can talk to this, with root the authentication can be bypassed
- Transparently encrypts and decrypts files
- Kernel doesn’t (shouldn’t!) know the key
- Used by the HiDisk application, the ‘Safe’ feature of the Files app
- Type confusion, CVE-2016-8764
Step 2 - Kernel to Trustlet tc_ns_client
Secure Storage
smc to trustlets
TEE kernel driver
Trustlets
15. Into CVE-2016-8764 - Passing params to a Trustlet
- Support for passing both buffer and integer values to up to TEE
paramTypes encoded here, allows for type
checking inside TEE
16. CVE-2016-8764 - Read and Write in a Trustlet
- The Secure Storage trustlet never checks paramTypes
- An integer can be confused with a memory reference
- We can write to any address in the trustlet with controlled data and size!
- Similarly, STORAGE_CMD_ID_WRITE can be used to read arbitrarily
17. Exploitation - Hijacking TEE_Malloc
- TEE_Malloc uses a function pointer table to handle different size classes
- Write to a new secure file with our desired function pointer value, then ‘read’ that over TEE_Malloc’s function pointer
table
- Remember… the Trusted Core takes care of remapping memory references into our trustlet…
- Let’s put our shellcode in a memref and jump there!
Trustlet .text
r-x
Trustlet .bss
rw-
Trusted Core
---
Passed Memrefs
rwx
lower addresses higher addresses
Address space of a Trustlet
18. Exploitation - One problem… ASLR
- New phones use some OS-level mitigations trustlet loading now implements ASLR
One byte of entropy
- Randomization takes place once, not re-randomized on a reload
19. Exploitation - Defeating ASLR
- We could bruteforce, 1 byte means at most 256 attempts
- But root can read anything on disk…
- Information leak in /dev/hisi_teelog
20. Step 3 - Trustlet to the Trusted Core
- Target System calls in the TrustZone kernel
- Provides IPC primitive for message passing between trustlets
- Supports memory address translation
- Directs calls from normal world to requested trustlets
- Has all trustlets in its address space
- One big vulnerability, no CVE :(
Secure Storage
Trusted
Core
svc calls to trusted kernel
21. One big bug...
NO POINTER SANITIZATION
- Mostly a reverse engineering task
- Find a sequence of system calls which give us arbitrary write
- Don’t need a direct understanding of the syscalls, just primitives
22. Trusted Core Environment
- No ASLR, other access checks require a hardcoded bounds
- PXN, can’t jump to userspace, but no PAN, can access userspace
- No DEP, kernel heap is executable
- Supports over 300 system calls, some behind permission checks
23. Trusted Core - Finding Primitives
- No magical ‘write arg 1 to arg 0’ system calls
- We do have system calls to
- 0xf1c8 - Write an allocated pointer, points to a 16-byte string we control
- 0xf079 - Allocate an arbitrary size kernel heap buffer and return its address
- 0xf0c3 - Write an uncontrolled dynamic value from a linked list in the kernel
- 0xf04a - Copy the trustlet’s process name to an arbitrary address
- 0xc0d8 - Leak arbitrarily via an int overflow
24. Trusted Core - Combining the Pieces
Use 0xf079 to allocate a kernel buffer for our trusted core shellcode
Use 0xc0d8 to leak addresses of string table pointers
Use 0xf1c8 to write over 0xf0c3’s linked-list pointer to a string containing our stack pointer
0xf0c3 can now write the address of our stack anywhere - write over the process name string table
0xf04a can now be used to write our stack contents anywhere - update our stack to change value
Write in our kernel shellcode, write over a function pointer, trigger function pointer call
25. Step 4 - Disable Fingerprint Auth
- Find trustlet responsible for recognizing fingerprints
- Reverse and hot patch it
- But where is it?
- Fingerprint checking logic should be complex, larger than 100K
26. Follow the userland daemon
- Reverse fingerprintd
- It has lib_fpc_tac_shared.so mapped in… what’s that?
- lib_fpc_tac_shared.so requests to load /system/bin/fd1bbfb2-9a62-4b27-8fdb-a503529076af.sec?
- Encrypted trustlet
27. Finding and patching
- With TrustedCore code exec we can dump the decrypted memory
- Crawl TEE memory for ARM instructions, dump surrounding areas to disk
- Check dumps for any references to fingerprints
- fpc, fingerprint, fingerprintd
- Now just reverse and patch!