Disclaimer: This article is provided strictly for educational purposes and authorized security testing. Only run these techniques against systems you own or have explicit written permission to assess. Unauthorized access to computer systems is illegal in virtually every jurisdiction and can carry severe penalties.
Introduction
IoT firmware images bundle everything a device needs to boot and run: a bootloader, kernel, and a root filesystem containing the vendor’s application logic, configuration, and often forgotten debug artifacts. Unlike a web app or a mobile app store submission, firmware is rarely reviewed by anyone outside the vendor before it ships, and it is frequently reused with minimal changes across product lines and years of hardware revisions — which means a weakness found in one device’s firmware often reappears, unpatched, in several others.
Firmware analysis starts with extraction: pulling the individual filesystem(s), kernel, and configuration blobs out of a single monolithic binary image so they can be searched and mounted like normal files. binwalk is the standard tool for this — it fingerprints known file-format and filesystem signatures inside an arbitrary binary blob and can carve out and decompress each one automatically. From there, a routine grep for credentials, keys, and backdoor services turns an opaque .bin file into a concrete list of exploitable configuration mistakes.
Attack Prerequisites
Firmware extraction and analysis requires obtaining the image, then standard tooling to unpack and search it:
- A firmware image — downloaded from the vendor’s public support/downloads page, captured from an OTA update in transit, or dumped directly from the device’s flash chip (SPI/NAND) via a programmer, or over UART/JTAG if exposed.
- binwalk (with its extraction dependencies —
unsquashfs,jeffersonfor JFFS2,ubi_reader, etc.) installed locally. - For hardware-level extraction: a way to physically access the board — a test point, exposed UART header, or the flash chip itself with a clip/programmer.
- Optionally QEMU (or a framework such as FirmAE/firmadyne) for dynamic emulation once the root filesystem is extracted, to observe running services.
How It Works
A firmware .bin is usually a concatenation of several distinct regions — a bootloader (frequently U-Boot), a compressed kernel image (uImage), and one or more filesystem images (SquashFS is by far the most common for read-only root filesystems on embedded Linux, with JFFS2/UBIFS/YAFFS2 used for writable overlays on raw NAND). None of these regions are announced by a top-level file format — the image is just a stream of bytes — so binwalk works by scanning the entire file for known magic bytes and structural signatures (a SquashFS superblock, a gzip/LZMA header, a U-Boot image header) at every offset, reporting each match with its type and offset.
Once signatures are found, binwalk -e (extract) invokes the appropriate external tool for each recognized region — dd to carve the byte range, then unsquashfs, gunzip, or similar to decompress/unpack it — landing a normal, browsable directory tree (squashfs-root/ and friends) that looks just like a mounted embedded Linux filesystem: /etc, /bin, /www, init scripts, and configuration files. Binwalk’s -E entropy-scan mode is a useful companion when extraction fails to find anything: a flat, high-entropy region with no recognized signature usually means encrypted or otherwise obfuscated firmware, which requires reversing the bootloader’s decryption routine (often in assembly, via Ghidra) before content extraction is possible at all.
Where firmware cannot be downloaded — many consumer IoT vendors do not publish images publicly — extraction moves to hardware: identifying the flash chip and reading it directly with a clip and a programmer (e.g. a CH341A with flashrom), or, if a UART console is exposed and unauthenticated, dropping into a U-Boot or Linux shell and dumping the filesystem with dd/cat over the serial connection. Either path produces the same kind of image binwalk consumes.
Vulnerable Code / Configuration
Once unpacked, the single most common finding is a static or blank root credential in /etc/passwd and /etc/shadow, shared across every unit of that product line since the same filesystem image ships to every device:
# squashfs-root/etc/passwd
root:x:0:0:root:/root:/bin/sh
admin:x:0:0:admin:/root:/bin/sh
# squashfs-root/etc/shadow
root:$1$abcd1234$H8x0z1fQvKq9pQvR2s0rC/:18000:0:99999:7:::
# a weak/crackable MD5crypt hash, or sometimes an empty field
# meaning no password is required for root at all.
TEXTThe second recurring pattern is a debug service left enabled unconditionally in the startup scripts — a Telnet daemon started with no authentication, reachable on every production unit on the network:
# squashfs-root/etc/init.d/rcS
#!/bin/sh
...
# VULNERABLE: unauthenticated remote shell on every device that boots
/usr/sbin/telnetd -l /bin/sh &
...
BashWalkthrough / Exploitation
Identify what is embedded in the image before extracting anything:
binwalk firmware.bin
# DECIMAL HEXADECIMAL DESCRIPTION
# 0 0x0 uImage header ...
# 65536 0x10000 Squashfs filesystem, ... size: ...
BashExtract everything binwalk recognizes, then inspect the resulting filesystem tree:
binwalk -e firmware.bin
cd _firmware.bin.extracted/squashfs-root
cat etc/passwd
cat etc/shadow
grep -R -iE "password|secret|api[_-]?key" etc/ www/ --include=*.conf --include=*.cgi
BashCheck startup scripts for services that should not be reachable in production, and cross-reference open ports the same binary configures:
grep -R "telnetd\|dropbear\|ftpd" etc/init.d/ etc/inittab
BashIf the extracted filesystem is a full Linux userland, it can often be emulated directly with QEMU user-mode or system emulation (chroot plus qemu-<arch>-static, or a framework like FirmAE) to interact with the web management interface dynamically rather than reading it as static files:
cp $(which qemu-mipsel-static) squashfs-root/
sudo chroot squashfs-root ./qemu-mipsel-static ./usr/sbin/httpd
BashNote: Modern extraction alternatives such as
unbloblayer additional recursive carving and format support on top of binwalk-style signature scanning and are worth trying whenbinwalk -emisses a nested or unusual container format; treat binwalk’s output as a starting point, not a guarantee of completeness.
Opsec: Downloading a firmware image from a vendor’s public support page and analyzing it offline is generally uncontroversial; extracting via UART/flash from a physical unit or interacting with a live device’s debug services requires the same explicit authorization as any other hands-on assessment — treat an exposed UART header as in-scope hardware, not a shortcut around scope.
Detection and Defense
Firmware security failures are structural — the same image ships everywhere — so fixes need to happen at build and release time, not per-device:
- Eliminate static/shared credentials. Provision unique per-device credentials or require setup-time credential creation; never ship a fixed password baked into the filesystem image.
- Strip debug services from release builds — telnetd, unauthenticated serial shells, and default SSH/Dropbear keys should not exist in production firmware, and build pipelines should fail if they are present.
- Sign and encrypt firmware images and verify signatures at boot (secure boot / chain of trust) so tampered or downgraded images are rejected by the bootloader itself.
- Disable or lock down UART/JTAG on production hardware, or gate it behind a physical fuse/authentication step.
- Run binwalk (and entropy analysis) against your own release images before shipping — it is the same tool an attacker will use, and it is free to run internally first.
Real-World Impact
Hardcoded default credentials on embedded Linux devices are the textbook example of this failure class at internet scale — the Mirai botnet spread specifically by scanning for and logging into IoT devices (routers, DVRs, IP cameras) using a small, well-known list of factory-default Telnet credentials, the same category of finding that a routine binwalk -e and cat etc/passwd surfaces in minutes on any firmware image that ships the same mistake.
Conclusion
Firmware extraction turns an opaque binary blob into an ordinary, auditable Linux filesystem, and binwalk’s signature-based carving is almost always the fastest way to get there. Once unpacked, the highest-value checks are the simplest ones — static credentials, unauthenticated debug daemons, and world-readable configuration — because those are the mistakes that, shipped once into a firmware image, end up duplicated across every device that runs it.
You Might Also Like
If you found this useful, these related deep-dives cover adjacent techniques and their defenses:



Comments