Android Hardware Reverse Engineering

Practical Guide to TEE Application (Trustlet) Reverse Engineering: Extraction, Decompilation, and Analysis

Google AdSense Native Placement - Horizontal Top-Post banner

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_CreateEntryPoint
  • TA_OpenSessionEntryPoint
  • TA_InvokeCommandEntryPoint
  • TA_CloseSessionEntryPoint
  • TA_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_types is validated and how params[] (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_InvokeTACommand is 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 →
Google AdSense Inline Placement - Content Footer banner