Introduction to TrustZone TEE and Trustlets
The Trusted Execution Environment (TEE) is a security-critical component within modern System-on-Chips (SoCs), providing a hardware-isolated environment for sensitive operations. ARM TrustZone is a widely adopted architecture enabling this by partitioning the SoC into a Secure World and a Non-Secure World. Applications running in the Secure World are often referred to as Trusted Applications (TAs) or Trustlets. These Trustlets handle functions like secure boot, DRM, mobile payment processing, and cryptographic key management.
Reverse engineering Trustlets is a vital skill for security researchers, enabling vulnerability discovery, auditing proprietary implementations, and understanding the underlying security mechanisms. This guide provides a practical, step-by-step approach to extracting, decompiling, and analyzing Trustlets.
Understanding Trustlet Architecture
Trustlets adhere to standards, most notably the GlobalPlatform TEE Client API and Internal API specifications. They typically communicate with applications in the Non-Secure World (Rich Execution Environment or REE) via an Inter-Process Communication (IPC) mechanism, often involving shared memory. Each Trustlet is identified by a unique UUID and exposes a set of commands for interaction.
Key components within a Trustlet lifecycle include:
TA_CreateEntryPoint: Called when the Trustlet is loaded.TA_OpenSessionEntryPoint: Called when a new session is opened from the REE.TA_InvokeCommandEntryPoint: The main entry point for processing commands from the REE.TA_CloseSessionEntryPoint: Called when a session is closed.TA_DestroyEntryPoint: Called when the Trustlet is unloaded.
Phase 1: Trustlet Extraction
Locating Trustlets on an Android Device
Trustlets are typically part of the device’s firmware and can reside in various locations within the Android file system, depending on the vendor (Qualcomm, MediaTek, Samsung, etc.) and the specific TEE implementation (e.g., OP-TEE, Trusty, QSEE). Common paths include:
/vendor/firmware/tee//vendor/firmware_mnt/image//system/lib/optee_armtz//vendor/lib/optee_armtz//data/vendor_overlay/(for dynamically loaded TAs)
To extract them, you’ll need root access on the device. Connect your device via ADB:
adb shell
su
Navigate to potential directories and list their contents. Trustlets often have .ta, .elf, or no specific extension.
cd /vendor/firmware/tee/
ls -la
Once identified, pull the files to your host machine:
adb pull /vendor/firmware/tee/example_ta.ta .
Extracting from Firmware Images
If you don’t have a rooted device, you can often extract Trustlets from publicly available firmware images. Tools like Binwalk or Firmware Mod Kit (FMK) can be used to unpack these images and locate relevant partitions (e.g., `tz`, `tee`, `modem`). Trustlets within firmware images will typically be ELF binaries, potentially compressed or encrypted.
Initial Identification and Verification
After extraction, verify the file type using the file command. Most Trustlets are ELF (Executable and Linkable Format) binaries.
file example_ta.ta
Expected output might look like:
example_ta.ta: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV), dynamically linked, BuildID[sha1]=..., stripped
Phase 2: Initial Analysis and Preparation
Determining Architecture and Endianness
The file command output already provides crucial information: architecture (e.g., ARM aarch64) and endianness (LSB – Little Endian). This is essential when loading the Trustlet into a disassembler/decompiler.
Symbol Information
Use readelf to inspect the ELF headers, sections, and symbols. Trustlets are often stripped, meaning debugging symbols are removed to reduce size and obfuscate functionality.
readelf -h example_ta.ta
readelf -S example_ta.ta
readelf -s example_ta.ta
Even if stripped, some internal function names or string references might remain, offering hints about functionality.
Phase 3: Decompilation and Static Analysis
Loading into a Decompiler
Open your extracted Trustlet in a reverse engineering tool like Ghidra or IDA Pro. Set the correct architecture (ARM or AArch64) and endianness. If the tool asks for the base address, it’s often 0x0 for shared objects or a default load address for an executable. For Ghidra, ensure you select the correct processor type (e.g., ARM:LE:64:v8A for AArch64).
Identifying Entry Points
The first step in static analysis is to locate the standard GlobalPlatform TEE entry points. Even if stripped, these functions typically have a distinct structure that decompilers can recognize:
TA_CreateEntryPointTA_OpenSessionEntryPointTA_InvokeCommandEntryPointTA_CloseSessionEntryPointTA_DestroyEntryPoint
Look for calls to TEE internal APIs or common library functions. In Ghidra, search for cross-references to these function names if they are present. If stripped, you’ll need to identify them by their typical function signatures and call patterns. For instance, `TA_InvokeCommandEntryPoint` will usually take `void *session_context, uint32_t command_id, uint32_t param_types, TEE_Param params[]` or similar arguments in its compiled form.
Analyzing TA_InvokeCommandEntryPoint
This function is the most critical for understanding a Trustlet’s functionality. It typically contains a large switch-case statement or a series of if-else branches, dispatching control based on the `command_id` passed from the REE. Each case corresponds to a specific service or operation offered by the Trustlet.
// Simplified pseudo-code for TA_InvokeCommandEntryPoint
TEE_Result TA_InvokeCommandEntryPoint(
void *session_context,
uint32_t command_id,
uint32_t param_types,
TEE_Param params[]
) {
TEE_Result res;
switch (command_id) {
case CMD_SECURE_STORAGE_READ:
// Handle secure storage read operation
res = handle_secure_read(session_context, param_types, params);
break;
case CMD_ENCRYPT_DATA:
// Handle data encryption
res = handle_encrypt_data(session_context, param_types, params);
break;
case CMD_GENERATE_KEY:
// Handle key generation
res = handle_generate_key(session_context, param_types, params);
break;
// ... other commands
default:
res = TEE_ERROR_BAD_PARAMETERS;
break;
}
return res;
}
Inside each command handler, pay close attention to:
- Parameter handling: How
param_typesis validated and howparams[](containing values, memory references, etc.) are accessed. Vulnerabilities often arise from improper validation of input parameters, leading to buffer overflows or information leaks. - TEE APIs: Identify calls to functions like
TEE_Malloc,TEE_Free,TEE_MemMove,TEE_CheckAccessRights,TEE_OpenPersistentObject,TEE_ReadObjectData,TEE_WriteObjectData,TEE_InvokeTACommand(for inter-TA communication), and cryptographic primitives (e.g.,TEE_CipherInit,TEE_AEInit). These indicate sensitive operations. - Secure Storage: If the Trustlet interacts with secure storage, trace how objects are opened, read, and written. This can reveal how sensitive data (like cryptographic keys) is protected.
- Inter-TA Communication: If
TEE_InvokeTACommandis used, identify which other Trustlets are being called and what commands are invoked. This maps out the TEE’s internal dependencies.
Data Flow and Vulnerability Spotting
Trace data flow from input parameters to sensitive operations. Look for common vulnerability patterns:
- Integer Overflows/Underflows: Especially when calculating buffer sizes or offsets.
- Buffer Overflows: When copying data from untrusted REE buffers into TEE buffers without proper size checks.
- Use-After-Free: Improper memory management.
- Information Disclosure: Returning sensitive data to the REE that should remain private.
- Logic Bugs: Flaws in the implementation of cryptographic algorithms or access control policies.
Phase 4: Dynamic Analysis (Challenges)
Dynamic analysis of Trustlets is significantly harder than for REE applications due to the TEE’s isolation. Direct debugging with traditional debuggers is usually not possible without specialized hardware or a modified TEE OS build. Approaches include:
- Logging: Modifying the TEE OS or Trustlet to output debug information to secure console.
- Emulation: Using frameworks like QEMU with TEE support (e.g., OP-TEE on QEMU) to enable debugging.
- Fuzzing: Sending various inputs via the REE client application to trigger crashes or unexpected behavior.
Conclusion
Reverse engineering Trustlets is a complex but rewarding endeavor. By systematically extracting, analyzing, and decompiling these secure applications, researchers can gain deep insights into device security, uncover vulnerabilities, and contribute to the overall robustness of trusted execution environments. While challenging, mastering these techniques is essential for anyone serious about modern hardware and mobile security.
Android Mobile Specs & Compare Directory
Are you researching mobile hardware properties, processor SoCs, GPU chipsets, or RAM configurations? Access our complete specs catalog to compare up to 5 devices side-by-side!
Compare Devices Specs →