Android Hardware Reverse Engineering

Your First EM-Field Lab: Extracting Cryptographic Keys from Android Devices (Step-by-Step)

Google AdSense Native Placement - Horizontal Top-Post banner

Introduction to EM-Field Side-Channel Analysis

Electromagnetic (EM) side-channel analysis is a powerful, non-invasive technique used to extract sensitive information, such as cryptographic keys, from electronic devices. It relies on the principle that electrical activity within a device generates measurable electromagnetic radiation. By carefully analyzing these radiated EM fields during cryptographic operations, an attacker can infer the secret keys being processed. This article provides a comprehensive, step-by-step guide to setting up an EM-field laboratory and outlines the methodology for attempting cryptographic key extraction from Android devices.

The Physics of Information Leakage

Every transistor switching, every current flowing, generates a tiny electromagnetic field. During cryptographic computations, these operations are highly dependent on the processed data, including the secret key. The variations in EM radiation, though subtle, can be correlated with the internal state of the cryptographic algorithm. Specialized EM probes and high-bandwidth oscilloscopes are used to capture these minute fluctuations, transforming them into usable data traces for analysis.

Why Android Devices?

Android devices, despite their robust software security, remain vulnerable to physical side-channel attacks due to their widespread use, diverse hardware implementations, and often accessible physical architecture. While modern SoCs integrate hardware security modules, their physical implementations still present opportunities for EM leakage. Targeting specific cryptographic operations, such as AES or RSA computations performed by the CPU or dedicated cryptographic accelerators, can yield exploitable EM traces.

Setting Up Your EM-Field Laboratory

A successful EM-field attack requires specialized equipment and a careful setup to minimize noise and maximize signal acquisition quality.

Essential Equipment

  • Near-Field EM Probes: Various types (H-field, E-field, current probes) are needed to detect different components of the EM field. Loop probes are common for H-field detection.
  • High-Bandwidth Oscilloscope: A digital storage oscilloscope (DSO) with at least 1 GHz bandwidth and a high sampling rate (e.g., 5 GS/s) is crucial for capturing fast transient signals.
  • Low-Noise Amplifier (LNA): To boost the weak EM signals captured by the probe before feeding them into the oscilloscope.
  • Motorized XYZ Stage: For precise and repeatable positioning of the EM probe over the target device.
  • Faraday Cage/Shielded Enclosure: To reduce ambient EM noise interference, ensuring clean signal acquisition.
  • Target Android Device: A device that can be physically modified, rooted, and ideally has a known cryptographic operation that can be triggered repeatedly.
  • Triggering Mechanism: A way to synchronize the oscilloscope’s acquisition with the start of the cryptographic operation on the Android device (e.g., GPIO pin, software trigger).

Software Toolkit

  • Oscilloscope Control Software: For automated data acquisition from the DSO (e.g., custom Python scripts using SCPI commands).
  • Data Analysis Framework: Tools like ChipWhisperer, open-source libraries (e.g., NumPy, SciPy for Python), or commercial solutions for signal processing and side-channel analysis.
  • Firmware/OS Modification Tools: ADB, fastboot, custom recovery (TWRP) for preparing the Android device.

Step-by-Step Key Extraction Methodology

Step 1: Device Preparation and Target Identification

First, physically prepare the Android device. This often involves carefully disassembling the device to expose the main printed circuit board (PCB) and the System-on-Chip (SoC). Use a microscope to identify key components: the main CPU, cryptographic accelerators, and memory. Research the SoC architecture to pinpoint the most likely areas of cryptographic activity.

Simultaneously, prepare the software environment:

  1. Root the Android Device: This grants necessary permissions for advanced control.
  2. Develop a Test Application: Create a native Android application (NDK) that repeatedly performs the target cryptographic operation (e.g., AES encryption with a known plaintext). This allows precise control over the operation timing.
  3. Implement a Software Trigger: Modify the Android kernel or test application to toggle a GPIO pin at the precise moment the cryptographic operation begins. This provides a hardware synchronization signal for the oscilloscope.
// Example C code snippet in a native Android app for triggering and crypto operation
#include 
#include 
#include 
#include 

#define LOG_TAG "CryptoTrigger"

// Placeholder for a function to toggle GPIO (requires root/kernel module)
void toggle_gpio_trigger(int state) {
    // In a real scenario, this would involve writing to /sys/class/gpio/gpioX/value
    // or calling a custom kernel module. For demonstration, we just log.
    __android_log_print(ANDROID_LOG_INFO, LOG_TAG, "GPIO Trigger: %d", state);
}

JNIEXPORT void JNICALL
Java_com_example_cryptotrigger_MainActivity_performAES(JNIEnv *env, jobject thiz,
                                                           jbyteArray plaintext_arr,
                                                           jbyteArray key_arr) {
    jbyte *plaintext = (*env)->GetByteArrayElements(env, plaintext_arr, NULL);
    jbyte *key = (*env)->GetByteArrayElements(env, key_arr, NULL);
    jsize plaintext_len = (*env)->GetArrayLength(env, plaintext_arr);
    jsize key_len = (*env)->GetArrayLength(env, key_arr);

    if (key_len != 16 && key_len != 24 && key_len != 32) {
        __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "Invalid AES key length");
        goto cleanup;
    }

    AES_KEY aes_key;
    AES_set_encrypt_key((const unsigned char *)key, key_len * 8, &aes_key);

    // Trigger ON before crypto operation
    toggle_gpio_trigger(1);
    __android_log_print(ANDROID_LOG_INFO, LOG_TAG, "Starting AES encryption");

    // Perform AES encryption (simplified, usually done in blocks)
    unsigned char ciphertext[plaintext_len];
    // AES_encrypt((const unsigned char *)plaintext, ciphertext, &aes_key);
    // For a real attack, we'd loop this for multiple blocks or operations
    for (int i = 0; i < plaintext_len; i += AES_BLOCK_SIZE) {
        if (i + AES_BLOCK_SIZE ReleaseByteArrayElements(env, plaintext_arr, plaintext, JNI_ABORT);
    (*env)->ReleaseByteArrayElements(env, key_arr, key, JNI_ABORT);
}

Step 2: EM Trace Acquisition

Mount the EM probe on the XYZ stage. Carefully position the probe directly over the identified cryptographic module on the exposed PCB. Connect the probe to the LNA, then to an input channel of the oscilloscope. Connect the Android device’s GPIO trigger output to another oscilloscope channel.

  • Oscilloscope Setup: Configure the oscilloscope to trigger on the rising edge of the GPIO signal. Set the acquisition window to capture the entire cryptographic operation. Adjust vertical sensitivity and horizontal scale for optimal signal visibility.
  • Automated Acquisition: Use a script to repeatedly run the test application on the Android device, triggering the cryptographic operation. For each operation, the script should command the oscilloscope to capture and save the EM trace data (voltage samples over time). Thousands or even millions of traces might be required for effective analysis.
# Pseudocode for automated trace acquisition using PyVISA (SCPI commands)
import visa
import time
import numpy as np

# rm = visa.ResourceManager() # Initialize VISA resource manager
# scope = rm.open_resource('GPIB0::7::INSTR') # Replace with your oscilloscope address

def acquire_trace(scope_obj, trace_num):
    # Example: Send SCPI commands to acquire a single trace
    scope_obj.write(":STOP") # Stop continuous acquisition
    scope_obj.write(":SINGLE") # Set to single acquisition mode
    time.sleep(0.5) # Wait for acquisition to complete
    # scope_obj.write(":WAV:DATA? CH1") # Query waveform data for Channel 1
    # data = scope_obj.read_bytes(buffer_size=1024*1024)
    # Process and save data (e.g., to CSV or binary format)
    print(f"Acquired trace {trace_num}")
    return np.random.rand(1000) # Placeholder for actual data

def trigger_android_crypto():
    # ADB command to start the crypto operation in the Android app
    # adb shell am start -n com.example.cryptotrigger/.MainActivity
    # adb shell input tap X Y # Or use an actual Intent
    print("Triggering Android crypto operation...")
    time.sleep(0.1) # Simulate delay

# main acquisition loop
# for i in range(NUM_TRACES):
#     trigger_android_crypto()
#     trace_data = acquire_trace(scope, i)
#     np.save(f"trace_{i}.npy", trace_data)

Step 3: Data Pre-processing and Analysis

Once traces are acquired, pre-processing is essential to prepare them for analysis.

  • Alignment: Traces often have slight timing jitters. Techniques like cross-correlation or phase-locked loops are used to align them precisely.
  • Filtering: Apply digital filters (e.g., low-pass, band-pass) to remove high-frequency noise and isolate signals of interest.
  • Dimensionality Reduction: Techniques like Principal Component Analysis (PCA) can reduce the complexity of high-dimensional trace data.

The core of key extraction lies in side-channel analysis techniques:

  • Differential Power Analysis (DPA): This involves dividing the acquired traces into groups based on hypothetical intermediate values (e.g., output of a specific S-box operation) derived from a guessed key byte. By computing the difference between the average traces of these groups, a distinct spike appears if the key byte guess is correct.
  • Correlation Power Analysis (CPA): A more powerful variant, CPA calculates the Pearson correlation coefficient between hypothetical intermediate power consumption (modeled using a Hamming weight or Hamming distance model) and the actual EM traces. A strong correlation coefficient indicates a correct key byte guess.
# Pseudocode for a simplified CPA attack
import numpy as np

def hamming_weight(n):
    return bin(n).count('1')

def perform_cpa(traces, plaintexts, partial_key_guesses):
    num_traces, trace_len = traces.shape
    num_guesses = len(partial_key_guesses)
    
    correlation_matrix = np.zeros((num_guesses, trace_len))
    
    for guess_idx, guess in enumerate(partial_key_guesses):
        # Simulate intermediate value calculation (e.g., S-box output after XORing with key)
        # For AES, this would involve one byte of plaintext XORed with one byte of key
        # then passed through the S-box.
        
        # Placeholder: Assume 'intermediate_values' are derived from plaintext[0] ^ guess
        hypothetical_intermediates = np.array([
            hamming_weight(plaintext[0] ^ guess) # Example for one S-box input
            for plaintext in plaintexts
        ])
        
        # Calculate correlation for each time point
        for t in range(trace_len):
            correlation_matrix[guess_idx, t] = np.corrcoef(hypothetical_intermediates, traces[:, t])[0, 1]
            
    # The correct key guess will show a peak in correlation_matrix
    # Find the guess index with the maximum absolute correlation over all time points
    best_guess_idx = np.unravel_index(np.argmax(np.abs(correlation_matrix)), correlation_matrix.shape)[0]
    
    return partial_key_guesses[best_guess_idx], correlation_matrix[best_guess_idx, :]

# Example usage:
# traces = np.load("all_traces.npy") # Shape: (num_traces, trace_length)
# plaintexts = np.load("all_plaintexts.npy") # Shape: (num_traces, 16) for AES
# potential_key_bytes = range(256) # All possible values for a single key byte

# best_byte_guess, max_correlation_trace = perform_cpa(traces, plaintexts, potential_key_bytes)
# print(f"Best guessed key byte: {best_byte_guess}")

Step 4: Key Hypothesis and Verification

By repeatedly applying DPA or CPA, one can deduce each byte of the cryptographic key. Once a candidate key is assembled, it must be verified. This involves decrypting known ciphertexts (captured during the attack) using the hypothesized key. If the decrypted output matches the original plaintexts, the key extraction is successful.

Challenges and Ethical Considerations

EM-field analysis is not without its challenges. High levels of environmental noise, complex chip designs, and countermeasures (e.g., randomization, noise injection, dual-rail logic) can significantly hinder attacks. Advanced techniques like template attacks or machine learning-based side-channel analysis might be required for modern devices.

It is crucial to emphasize that performing such attacks without explicit authorization is illegal and unethical. This guide is for educational and research purposes only, intended to foster understanding of device security and vulnerabilities. Always ensure you have appropriate permissions and adhere to all legal and ethical guidelines when conducting any form of security research.

Conclusion

EM-field side-channel analysis represents a fascinating and powerful domain within hardware security. While technically demanding, setting up an EM-field lab and understanding the principles of key extraction from Android devices provides invaluable insights into the physical security of embedded systems. By following this detailed guide, researchers and security enthusiasts can begin their journey into the exciting world of EM-based cryptographic attacks, contributing to a deeper understanding of device vulnerabilities and the development of more robust security countermeasures.

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