Tutorial

SPI and JTAG Flash Dumping from Hardware

Identify SPI flash chips, dump them with a CH341A programmer or in-circuit SOIC clip, and use OpenOCD over JTAG to extract firmware with no removable chip.

12 min read advanced
Embedded SPI JTAG Flash Dumping

Prerequisites

  • Tutorial: Firmware RE with Binwalk and Ghidra
  • Comfortable with a multimeter
  • $30-50 of inexpensive hardware (programmer + clip + jumper wires)

Part 7 of 7 in Embedded Systems & Firmware

Table of Contents

The previous tutorials in this series got firmware from vendor downloads, U-Boot consoles over UART, and update-traffic interception. All of those work without ever picking up a soldering iron. But sometimes the file you want is not on the vendor’s support site, the bootloader refuses to give you a shell, and the OTA update is signed and encrypted end-to-end. At that point the firmware is still right there on the board, in a flash chip you can physically touch. This tutorial covers how to read it.

We cover two interfaces. SPI flash, which is the discrete chip soldered next to the SoC on a huge fraction of consumer devices, and JTAG (or SWD), which is how you talk to the CPU itself when the flash is internal or behind an unfriendly NAND controller. Both come with their own footguns; both are routine if you know the drill.

Where firmware comes from:

  Easy ────────────────────────────────────────────── Hard
  Vendor      U-Boot/    SPI flash     JTAG        eMMC/NAND
  download    serial     in-circuit    + OpenOCD   in-circuit

  (no HW)   (USB-TTL)  (CH341A+clip)   ($20 J-Link)  (specialist)
                            ↑ this tutorial ↑

When to dump from hardware

Software-only firmware extraction (covered in Firmware RE with Binwalk and Ghidra) handles the common case: download the update file, run binwalk, get a SquashFS root. Reach for hardware when one of these is true:

  • Encrypted vendor packages. The OTA .bin is high-entropy from byte zero. The decryption key is somewhere on the running device, often in the bootloader or a one-time-programmable region you cannot read remotely.
  • No public download. Industrial, automotive, and a lot of “smart appliance” firmware never ships outside the vendor’s manufacturing chain. The chip on the board is the only copy you have access to.
  • Bootloader extraction for secure-boot work. ROM-loaded first-stage bootloaders are rarely included in OTA updates. To audit the secure-boot chain you need the actual contents of the boot partition or internal mask ROM, which means reading the chip directly.
  • Runtime config blobs not in the OTA. Per-device calibration, provisioning data, MAC addresses, Wi-Fi credentials, paired-device lists. These are written at the factory or by the user, never present in a stock firmware download.
  • Recovering a bricked device. If you flash garbage, the device won’t boot, but the chip still reads fine. Pulling a known-good dump from another unit and writing it back is sometimes the only way back.

If you don’t have one of those reasons, save yourself the soldering and use the firmware-RE workflow.

Identifying SPI flash on a board

Pop the case off and look at the PCB. SPI flash is almost always a small chip near the SoC, in one of a few standard packages:

PackagePinsFootprintNotes
SOIC-8 (208 mil)8~5 x 8 mmThe most common, easy to clip
SOIC-1616~7 x 10 mmLarger capacities; clip is bigger and pricier
WSON-8 (DFN)8~5 x 6 mmLeadless, no exposed legs - clip won’t work, must desolder
TSOP-4848~12 x 20 mmParallel NOR; not SPI, ignore for this workflow
BGAmany6 x 8 mm typicalSolder balls under the package; specialist tooling only

Read the markings on the chip. Common SPI flash families:

  • Winbond W25Q-series (W25Q32, W25Q64, W25Q128, W25Q256). Number after W25Q is the size in megabits. By far the most common in consumer gear.
  • Macronix MX25-series (MX25L12835F, MX25U25645G). Similar conventions; MX25U parts are 1.8V, MX25L parts are 3.3V.
  • GigaDevice GD25-series (GD25Q128, GD25LQ64). Pin-compatible Winbond clones, plus 1.8V variants in the LQ line.
  • Spansion / Cypress / Infineon S25FL-series. More common in industrial and automotive.

Always cross-reference the full part number against the manufacturer’s datasheet to confirm two things: it’s an SPI device (not I2C EEPROM, not parallel NOR), and its supply voltage. The “L” vs “U” suffix on Macronix, or “Q” vs “LQ” on GigaDevice, is the difference between a chip you can power from a 3.3V CH341A and a chip you’ll destroy doing exactly that.

Typical PCB layout (top-down):

   ┌────────────────────────────────────────┐
   │  ┌──────┐                              │
   │  │ RAM  │   ┌─────────────┐            │
   │  │ DDR3 │   │   Main SoC  │   ┌────┐   │
   │  └──────┘   │  (BGA, hot) │   │RJ45│   │
   │             └─────────────┘   └────┘   │
   │                  │                      │
   │             ┌────┴────┐  ← SPI bus      │
   │             │ W25Q128 │  ← SOIC-8 here  │
   │             └─────────┘                 │
   │                                         │
   └────────────────────────────────────────┘

The flash is usually within a centimeter or two of the SoC, on whichever PCB layer is easier to route. If the board is two-sided, check the back; manufacturers often hide flash chips on the underside to keep the top clean.

Tip

Photograph and annotate Before you clip anything, take a high-resolution photo of the PCB and label every chip you can identify. You’ll refer back to this constantly when something doesn’t power up the way you expected, and it’s also the artifact you publish in a writeup. A USB microscope is $30 and worth every cent.

The cheap rig: CH341A + SOIC-8 clip

The CH341A is a USB-to-multi-protocol bridge that, with flashrom driving it, reads and writes SPI flash. Clones cost $5-15. Add a SOIC-8 test clip (Pomona 5250 if you want quality, AliExpress generic if you don’t) and a fistful of jumper wires and you’re done. Total: under $30.

Pinout

SPI flash in a SOIC-8 has a standardized pinout. Pin 1 is marked with a dot or notch on the chip; the clip’s red wire (or pin 1 marker) must align with it.

  SOIC-8 SPI flash (top view, dot at pin 1):

         ┌────●────┐
    /CS ─┤ 1     8 ├─ VCC
    DO  ─┤ 2     7 ├─ /HOLD or /RESET
   /WP  ─┤ 3     6 ├─ CLK
    GND ─┤ 4     5 ├─ DI
         └─────────┘

  Standard names:
    /CS   = Chip Select (active low)
    DO    = Data Out (chip → host) = MISO
    /WP   = Write Protect (active low) — tie high for normal use
    GND   = Ground
    DI    = Data In (host → chip)   = MOSI
    CLK   = SPI Clock
    /HOLD = Hold (active low) — tie high
    VCC   = Supply (3.3V or 1.8V — check datasheet)

The CH341A programmer board has a 2x4 header labeled for 25-series SPI flash. The labels match one-to-one with the chip pins, so connecting clip → header is just matching names:

CH341A headerConnects to chip pinFunction
CS1/CS
MISO2DO
(3.3V via solder bridge)3/WP - pull high
GND4GND
MOSI5DI
SCK6CLK
(3.3V via solder bridge)7/HOLD - pull high
3.3V8VCC

In practice, the SOIC-8 clip you buy with the CH341A already has the wire ordering correct, you just plug it into the matching header. Look at the printed labels; if it doesn’t fit cleanly, double-check pin 1 alignment before you apply power.

In-circuit clipping

The clip closes around the chip, the spring-loaded teeth contact each pin from above, and you read without desoldering. In theory.

In practice: when you power VCC through the clip, you also power every other component on that 3.3V rail. The SoC, the RAM, the Ethernet PHY, the LEDs - everything. The CH341A’s onboard regulator can supply maybe 100-200 mA. A live SoC needs an amp. The voltage collapses, the read fails, and the longer-term failure mode is that something actually does start booting on partial power and contends with you on the SPI bus.

Warning

Never dump while the device is also powered Connecting the CH341A’s 3.3V to a board that’s powered from its own supply puts two regulators in parallel. The one with the slightly higher voltage backfeeds the other. Best case: undefined behavior on the bus and a corrupt dump. Worst case: you blow out the CH341A’s regulator, the board’s regulator, or both, and possibly the chip you were trying to read. Always disconnect the device’s own power supply before clipping.

The flow is:

  1. Disconnect the device from its wall adapter and let any large capacitors drain (a minute is plenty).
  2. Locate the flash chip and align the clip - pin 1 marker on the clip to pin 1 on the chip.
  3. Squeeze the clip closed; verify all eight legs are making contact.
  4. Plug the CH341A into USB. The board’s 3.3V rail comes up through the clip.
  5. Run flashrom (next section).

If the chip won’t power up because something downstream draws too much current, the voltage on the bus will sag and reads will fail with timeouts or noise. Some boards have a small jumper or zero-ohm resistor that isolates the flash rail; cutting that lets you power just the chip. Otherwise, you’re desoldering.

Reading with flashrom

flashrom is the canonical Linux tool for SPI flash. It comes with most distros.

# Debian/Ubuntu
sudo apt install flashrom

# Arch
sudo pacman -S flashrom

# Verify
flashrom --version

Probing the chip

First confirm flashrom can see the chip. Run with no -c (chip) argument:

sudo flashrom -p ch341a_spi
flashrom v1.3.0 on Linux ...
Calibrating delay loop... OK.
Found Winbond flash chip "W25Q128.V" (16384 kB, SPI) on ch341a_spi.
No operations were specified.

That’s the happy path. The chip identified itself by its JEDEC ID (the three-byte response to a 0x9F opcode) and flashrom looked it up in its built-in database.

If you see something like:

Probing for Generic unknown SPI chip (RDID), 0 kB: probe_spi_rdid: id1 0xff, id2 0xffff
No EEPROM/flash device found.

Either pin 1 alignment is wrong, the clip isn’t seated, or the device is stealing the bus. Disconnect, re-seat, try again. If flashrom reports a JEDEC ID but no matching chip name (e.g. Found unknown chip "0xef 0x40 0x18"), you have a chip the database doesn’t know. Look up the JEDEC ID at flashrom.org/Supported_hardware or in the manufacturer’s datasheet, and pass -c with the closest pin-compatible chip name.

Dumping

Once probing works, read it twice and compare:

sudo flashrom -p ch341a_spi -c W25Q128.V -r dump1.bin
sudo flashrom -p ch341a_spi -c W25Q128.V -r dump2.bin
sha256sum dump1.bin dump2.bin
6f5902ac237024bdd0c176cb93063dc4...  dump1.bin
6f5902ac237024bdd0c176cb93063dc4...  dump2.bin

Identical hashes mean both reads agree. Different hashes mean somewhere you have a bus glitch, contention, or marginal contact through the clip. Read a third time and pick the two that match - or, better, fix the underlying issue (re-seat the clip, shorten jumper wires, isolate the flash power rail) before trusting the data.

Warning

Dump twice, always This is non-negotiable. SPI dumps are not protected by any kind of checksum at the wire level. A single bit flip from contact noise produces a file that looks structurally correct - binwalk will still extract it, the partition table will still parse - but you’ll spend hours wondering why a checksum somewhere deep in the firmware is off by one. Two reads with a sha256sum comparison costs you sixty extra seconds and saves entire afternoons.

A 16 MB chip dumps in roughly 90 seconds at the CH341A’s nominal speed. 128 MB chips (W25Q01JV etc.) take ten minutes per read.

Speed and reliability tweaks

If reads are unreliable:

  • Shorten the jumper wires. SPI clock at 12 MHz doesn’t tolerate 30 cm of breadboard wire well. The fewer centimeters between programmer and chip, the better.
  • Slow the clock. flashrom -p ch341a_spi=spispeed=100kHz runs much slower but gets through marginal connections.
  • Check the 3.3V rail with a multimeter while reading. If it sags below 3.0V, you’re powering more than just the chip.

Writing back (and why you usually shouldn’t)

flashrom -w newdump.bin -c W25Q128.V -p ch341a_spi writes a file back to the chip. The same syntax you’ve been using to read, with -w instead of -r. It’s two seconds of typing between functional firmware and a brick.

For research work, do read-only analysis. There is essentially never a reason to write to a chip you’re investigating; you’re trying to understand it, not modify it.

If you do have to write (recovering a brick, modifying a firmware to test a vulnerability fix, persistence research), save the original first:

# Always do this BEFORE any write
sudo flashrom -p ch341a_spi -c W25Q128.V -r original.bin
sha256sum original.bin > original.sha256
cp original.bin original.backup.bin

# Now you can experiment
sudo flashrom -p ch341a_spi -c W25Q128.V -w modified.bin

# Verify what's on the chip after the write
sudo flashrom -p ch341a_spi -c W25Q128.V -r verify.bin
diff <(xxd modified.bin) <(xxd verify.bin) | head

Warning

1.8V flash on a 3.3V programmer Many newer Winbond and Macronix parts are 1.8V only - W25Q128JW, MX25U12832F, etc. The “U” or “JW” suffix in the part number is the giveaway. Putting 3.3V on the VCC pin of a 1.8V chip permanently damages it within milliseconds, and clones often also drive the data lines at the wrong level. If your part is 1.8V, you need either a CH341A “1.8V mod” board (a level-shifter daughtercard) or a programmer that natively does 1.8V, like an XGecu T48. Always check the datasheet voltage range for the full part number, not just the family.

Warning

CH341A 5V on data lines A widely-known issue with cheap CH341A clones: although VCC outputs 3.3V (when the jumper is set correctly), the SPI data lines (MISO/MOSI/CS/CLK) often swing to 5V because the chip’s I/O is internally tied to the USB 5V rail. Reading is usually tolerated by 3.3V chips because the line voltage drops under load, but it’s outside spec and can damage the flash over time. The “1.8V mod” mentioned above is really a 5V→3.3V (or 1.8V) level shifter for the data lines. Search “CH341A 1.8V mod” for the schematic; it’s about $10 in parts.

Desoldering when in-circuit fails

If clip-based reading won’t work - too much downstream current, broken pins, you need to do many reads quickly and the clip keeps slipping - desolder the chip.

You need:

  • A hot air rework station ($60-200, a Yihua 858D clone is fine to start)
  • Flux paste (any brand)
  • A SOIC-8 socket for repeated reads after removal (~$5)
  • Isopropyl alcohol and a brush for cleanup

The procedure for a SOIC-8:

  1. Apply flux generously to all pins.
  2. Set the hot air station to ~340°C, low airflow.
  3. Heat the chip evenly, moving the nozzle in small circles, for 30-60 seconds. Do not stay on one corner.
  4. When the solder visibly melts on all sides, lift the chip with tweezers - it should come up effortlessly. If you have to pry, the solder isn’t molten yet; reheat.
  5. Clean residual solder from the pads with braid and flux.
  6. Drop the chip into the SOIC-8 socket, dump as needed, and either solder it back when finished or leave it socketed if you’ll come back to it.
After desolder:

   ┌─────────┐         ┌──────────┐
   │  PCB    │         │  SOIC-8  │
   │  (chip  │   →     │  socket  │ ← chip drops in here
   │  removed)│         │ on CH341A│
   └─────────┘         └──────────┘

Warning

Pads come off if you go too hot or too long The PCB pads under a SOIC-8 are bonded to the laminate with adhesive that fails above ~250°C sustained. Hot air at 340°C for sixty seconds is fine; the same heat for three minutes lifts pads. If a pad lifts, you can sometimes scrape solder mask off the trace and bridge to a nearby via, but it’s tedious. Move quickly, use plenty of flux to lower the effective melting point of the solder, and don’t park the nozzle.

After desoldering, a SOIC-8 socket on the CH341A header gives you the cleanest possible read path - no clip drift, no contention, no power-rail issues. Put any chip you’ll dump more than once into a socket.

JTAG: when there’s no removable flash

Plenty of modern devices have no SPI chip at all. The flash is inside the SoC package (eFlash on microcontrollers), or it’s NAND wired directly to the SoC’s controller, or it’s eMMC under a metal can. You can’t clip what isn’t there. JTAG (or, on Cortex-M parts, SWD) talks to the CPU itself, and the CPU can be told to read its own flash and hand the bytes back to you over the debug link.

Hardware options, cheapest to most expensive:

  • Raspberry Pi running OpenOCD on its GPIO - $0 if you already own a Pi. Slow (a few hundred kB/s) but it works.
  • FT2232H breakout board - $15-30. Reliable, fast (multi-MB/s), well-supported by OpenOCD’s ftdi driver.
  • J-Link clone - $20-40. Best speed and stability for the price. Some “EDU” J-Links are restricted to non-commercial use; clones are clones.
  • Genuine Segger J-Link - $400+. Worth it for daily professional use, overkill for a one-off dump.

OpenOCD basics

OpenOCD is the open-source JTAG/SWD daemon. It speaks to your debug adapter on one side and to the target CPU on the other. Configuration is two pieces: the interface (your adapter) and the target (the chip you’re debugging).

sudo apt install openocd
openocd --version

Cortex-M example: STM32F4

A small Cortex-M target. Connect SWDIO/SWCLK/GND from your J-Link to the SWD pins on the board, power the target normally.

Save as stm32f4-dump.cfg:

# Interface: J-Link clone over SWD
source [find interface/jlink.cfg]
transport select swd

# Target: STM32F4 series
source [find target/stm32f4x.cfg]

# Slow adapter speed for reliability
adapter speed 1000

# Run on connect
init
reset halt

# Dump 1 MB of internal flash starting at 0x08000000
dump_image stm32_dump.bin 0x08000000 0x100000

# Done
exit

Run it:

openocd -f stm32f4-dump.cfg
Open On-Chip Debugger 0.12.0
...
Info : J-Link V11 compiled Oct  4 2023 ...
Info : SWD DPIDR 0x2ba01477
Info : [stm32f4x.cpu] Cortex-M4 r0p1 processor detected
Info : [stm32f4x.cpu] target halted due to debug-request
dumped 1048576 bytes in 4.221234s (242.598 KiB/s)

You now have stm32_dump.bin. The address 0x08000000 is the standard Cortex-M flash base for STM32; other vendors map their flash differently (NXP at 0x00000000, Nordic at 0x00000000, etc.). The target/<chip>x.cfg file shipped with OpenOCD usually documents the right base.

Cortex-A example: AM335x (BeagleBone-class)

Cortex-A SoCs are messier. The CPU sits behind a DAP (Debug Access Port), which sits behind a TAP chain that may include other components, and the flash is reached via the SoC’s external memory controller, not a fixed memory map. There is no “one-size-fits-all” config; you need one specific to your SoC.

For an AM335x:

source [find interface/ftdi/olimex-arm-usb-tiny-h.cfg]
transport select jtag

source [find target/am335x.cfg]

adapter speed 1000
init
reset halt
targets

# AM335x has DDR that needs configuration before you can read it
# but the L3/L4 OCRAM and ROM are accessible immediately
mdw 0x40000000 16    ;# read 16 words from boot ROM

# To read external flash you usually have to:
# 1. Halt the CPU
# 2. Configure the GPMC (NAND controller) or QSPI controller via mww
# 3. Read from the mapped address range
# This is highly SoC-specific; consult the TRM.

For Cortex-A targets, plan to spend more time on memory-controller setup than on the actual dump. The right approach is often to let the device boot to U-Boot, halt the CPU there (so the memory controller is already initialized), then dump.

The halt → read → dump pattern

Once OpenOCD is connected and the target is halted, you can interact via the OpenOCD telnet interface (port 4444):

openocd -f your-config.cfg &
telnet localhost 4444
> halt
> mdw 0x08000000 4
0x08000000: 20020000 080001a1 080001f9 080001fb
> dump_image firmware.bin 0x08000000 0x100000
dumped 1048576 bytes in 4.012s
> resume
> exit

mdw (memory display word) is your sanity check - if you see plausible values at a known flash address, dumping will work. dump_image writes a contiguous range to a file.

JTAGulator for pinout discovery

JTAG needs at least four signals (TCK, TMS, TDI, TDO; sometimes TRST). On a finished product, the test points are usually unlabeled - if they’re broken out at all. Probing them by hand is theoretically possible but tedious and risky.

The JTAGulator is a Parallax Propeller-based tool that brute-forces JTAG pinouts. You connect every test point on the board to one of its 24 channels, tell it the voltage range, and it tries every permutation of TCK/TMS/TDI/TDO across them, watching for a valid IDCODE response. In ten minutes it tells you which pins are which.

Commercial price: ~$150 from the original designer. The design is open-source hardware; you can build your own from the gerbers for ~$40 in parts if you don’t mind soldering a Propeller.

For a budget alternative: the jtagenum Arduino sketch does the same brute-force on an Arduino. Slower, less polished UI, but functional and runs on a $5 Nano. Pair it with a logic-level shifter if your target is 1.8V.

JTAGulator workflow:

  Test points → 24 input channels → brute-force loop:
                                       for tck in 0..23:
                                         for tms in 0..23:
                                           for tdi in 0..23:
                                             for tdo in 0..23:
                                               try IDCODE → record hits

                                  "TDO=4, TCK=11, TMS=7, TDI=12,
                                   IDCODE 0x2ba01477"

Once you have the pinout, plug those four signals into your J-Link or FT2232H and proceed with OpenOCD as above.

eMMC and NAND, briefly

Two more on-board storage types you’ll meet, with different tooling.

eMMC is essentially an SD card in a BGA package soldered to the board. The interface is standard MMC/SD - command bus, data bus, clock, voltage, ground. With the right adapter you can read an eMMC chip in-circuit by connecting to its test points (DAT0, CMD, CLK, VCC, VCCQ, GND) and using a USB-to-MMC bridge. Tools like the EMMC-DDR-Reader (~$30) or a Bus Pirate with the eMMC-test-mode workaround do this. The “in-circuit” caveat is severe though: you must hold the SoC in reset throughout the read, otherwise it contends on the bus.

NAND flash in TSOP-48 packages can be desoldered and read with a TSOP-48 socket plus a programmer that knows NAND - the FlashcatUSB ($120) is the canonical hobbyist tool. NAND is harder than NOR/SPI because of bad-block tables, ECC, and the fact that each manufacturer encodes spare-area metadata slightly differently. Expect to spend a session understanding the page layout for your specific chip.

Both topics have enough depth for their own tutorials. If you’ve got an eMMC or NAND target, the high-level workflow is the same as SPI - power and bus discipline, dump twice, compare hashes - but the wire protocol and tool choice differ. Future tutorials in this series will cover them.

What to do with the dump

Hardware extraction gives you a binary file. Everything from there is the same workflow as a vendor download - except now you also have the bootloader, the U-Boot environment, and any factory-provisioned config blobs.

# Same workflow as the firmware-RE tutorial
binwalk dump.bin
DECIMAL       HEXADECIMAL     DESCRIPTION
-------------------------------------------------------
0             0x0             U-Boot bootloader (probably)
65536         0x10000         U-Boot environment, big-endian
131072        0x20000         uImage header, image size: 1572864
131136        0x20040         LZMA compressed data (kernel)
1703936       0x1A0000        Squashfs filesystem, ...
15728640      0xF00000        JFFS2 filesystem, ... (config partition)

Compare this to the same scan on a vendor .bin - the OTA file usually starts at offset 0x20000 (the kernel) and ends at the end of the SquashFS. The bootloader before it and the JFFS2 config partition after it are exclusively visible from a hardware dump.

The most productive payoff: encrypted firmware partitions decrypted by the bootloader. A common pattern in higher-security devices:

  1. The OTA .bin is one big encrypted blob.
  2. The bootloader (only present in a hardware dump) reads it, verifies the signature, decrypts it with a key compiled into the bootloader binary, and jumps to the kernel.
  3. Reverse engineering the bootloader in Ghidra reveals the decryption routine and the key.
  4. Now you can decrypt every existing OTA, including future ones, without ever touching the hardware again.

Apply the workflow from Firmware RE with Binwalk and Ghidra to each extracted partition: identify the architecture, find the high-value binaries, audit them for vulnerabilities. The hardware dump is the start of analysis, not the end.

Practical exercise

You’ll need a target device with an SOIC-8 SPI flash chip - a cheap Wi-Fi router from a thrift store is ideal. Don’t pick anything you depend on; the first few attempts often end with a brick.

  1. Open the case, photograph the PCB, and identify the flash chip. Read the part number aloud and find the datasheet. Confirm voltage.
  2. Connect a CH341A and a SOIC-8 clip to the chip with the device unpowered. Verify pin 1 alignment.
  3. Run flashrom -p ch341a_spi (no -c) and confirm the chip is detected.
  4. Dump twice with -r. Compare SHA-256s. If they don’t match, troubleshoot until they do.
  5. Run binwalk on the dump and identify partition boundaries. How does the layout compare to the vendor’s OTA .bin for the same device, if you can find one?
  6. Pick the bootloader partition, load it in Ghidra, and look for strings like “decrypt”, “AES”, “signature”, or hardcoded keys. Document what you find.

If you can finish those steps without bricking anything, you have the entire SPI workflow down. JTAG is the same shape - identify, connect, configure, dump - just with a more complex pinout discovery and target-specific configuration.

Where to go from here

  • JTAG glitching and secure-boot bypass. Once you can talk to the CPU, voltage- or clock-glitching attacks at the right moment in the boot ROM can skip signature verification. Tools: ChipWhisperer.
  • eMMC and NAND deep dives. Coming in later tutorials in this series.
  • Side-channel extraction. When even hardware dumping fails (locked debug ports, encrypted-and-signed flash, anti-tamper meshes), power analysis and EM emanations sometimes still leak keys. Out of scope here, but the rabbit hole goes deep.

Each of these escalates effort and equipment cost by an order of magnitude. The good news: 95% of consumer and SMB embedded devices fall to a CH341A and a $4 clip, and you’ve now got the workflow for them.