Skip to main content

Deep Dive: Bypassing U-Boot Secure Boot via DMA Attack (QEMU Lab)

·959 words·5 mins
JustThinkingHard
Author
JustThinkingHard
Cybersecurity student | Low level enjoyer

Bypassing U-Boot Secure Boot via DMA Attack (QEMU Lab)
#

Today, we are diving into a formidable hardware attack: bypassing Secure Boot using a DMA (Direct Memory Access) attack.

The scenario is a classic in hardware security challenges. We have an ARM64 architecture where U-Boot is configured with Secure Boot enabled. It loads a Linux kernel encapsulated in a FIT Image, verifies its cryptographic signature (RSA 4096), and if it’s legitimate, boots it. The chain of trust is cryptographically flawless.

But what happens if we attack the RAM after the verification, but before the execution? This is what we call a TOCTOU (Time-Of-Check to Time-Of-Use) vulnerability. In this post, we will set up a complete QEMU lab to simulate this attack and pop a root shell.

Lab Setup
#

Before breaking everything, we need to build our target. I scripted the environment to make our lives easier.

Required dependencies:

  • qemu-system-aarch64 (v7.0+)
  • gcc-aarch64-linux-gnu (cross-compiler)
  • mtools & dosfstools (for forging the FAT SD card)
  • openssl (for generating the signing keys)
  • gdb-multiarch (our injection weapon)

For the project structure, simply clone U-Boot and Buildroot (to get a minimalist Linux kernel) at the root, then run the setup script:

git clone https://github.com/u-boot/u-boot.git
git clone https://github.com/buildroot/buildroot.git
cd src
chmod +x setup_lab.sh
./setup_lab.sh setup

Technical note: The script generates a dynamic Device Tree (DTB) from QEMU, injects our RSA public key into it, seals the kernel in a FIT Image, and places everything on a virtual SD card.

Once ready, start the machine:

./setup_lab.sh run

Theory: How Do the “Pros” Do It?
#

In the real world, the attacker doesn’t type magic commands on their keyboard. They open the device’s case and plug an FPGA card (often flashed with the PCILeech project) into a PCIe or Thunderbolt port.

The goal is to use the DMA channel to read and write to the physical RAM at the speed of light, completely bypassing the central processor. The attacker lets U-Boot calculate the SHA256 hash of the kernel in RAM. The verification passes. But in the microsecond separating this “OK” from the actual Linux boot, the FPGA bombards the target memory to overwrite the legitimate code with a malicious payload.

In our virtual lab, we don’t have an FPGA. Our DMA attack tool will be GDB. It will allow us to pause the motherboard and alter the RAM manually with the precision of a surgeon.


Attack Level 1: Overwriting the Kernel (Pwned)
#

We start with a simple proof of concept: replacing the legitimate kernel with a small shellcode (pwned.bin) that prints a message and halts.

First, build the payload with make pwned, then launch the attack sequence with ./setup_lab.sh attack.

In another terminal, pull out your virtual PCIe card:

gdb-multiarch

Connect to the QEMU debug server, and place a hardware breakpoint exactly where the kernel will be executed in RAM (0x40200000):

(gdb) target remote localhost:1234
(gdb) hb *0x40200000
(gdb) c

U-Boot verifies the signature, prints OK, and gets ready to boot. QEMU freezes on the message Starting kernel .... This is our TOCTOU window. We brutally inject our binary into RAM to overwrite the kernel, then resume execution:

(gdb) restore pwned.bin binary 0x40200000
(gdb) c

Result: U-Boot validated a legitimate Linux kernel, but is now executing our shellcode. Secure Boot bypassed.


Attack Level 2: Open Sesame (Root Shell)
#

Crashing the machine is fun. Getting an interactive passwordless root shell is better.

This time, we won’t overwrite the entire kernel, but rather modify its boot arguments (bootargs) located in the Device Tree in RAM. Our goal: force Linux to run init=/bin/sh.

1. Hunting in Memory
#

In GDB (still frozen at the kernel start), the $x0 register holds the address of the Device Tree. We look for the legitimate string passed by U-Boot:

(gdb) find $x0, +0x100000, "root=/dev/vdb"

GDB returns an address. The problem: we can’t overwrite root=/dev/vdb, because Linux absolutely needs it to mount the filesystem. We must find a “sacrificial” zone nearby.

Let’s do a quick RAM autopsy to see the full sentence. We step back a few dozen bytes and display the memory as a string:

(gdb) x/s OUTPUT_OF_FIND_COMMAND - 42 

(Feel free to play with the offset to align the string properly). Bingo! The memory reveals the exact line: console=ttyAMA0 earlycon=pl011,0x09000000 root=/dev/vdb

2. Cannibalizing the RAM
#

In embedded systems, memory allocation is strict. If we lengthen the string, we will overwrite neighboring Device Tree components and trigger a Kernel Panic. We must “cannibalize” the existing space, down to the exact character count.

The perfect target is earlycon=pl011,0x09000000. It’s useful for early debug logs, but not vital for the boot process. We will overwrite this part with our init=/bin/sh payload.

Precision calculation: The offset between the beginning of the string and the word earlycon is 16 bytes. We will fill the remaining gap with spaces so we don’t shift the root=/dev/vdb that comes right after. The payload will be exactly the same size (25 characters): "init=/bin/sh ".

3. The Final Injection
#

We launch the surgical strike:

(gdb) set {char[25]} (ADDRESS_OF_BOOTARGS_STRING + 16) = "init=/bin/sh             "
(gdb) c

Linux launches. It reads its altered RAM configuration, initializes its disks, and instead of spawning the classic authentication process… it graciously hands us a # shell with root privileges.


Conclusion
#

This lab demonstrates a harsh reality of Hardware Security: software cryptography is useless if the underlying hardware is not protected against direct memory access.

Even with a perfectly implemented Secure Boot and robust RSA 4096 keys, a DMA attack can corrupt system integrity just before its use. To defend against this kind of attack in the real world, modern architectures must rely on hardware units like the IOMMU (which filters illegitimate DMA requests)—provided the bootloader is capable of configuring it early enough!

Happy hacking!