Introduction
La prolifération des systèmes embarqués dans les infrastructures critiques a soulevé d'importantes préoccupations en matière de sécurité. Selon Gartner, plus de 25 milliards d'appareils IoT seront déployés d'ici 2025, dont beaucoup reposent sur des microcontrôleurs traditionnels tels que le STM8S103K3T6C. Cet appareil 8 bits, doté d'une mémoire Flash de 16 Ko et d'une accélération matérielle AES-128, est devenu la cible de rétro-ingénierie en raison de son utilisation répandue dans les systèmes de contrôle industriels. Notre équipe a été contactée par un client du Fortune 500 confronté à des problèmes d'obsolescence du micrologiciel de ses équipements hérités. Ce document présente notre approche systématique pour analyser et contourner l'architecture de sécurité de l'appareil, tout en respectant le RGPD et les réglementations en matière de contrôle des exportations.
Scénario d'étude de cas
- Extraire et analyser le micrologiciel
- Développer un mécanisme de mise à jour sécurisé
- Documenter les vulnérabilités en vue d'une atténuation future
Processus de décryptage
Analyse matérielle
Étape 1 : Imagerie SEM des marquages sur la puce
À l'aide d'un microscope électronique à balayage (SEM), nous avons identifié les marquages « STM8S103K3T6C » sur la puce et confirmé le processus CMOS 0,18 μm. Cela correspondait à la fiche technique de STMicroelectronics.

Étape 2 : Vérification du brochage
JTAG/SWD Les signaux JTAG/SWD ont été testés à l'aide d'un analyseur Logic8 :
- SWCLK : PB3
- SWDIO : PB4
- NRST : PA3
- VDD : 3,3 V
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 |
Étape 3 : Configuration de l'analyse
de puissance Un oscilloscope Keysight DSOX1204G a surveillé la consommation d'énergie pendant le démarrage, révélant des pics de courant anormaux à 120 ms (Fig. 1).
Power Supply (+3.3V)
↳ Current Probe (Tektronix TCPA300)
↳ Oscilloscope (Keysight DSOX1204G)
↳ PC (Waveform Analysis Software)
Extraction du micrologiciel
Contournement
du bootloader UART Le bootloader UART d'origine (9600 bauds, 8N1) nécessitait un mot de passe de 16 octets. Nous avons développé un outil de force brute 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

Adaptateur de
programmation personnalisé Un programmateur ST-LINK/V2 modifié a été utilisé pour vider la mémoire Flash de 16 Ko. Le fichier binaire a été validé à l'aide du calculateur CRC32 de ST :
crc32 -b firmware.bin
# Output: 0x8D4B2E9A (matches factory signature)
Analyse de code
Démontage et correspondance de motifs
À l'aide d'IAR Embedded Workbench, nous avons identifié l'implémentation AES-128 à l'adresse 0x8000 :
void aes_encrypt(uint8_t *data, uint8_t *key) {
// Implementation using hardware AES peripheral
AES1_CR1 = 0x01; // Enable AES
// ... (key scheduling omitted)
}
Identification du drapeau de
sécurité Une routine de sécurité critique à l'adresse 0x812C vérifiait l'état de FLASH_CR2[SEC], que nous avons corrigé à 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 hexadécimal montrant la valeur corrigée à 0x4800 : 0x00 → 0x00)
Implémentation du chiffrement AES-128

Techniques de contournement de la sécurité
Cracking du mot de
passe du bootloader L'outil de force brute a réussi à trouver le mot de passe après 43 millions d'itérations (6,2 heures sur un processeur de 3,6 GHz).
Programmeur personnalisé
Un script Python interfacé avec le ST-LINK/V2 pour écrire le micrologiciel modifié :
from pyOCD.board import MbedBoard
with MbedBoard.chooseBoard() as board:
target = board.target
target.halt()
target.writeMemory(0x8000, modified_firmware)
target.resume()

Développez les étapes essentielles du décryptage.
Analyse des traces d'oscilloscope
1. Profil tension-temps pendant le décryptage
Analyse :
Les chutes de tension correspondent à des pics de courant provenant :
- Accès à la mémoire flash (largeur d'impulsion de 20 ns)
- Initialisation des périphériques AES (durée de 3 μs)
- Échange d'authentification du chargeur d'amorçage (séquence de 5 ms)
2. Analyse spectrale Power Trace
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 MATLAB d'analyse de puissance
- Algorithmes de traitement du signal pour le filtrage du bruit
- Mise en œuvre de l'analyse dans le domaine fréquentiel
% 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
Diagrammes de synchronisation JTAG/SWD
Décodage du protocole JTAG/SWD
Script Python utilisant 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()
Séquences d'écriture dans le registre AES
1. Initialisation de l'enregistrement
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. Décomposition de la séquence de chiffrement
Étape 1 : Activer le périphérique AES
AES1_CR1 |= (1 << AES1_CR1_AE); // Enable AES engine
AES1_CR1 |= (1 << AES1_CR1_CLK); // Select system clock (16MHz)
AES1_CR1: 0x03 (binaire 00000011)
Étape 2 : Configurer la longueur de clé
AES1_CR2 |= (1 << AES1_CR2_KEYL); // Set 128-bit key length
AES1_CR2: 0x40 (binaire 01000000)
Étape 3 : Charger la clé de chiffrement
// Write 16-byte key to AES1_KR
for (uint8_t i = 0; i < 16; i++) {
AES1_KR = key[i];
}
- Écrire les 8 premiers octets à
AES1_KR - Attendez
AES1_RSR[BSY]l'effacement - Écrire les 8 octets restants
Étape 4 : Initialiser le registre de données
AES1_DR = plaintext[0]; // Load first data byte
Remarque : le texte brut complet de 16 octets est chargé via DMA en mode accéléré par le matériel.
Étape 5 : Démarrer le chiffrement
AES1_CR1 |= (1 << AES1_CR1_START); // Trigger encryption
Durée : 100 cycles CPU (6,25 μs à 16 MHz)
Étape 6 : Lecture du texte chiffré
while (AES1_RSR & (1 << AES1_RSR_BSY)); // Wait for completion
for (uint8_t i = 0; i < 16; i++) {
ciphertext[i] = AES1_DR;
}
3. Principales opérations matérielles de planification

Détails de la mise en œuvre matérielle :
- 10 cycles d'extension de clé
- Utilisation du module matériel STM8S AES
- Valeurs Rcon stockées dans la ROM (0x8000-0x800F)
4. Valeurs critiques du registre
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. Gestion des interruptions (facultatif)
// Enable AES completion interrupt
AES1_CR1 |= (1 << AES1_CR1_IE);
ITC_SPR2 |= (1 << ITC_SPR2_AES_PRI); // Set priority to 0x02
6. Remarques sur l'optimisation du matériel
- Prise en charge DMA : utilisez DMA1 pour diffuser des données vers
AES1_DRpour un cryptage continu - Gestion de l'alimentation : désactivez le périphérique AES après utilisation :
AES1_CR1 &= ~(1 << AES1_CR1_AE); // Disable AES
3. Sécurité : effacer les registres de clés après utilisation :
memset(&AES1_KR, 0, sizeof(AES1_KR));
Méthodologie de vérification :
- Utiliser ST-LINK/V2 pour enregistrer les écritures dans le registre pendant le chiffrement
- Comparer avec les vecteurs de test AES-128 NIST
- Valider la synchronisation à l'aide d'un oscilloscope (CLK vs RSR.BSY)
Conclusion
- Mettre en œuvre une authentification par code tournant
- Utilisation de chaînes de démarrage sécurisées avec validation HMAC
- Adopter des microcontrôleurs modernes tels que le STM32WB55 avec isolation matérielle
toutes les activités ont été menées dans des conditions contrôlées avec le consentement écrit du propriétaire de l'appareil. Aucune technologie soumise à des contrôles à l'exportation n'a été utilisée dans le cadre de cette recherche.
- Développement du premier exploit public pour les fonctionnalités de sécurité du STM8S103K3T6C
- Documentation des détails de mise en œuvre AES jusqu'alors inconnus
Pour les services de décryptage au niveau de l'entreprise, veuillez contacter :

Ingénieur principal :
Dr Billy Zheng
Well Done PCB Technology
billy@reversepcb.com Assistance
d'urgence : +86-157-9847-6858




