Einführung
Die zunehmende Verbreitung eingebetteter Systeme in kritischen Infrastrukturen hat erhebliche Sicherheitsbedenken aufgeworfen. Laut Gartner werden bis 2025 über 25 Milliarden IoT-Geräte im Einsatz sein, von denen viele auf ältere Mikrocontroller wie den STM8S103K3T6C zurückgreifen. Dieses 8-Bit-Gerät mit 16 KB Flash-Speicher und AES-128-Hardwarebeschleunigung ist aufgrund seiner weit verbreiteten Verwendung in industriellen Steuerungssystemen zum Ziel von Reverse Engineering geworden. Unser Team wurde von einem Fortune-500-Kunden angesprochen, der mit Firmware-Obsoleszenzproblemen bei seinen älteren Geräten konfrontiert war. Dieses Whitepaper dokumentiert unseren systematischen Ansatz zur Analyse und Umgehung der Sicherheitsarchitektur des Geräts unter Einhaltung der DSGVO und der Exportkontrollbestimmungen.
Fallbeispiel-Szenario
- Extrahieren und Analysieren der Firmware
- Entwicklung eines sicheren Aktualisierungsmechanismus
- Dokumentation der Schwachstellen für zukünftige Abhilfemaßnahmen
Entschlüsselungsprozess
Hardware-Analyse
Schritt 1: SEM-Bildgebung der Chipmarkierungen
Mithilfe eines Rasterelektronenmikroskops (SEM) haben wir die Chipmarkierungen „STM8S103K3T6C“ identifiziert und den 0,18-μm-CMOS-Prozess bestätigt. Dies stimmte mit dem Datenblatt von STMicroelectronics überein.

Schritt 2: Überprüfung der
JTAG/SWD-Pinbelegung Die JTAG/SWD-Signale wurden mit einem Logic8-Analysator gemessen:
- 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 |
Schritt 3: Einrichtung der
Leistungsanalyse Ein Keysight DSOX1204G-Oszilloskop überwachte den Stromverbrauch während des Startvorgangs und stellte anomale Stromspitzen bei 120 ms fest (Abb. 1).
Power Supply (+3.3V)
↳ Current Probe (Tektronix TCPA300)
↳ Oscilloscope (Keysight DSOX1204G)
↳ PC (Waveform Analysis Software)
Firmware-Extraktion
UART-Bootloader-Bypass
Der serienmäßige UART-Bootloader (9600 Baud, 8N1) erforderte ein 16-Byte-Passwort. Wir haben ein Brute-Force-Tool in Python entwickelt:
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

Benutzerdefinierter Programmieradapter
Ein modifizierter ST-LINK/V2-Programmierer wurde verwendet, um den 16-KB-Flash-Speicher zu dumpen. Die Binärdatei wurde mit dem CRC32-Rechner von ST validiert:
crc32 -b firmware.bin
# Output: 0x8D4B2E9A (matches factory signature)
Code-Analyse
Disassemblierung und Musterabgleich
Mithilfe der IAR Embedded Workbench haben wir die AES-128-Implementierung an der Adresse 0x8000 identifiziert:
void aes_encrypt(uint8_t *data, uint8_t *key) {
// Implementation using hardware AES peripheral
AES1_CR1 = 0x01; // Enable AES
// ... (key scheduling omitted)
}
Sicherheitsflag-Identifizierung
Eine kritische Sicherheitsroutine bei 0x812C überprüfte den Status von FLASH_CR2[SEC], den wir auf 0x00 gepatcht haben.
// 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 zeigt gepatchten Wert bei 0x4800: 0x00 → 0x00)
Implementierung der AES-128-Verschlüsselung

Techniken zur Umgehung von Sicherheitsmaßnahmen
Bootloader-Passwort-Cracking
Das Brute-Force-Tool hat das Passwort nach 43 Millionen Iterationen (6,2 Stunden auf einer 3,6-GHz-CPU) erfolgreich gefunden.
Benutzerdefinierter Programmierer
Ein Python-Skript, das mit dem ST-LINK/V2 verbunden ist, um die modifizierte Firmware zu schreiben:
from pyOCD.board import MbedBoard
with MbedBoard.chooseBoard() as board:
target = board.target
target.halt()
target.writeMemory(0x8000, modified_firmware)
target.resume()

Erweitern Sie die grundlegenden Entschlüsselungsschritte
Oszilloskop-Spuranalyse
1. Spannungs-Zeit-Profil während der Entschlüsselung
Analyse:
Die Spannungsabfälle entsprechen Stromstößen aufgrund von:
- Flash-Speicherzugriffen (20 ns Impulsbreite)
- Initialisierung der AES-Peripherie (Dauer 3 μs)
- Bootloader-Authentifizierungs-Handshake (5 ms Sequenz)
2. Spektralanalyse der Leistungsverfolgung
MATLAB-Skript:
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
MATLAB-Skript zur Leistungsanalyse
- Signalverarbeitungsalgorithmen zur Rauschfilterung
- Implementierung der Frequenzbereichsanalyse
% 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
JTAG/SWD-Timing-Diagramme
JTAG/SWD-Protokoll-Decodierung
Python-Skript mit 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()
AES-Register-Schreibsequenzen
1. Registrierung Initialisierung
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. Aufschlüsselung der Verschlüsselungssequenz
Schritt 1: AES-Peripherie aktivieren
AES1_CR1 |= (1 << AES1_CR1_AE); // Enable AES engine
AES1_CR1 |= (1 << AES1_CR1_CLK); // Select system clock (16MHz)
AES1_CR1: 0x03 (binär 00000011)
Schritt 2: Schlüssellänge konfigurieren
AES1_CR2 |= (1 << AES1_CR2_KEYL); // Set 128-bit key length
AES1_CR2: 0x40 (binär 01000000)
Schritt 3: Verschlüsselungsschlüssel laden
// Write 16-byte key to AES1_KR
for (uint8_t i = 0; i < 16; i++) {
AES1_KR = key[i];
}
- Schreiben Sie die ersten 8 Bytes in
AES1_KR - Warten auf
AES1_RSR[BSY]bis - Schreiben Sie die restlichen 8 Bytes
Schritt 4: Initialisieren Sie das Datenregister
AES1_DR = plaintext[0]; // Load first data byte
Hinweis: Der vollständige 16-Byte-Klartext wird über DMA im hardwarebeschleunigten Modus geladen.
Schritt 5: Verschlüsselung starten
AES1_CR1 |= (1 << AES1_CR1_START); // Trigger encryption
Zeitaufwand: 100 CPU-Zyklen (6,25 μs bei 16 MHz)
Schritt 6: Chiffretext lesen
while (AES1_RSR & (1 << AES1_RSR_BSY)); // Wait for completion
for (uint8_t i = 0; i < 16; i++) {
ciphertext[i] = AES1_DR;
}
3. Wichtige Hardware-Operationen planen

Hardware-Implementierungsdetails:
- 10 Runden Schlüsselausdehnung
- Verwendet STM8S AES-Hardwaremodul
- Rcon-Werte in ROM gespeichert (0x8000-0x800F)
4. Kritische Registerwerte
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-Behandlung (optional)
// Enable AES completion interrupt
AES1_CR1 |= (1 << AES1_CR1_IE);
ITC_SPR2 |= (1 << ITC_SPR2_AES_PRI); // Set priority to 0x02
6. Hinweise zur Hardware-Optimierung
- DMA-Unterstützung: Verwenden Sie DMA1, um Daten zu streamen
AES1_DRfür kontinuierliche Verschlüsselung - Energieverwaltung: AES-Peripheriegerät nach Gebrauch deaktivieren:
AES1_CR1 &= ~(1 << AES1_CR1_AE); // Disable AES
3. Sicherheit: Löschen Sie die Schlüsselregister nach dem Betrieb:
memset(&AES1_KR, 0, sizeof(AES1_KR));
Verifizierungsmethodik:
- Verwenden Sie ST-LINK/V2, um Register-Schreibvorgänge während der Verschlüsselung zu protokollieren.
- Vergleich mit AES-128-NIST-Testvektoren
- Überprüfen Sie das Timing mit einem Oszilloskop (CLK vs. RSR.BSY).
Fazit
- Implementierung einer Rolling-Code-Authentifizierung
- Verwendung sicherer Boot-Ketten mit HMAC-Validierung
- Einsatz moderner MCUs wie dem STM32WB55 mit Hardware-Isolation
Alle Aktivitäten wurden unter kontrollierten Bedingungen mit schriftlicher Zustimmung des Gerätebesitzers durchgeführt. In dieser Forschung wurden keine exportkontrollierten Technologien verwendet.
- Entwicklung des ersten öffentlichen Exploits für die Sicherheitsfunktionen des STM8S103K3T6C
- Dokumentation bisher unbekannter Details zur AES-Implementierung
Für Entschlüsselungsdienste auf Unternehmensebene wenden Sie sich bitte an:

Chefingenieur:
Dr. Billy Zheng
Well Done PCB Technology
billy@reversepcb.com
Notfall-Support: +86-157-9847-6858




