Reading & Verifying
practicalReading & Verifying
A dump file is only useful if it's correct. This lesson covers the complete workflow from physical connection to verified dump, and the analysis steps that confirm you have valid firmware β not garbage from a bad read.
Full Read Workflow
This is the sequence from scratch every time:
# 1. Probe β identify chip without reading
flashrom -p ch341a_spi -V
# 2. Note the detected chip name from probe output
# Example: "Found Winbond flash chip "W25Q128JV" (16384 kB, SPI)"
# 3. First read β specify chip explicitly
flashrom -p ch341a_spi -c "W25Q128JV" -r dump1.bin
# 4. Second read β same command, different output file
flashrom -p ch341a_spi -c "W25Q128JV" -r dump2.bin
# 5. Verify β hashes must match
md5sum dump1.bin dump2.bin
sha256sum dump1.bin dump2.bin
# 6. Keep the original
cp dump1.bin dump_original.bin
chmod 444 dump_original.bin # make it read-only to protect it
All subsequent analysis runs on dump1.bin (or a working copy). The original never gets modified.
What a Clean Read Looks Like
Before running any analysis tool, do a basic sanity check on the raw bytes.
File size should match chip capacity:
ls -lh dump1.bin
# W25Q128JV = 16 MB
# Expect: 16777216 bytes exactly
A dump that is too small usually means flashrom was force-reading an unknown chip with a wrong geometry.
Hex inspection β first and last bytes:
# First 32 bytes
xxd dump1.bin | head -4
# Last 32 bytes
xxd dump1.bin | tail -4
# Check for all-0xFF (erased) or all-0x00 (likely bad read)
A real firmware dump starts with structured data. The first few bytes are often a bootloader magic, a filesystem header, or raw code. Pure 0xFF from offset 0 is suspicious unless you've just erased the chip. Pure 0x00 anywhere comprehensive is almost always a bad read.
binwalk: First Analysis Pass
binwalk scans a binary for known signatures and prints their offsets:
binwalk dump1.bin
Example clean output:
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
0 0x0 U-Boot legacy image, ...
65536 0x10000 LZMA compressed data, ...
262144 0x40000 Squashfs filesystem, little endian, ...
4456448 0x440000 JFFS2 filesystem data little endian
This tells you the dump contains: - A bootloader at offset 0 - Compressed kernel at 0x10000 - Root filesystem at 0x40000 - Writable filesystem (config/data) at 0x440000
What a corrupted dump looks like:
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
# Nothing, or only spurious matches scattered everywhere
No signatures, or random signature hits with no coherent structure, means the dump is corrupted. Go back and fix the connection before proceeding.
Entropy Analysis
Entropy measures the randomness of data β how compressed or encrypted sections look versus plaintext code.
binwalk -E dump1.bin
This generates an entropy graph (or prints values if no GUI). What to expect:
| Region | Entropy | Meaning |
|---|---|---|
| Bootloader code | 0.6-0.8 | ARM/MIPS instructions β moderate entropy |
| Compressed kernel | ~1.0 | Near-maximum β high entropy is expected for compressed data |
| Squashfs | ~1.0 | Compressed filesystem β high entropy |
| Config partition | 0.3-0.7 | Mixed text and binary β lower entropy |
| Erased regions | ~0.0 | All 0xFF bytes β zero entropy |
A dump where every region shows entropy near 1.0 and binwalk finds no signatures may indicate full-disk encryption. That's a different problem requiring a different approach (key extraction via JTAG, DRAM forensics, or finding the key in the bootloader).
Extracting Partitions with dd
Once you have offsets from binwalk, dd extracts individual partitions:
# Extract Squashfs at offset 0x40000 (262144 decimal), size TBD
dd if=dump1.bin of=rootfs.bin bs=1 skip=262144
# Better: extract just the filesystem (if you know its size)
dd if=dump1.bin of=rootfs.bin bs=1 skip=262144 count=4194304
# Mount the extracted Squashfs
unsquashfs rootfs.bin
# Output: squashfs-root/ directory tree
After extracting the rootfs:
ls squashfs-root/
# You now have the full device filesystem
# Look for: /etc/passwd, /etc/shadow, /etc/config/, hardcoded credentials
Strings on the Raw Dump
Before full extraction, strings gives a fast overview of what's in the dump:
# Basic strings scan (minimum 8 chars to reduce noise)
strings -n 8 dump1.bin | less
# Filter for interesting patterns
strings -n 8 dump1.bin | grep -i "password\|passwd\|secret\|key\|admin\|default"
strings -n 8 dump1.bin | grep -E "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}" # IPs
strings -n 8 dump1.bin | grep -E "http[s]?://" # URLs
# Look for version strings and build info
strings -n 8 dump1.bin | grep -i "version\|build\|firmware\|kernel"
Strings on raw firmware often reveals hardcoded credentials, URLs, API endpoints, and version information without needing to extract the filesystem first.
Write Protection: Detection and Bypass
Some chips have hardware and software write protection. This affects writing (not reading), but detection is useful β a protected chip tells you about the device's security posture, and bypassing it is necessary if you want to modify firmware.
Status Register: NOR flash chips have a status register accessible via SPI. Bits BP0, BP1, BP2 (Block Protect bits) define which regions of flash are write-protected.
# Read the status register
flashrom -p ch341a_spi -c "W25Q128JV" --get-size # check access
flashrom -p ch341a_spi -c "W25Q128JV" -r /dev/null # read to check access
flashrom will warn during write operations if BP bits are set. For reads, write protection has no effect β BP bits only protect against erase and write commands.
WP# pin: Pin 3 of SOIC-8 flash is WP# (Write Protect). When pulled low, software cannot clear the BP bits. The CH341A ties WP# to VCC (high = write enable) for read/write operations, which is correct.
If you're attempting to write and getting protection errors:
# Check if BP bits are the issue β flashrom reports this during write
# To clear BP bits (software write protect only, no hardware WP)
# Some chips allow: write 0x00 to status register via flashrom
For research purposes: detecting that BP bits are set, or that WP# is hardwired low on the board, tells you the vendor made an attempt to prevent firmware modification. Document it.
Storing the Dump
# Directory structure for a target
mkdir -p target_device/flash/
cp dump1.bin target_device/flash/dump_original.bin
chmod 444 target_device/flash/dump_original.bin
# Working copies
cp dump1.bin target_device/flash/dump_working.bin
# Extraction output
cd target_device/flash/
unsquashfs -d rootfs dump_working.bin # or via binwalk
# Document the chip
echo "Chip: W25Q128JV, 16MB, read date: $(date), md5: $(md5sum dump1.bin)" > target_device/flash/metadata.txt
Never modify the original dump. If analysis goes wrong, you should always be able to go back to a known-good copy.
Full Verification Checklist
Before calling a dump done:
- [ ] Two reads produce identical MD5/SHA256 hashes
- [ ] File size matches chip capacity exactly
- [ ]
binwalkshows recognizable structures (bootloader, filesystem, kernel) - [ ]
stringsreturns readable text from expected sections - [ ] Entropy analysis is coherent (not uniformly high everywhere)
- [ ] Original dump is write-protected and stored separately
- [ ] Chip info and read parameters are documented
A dump that passes these checks is a reliable starting point for analysis.