Dumping SPI Flash Chip Firmware
_

Dumping SPI Flash Chip Firmware

Published: April 9, 2025
Warning: This article discusses techniques that should only be used on hardware you own or have explicit permission to modify. Always respect intellectual property rights and applicable laws.

Within hardware hacking, there are plenty of techniques that can be used to extract information from a device, interface with it or increase its attack surface - it all really depends on what comes out of your investigations into the device.

One such vector is gaining access to the device's firmware, which commonly includes a small linux filesystem of some description. This can give a big insight into the inner workings of the embedded system, and depending on how far the manufacturer has deviated from best practices, can expose hardcoded secrets or obvious vulnerabilities.

Obtaining the firmware can be achieved through dumping non-volatile flash chips, the most common of which are SPI (Serial Peripheral Interface) flash chips. We can interface with these chips using software, and pretend to be a processor that can send commands to the chip to read the firmware.

Understanding SPI Flash Memory

Note: When working with electronic components, you will almost certainly encounter an architecture archaically known as a "Master and Slave" relationship.

In recent years, we have collectively migrated to calling this a "Controller and Peripheral" relationship, but the terminology is still widely used in the industry. So when you see "MISO" (Master In Slave Out) or "MOSI" (Master Out Slave In), this is identical to "PICO" (Peripheral In Controller Out) or "POCI" (Peripheral Out Controller In).

SPI (Serial Peripheral Interface) is a synchronous serial communication interface that uses a controller-peripheral architecture. The communication interface is done over 8 different pins on the chip, each of which have a specific purpose:

Identifying Flash Chips

Different SPI flash chip packages exist, I have rarely encountered packages outside of the following formats:


Note: The "8" in SOIC-8 and WSON-8 indicates the number of pins. SOIC-44 for example would denote that the chip has 44 pins. 8 pin configurations are the most common for simple, single purpose IoT devices such as IP cameras.

Chip Markings

It is also typical for chip manufacturers to print reference markings on the top of their chips. These markings are used to identify the chip, and are usually a combination of the manufacturer, the type of chip and the capacity. So if you think you have found a candidate chip, you can simply google the markings and find its datasheet.

Chip Markings

From the above, we know the manufacturer is Winbond, and the chip is a W25Q256JVEQ. If we google this string "W25Q256JVEQ", we will get results including the datasheet for the chip.

Interpreting Datasheets

The datasheet will inform us of the chip's pinout, as well as other specifications including voltage requirements, speeds, chip packages and more.

The below diagram is taken from the datasheet we found for the above chip:

Chip Pinout from Datasheet

The physical chip is marked with a dot in one of its corners. This dot is used to identify pin 1 on the chip, and helps us line up the pins in the diagram with the pins on the chip.

Chip Off vs Chip On

There are two main ways to actually dump the firmware from a chip; chip off and chip on. These are pretty self explanatory - chip off is when you remove the chip from the board by de-soldering it, and chip on is when you leave the chip on the board and use a test clip or probes to connect to its pins.

The chip off method is generally preferred because when you introduce the 3.3V power supply to the chip, you can also inadvertenly power up other device components. This can cause clashing behaviours when you are trying to send commands to the chip to read the firmware.

Dumping the Firmware

Warning: If you are investigating a device for vulnerabilities and not a specific older firmware version, make sure your firmware is up-to-date. Any vulnerabilities you find may have already been patched in a newer firmware release, and you will have to repeat all of your hard work. If you break the chip or brick the device, you might not even be able to grab the latest firmware, so exercise caution and solder with purpose.

Here is a part list of equipment you might typically need:

Breakout

The first thing we need to do is get reliable connections to the chip's pins. If you are performing a chip on, this is as simple as connecting the test clip to the chip's pins, ensuring that proper contact is made to each pin. Test clips commonly have a red cable, marking it as pin 1.

If you are performing a chip off, this is the point where you will need to de-solder the chip from the board.

  1. Apply a healthy amount of solder flux to the chip's pins / connections on the board.

  2. Start heating the area of the board with the chip on using a hot air gun. I tend to start around 300C for this.

  3. Once the area around the chip is heated, increase your temperature to around 400C (thicker PCB boards may require heating up to 420C). Point your hot air gun at the chip, slowly moving around to apply even heat.

  4. You will eventually see the solder around the chip's pins melt and go shiny. This is the point at which you take your tweezers and carefully lift the chip off the board.

  5. Once the chip is removed, it is important to clean up. Use solder wick to remove any excess solder (from the chip and the board), and use isopropyl alcohol to remove flux residue.

  6. Pop the chip into your socket adapter / chip cradle. There are again usually markings on the adapter which tell you where pin 1 should go.


WSON-8 Socket Adapter

Connecting to the Chip

Now that we have access to the chip's pins, we will connect the chip to our Bus Pirate. Recent iterations of the Bus Pirate have a cool LED screen, which tells you which connection correlates to which pin. We have to set up the Bus Pirate first to get this information.

The Bus Pirate 5 works over a serial interface, so, using a cable that supports power and data, connect it to your computer. We can then identify the serial interface port either by listing devices in /dev/ if you are on linux, or looking at device manager COM ports if you are on windows. Once identified, connect to the serial interface with a baud rate of 115200 using a terminal emulator like MobaXterm, or a tool like screen or tio.

┌──(kali㉿kali)-[~] └─$ tio /dev/ttyACM0 -b 115200 [12:49:35.407] tio 3.8 [12:49:35.407] Press ctrl-t q to quit [12:49:35.410] Connected to /dev/ttyACM0 HiZ>

Now we can configure the bus pirate to be in SPI mode. The default settings are pretty universal for SPI flash chips, but remember, the datasheet will give you clarity on the best settings for your chip. You can accept default settings by pressing enter.

HiZ> m Mode selection 1. HiZ 2. 1WIRE 3. UART 4. HDUART 5. I2C 6. SPI 7. 2WIRE 8. 3WIRE 9. DIO 10. LED 11. INFRARED 12. JTAG x. Exit Mode > 6 Mode: SPI SPI speed 1 to 62500kHz x. Exit kHz (100kHz*) > Data bits 4 to 8 bits x. Exit Bits (8*) > Clock polarity 1. Idle LOW* 2. Idle HIGH x. Exit Polarity (1) > Clock phase 1. LEADING edge* 2. TRAILING edge x. Exit Phase (1) > 0.0V 0.0V 0.0V 0.0V 0.0V 0.0V 0.0V Chip select 1. Active HIGH (CS) 2. Active LOW (/CS)* x. Exit CS (2) > Actual speed: 99kHz

Once configured, we can see that the Bus Pirate's LED screen has changed to show what each pin is expected to be connected to.


Bus Pirate SPI Mode

As previously mentioned, we need to pull the HOLD/RESET and WP pins to high. We can do this by configuring two of our spare pins to "HIGH" mode.

SPI> A 1 IO1 set to OUTPUT: 1 SPI> A 0 IO0 set to OUTPUT: 1

Now let's connect the chip to the Bus Pirate. Most of the connections are pretty easy to figure out - some things to consider:

Here's a really polished wiring diagram I made at 2AM in MS Paint - please try to contain yourself when viewing:

Wiring Diagram

Once all your connections are made, we can supply some power to the chip. The below commands are specific to the Bus Pirate 5. Again, default settings are usually fine, but you can always consult the datasheet if you are not sure.

SPI> W Power supply Volts (0.80V-5.00V) x to exit (3.30) > Maximum current (0mA-500mA), for none x to exit (none) > 3.30V requested, closest value: 3.30V Current limit:Disabled Power supply:Enabled Vreg output: 3.3V, Vref/Vout pin: 3.3V, Current: 4.8mA

To test everything is working, we use the probe command. This will read the first 16 bytes of the chip which stores the manufacturer ID (or JEDEC ID). The bus pirate will then look up the ID in its database and return information about the chip.

SPI> flash probe Probing: Device ID Manuf ID Type ID Capacity ID RESID (0xAB) 0x18 REMSID (0x90) 0x18 0xef RDID (0x9F) 0xef 0x40 0x19 SFDP (0x5A): found 0x50444653 "PDFS" Version: 1.5 Headers: 1 **Param Table 0** Type Ver. Length Address Table 0 JEDEC (0x00) 1.5 64 0x000080 MSB-LSB 3 2 1 0 [0001] 0xFF 0xFB 0x20 0xE5 [0002] 0x0F 0xFF 0xFF 0xFF [0003] 0x6B 0x08 0xEB 0x44 [0004] 0xBB 0x42 0x3B 0x08 [0005] 0xFF 0xFF 0xFF 0xFE [0006] 0x00 0x00 0xFF 0xFF [0007] 0xEB 0x40 0xFF 0xFF [0008] 0x52 0x0F 0x20 0x0C [0009] 0x00 0x00 0xD8 0x10 [0010] 0x00 0xA6 0x02 0x36 [0011] 0xD3 0x14 0xEA 0x82 [0012] 0x33 0x76 0x63 0xE9 [0013] 0x75 0x7A 0x75 0x7A [0014] 0x5C 0xD5 0xA2 0xF7 [0015] 0xFF 0x4D 0xF7 0x19 [0016] 0xA5 0xF9 0x70 0xE9 Density: 33554432 bytes Address bytes: 3 or 4 Write granularity:>=64B Write Enable Volatile: 0 Write Enable instruction: 0x50 4K erase instruction: 0x20 Fast read: 1-1-2 1-1-4 1-2-2 1-4-4 2-2-2 4-4-4 Instruction: 0x3b 0x6b 0xbb 0xeb -- 0xeb Wait states: 8 8 2 4 0 0 Mode clocks: 0 0 4 4 0 4 Erase: 1 2 3 4 Instruction: 0x20 0x52 0xd8 0x00 Size: 4K 32K 64K 1B Initializing SPI flash... Flash device manufacturer ID 0xEF, type ID 0x40, capacity ID 0x19 SFDP V1.5, 0 parameter headers Type Ver. Length Address Table 0 JEDEC (0x00) 1.5 64B 0x000080 JEDEC basic flash parameter table info: MSB-LSB 3 2 1 0 [0001] 0xFF 0xFB 0x20 0xE5 [0002] 0x0F 0xFF 0xFF 0xFF [0003] 0x6B 0x08 0xEB 0x44 [0004] 0xBB 0x42 0x3B 0x08 [0005] 0xFF 0xFF 0xFF 0xFE [0006] 0x00 0x00 0xFF 0xFF [0007] 0xEB 0x40 0xFF 0xFF [0008] 0x52 0x0F 0x20 0x0C [0009] 0x00 0x00 0xD8 0x10 4 KB Erase is supported throughout the device (instruction 0x20) Write granularity is 64 bytes or larger Flash status register is non-volatile 3- or 4-Byte addressing Capacity is 33554432 Bytes Flash device supports 4KB block erase (instruction 0x20) Flash device supports 32KB block erase (instruction 0x52) Flash device supports 64KB block erase (instruction 0xD8) Found a Winbond flash chip (33554432 bytes) Flash device reset success [SFUD](/root/bp5-main/src/lib/sfud/inc/sfud.c:958) Enter 4-Byte addressing mode success.

If this doesn't work, you can troubleshoot with the following:

Otherwise, if everything is working, we can dump the firmware to a file!

SPI> flash read -f flash.bin Probing: Device ID Manuf ID Type ID Capacity ID RESID (0xAB) 0x18 REMSID (0x90) 0x18 0xef RDID (0x9F) 0xef 0x40 0x19 SFDP (0x5A): found 0x50444653 "PDFS" Version: 1.5 Headers: 1 **Param Table 0** Type Ver. Length Address Table 0 JEDEC (0x00) 1.5 64 0x000080 MSB-LSB 3 2 1 0 [0001] 0xFF 0xFB 0x20 0xE5 [0002] 0x0F 0xFF 0xFF 0xFF [0003] 0x6B 0x08 0xEB 0x44 [0004] 0xBB 0x42 0x3B 0x08 [0005] 0xFF 0xFF 0xFF 0xFE [0006] 0x00 0x00 0xFF 0xFF [0007] 0xEB 0x40 0xFF 0xFF [0008] 0x52 0x0F 0x20 0x0C [0009] 0x00 0x00 0xD8 0x10 [0010] 0x00 0xA6 0x02 0x36 [0011] 0xD3 0x14 0xEA 0x82 [0012] 0x33 0x76 0x63 0xE9 [0013] 0x75 0x7A 0x75 0x7A [0014] 0x5C 0xD5 0xA2 0xF7 [0015] 0xFF 0x4D 0xF7 0x19 [0016] 0xA5 0xF9 0x70 0xE9 Density: 33554432 bytes Address bytes: 3 or 4 Write granularity:>=64B Write Enable Volatile: 0 Write Enable instruction: 0x50 4K erase instruction: 0x20 Fast read: 1-1-2 1-1-4 1-2-2 1-4-4 2-2-2 4-4-4 Instruction: 0x3b 0x6b 0xbb 0xeb -- 0xeb Wait states: 8 8 2 4 0 0 Mode clocks: 0 0 4 4 0 4 Erase: 1 2 3 4 Instruction: 0x20 0x52 0xd8 0x00 Size: 4K 32K 64K 1B Initializing SPI flash... Flash device manufacturer ID 0xEF, type ID 0x40, capacity ID 0x19 SFDP V1.5, 0 parameter headers Type Ver. Length Address Table 0 JEDEC (0x00) 1.5 64B 0x000080 JEDEC basic flash parameter table info: MSB-LSB 3 2 1 0 [0001] 0xFF 0xFB 0x20 0xE5 [0002] 0x0F 0xFF 0xFF 0xFF [0003] 0x6B 0x08 0xEB 0x44 [0004] 0xBB 0x42 0x3B 0x08 [0005] 0xFF 0xFF 0xFF 0xFE [0006] 0x00 0x00 0xFF 0xFF [0007] 0xEB 0x40 0xFF 0xFF [0008] 0x52 0x0F 0x20 0x0C [0009] 0x00 0x00 0xD8 0x10 4 KB Erase is supported throughout the device (instruction 0x20) Write granularity is 64 bytes or larger Flash status register is non-volatile 3- or 4-Byte addressing Capacity is 33554432 Bytes Flash device supports 4KB block erase (instruction 0x20) Flash device supports 32KB block erase (instruction 0x52) Flash device supports 64KB block erase (instruction 0xD8) Found a Winbond flash chip (33554432 bytes) Flash device reset success [SFUD](/root/bp5-main/src/lib/sfud/inc/sfud.c:958) Enter 4-Byte addressing mode success. Dumping to flash.bin... [-------------------C] Dump OK

Once the dump is complete, you can grab it from the Bus Pirate's internal storage; it shows up like a USB drive on your system. Tools like binwalk and unblob can be used against the bin file to carve out interesting file contents, however this is beyond the scope of this article.

Conclusion

Whether you're exploring the security of your own devices, conducting authorised penetration testing or developing more secure hardware, understanding how to access and analyse flash memory contents provides valuable insights into the inner workings of embedded systems.

Dumping SPI flash chips is a fundamental skill in hardware security assessment and reverse engineering. While the basic process is straightforward, mastering the techniques for analysis and overcoming common challenges takes practice and experience. Practise on devices you find through ebay, cheap manufacturers, e-waste or old unused devices.

Remember that with great power comes great responsibility - always use these techniques ethically and legally, respecting intellectual property rights and applicable laws.

← Back to Home