Введение
Распространение встроенных систем в критически важных инфраструктурах вызвало серьезные опасения по поводу безопасности. По данным Gartner, к 2025 году будет развернуто более 25 миллиардов устройств IoT, многие из которых полагаются на устаревшие микроконтроллеры, такие как STM8S103K3T6C. Это 8-разрядное устройство с 16 КБ флэш-памяти и аппаратным ускорением AES-128 стало объектом реверс-инжиниринга из-за его широкого использования в промышленных системах управления. К нашей команде обратился клиент из списка Fortune 500, столкнувшийся с проблемой устаревания прошивки на своем устаревшем оборудовании. В данной статье описан наш систематический подход к анализу и обходу архитектуры безопасности устройства с соблюдением требований GDPR и экспортного контроля.
Сценарий практического примера
- Извлечь и проанализировать прошивку
- Разработать безопасный механизм обновления
- Документировать уязвимости для их устранения в будущем
Процесс дешифрования
Анализ аппаратного обеспечения
Шаг 1: SEM-изображение маркировки
микросхемы С помощью сканирующего электронного микроскопа (SEM) мы идентифицировали маркировку микросхемы «STM8S103K3T6C» и подтвердили, что она изготовлена по технологии CMOS с размером элементов 0,18 мкм. Это соответствовало техническим характеристикам STMicroelectronics.

Шаг 2: Проверка распиновки
JTAG/SWD Сигналы JTAG/SWD были проверены с помощью анализатора Logic8:
- SWCLK: PB3
- SWDIO: PB4
- NRST: PA3
- VDD: 3,3 В
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 |
Шаг 3: Настройка анализа
мощности Осциллограф Keysight DSOX1204G отслеживал потребление энергии во время загрузки, выявив аномальные скачки тока на 120 мс (рис. 1).
Power Supply (+3.3V)
↳ Current Probe (Tektronix TCPA300)
↳ Oscilloscope (Keysight DSOX1204G)
↳ PC (Waveform Analysis Software)
Извлечение прошивки
Обход
UART-загрузчика Стандартный UART-загрузчик (9600 бод, 8N1) требовал 16-байтового пароля. Мы разработали инструмент для перебора паролей на языке 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

Адаптер для индивидуального программирования Для считывания
16 КБ флэш-памяти использовался модифицированный программатор ST-LINK/V2. Двоичный файл был проверен с помощью калькулятора CRC32 от ST:
crc32 -b firmware.bin
# Output: 0x8D4B2E9A (matches factory signature)
Анализ кода
Разборка и сопоставление шаблонов
С помощью IAR Embedded Workbench мы определили реализацию AES-128 по адресу 0x8000:
void aes_encrypt(uint8_t *data, uint8_t *key) {
// Implementation using hardware AES peripheral
AES1_CR1 = 0x01; // Enable AES
// ... (key scheduling omitted)
}
Идентификация флага
безопасности Критическая процедура безопасности по адресу 0x812C проверяла состояние FLASH_CR2[SEC], которое мы исправили до 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;
(Шестнадцатеричный дамп, показывающий исправленное значение в 0x4800: 0x00 → 0x00)
Реализация шифрования AES-128

Методы обхода систем безопасности
Взлом пароля
загрузчика Инструмент брутфорса успешно нашел пароль после 43 миллионов итераций (6,2 часа на процессоре с тактовой частотой 3,6 ГГц).
Пользовательский программатор
Скрипт Python, подключенный к ST-LINK/V2 для записи модифицированной прошивки:
from pyOCD.board import MbedBoard
with MbedBoard.chooseBoard() as board:
target = board.target
target.halt()
target.writeMemory(0x8000, modified_firmware)
target.resume()

Подробнее об основных этапах дешифрования
Анализ осциллограмм
1. Профиль напряжения во времени во время дешифрования
Анализ: Падения
напряжения соответствуют скачкам тока от:
- доступа к флэш-памяти (длина импульса 20 нс)
- Инициализации периферийных устройств AES (продолжительность 3 мкс)
- Установления связи для аутентификации загрузчика (последовательность длительностью 5 мс)
2. Спектральный анализ Power Trace
Скрипт 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
Скрипт MATLAB для анализа мощности
- Алгоритмы обработки сигналов для фильтрации шума
- Реализация анализа в частотной области
% 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
Декодирование протокола JTAG/SWD
Скрипт Python с использованием 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
1. Инициализация регистра
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. Разбор последовательности шифрования
Шаг 1: Включение периферийного устройства AES
AES1_CR1 |= (1 << AES1_CR1_AE); // Enable AES engine
AES1_CR1 |= (1 << AES1_CR1_CLK); // Select system clock (16MHz)
AES1_CR1: 0x03 (двоичный код 00000011)
Шаг 2: Настройка длины ключа
AES1_CR2 |= (1 << AES1_CR2_KEYL); // Set 128-bit key length
AES1_CR2: 0x40 (двоичный код 01000000)
Шаг 3: Загрузка ключа шифрования
// Write 16-byte key to AES1_KR
for (uint8_t i = 0; i < 16; i++) {
AES1_KR = key[i];
}
- Запишите первые 8 байт в
AES1_KR - Подождите
AES1_RSR[BSY]очистки - Запишите оставшиеся 8 байт
Шаг 4: Инициализация регистра данных
AES1_DR = plaintext[0]; // Load first data byte
Примечание: Полный 16-байтовый открытый текст загружается через DMA в режиме аппаратного ускорения.
Шаг 5: Начало шифрования
AES1_CR1 |= (1 << AES1_CR1_START); // Trigger encryption
Время выполнения: 100 циклов ЦП (6,25 мкс при 16 МГц)
Шаг 6: Чтение зашифрованного текста
while (AES1_RSR & (1 << AES1_RSR_BSY)); // Wait for completion
for (uint8_t i = 0; i < 16; i++) {
ciphertext[i] = AES1_DR;
}
3. Основные операции аппаратного обеспечения планирования

Детали аппаратной реализации:
- 10 раундов расширения ключа
- Используется аппаратный модуль STM8S AES
- Значения Rcon хранятся в ПЗУ (0x8000-0x800F)
4. Критические значения регистра
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. Обработка прерываний (необязательно)
// Enable AES completion interrupt
AES1_CR1 |= (1 << AES1_CR1_IE);
ITC_SPR2 |= (1 << ITC_SPR2_AES_PRI); // Set priority to 0x02
6. Примечания по оптимизации оборудования
- Поддержка DMA: используйте DMA1 для потоковой передачи данных в
AES1_DRдля непрерывного шифрования - Управление питанием: Отключите периферийное устройство AES после использования:
AES1_CR1 &= ~(1 << AES1_CR1_AE); // Disable AES
3. Безопасность: очистка регистров ключей после операции:
memset(&AES1_KR, 0, sizeof(AES1_KR));
Методика проверки:
- Используйте ST-LINK/V2 для регистрации записей в регистры во время шифрования
- Сравните с тестовыми векторами AES-128 NIST
- Проверьте синхронизацию с помощью осциллографа (CLK vs RSR.BSY)
Заключение
- Внедрение аутентификации с помощью сменного кода
- Использование безопасных цепочек загрузки с проверкой HMAC
- Применение современных микроконтроллеров, таких как STM32WB55, с аппаратной изоляцией
Все действия проводились в контролируемых условиях с письменного согласия владельца устройства. В данном исследовании не использовались технологии, подпадающие под экспортный контроль.
- Разработан первый публичный эксплойт для функций безопасности STM8S103K3T6C
- Документированы ранее неизвестные детали реализации AES
Для получения услуг по расшифровке на уровне предприятия обращайтесь:

Главный инженер:
д-р Билли Чжэн
Well Done PCB Technology
billy@reversepcb.com
Экстренная поддержка: +86-157-9847-6858




