HITB GSEC 2019 Singapore
Launching feedback-driven fuzzing
on TrustZone TEE
Andrey Akimov,
security researcher
Agenda
• Samsung S8 usage of ARM TrustZone – Trustonic Kinibi
• Searching for attack target
• Exploring TrustZone implementation
• Trusted applications
• Fuzzing
• Crash analysis
• Results
• Exploitation of SVE-2019-14126
3
ARM TrustZone
Usage
• Corporate services • Hardware secure storage
• Content management • Authentication, biometrics
• Personal data protection • Hardware cryptographic engine
• Connectivity protection • Digital Rights Management (DRM)
• Protecting and monitoring of the Normal World by
• Mobile financial services the Secure World
• Real-Time Kernel Protection (RKP)
• Periodic Kernel Measurement (PKM)
• Trusted user interface
4
Trustonic Kinibi
TEE operating system
• Ex. G&D mobicore, <t-base
• Samsung Exynos SoCs: Galaxy S3 to Galaxy S9 – Trustonic Kinibi
• Samsung Galaxy S10 – Samsung Teegris
• github: trustonic-tee-user-space
• github: trustonic-tee-driver
• Old Qualcomm leak with Trustonic Kinibi SDK qcom_leaked_sources.zip
• secure world headers
• secure world static libraries
• documentation
• etc.
5
Trustonic Kinibi
Normal World and Secure World
Architecture Developer’s view
6
Normal World
Exploring Android file system
Trustonic Kinibi
Client applications
• Keymaster
• access to key information
• Fingerprintd Fingerprintd
• biometrics Keymaster
• Samsung Pay
• …
8
Trustonic Kinibi
Trusted application connector
• Native libraries
• libtlcotp.so
• libtlc_direct_comm.so
• …
• Binder /system/bin/tlc_server
libtlcotp.so
• /system/bin/tlc_server – access to
trustlets via Binder interface TuiService.apk
RootPA.apk
• TuiService.apk – access to TUI
• Service provider provisioning agent
• Root provisioning agent
• RootPA.apk – gd.mobicore.pa
9
Trustonic Kinibi
Client API
• /system/vendor/lib64/libMcClient.so – trustlet
communication
• mcOpenSession
• mcMallocWsm
• mcNotify
• …
• /system/vendor/lib64/libMcRegistry.so –
registry management libMcRegistry.so
• mcRegistryStoreAuthToken libMcClient.so
• mcRegistryStoreSp
• …
10
Trustonic Kinibi
Daemon
• /system/vendor/bin/mcDriverDaemon
• Communicates through @mcdaemon socket
• SELinux
• u:object_r:mobicoredaemon_exec:s0
@mcdaemon
mcDriverDaemon
11
Trustonic Kinibi
Kernel components
• Official open source Android kernel
• Community builds
• TGP Kernel
• Xceed
• BatStock-Kernel V1.8.0
• …
• make menuconfig
• TrustZone related kernel components
• Trustonic TEE Driver
• triggers SMC to switch CPU to Secure World
12
Trustonic Kinibi
Kernel components
• Main kernel entry points
• /dev/mobicore – administration tasks
• /dev/mobicore-user – client application –
trusted application communication
• /dev/t-base-tui – trusted user interface
• SELinux enforced
• u:object_r:mobicore_device:s0
• u:object_r:mobicore_user_device:s0
• u:object_r:tui_device:s0
mobicore-user
mobicore t-base-tui
13
Secure World
Exploring binary images
Trustonic Kinibi
Secure World
• sboot.bin
• Fernand Lone Sang – Reverse Engineering Samsung S6 SBOOT
• Alexander Tarasikov – Reverse-engineering Samsung Exynos 9820 bootloader and TZ
+---Firmware----------------------------+
+-+ G950FXXU3CRGH_G950FOXM3CRGH_SER.zip |
| +---------------------------------------+
|
| +---Firmware content------------------------------------------------------------+
+--->+ AP_G950FXXU3CRGH_CL14023573_QB19093103_REV00_user_low_ship_meta.tar.md5 |
+-+ BL_G950FXXU3CRGH_CL14023573_QB19093103_REV00_user_low_ship.tar.md5 |
| | CP_G950FXXU3CRGH_CP10267592_CL14023573_QB19093103_REV00_user_low_ship.tar.md5 |
| | CSC_OXM_G950FOXM3CRGH_CL14023573_QB19093103_REV00_user_low_ship.tar.md5 |
| | HOME_CSC_OXM_G950FOXM3CRGH_CL14023573_QB19093103_REV00_user_low_ship.tar.md5 |
| +-------------------------------------------------------------------------------+
|
| +--BL_G950FXXU3CRGH...--+
+--->+ cm.bin.lz4 |
| param.bin.lz4 |
+-+ sboot.bin.lz4 |
| | up_param.bin.lz4 |
| +-----------------------+
|
+-------------------------------------------------------------------------------------->
15
Trustonic Kinibi
S-Boot
• Based on ARM Trusted Firmware (now Trusted Firmware-A)
• Secondary bootloader – AP_BL2
• EL3 Monitor – AP_BL31
• Secure EL-1 Payload – AP_BL32
• U-boot – AP_BL33
+--sboot.bin-----------+
+--> Secondary Bootloader |
| EL3 Monitor |
+-+ Secure EL-1 Payload |
| | Non-secure Payload |
| +----------------------+
|
+---------------------------->
16
Trustonic Kinibi
Secure EL-1 Payload
• Contains most parts of TEE
+--Secure EL-1 Payload--+
+--> MTK |
| RTM |
| mclib |
| TAs |
| TDs |
+-----------------------+
17
Trustonic Kinibi
Secure EL-1 Payload
• Kinibi kernel – MTK
• Runtime manager – RTM
• Some trusted drivers – drcrypto, …
• Some trusted applications – STH2, …
• Internal API library - mclib
mclib
drcrypto
RTM
MTK
18
Trustonic Kinibi
Trustlets
• Trusted applications - TA, CM system TA, SP TAs
• Reside in Android file system
• Identified by GUID
GUID_3
GUID_1
GUID_2
19
Trustonic Kinibi
Inter-world communication
20
Trustonic Kinibi
Inter-world communication flow
21
Trustonic Kinibi
Trustlets
• MobiCore Load Format – MCLF
• github: mcLoadFormat.h
• IDA Pro loader
• Ghidra loader
• Signed binaries
• 32-bit executables
• Uninitialized fields
• tciBuffer_ptr
• tciBuffer_len
• mcLibEntry
• …
• Internal API via mclib
22
Zoom in
• All external calls are through mclib entry field in MCLF header
• Easy to emulate such an isolated code
• Easy to wrap in fuzzing environment
23
Fuzz smartly
AFL
Fuzz smartly
• Straightforward approach
• Fuzz trustlets from Normal World
• Non-controlled environment
• No coverage control
• No crash information
• Smart approach
• Controlled environment
• Control fuzzing coverage
• All crash information
• Explore crashes with all tools
25
Fuzz smartly
AFL
• AFL fuzzes applications
• source code – afl-gcc
• binary code – afl-unicorn
• executables – qemu usermode
• AFL mutates standard input (--) or file input (@@)
• Use AFL qemu usermode
• Convert MCLF trustlet to ELF executable
• Make a wrapper to forward standard input to the trustlet TCI
• Fuzz it with qemu mode!
26
Binary porting
Transform a trustlet to a linux application
• Make an initial stub to forward input
• Make an ELF with initial stub and trustlet
• Relocate trustlet image properly
• Transfer execution to the trustlet entry point
• Mock mclib
• Automate it for all trustlets
27
Binary porting
Call TA’s entry point
• Make an initial stub code
• Define symbols
• tciBuffer_ptr
• tciBuffer_len
• tlMain
// tlrun.c
tciBuffer = malloc(TCILEN); // get memory for TCI buffer
tciBufferLen = read(STDIN_FILENO, tciBuffer, TCILEN); // fill it from standard input
*(int*)sym_tciBuffer = tciBuffer; // fill in the fields in the trustlet's header
*(int*)sym_tciBufferLen = tciBufferLen;
tlMain_t tlmain = (tlMain_t)&sym_tlMain; // get tlMain address from symbols
tlmain(tciBuffer, tciBufferLen); // call tlMain
28
Binary porting
Relocating TA properly
• Compile our stub
• gcc –c tlrun.c –o tlrun.o
• Define symbols
• objcopy --add-symbol tlMain=$(TLMAIN)
• Adding sections
• objcopy --add-section .tlbin_text=.text.bin \
--set-section-flags .tlbin_text=code,contents,alloc,load \
tlrun.o tlrun.o.1
• Locating sections
• gcc tlrun.o.1 --section-start=.tlbin_text=0x1000 –o tlrun
29
Binary porting
Implement mclib API
• TlApi.h
• TlApiCom.h _TLAPI_EXTERN_C tlApiResult_t tlApiUnwrapObjectExt(
void *src,
• TlApiCommon.h
size_t srcLen,
• TlApiCrypto.h void *dest,
• TlApiError.h size_t *destLen,
uint32_t flags );
• TlApiHeap.h
• TlApiLogging.h
• TlApiMcSystem.h
_TLAPI_EXTERN_C void tlApiLogPrintf(
• TlApiSecurity.h const char *fmt,
• TlApiTime.h ...);
• TlApiTplay.h
• TlApiTui.h
30
Binary porting
Implement mclib dispatch
• Dispatch function
• tlApiLibEntry // entry.S
// tlrun.c .syntax unified
.arch armv7a
typedef void (*tlApiEntry_t)(int num); .globl tlApiEntry
tlApiEntry:
void (*tlApiLibEntry)(int num) __attribute__((weak)); push {r0-r4,lr}
void tlApiEntry(int num) __attribute__((noplt));
bl get_api
__attribute__((constructor)) void init() mov r12, r0
{ pop {r0}
tlApiLibEntry = tlApiEntry; pop {r0-r3,lr}
} bx r12
// tllib.c
void* get_api(int num)
{
return ptrs[num];
}
31
Binary porting
Automation for multiple TAs
• Trustlet porting parameters • Trustlet entry point
• Entry point • objcopy --add-symbol tlMain=$(TLMAIN)
• Sections locations • Sections locations
• TCI buffer length • gcc tlrun.o.1 --section-
start=.tlbin_data=$(TLDATA) –o tlrun
• Old good Makefiles
• TCI buffer length
• gcc -DTCILEN=$(TLTCI_LEN) –c tlrun.c –o
tlrun.o
32
Binary porting
Automation for multiple TAs
rem ida_auto.bat
• IDA Pro
• batch mode for /r %%f in (*.idb) do (
idascript %%f %TOOLDIR%\tlinfo.py
• Idascript )
• Ghidra
# tlinfo.py
• Headless mode
def info_segments():
ss = dict()
for s in Segments():
name = idc.get_segm_name(s)
segs.update({name: [s, idc.get_segm_end(s)]})
return segs
if __name__ == "__main__":
try:
kinibi_api.main()
print "TLMAIN := 0x%x" % (locate_tlmain() + 1)
ss = info_segments()
env_names = {".text": "TLTEXT",
".data": "TLDATA",
".bss": "TLBSS"}
33
Binary porting
Launch
~ # ./tlrun < test
34
Fuzzing
Poexali!
Fuzzing
Hardships
• QEMU and AFL QEMU patches issues
• toolchain
• AFL instrumentation issues
• Study AFL thoroughly
36
Fuzzing
It works!
37
Gathering crashes
23 trustlets – 477 crashes
afl-cmin – 225 unique cases
38
Crash analysis
Crash analysis
• Get to ARM machine
• Dynamic analysis
• Gdb scripts
• Dynamic Binary Instrumentation
• DynamoRIO
• Valgrind
• Symbolic execution
• angr
40
Crash analysis
• gdb crash analyzer
• poor information
• DynamoRIO
• cannot load so specifically constructed file
• Valgrind
• callgrind
• memcheck
• not for automatic parsing
• angr
• error-prone, time-consuming
• gdb is the only friend
41
Crash analysis
• gdb scripts
# catch.py
• Make more logging from our mclib
def handler_stop(event):
• Build SQLite database if isinstance(event, gdb.SignalEvent):
# stub.gdb print "%s at %s" % (event.stop_signal,
hex(int(gdb.parse_and_eval("$pc").cast(gdb.lookup_type("int"
set logging on )))))
set logging redirect on
target remote :5555 def handler_exit(event):
source catch.py print "================================"
continue gdb.execute("quit")
# analyze.sh
for f in $(ls $1/out/crashes)
do
echo === $f === | tee -a gdb.txt
../afl-qemu-trace -L /usr/arm-linux-gnueabi/ -g 5555 $1/tlrun < $1/out/crashes/$f 1>/dev/null 2>/dev/null
2>/dev/null &
arm-none-eabi-gdb -x stub.gdb -batch 2>/dev/null
tail -n 2 gdb.txt
../afl-qemu-trace -L /usr/arm-linux-gnueabi/ $1/tlrun < $1/out/crashes/$f > /tmp/1.qemu
done
42
Crash analysis
• Non-trivial functions
• tlApiSecSPICmd
• tlApi_callDriver
• tlApiWrapObjectExt
• tlApiUnWrapObjectExt
• …
• Exclude such cases
• Implement and get more accurate fuzzing results
43
Crash analysis
~ # sqlite3 analyze-cmin.db ‘select * from main’ | grep –v tlApiSecSPICmd
44
Results
• https://security.samsungmobile.com/securityUpdate.smsb
• SVE-2019-13958
• SVE-2019-14126
45
SVE-2019-14126
Heap overflow in keymaster trusted application
SVE-2019-14126
Root cause
• Parsing DER-encoded ASN.1
• malloc – size 1 – little endian
• memcpy – size 2 – big endian
TCI buffer
SVE-2019-14126
Security mitigations
• Trusted applications
• Per TA virtual memory
• Unable to access kernel or physical memory
• Divided into sections with different memory attributes
• TCI buffers are non-executable
• No ASLR
• only in future plans (Adding ASLR to a microkernel-based operating system)
48
SVE-2019-14126
Exploitation overview
• Strategy
1. Find a function pointer in .bss;
2. Relocate a heap chunk before the pointer;
3. Trigger memory allocation and copying at this chunk to overwrite the pointer;
4. Call overwritten pointer.
• Heap exploitation in Kinibi
• Eloi Sanfelix - TEE Exploitation
49
SVE-2019-14126
Relocating heap
• Brute force
• In heap
• create a fake chunk, pointing to .bss
• In .bss
• create one more fake chunk, pointing to itself
• next allocations loop infinitely?
• Yes – suitable address
• No, the trustlet crashed – the relocation failed
50
SVE-2019-14126
Relocating heap
• Brute force + passing the execution demo
51
SVE-2019-14126
Exploitation
• What we have
• Calling an arbitrary executable code
• No chances to execute a shellcode
• Code-reuse is possible
• Canaries in the stack
52
SVE-2019-14126
Exploitation
• JOP (Jump Oriented Programming)
ROP gadget ROP gadget JOP gadget
53
SVE-2019-14126
Exploitation
• ROPgadget --binary tlrun --thumb --range 0x1000-0xbeb44
• grep -E "; b.+ r[0-9]+$"
54
SVE-2019-14126
Exploitation
• JOP (Jump Oriented Programming)
• Jump table in memory
• One super gadget as a dispatcher
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0068b/BABEFCIB.html 55
SVE-2019-14126
Exploitation
• ROPgadget --binary tlrun --thumb --range 0x1000-0xbeb44
• grep -E "; b.+ r[0-9]+$"
• grep –E “ldm..”
56
SVE-2019-14126
Breaking keymaster
• Demo
57
SVE-2019-14126
Breaking keymaster
• Demo
• Break Android FDE through keymaster
• Extracting Qualcomm's KeyMaster Keys - Breaking Android Full Disk Encryption
• Post-Exploitation
• Escalate to Trusted Drivers
• Escalate to TEE kernel
• Escalate to EL3 Monitor
• Do anything you want
58
Conclusion
• Porting a binary to get all available toolset
• Easy
• Portable
• Fuzzing with AFL qemu mode
• Fast
• Reliable
• Exploiting vulnerabilities in Kinibi trustlets
• No ASLR
• A starting point for pwning TrustZone
• One more way to pwn Android kernel
59
Useful links
• Reverse Engineering Samsung S6 SBOOT
• Unbox Your Phone
• Trust Issues: Exploiting TrustZone TEEs
• TEE Exploitation: Exploiting Trusted Apps on Samsung’s TEE at Zer0con 2019
• BREAKING SAMSUNG'S ARM TRUSTZONE at BlackHat USA 2019
• Reverse-engineering Samsung Exynos 9820 bootloader and TZ
60
Thanks for your attention!
Andrey Akimov,
security researcher
tg: @e13fter
29 Krasnogo Kursanta st., building 2, Saint Petersburg DSecRU