Wiki / Concepts

Flash Memory

Non-volatile storage that erases in blocks and writes in pages, only ever clearing bits from 1 to 0. Every quirk of embedded storage, and several forensic opportunities, follow from that.

What a raw flash dump looks like
Written data code, config, mixed bytes
Erased free space all 0xFF, not a truncated read
Erase sets a whole block back to 0xFF and program only clears bits 1 to 0, so unused regions read as solid 0xFF while written regions do not. A dump ending in a long run of 0xFF is free space, not a truncated read - and old copies of changed data often survive in obsolete blocks.

Flash memory is the non-volatile storage in essentially every embedded device. It behaves unlike RAM or a disk in one specific way that explains almost everything else about it: programming can only change a bit from 1 to 0. Going back to 1 requires erasing, and erasing works on a whole block at a time.

Read      byte or page granularity, fast
Program   page granularity (256 B typical), only clears bits 1 -> 0
Erase     block granularity (4 KB to 128 KB), sets a whole block back to 0xFF, slow

An erased chip is all 0xFF. That is why unused flash regions in a dump are solid 0xFF, and why a region of 0x00 is written data, not empty space.

NOR and NAND

Two families with different trade-offs, and you meet both:

NOR NAND
Read random access, byte addressable page at a time
Execute in place yes no
Density and cost lower density, more expensive per bit high density, cheap
Bad blocks none from the factory expected, from the factory onwards
Typical size 1 to 32 MB 128 MB and up
Typical use boot code, small firmware rootfs, bulk storage

NOR is what a small device boots from and often the only storage it has, usually an 8-pin SPI part you can read with a soic-clip and flashrom. NAND appears on larger devices, needs error correction, and ships with blocks marked bad from the factory, so software must track and avoid them.

Wear, and what it leaves behind

Each erase block tolerates a finite number of erase cycles, roughly 10,000 to 100,000. Writing the same logical location repeatedly would destroy one block long before the rest of the chip aged, so systems spread writes out:

  • Wear levelling remaps logical addresses to different physical blocks over time.
  • Erase-before-write means an update usually writes a new copy elsewhere and marks the old one obsolete, rather than overwriting in place.

Both have a direct forensic consequence: old copies of data survive. A configuration value changed ten times may leave several previous versions readable in the raw dump, and a "deleted" secret is frequently still there in an obsolete block. This is why imaging the raw chip is worth more than reading the filesystem through the device, and why the ESP32 NVS partition in particular tends to contain a history rather than a state.

Filesystems built for it

Ordinary filesystems assume overwrite-in-place, so flash gets its own: JFFS2 and UBIFS on raw NAND under Linux MTD, SquashFS for read-only compressed roots, LittleFS and SPIFFS on microcontrollers, and NVS for key-value storage on ESP32. Managed flash (eMMC, SD cards, SSDs) hides all of this behind a controller doing wear levelling and remapping internally, which also means you cannot see the spare blocks from outside.

Security-relevant properties

  • Reading the chip physically bypasses the software. Access control enforced by the firmware is irrelevant to a clip on the package.
  • One-time-programmable regions exist. eFuses and OTP areas are flash-like cells that can be burned once, which is where secure-boot keys and lifecycle state live. See efuse.
  • Encryption at rest is separate. flash-encryption and xts-mode cover what an encrypted dump looks like: high flat entropy, no signatures, nothing for binwalk to find.
  • Data remanence. Even after an erase, residual charge can in principle be measured with laboratory equipment. This matters for very high-value targets and almost never in practice.

Pitfalls

  • Reading a chip in-circuit can fail or corrupt, because the host SoC is also driving the bus. Hold the host in reset, or desolder.
  • A dump full of 0xFF at the end is unused space, not a truncated read.
  • Voltage matters: many SPI flash parts are 3.3 V and a 5 V programmer will damage them.
  • Two dumps of the same chip that differ are normal on a running device, and a strong hint about where mutable state lives.

What it pairs with

spi-flash-soic8 is the package you clip onto, flashrom and ch341a read it, binwalk parses what comes out, and partition-table explains how it is divided.

Further reading