Firmware challenges: the filesystem hiding inside the blob
A firmware image is a whole embedded Linux system packed into one file. How to pull the filesystem out with binwalk, find the hardcoded secrets and backdoors CTF authors plant, and recognise the bootloader and flash layout around it.
A firmware challenge hands you a single binary blob - a .bin dumped from a router, a camera, a smart plug - and the flag is somewhere inside a complete embedded Linux system that has been compressed and concatenated into that one file. It looks impenetrable. It almost never is, because embedded firmware is built from a small number of standard, well-understood pieces, and the tooling to take them apart is mature.
The mental model that makes firmware tractable: the blob is a stack of regions laid end to end. When the blob was read off the board rather than downloaded, the capture itself is the challenge - see hardware and signal challenges. A bootloader, a kernel, a root filesystem, maybe a second filesystem for configuration. Your job is to find where each region starts, decompress the one that holds files, and then treat it as an ordinary Linux box to enumerate.
Step one: let binwalk read the layout
binwalk scans the blob for the magic signatures of known formats and prints a map of what is where - and if the interesting region turns out to be an archive, archive attacks picks up from there. This one command usually tells you the whole structure.
binwalk firmware.bin
# DECIMAL HEX DESCRIPTION
# 0 0x0 uImage header, kernel, ...
# 64 0x40 LZMA compressed data
# 1310720 0x140000 Squashfs filesystem, little endian, version 4.0The signature types you will see over and over: a uImage or bootloader header at the front, an LZMA/gzip/xz blob (the compressed kernel), and a filesystem - Squashfs most often, sometimes JFFS2, CramFS, UBIFS, or a plain ext. Recognising these by name tells you which extraction tool each region needs.
Step two: extract the filesystem
binwalk's -e flag carves and decompresses everything it recognised, unpacking the filesystem into a directory tree you can walk.
binwalk -e firmware.bin # extract known regions
# newer binwalk: use -Me to recurse into nested archives automatically
# The result lands in _firmware.bin.extracted/
ls _firmware.bin.extracted/
cd _firmware.bin.extracted/squashfs-root/ # a full root filesystemStep three: enumerate it like a Linux box
You now have a root filesystem. Everything from the Linux side of CTF applies, but firmware has its own reliable hiding places because embedded developers cut corners the same way every time.
- Hardcoded credentials.
/etc/passwdand/etc/shadow- crack the hashes; embedded devices reuse weak root passwords.grep -rniE 'password|passwd|secret|key|token' etc/finds the ones left in config files and init scripts. - Backdoors in startup.
/etc/init.d/,/etc/rc.local, and the busybox startup scripts. CTF firmware often plants a listener or a magic-string check here - read what runs at boot. - Keys and certificates.
find . -name '*.pem' -o -name '*.key' -o -name '*.crt'. Private keys baked into firmware are a classic finding and a common flag. - The web interface. Most devices ship a web admin. Find the CGI binaries or PHP under
/www,/web, or/htdocsand read them - command injection in a router's CGI is the archetypal IoT bug. - Custom binaries. The vendor's own daemons in
/bin,/sbin,/usr/bin. A binary that is not part of standard busybox is where the intended vulnerability usually lives; pull it out and reverse it.
# The fast sweep across the whole extracted tree:
grep -rniE 'flag|ctf\{|backdoor|admin|root' . 2>/dev/null | head
strings -n 8 bin/the-vendor-daemon | grep -iE 'password|/bin/sh|system|flag'The hardware layer, briefly
Some challenges do not hand you the blob - they hand you a photo of a board, or a memory dump taken over a hardware interface, and expect you to know where firmware comes from. The vocabulary worth having: UART is the serial console, often a boot log and sometimes a root shell on four unlabelled pads; SPI flash is the chip that stores the firmware, dumpable with a clip and a cheap programmer into exactly the kind of blob above; JTAG is the debug interface that can halt the CPU and read memory. If a challenge mentions pin headers, a flash chip part number, or a flashrom dump, it is telling you the firmware was read off the hardware and the analysis is the same from there.
The workflow
- binwalk the blob to map its regions; identify the filesystem type.
- binwalk -e (or unsquashfs/sasquatch) to extract the root filesystem.
- If extraction fails, check entropy for encryption or single-byte obfuscation.
- Enumerate the filesystem: credentials, boot scripts, keys, the web interface, custom binaries.
- Reverse the vendor's own daemon or CGI - that is where the planted bug lives.