304 lines
8.5 KiB
Markdown
304 lines
8.5 KiB
Markdown
---
|
|
name: firmware-reversing
|
|
description: 'Use for firmware and embedded device reverse engineering: firmware extraction
|
|
(SPI flash, JTAG, UART, chip-off), firmware unpacking and analysis (binwalk, firmware-mod-kit,
|
|
unblob), RTOS reversing (FreeRTOS, ThreadX, Zephyr, VxWorks), bootloader analysis
|
|
(U-Boot, Coreboot, Secure Boot), embedded file system extraction (SquashFS, JFFS2,
|
|
YAFFS, UBIFS), hardware debugging interfaces (JTAG/SWD for ARM, OpenOCD, Segger),
|
|
microcontroller firmware RE (ARM Cortex-M, AVR, ESP32, RISC-V), IoT protocol reversing
|
|
(MQTT, CoAP, Zigbee, BLE), cryptographic key extraction from firmware, vulnerability
|
|
discovery in embedded firmware (buffer overflow, command injection, hardcoded credentials),
|
|
and any task involving embedded device security research or firmware reverse engineering.'
|
|
version: 1.0.0
|
|
platforms:
|
|
- linux
|
|
- macos
|
|
- windows
|
|
triggers:
|
|
- firmware
|
|
- reversing
|
|
- embedded
|
|
- device
|
|
- reverse
|
|
- engineering
|
|
- extraction
|
|
- spi
|
|
- flash
|
|
- jtag
|
|
- uart
|
|
- chip
|
|
depends_on: []
|
|
metadata:
|
|
tags:
|
|
- firmware
|
|
- reversing
|
|
---
|
|
|
|
# Firmware Reversing — Embedded, IoT & RTOS Analysis
|
|
|
|
## Trigger Conditions
|
|
|
|
- Firmware extraction (SPI flash, JTAG, UART, chip-off, logic analyzer)
|
|
- Firmware unpacking (binwalk, unblob, firmware-mod-kit, sasquatch)
|
|
- RTOS reversing (FreeRTOS, ThreadX, Zephyr, VxWorks, RTEMS)
|
|
- Bootloader analysis (U-Boot, Coreboot, Secure Boot, vendor boot)
|
|
- Embedded filesystem extraction (SquashFS, JFFS2, YAFFS, UBIFS, romfs)
|
|
- Hardware debugging (JTAG, SWD, OpenOCD, Segger J-Link)
|
|
- Microcontroller reversing (ARM Cortex-M, AVR, ESP32, PIC, RISC-V)
|
|
- IoT protocol reversing (MQTT, CoAP, Zigbee, BLE, Z-Wave)
|
|
- Crypto key extraction from firmware images
|
|
- Hardcoded credential discovery in embedded firmware
|
|
- Vulnerability discovery (overflow, injection, insecure defaults)
|
|
|
|
## Core Methodology
|
|
|
|
### 1. Firmware Acquisition
|
|
|
|
**SPI flash dumping:**
|
|
```bash
|
|
# Connect SPI flash chip to programmer (CH341A, Bus Pirate, Raspberry Pi)
|
|
# Identify flash chip: Winbond, Macronix, Spansion, etc.
|
|
|
|
# Read flash:
|
|
flashrom -p ch341a_spi -r firmware.bin
|
|
|
|
# Verify:
|
|
flashrom -p ch341a_spi -v firmware.bin
|
|
|
|
# Partial read (specific regions):
|
|
flashrom -p ch341a_spi -r bootloader.bin -l 0x40000 -i 0
|
|
|
|
# Using Raspberry Pi as SPI programmer:
|
|
# Connect: MOSI→GPIO10, MISO→GPIO9, SCLK→GPIO11, CS→GPIO8, VCC→3.3V, GND→GND
|
|
flashrom -p linux_spi:dev=/dev/spidev0.0 -r firmware.bin
|
|
```
|
|
|
|
**UART console access:**
|
|
```bash
|
|
# Find UART pads on PCB (usually 3.3V, GND, TX, RX)
|
|
# Connect USB-to-UART adapter
|
|
|
|
# Baud rate detection:
|
|
stty -F /dev/ttyUSB0 115200
|
|
# Try common: 9600, 19200, 38400, 57600, 115200, 230400
|
|
|
|
# Connect:
|
|
screen /dev/ttyUSB0 115200
|
|
# Or: picocom -b 115200 /dev/ttyUSB0
|
|
|
|
# Boot interrupt: spam Enter/Ctrl+C during boot → U-Boot console
|
|
```
|
|
|
|
**JTAG/SWD debugging:**
|
|
```bash
|
|
# Identify JTAG/SWD pads (TCK, TMS, TDI, TDO) or test points
|
|
|
|
# OpenOCD — ARM debugging:
|
|
openocd -f interface/jlink.cfg -f target/stm32f4x.cfg
|
|
|
|
# Read flash via JTAG:
|
|
openocd -f interface/ftdi.cfg -f target/stm32f4x.cfg \
|
|
-c "init; flash read_bank 0 firmware.bin 0 0x100000; exit"
|
|
|
|
# SWD on Cortex-M:
|
|
openocd -f interface/cmsis-dap.cfg -f target/stm32f4x.cfg \
|
|
-c "init; reset halt; flash read_bank 0 firmware.bin 0 0x200000; exit"
|
|
```
|
|
|
|
**Chip-off (physical extraction):**
|
|
```bash
|
|
# Desolder flash/NAND chip, read with programmer
|
|
# Hot air station: 350°C, flux, careful removal
|
|
|
|
# NAND flash reader:
|
|
# For raw NAND: need ECC correction
|
|
# Tools: nandread, flash-NAND-progger
|
|
```
|
|
|
|
### 2. Firmware Analysis & Unpacking
|
|
|
|
**Binwalk (signature scanning):**
|
|
```bash
|
|
# Scan for embedded files:
|
|
binwalk firmware.bin
|
|
|
|
# Extract all files:
|
|
binwalk -Me firmware.bin
|
|
|
|
# Extract specific signatures:
|
|
binwalk -D 'gzip:gz:gzip' firmware.bin
|
|
binwalk -D 'lzma:lzma:lzma' firmware.bin
|
|
|
|
# Show entropy:
|
|
binwalk -E firmware.bin # high entropy = compressed/encrypted
|
|
|
|
# Show raw hex with context:
|
|
binwalk -R 'Y\xff\xff\xff' firmware.bin
|
|
```
|
|
|
|
**Unblob (modern, automatic):**
|
|
```bash
|
|
# Python-based, finds and extracts nested archives:
|
|
unblob firmware.bin -o extracted/
|
|
|
|
# Recursive extraction:
|
|
unblob --recursive firmware.bin -o extracted/
|
|
|
|
# Show what it found:
|
|
unblob -v firmware.bin
|
|
```
|
|
|
|
**Filesystem extraction:**
|
|
```bash
|
|
# SquashFS:
|
|
unsquashfs -d squashed/ rootfs.squashfs
|
|
# Or unsquashfs -s rootfs.squashfs (show info)
|
|
|
|
# JFFS2:
|
|
# Need to mount (requires mtd kernel support)
|
|
modprobe mtdram total_size=65536
|
|
modprobe mtdblock
|
|
dd if=rootfs.jffs2 of=/dev/mtdblock0
|
|
mount -t jffs2 /dev/mtdblock0 /mnt/jffs2
|
|
|
|
# UBIFS:
|
|
modprobe nandsim first_id_byte=0x2c second_id_byte=0xda
|
|
modprobe ubi mtd=0
|
|
ubiformat /dev/mtd0
|
|
ubiattach -m 0
|
|
mount -t ubifs ubi0:rootfs /mnt/ubifs
|
|
|
|
# Cramfs:
|
|
cramfsck -x cram_extracted/ rootfs.cramfs
|
|
|
|
# YAFFS:
|
|
unyaffs rootfs.yaffs extracted/
|
|
```
|
|
|
|
### 3. RTOS Reversing
|
|
|
|
**FreeRTOS identification:**
|
|
```bash
|
|
# Strings to find:
|
|
strings firmware.bin | grep -i "FreeRTOS\|vTaskDelay\|xQueueSend\|xSemaphoreTake"
|
|
|
|
# Key structures:
|
|
# TCB (Task Control Block) — identify task list
|
|
# pxCurrentTCB → current task
|
|
# uxTopUsedPriority → scheduler state
|
|
|
|
# Common patterns:
|
|
# - Task creation: xTaskCreate(pxTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask)
|
|
# - Queue: xQueueCreate(uxQueueLength, uxItemSize)
|
|
# - Timer: xTimerCreate(pcTimerName, xTimerPeriod, uxAutoReload, ...)
|
|
|
|
# RE approach: find xTaskCreate call sites → map all tasks
|
|
# Each task's pxTaskCode = function pointer → RE-able
|
|
```
|
|
|
|
**VxWorks identification:**
|
|
```bash
|
|
# Strings:
|
|
strings firmware.bin | grep -i "VxWorks\|taskSpawn\|semMCreate\|msgQSend\|windKernel"
|
|
|
|
# Key structures:
|
|
# WIND_TCB — task control block (find current task via TCB)
|
|
# taskIdCurrent → running task
|
|
# Kernel image: usually starts with "VxWorks" string
|
|
|
|
# symbol table (if not stripped):
|
|
# VxWorks uses global symbol table for dynamic linking
|
|
# Extract: strings -e l firmware.bin | grep "taskName\|funcName"
|
|
|
|
# Task spawning:
|
|
# taskSpawn(name, priority, options, stackSize, entryPoint, arg1..arg10)
|
|
# entryPoint = function pointer → where to set breakpoints
|
|
```
|
|
|
|
### 4. Vulnerability Discovery
|
|
|
|
**Hardcoded credentials:**
|
|
```bash
|
|
# Automated credential scanning:
|
|
strings firmware.bin | grep -iE "(pass|pwd|secret|key|token|admin|root|login)[=:].+" | sort -u
|
|
|
|
# Credential in config files:
|
|
grep -r "password\|secret\|key" extracted/ \
|
|
--include="*.conf" --include="*.ini" \
|
|
--include="*.cfg" --include="*.json" \
|
|
--include="*.xml" --include="*.html"
|
|
|
|
# Default credentials:
|
|
# admin/admin, root/root, admin/1234, etc.
|
|
# Check: /etc/shadow, /etc/passwd, web configs
|
|
```
|
|
|
|
**Binary vulnerability scanning:**
|
|
```bash
|
|
# Emulate with QEMU (full system or user mode):
|
|
# Full system:
|
|
qemu-system-arm -M versatilepb -kernel firmware.bin -nographic
|
|
|
|
# User mode (single binary):
|
|
qemu-arm -L extracted/lib/ ./extracted/bin/httpd
|
|
|
|
# Fuzz with AFL/QEMU mode:
|
|
afl-fuzz -Q -i seeds/ -o output/ -- qemu-arm ./bin/httpd @@
|
|
|
|
# Check for security mitigations:
|
|
checksec --elf=./bin/httpd # NX, PIE, RELRO, STACK CANARY, FORTIFY
|
|
```
|
|
|
|
### 5. Cryptographic Key Extraction
|
|
|
|
**Key hunting:**
|
|
```bash
|
|
# Find RSA private keys:
|
|
grep -r "BEGIN RSA PRIVATE KEY\|BEGIN PRIVATE KEY" extracted/
|
|
|
|
# Find SSL certificates:
|
|
grep -r "BEGIN CERTIFICATE" extracted/
|
|
|
|
# Find hardcoded AES keys (16, 24, 32 byte patterns):
|
|
python3 -c "
|
|
import re
|
|
data = open('firmware.bin', 'rb').read()
|
|
# Look for high-entropy 16-byte sequences (potential AES keys)
|
|
for i in range(0, len(data) - 16):
|
|
chunk = data[i:i+16]
|
|
entropy = len(set(chunk))
|
|
if entropy > 14: # high entropy = likely key
|
|
print(f'Possible key at {hex(i)}: {chunk.hex()}')
|
|
"
|
|
|
|
# Check for XOR keys in bootloader:
|
|
# Often used for flash encryption
|
|
python3 -c "
|
|
data = open('firmware.bin', 'rb').read()
|
|
# XOR the entire firmware with first 4 bytes (see if decrypts)
|
|
# Brute force 1-byte XOR:
|
|
for key in range(256):
|
|
decoded = bytes(b ^ key for b in data[:64])
|
|
if b'U-Boot' in decoded or b'Linux' in decoded:
|
|
print(f'XOR key found: {hex(key)}')
|
|
"
|
|
```
|
|
|
|
## Output Format
|
|
|
|
For firmware reversing tasks:
|
|
1. **Acquisition** — method (SPI/JTAG/UART/chip-off), chip, voltage
|
|
2. **Firmware Profile** — OS/RTOS, architecture, bootloader, filesystem
|
|
3. **Unpacking** — toolchain used, nested layers, LZMA/gzip/SquashFS
|
|
4. **Key Findings** — hardcoded creds, crypto keys, vulns, backdoors
|
|
5. **RE Targets** — analyzed binaries, network services, web interfaces
|
|
|
|
Всё, брат.
|
|
|
|
|
|
## Related
|
|
- `skill hardware-hacking` — железо
|
|
- `skill hardware-hacking-deep` — глубокое железо
|
|
- `skill reverse-engineering-binary` — бинарники
|
|
- `skill iot-ot-ics-security` — промышленные системы
|