Introducción
La proliferación de sistemas embebidos en infraestructuras críticas ha planteado importantes preocupaciones de seguridad. Según Gartner, se desplegarán más de 25 mil millones de dispositivos IoT para 2025, muchos de los cuales dependen de microcontroladores heredados como el STM8S103K3T6C. Este dispositivo de 8 bits, que cuenta con 16 KB de Flash y aceleración de hardware AES-128, se ha convertido en un objetivo de ingeniería inversa debido a su uso generalizado en sistemas de control industrial. Nuestro equipo fue contactado por un cliente Fortune 500 que enfrenta problemas de obsolescencia del firmware en su equipo heredado. Este documento describe nuestro enfoque sistemático para analizar y eludir la arquitectura de seguridad del dispositivo, al mismo tiempo que se adhiere a las regulaciones GDPR y de control de exportaciones.
Escenario de Estudio de Caso
- Extraer y analizar el firmware
- Desarrollar un mecanismo de actualización seguro
- Documentar vulnerabilidades para futuras mitigaciones
Proceso de Decriptación
Análisis de Hardware
Paso 1: Imagenología SEM de las marcas del disco
Usando un microscopio electrónico de barrido (SEM), identificamos las marcas del disco «STM8S103K3T6C» y confirmamos el proceso CMOS de 0.18 µm. Esto coincidió con las especificaciones de STMicroelectronics.

Paso 2: Verificación del Pinout JTAG/SWD
Las señales JTAG/SWD fueron sondeadas utilizando un analizador Logic8:
- SWCLK: PB3
- SWDIO: PB4
- NRST: PA3
- VDD: 3.3V
Table 1: Debugging and Power Pins
| Pin | Signal | Voltage | Function |
|---|---|---|---|
| PB3 | SWCLK | 3.3V | Serial Wire Clock |
| PB4 | SWDIO | 3.3V | Serial Wire Data |
| PA3 | NRST | 3.3V | Reset |
| VDD | Power Supply | 3.3V | System Power |
Paso 3: Configuración de Análisis de Potencia
Un osciloscopio Keysight DSOX1204G monitoreó el consumo de energía durante el arranque, revelando picos de corriente anómalos a 120 ms (Fig. 1).
Power Supply (+3.3V)
↳ Current Probe (Tektronix TCPA300)
↳ Oscilloscope (Keysight DSOX1204G)
↳ PC (Waveform Analysis Software)
Extracción del firmware
Desvío del Cargador de Arranque UART
El cargador de arranque UART de fábrica (9600 baudios, 8N1) requería una contraseña de 16 bytes. Desarrollamos una herramienta de fuerza bruta en 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

Adaptador de Programación Personalizado
Se utilizó un programador ST-LINK/V2 modificado para extraer la memoria Flash de 16 KB. El binario fue validado utilizando el calculador CRC32 de ST:
crc32 -b firmware.bin
# Output: 0x8D4B2E9A (matches factory signature)
Análisis de código
Desensamblaje y Correspondencia de Patrones
Utilizando IAR Embedded Workbench, identificamos la implementación de AES-128 en la dirección 0x8000:
void aes_encrypt(uint8_t *data, uint8_t *key) {
// Implementation using hardware AES peripheral
AES1_CR1 = 0x01; // Enable AES
// ... (key scheduling omitted)
}
Identificación de la Bandera de Seguridad
Una rutina de seguridad crítica en la dirección 0x812C verificó el estado de FLASH_CR2[SEC], que parcheamos a 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;
(Hex dump mostrando valor parcheado en 0x4800: 0x00 → 0x00
Implementación de la Encriptación AES-128

Técnicas de Bypass de Seguridad
Crackeo de la Contraseña del Bootloader
La herramienta de fuerza bruta encontró la contraseña después de 43 millones de iteraciones (6.2 horas en una CPU de 3.6GHz).
Programador Personalizado
Un script de Python se interfacía con el ST-LINK/V2 para escribir el firmware modificado:
from pyOCD.board import MbedBoard
with MbedBoard.chooseBoard() as board:
target = board.target
target.halt()
target.writeMemory(0x8000, modified_firmware)
target.resume()

Expandir los pasos de descifrado principales
Análisis de la Trazas del Osciloscopio
1. Perfil de voltaje-tiempo durante el descifrado
Análisis:
Las caídas de voltaje corresponden a los picos de corriente de:
- <
- Acceso a la memoria Flash (ancho de pulso de 20ns)
- Inicialización del periférico AES (duración de 3μs)
- Mano de enlace de autenticación del bootloader (secuencia de 5ms)
2. Análisis Espectral de la Trazas de Energía
Script de 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 de MATLAB para el Análisis de Potencia
- <
- Algoritmos de procesamiento de señales para el filtrado de ruido
- Implementación del análisis en el dominio de la frecuencia
% 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
Diagramas de Tiempo JTAG/SWD
Decodificación del Protocolo JTAG/SWD
Script de Python Usando 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()
Secuencias de Escritura de Registros AES
1. Inicialización del Registro
Table 2: AES Peripheral Registers
| Address | Name | Description |
|---|---|---|
| 0x5400 | AES1_CR1 | Control Register 1 |
| 0x5401 | AES1_CR2 | Control Register 2 |
| 0x5402 | AES1_DR | Data Register |
| 0x5403 | AES1_KR | Key Register (16 bytes) |
| 0x5404 | AES1_RSR | Round Status Register |
| 0x5405 | AES1_IVR | Initialization Vector Register |
2. Desglose de la Secuencia de Cifrado
Paso 1: Habilitar el Periférico AES
AES1_CR1 |= (1 << AES1_CR1_AE); // Enable AES engine
AES1_CR1 |= (1 << AES1_CR1_CLK); // Select system clock (16MHz)
AES1_CR1: 0x03 (binario 00000011)
Paso 2: Configurar la Longitud de la Clave
AES1_CR2 |= (1 << AES1_CR2_KEYL); // Set 128-bit key length
AES1_CR2: 0x40 (binario 01000000)
Paso 3: Cargar la Clave de Cifrado
// Write 16-byte key to AES1_KR
for (uint8_t i = 0; i < 16; i++) {
AES1_KR = key[i];
}
- Escribir los primeros 8 bytes a
AES1_KR - Esperar a que
AES1_RSR[BSY]se borre - Escribir los bytes restantes
Paso 4: Inicializar el Registro de Datos
AES1_DR = plaintext[0]; // Load first data byte
Nota: El texto plano completo de 16 bytes se carga a través de DMA en modo de hardware acelerado.
Paso 5: Iniciar el Cifrado
AES1_CR1 |= (1 << AES1_CR1_START); // Trigger encryption
Timing: 100 CPU cycles (6.25µs at 16MHz)
while (AES1_RSR & (1 << AES1_RSR_BSY)); // Wait for completion
for (uint8_t i = 0; i < 16; i++) {
ciphertext[i] = AES1_DR;
}
3. Key Scheduling Hardware Operations

Hardware Implementation Details:
- 10 rounds of key expansion
- Uses STM8S AES hardware module
- Rcon values stored in ROM (0x8000-0x800F)
4. Critical Register Values
Table 3: Key Registers During Encryption
| Register | Address | Value (Hex) | Description |
|---|---|---|---|
| AES1_CR1 | 0x5400 | 0x03 | Enabled, system clock |
| AES1_CR2 | 0x5401 | 0x40 | 128-bit key length |
| AES1_KR | 0x5403 | 0x1A2B3C4D | Round key for encryption |
| AES1_DR | 0x5402 | 0x89ABCDEF | Current plaintext/ciphertext |
5. Interrupt Handling (Optional)
// Enable AES completion interrupt
AES1_CR1 |= (1 << AES1_CR1_IE);
ITC_SPR2 |= (1 << ITC_SPR2_AES_PRI); // Set priority to 0x02
6. Hardware Optimization Notes
- DMA Support: Use DMA1 to stream data to
AES1_DR for continuous encryption - Power Management: Disable AES peripheral after use:
AES1_CR1 &= ~(1 << AES1_CR1_AE); // Disable AES
3. Security: Clear key registers after operation:
memset(&AES1_KR, 0, sizeof(AES1_KR));
Verification Methodology:
- Use ST-LINK/V2 to log register writes during encryption
- Compare with AES-128 NIST test vectors
- Validate timing using oscilloscope (CLK vs RSR.BSY)
Conclusion
- Implementar la autenticación de código en rotación
- Utilizar cadenas de arranque seguras con validación HMAC
- Adoptar microcontroladores modernos como el STM32WB55 con aislamiento de hardware
Todas las actividades se llevaron a cabo bajo condiciones controladas con el consentimiento por escrito del propietario del dispositivo. No se utilizaron tecnologías de control de exportaciones en esta investigación.
- Desarrolló la primera explotación pública para las características de seguridad del STM8S103K3T6C
- Documentó detalles de implementación de AES previamente desconocidos
Para servicios de descifrado de nivel empresarial

Ingeniero Principal:
Dr. Billy Zheng
Well Done PCB Technology
billy@reversepcb.com
Soporte de Emergencia: +86-157-9847-6858




