The Zyng is a family of chips from Xilinx that combines ARM9 cores with 7-series FPGA fabric. For a time it was one of the cheapest ways to bootstrap an ARM secure boot chain without minimum orders and NDAs. The author spent time learning how this system works.
First, they bought a Cora Development Board to poke around with the device. They messed around with the device post-boot to dump the On-Chip Memory (OCM) configuration and the register state. At the very top of the OCM, they found 512 bytes of assembly that noted two other OCM regions.
The goal was to glitch the device until something interesting happened. They had major troubles finding a consistent trigger point because of how widely the timing varied on the device. Eventually, they did get the glitch to work, bypass security protections and output the bootroom.
However, the author found an
easier way to grab the ROM. The ROM is built in a way that there is an initialization function for the boot mode selection interface; this uses a callback function. From there, the UART initialization routine sticks the entire payload in RAM. This code grabs
nbytes from an
offset in the ROM image and writes this to
dest.
Here is what the author found from this: the source address is not properly validated. offset is properly checked for the POSITIVE bound only; it never checks the negative bound. Even though this does not seem like a problem at first, we can turn this into a problem. If the attacker controls the offset and the location being written to exists passed initialization, it can be used to persist the ROM to be read later.
When the Zynq scans for
ONFI (Open NAND Flash Interface), there is a parameter page that populates local copies of several of these fields. Even though this is technically, considered
untrusted data (outside of the BootROM), no validation is done. Why the technically part? A custom chip emulator had to be made in order to exploit this!
These parameters represent data from physical characteristics to supported features of the ONFI interface. To make this work, they had to emulate the ONFI interface when it was communicating with the BootROM. Damn, that is wild!
To trigger this the author went for the element XNandPs_ReadSpareBytes. This field is normally used ECC data reads. This user controlled buffer is read in with no sanity checks though! Using this, a simple stack overflow is possible to overwrite the return instruction pointer on the stack. Using this, code execution can be hijacked.
How do you know you have triggered something though? After running this exploit, they set the data to a constant stream of uart_init addresses. Once this was hit, a UART sequence was outputted, showing that the hijack had been successful. To write proper shellcode (since they already had ROP working), they ran into a problem. This turned out to simply be a endian problem on the write (lolz).
Eventually, they wrote a payload that would hijack control flow to turn on JTAG for more thorough debugging. The main reason for this attack is when secure boot is turned on and all debug interfaces are turned off. Using this exploit, the boot chain could be compromised. Overall, interesting series of posts, with an official release by
xilinx even!