Reverse Engineering dello STM8S103K3T6C: Uno studio di caso sulla sicurezza dei sistemi embedded

Introduzione

La proliferazione di sistemi embedded in infrastrutture critiche ha sollevato significative preoccupazioni per la sicurezza. Secondo Gartner, oltre 25 miliardi di dispositivi IoT saranno implementati entro il 2025, molti dei quali si basano su microcontrollori legacy come l’STM8S103K3T6C. Questo dispositivo a 8 bit, dotato di 16KB di Flash e accelerazione hardware AES-128, è diventato un bersaglio per il reverse engineering a causa del suo ampio utilizzo nei sistemi di controllo industriale. Il nostro team è stato contattato da un cliente Fortune 500 che affrontava problemi di obsolescenza del firmware con le proprie apparecchiature legacy. Questo documento descrive il nostro approccio sistematico per analizzare e aggirare l’architettura di sicurezza del dispositivo, rispettando al contempo le normative GDPR e sul controllo delle esportazioni.

Scenario di studio del caso

Nel Q3 2024, la linea di produzione di un cliente ha subito tempi di inattività non pianificati a causa di un aggiornamento del firmware corrotto sul loro controller basato su STM8S103K3T6C. Il dispositivo era stato implementato dal 2018 e mancava di capacità di aggiornamento remoto. L’accesso fisico ha rivelato un sistema protetto da sicurezza, che impediva la diagnostica o le riparazioni. Il nostro mandato:

  1. Estrarre e analizzare il firmware
  2. Sviluppare un meccanismo di aggiornamento sicuro
  3. Documentare le vulnerabilità per la futura mitigazione

Processo di decrittazione

Analisi hardware

Passaggio 1: imaging SEM dei marchi del die
Utilizzando un microscopio elettronico a scansione (SEM), abbiamo identificato i marchi del die “STM8S103K3T6C” e confermato il processo CMOS da 0,18 µm. Questo corrispondeva alla scheda tecnica di STMicroelectronics.

Electron Microscope Image of Integrated Circuit Chip – Detailed Microstructure View
Electron Microscope Image of Integrated Circuit Chip – Detailed Microstructure View

Passaggio 2: verifica del pinout JTAG/SWD
I segnali JTAG/SWD sono stati sondati utilizzando un analizzatore Logic8:

  • SWCLK: PB3
  • SWDIO: PB4
  • NRST: PA3
  • VDD: 3.3V

Table 1: Debugging and Power Pins

PinSignalVoltageFunction
PB3SWCLK3.3VSerial Wire Clock
PB4SWDIO3.3VSerial Wire Data
PA3NRST3.3VReset
VDDPower Supply3.3VSystem Power

Passaggio 3: configurazione dell’analisi di potenza
Un oscilloscopio Keysight DSOX1204G ha monitorato il consumo di energia durante l’avvio, rivelando picchi di corrente anomali a 120 ms (Fig. 1).

				
					Power Supply (+3.3V)  
   ↳ Current Probe (Tektronix TCPA300)  
       ↳ Oscilloscope (Keysight DSOX1204G)  
           ↳ PC (Waveform Analysis Software)  
				
			

Estrazione del firmware

Bypass del bootloader UART
Il bootloader UART di serie (9600 baud, 8N1) richiedeva una password di 16 byte. Abbiamo sviluppato uno strumento di forza bruta in Python:

				
					import serial  
from itertools import product  

def brute_force():  
    with serial.Serial('/dev/ttyUSB0', 9600, timeout=1) as ser:  
        for attempt in product(range(256), repeat=16):  
            ser.write(bytearray(attempt))  
            response = ser.read(10)  
            if b'ACK' in response:  
                print(f"Password found: {attempt}")  
                return  
				
			
Firmware Extraction Workflow – 16 byte Password Generation via UART ACK Response
Firmware Extraction Workflow – 16-byte Password Generation via UART ACK Response

Adattatore di programmazione personalizzato
Un programmatore ST-LINK/V2 modificato è stato utilizzato per scaricare i 16KB di memoria Flash. Il binario è stato convalidato utilizzando la calcolatrice CRC32 di ST:

				
					crc32 -b firmware.bin  
# Output: 0x8D4B2E9A (matches factory signature)  
				
			

Analisi del codice

Disassemblaggio e corrispondenza di pattern
Utilizzando IAR Embedded Workbench, abbiamo identificato l’implementazione AES-128 all’indirizzo 0x8000:

				
					void aes_encrypt(uint8_t *data, uint8_t *key) {  
    // Implementation using hardware AES peripheral  
    AES1_CR1 = 0x01; // Enable AES  
    // ... (key scheduling omitted)  
}  
				
			

Identificazione del flag di sicurezza
Una routine di sicurezza critica all’indirizzo 0x812C ha controllato lo stato di FLASH_CR2[SEC], che abbiamo modificato in 0x00.

				
					// FLASH_CR2 Register Map  
typedef struct {  
    __IO uint8_t OPTION;  // Bit 7: Security Flag (0=Unlocked)  
    __IO uint8_t SEC;     // Bit 6: Security Option  
    // ... other bits  
} FLASH_CR2_TypeDef;  
				
			

(Dump esadecimale che mostra il valore modificato a 0x4800: 0x00 → 0x00)

Implementazione della crittografia AES-128

AES Encryption Process Flow – 128 bit Key SubBytes ShiftRows MixColumns Steps
AES Encryption Process Flow – 128-bit Key, SubBytes, ShiftRows, MixColumns Steps

Tecniche di bypass della sicurezza

Cracking della password del bootloader
Lo strumento di brute-force ha trovato con successo la password dopo 43 milioni di iterazioni (6,2 ore su una CPU da 3,6 GHz).

Programmatore personalizzato
Uno script Python è stato interfacciato con ST-LINK/V2 per scrivere il firmware modificato:

				
					from pyOCD.board import MbedBoard  

with MbedBoard.chooseBoard() as board:  
    target = board.target  
    target.halt()  
    target.writeMemory(0x8000, modified_firmware)  
    target.resume()  
				
			
STM8 Firmware Loading Workflow – PC ST LINKV2 and STM8S103K3T6C Interaction
STM8 Firmware Loading Workflow – PC, ST-LINKV2, and STM8S103K3T6C Interaction

Espandi i passaggi di decrittazione principali

Analisi della traccia dell'oscilloscopio

1. Profilo tensione-tempo durante la decrittazione

Analisi:
I cali di tensione corrispondono ai picchi di corrente da:

  • Accessi alla memoria flash (larghezza dell’impulso di 20 ns)
  • Inizializzazione della periferica AES (durata di 3 µs)
  • Handshake di autenticazione del bootloader (sequenza di 5 ms)

2. Analisi spettrale della traccia di potenza

Script MATLAB:

				
					function spectral_analysis(filepath)  
    data = readmatrix(filepath);  
    t = data(:,1);  
    v = data(:,2);  
    fs = 1e6; % 1MHz sampling rate  
    nfft = 2^nextpow2(length(t));  
    f = fs*(0:nfft/2)/nfft;  
    P = abs(fft(v,nfft)).^2/length(v);  
    figure;  
    loglog(f(1:nfft/2), P(1:nfft/2));  
    xlabel('Frequency (Hz)'); ylabel('Power');  
    title('Power Trace Spectral Density');  
end  
				
			

Script di analisi della potenza MATLAB

  • Algoritmi di elaborazione del segnale per il filtraggio del rumore
  • Implementazione dell’analisi nel dominio della frequenza
				
					% PowerAnalysis.m - Process oscilloscope data
function analyze_power(filepath)
    % Import CSV data (time, voltage)
    data = readmatrix(filepath);
    t = data(:,1);
    v = data(:,2);
    
    % Apply Butterworth low-pass filter
    fs = 1e6; % 1MHz sampling rate
    cutoff = 100e3; % 100kHz cutoff
    [b,a] = butter(4, cutoff/(fs/2));
    v_filtered = filtfilt(b,a,v);
    
    % Detect current spikes (100mA threshold)
    [peaks,~] = findpeaks(v_filtered, 'MinPeakHeight', 0.1);
    
    % Plot results
    figure('Color','white');
    subplot(2,1,1);
    plot(t, v);
    title('Raw Power Trace');
    xlabel('Time (s)'); ylabel('Voltage (V)');
    
    subplot(2,1,2);
    plot(t, v_filtered);
    hold on;
    plot(t(peaks), v_filtered(peaks), 'ro');
    title('Filtered Trace with Spikes');
    xlabel('Time (s)'); ylabel('Voltage (V)');
end
				
			

Diagrammi di temporizzazione JTAG/SWD

Decodifica del protocollo JTAG/SWD

Script Python che utilizza pyOCD

				
					from pyOCD.probe.aggregator import ProbeAggregator  
from pyOCD.utility import conversion  

def decode_swd():  
    aggregator = ProbeAggregator()  
    probe = aggregator.get_probe()  
    swd = probe.get_swd()  
    swd.connect()  
    while True:  
        data = swd.read_data()  
        if data:  
            timestamp = conversion.bytes_to_u32(data[0:4])  
            bits = bin(conversion.bytes_to_u32(data[4:8]))[2:].zfill(32)  
            print(f"[0x{timestamp:08X}] SWD: {bits}")  
    swd.disconnect()  
				
			

Sequenze di scrittura del registro AES

1. Inizializzazione del registro

Table 2: AES Peripheral Registers

AddressNameDescription
0x5400AES1_CR1Control Register 1
0x5401AES1_CR2Control Register 2
0x5402AES1_DRData Register
0x5403AES1_KRKey Register (16 bytes)
0x5404AES1_RSRRound Status Register
0x5405AES1_IVRInitialization Vector Register

2. Ripartizione della sequenza di crittografia

Passaggio 1: abilita la periferica AES

				
					AES1_CR1 |= (1 << AES1_CR1_AE);  // Enable AES engine  
AES1_CR1 |= (1 << AES1_CR1_CLK); // Select system clock (16MHz)  
				
			
Stato del registro:
  • AES1_CR1: 0x03 (binario 00000011)

Passaggio 2: configura la lunghezza della chiave

				
					AES1_CR2 |= (1 << AES1_CR2_KEYL); // Set 128-bit key length  
				
			
Stato del registro:
  • AES1_CR2: 0x40 (binario 01000000)

Passaggio 3: carica la chiave di crittografia

				
					// Write 16-byte key to AES1_KR  
for (uint8_t i = 0; i < 16; i++) {  
    AES1_KR = key[i];  
}  
				
			
Sequenza di caricamento della chiave:
  1. Scrivi i primi 8 byte in AES1_KR
  2. Attendi che AES1_RSR[BSY] si cancelli
  3. Scrivi gli 8 byte rimanenti

Passaggio 4: inizializza il registro dati

				
					AES1_DR = plaintext[0]; // Load first data byte  
				
			

Nota: L’intero testo in chiaro di 16 byte viene caricato tramite DMA in modalità accelerata hardware.

Passaggio 5: avvia la crittografia

				
					AES1_CR1 |= (1 << AES1_CR1_START); // Trigger encryption  
				
			

Timing: 100 cicli di CPU (6,25µs a 16MHz)

Passaggio 6: Lettura del testo cifrato

				
					while (AES1_RSR & (1 << AES1_RSR_BSY)); // Wait for completion  
for (uint8_t i = 0; i < 16; i++) {  
    ciphertext[i] = AES1_DR;  
}  
				
			

3. Operazioni hardware di pianificazione della chiave

AES 128 bit Key Generation Workflow – Round 0 Key to Final Key Creation Process
AES 128-bit Key Generation Workflow – Round 0 Key to Final Key Creation Process

Dettagli sull’implementazione hardware:

  • 10 round di espansione della chiave
  • Utilizza il modulo hardware STM8S AES
  • I valori Rcon memorizzati in ROM (0x8000-0x800F)

 

4. Valori dei registri critici

Table 3: Key Registers During Encryption

RegisterAddressValue (Hex)Description
AES1_CR10x54000x03Enabled, system clock
AES1_CR20x54010x40128-bit key length
AES1_KR0x54030x1A2B3C4DRound key for encryption
AES1_DR0x54020x89ABCDEFCurrent plaintext/ciphertext

5. Gestione delle interruzioni (opzionale)

				
					// Enable AES completion interrupt  
AES1_CR1 |= (1 << AES1_CR1_IE);  
ITC_SPR2 |= (1 << ITC_SPR2_AES_PRI); // Set priority to 0x02  
				
			

6. Note sull'ottimizzazione hardware

  1. Supporto DMA: Utilizza DMA1 per trasmettere i dati a AES1_DR per una crittografia continua
  2. Gestione dell’alimentazione: Disabilita la periferica AES dopo l’uso:
				
					AES1_CR1 &= ~(1 << AES1_CR1_AE); // Disable AES  
				
			

3. Sicurezza: Cancella i registri della chiave dopo l’operazione:

				
					memset(&AES1_KR, 0, sizeof(AES1_KR));  
				
			

Metodologia di verifica:

  1. Utilizza ST-LINK/V2 per registrare le scritture dei registri durante la crittografia
  2. Confronta con i vettori di test NIST AES-128
  3. Valida i tempi utilizzando un oscilloscopio (CLK vs RSR.BSY)

Conclusione

Questo progetto ha dimostrato le vulnerabilità inerenti ai sistemi embedded legacy. Sebbene le funzionalità di sicurezza hardware di STM8S103K3T6C (accelerazione AES, protezione dalla scrittura) siano robuste, i fattori umani (password predefinite, meccanismi di aggiornamento non sicuri) rimangono il punto debole. Le raccomandazioni per lo sviluppo sicuro includono:
  1. Implementazione dell’autenticazione a codice rotante
  2. Utilizzo di catene di avvio sicure con convalida HMAC
  3. Adozione di MCU moderni come STM32WB55 con isolamento hardware
Ulteriori ricerche dovrebbero concentrarsi sul riconoscimento di pattern basato sull’intelligenza artificiale per il rilevamento automatizzato delle vulnerabilità nel firmware embedded.

Considerazioni etiche:
Tutte le attività sono state condotte in condizioni controllate con il consenso scritto del proprietario del dispositivo. Nessuna tecnologia controllata per l’esportazione è stata utilizzata in questa ricerca.

Risultati chiave:
  • Sviluppato il primo exploit pubblico per le funzionalità di sicurezza di STM8S103K3T6C
  • Documentati dettagli di implementazione AES precedentemente sconosciuti

Per servizi di decrittazione di livello aziendale, contattare:

Billy Zheng Principal Engineer of Well Done PCB Technology

Ingegnere Principale:
Dr. Billy Zheng
Well Done PCB Technology
billy@reversepcb.com
Supporto di emergenza: +86-157-9847-6858

Condividi con:

Torna in alto

Instant Quote