Paradigm Shift - Introducing usbliter8
TLDR - here is the PoC
This write-up details a novel iPhone BootROM vulnerability discovered and exploited by our team. It covers the underlying bug, the associated exploitation techniques, and the post-exploitation steps required to achieve application processor's boot-chain compromise. The exploit leverages both a hardware bug in the USB controller and a specific configuration flaw present in the device firmware.
Currently supported SoCs include Apple A12, S4/S5, and A13. While technical support for A12X/Z is possible, it is not currently implemented. We limited our implementation to these devices, as demonstrating successful exploitation across this range was sufficient to thoroughly validate both the vulnerability and the exploitation strategy.
By publishing this research and the accompanying proof of concept, we aim to document the real-world impact of this class of hardware vulnerabilities, contribute to the broader understanding of modern BootROM security, and demonstrate that even recent SecureROM generations remain susceptible to subtle hardware flaws.
As these vulnerabilities reside in immutable code, affected users should be aware that migrating to newer hardware remains the most effective mitigation.
USB Setup Packets Anatomy
In the context of the USB specification, every control transfer must initiate with a Setup transaction. This is the mechanism the host uses to issue any kind of request to the attached device.
A proper Setup transaction consists of two packets sent by the host:
(1) TOKEN PACKET host → device<br>┌───────┬──────────┬─────────┬─────────┬────────┬──────┐<br>│ SYNC │ PID │ ADDR │ ENDP │ CRC5 │ EOP │<br>│ 8 bit │ 8 bit │ 7 bit │ 4 bit │ 5 bit │ │<br>│ │ (SETUP) │ device │endpoint │ │ │<br>└───────┴──────────┴─────────┴─────────┴────────┴──────┘
(2) DATA PACKET host → device<br>┌────────────────────────┐<br>┌───────┬──────────┤ DATA (8 bytes) ├────────┬──────┐<br>│ SYNC │ PID │ = USB Device Request │ CRC16 │ EOP │<br>│ 8 bit │ 8 bit │ │ 16 bit │ │<br>│ │ (DATA0) │ This is what the USB │ │ │<br>└───────┴──────────┤ driver receives ├────────┴──────┘<br>└────────────────────────┘<br>According to the specification, the data payload of a Setup transaction must be exactly 8 bytes and adhere to a strict format. The device request structure contained within this payload is passed verbatim to the software driver for handling.
To maintain clarity in our analysis, we will refer to this specific payload as the "Setup packet."
DWC2 Direct Memory Access
The USB controller used by Apple in their SoCs is the DWC2 by Synopsys. Detailed information on how this controller works can be inferred by analyzing other existing driver implementations, such as those found in the Linux kernel.
What we care about here is how the controller writes data to main memory. The AP configures DMA by allocating a memory region and writing its physical address to a specific register (DOEPDMA) in the controller's MMIO region.
The controller uses this buffer to store data received in SETUP and OUT packets, which is then processed by the device.
We did observe that when the USB controller writes data chunks, it directly increments the address stored in the DOEPDMA register. This is a crucial detail since it might mean that the register value acts as a direct source of truth, defining the physical address that will be used for the next DMA transfer, instead of just being a configuration facility.
The Bug
The DesignWare USB controller stores up to three consecutive Setup packets in memory.
Upon receiving a fourth Setup transaction, the DMA base address gets reset to its starting position before writing, akin to a ring buffer mechanism.
After writing each received packet, the controller increments DOEPDMA by the size of data written. The reset operation is implemented by decrementing DOEPDMA by 24.
The core issue arises because the controller also accepts smaller packets (though always stores in 4-byte chunks).
Since the pointer increment does not match the fixed decrement amount, we end up with a buffer underflow primitive in 12-byte steps.
We believe this is an inherent bug within the USB controller itself. While potentially affecting many devices, the vulnerability works under specific circumstances only.
As of today, we have confirmed that the A12 and A13 SecureROMs are vulnerable, whereas A11 is not. The difference is that the A11 USB driver manually resets the DMA address to its initial value after receiving each packet.
On A12 and A13, USB DART is configured in bypass mode, allowing us to overwrite SRAM data freely. In contrast, A14 and later generations appear to configure the DART correctly in SecureROM, making the vulnerability unexploitable.
PC control on A12
Achieving PC control on A12 is straightforward because the USB controller's DMA buffer is allocated on the heap shortly after the USB task's stack.
The simplest approach is to overwrite a saved LR on the stack and obtain direct...