Jump to: navigation, search

wInd3x Vulnerability

A Bootrom vulnerability discovered and exploited by q3k in December 2021. It allows code execution in the bootrom over USB.

Affected Devices

Device/SoC Vulnerable? Exploited?
Nano 3G Yes Yes
Nano 4G Yes Yes
Nano 5G Yes Yes
Nano 6G No
Nano 7G No
Classic “6G” Yes Yes
iPhone ?
iPhone 3G Yes No

Running / Usage

wInd3x currently allows you to:

  1. Decrypt IMG1 files, like OSOS or the bootloader/WTF/...
  2. Access arbitrary memory and experiment with peripherals
  3. Run unsigned DFU payloads
  4. Run an unsigned OSOS or U-Boot by first running an automatically patched WTF.

For guides, see


This exploits a vulnerability in the standard SETUP packet parsing code of the bootrom, in which the wIndex parameter is not checked for bmRequest == {0x20, 0x40}, but is still used to index an array of interface/class handlers (that in the Bootrom has a length of 1).

Nano 4G and 5G Exploit Chain

The first requirement is to find a suitable (blx r0) instruction in the bootrom code of the device. For Nano 4G the only one such instruction is at offset 0x3b0, and for Nano 5G there is such instruction at 0x37c. We'll refer to it as X below.

We abuse the fact that wIndex == 3 for bmRequest 0x40 treats a 'bytes left to sent over USB' counter as a function pointer and calls it with r0 == address of SETUP. We massage the DFU mode into attempting to send us X+0x40 bytes, and failing after 0x40 bytes, thereby leaving the counter at X bytes and executing code at address X.

Since the bootrom is mapped at offset 0x0 as well as 0x20000000 at boot, this means we execute bootrom code, and X happens to point to a 'blx r0' instruction. This in turn causes the CPU to interpret the SETUP packet received as ARM code, because the SETUP handler is called with the SETUP packet as its argument, i.e. r0.

We specially craft the SETUP packet to be a valid ARM branch instruction, pointing somewhere into a temporary DFU image buffer. By first sending a payload as a partial DFU image (aborting before causing a MANIFEST), we finally get up to be able to execute either 0x800 on Nano 4G or 0x400 on Nano 5G bytes of fully user controlled code.

In that payload, we send a stub which performs some runtime changes to the DFU's data structures to a) return a different product string b) overwrite an image verification vtable entry with a function that allows unsigned images. Some SRAM is carved out by this pay

Nano 3G and Classic (”6G”)

With bRequestType == 0x20 and wIndex == 6 we directly jump to code execution at the SETUP packet.

This Bootroom does not have a VTable which can be easily hooked to override functions to provide Haxed DFU functionality. However, an 'OnImage' function pointer is present in the State structure, which we override with our own code (copied to carved out SRAM). This code reimplements the bare minimum of the hooked function, without calling any decryption/verification code on the header/body.