The author of this post was hunting for vulnerabilities in the XBox 360 hypervisor. While doing this, they noticed the system call HvxKeysExecute that allowed running small pieces of ad-hoc code in hypervisor mode with code signed from Microsoft. They pulled down 25 of these payloads and found a vulnerability in one of them: Bad Update.
The Bootloader Update Payload for the HvxKeysExecute instruction is the one being attacked. It reads data from kernel mode and performs LZX decompression on it. This requires a scratch buffer on store the data structure with lots of interesting pointers to jump tables and such. This buffer is relocated to encrypted memory but NOT protected mode. The idea is to overwrite this pointer to hijack the control flow later on.
Encrypted memory is a section of memory on the XBox that is in the Hypervisor but modifiable by the kernel. Because of this, it's typically only used in a write-only fashion. In the vulnerability above, we want to modify pointers that are encrypted and used by the Hypervisor. The encryption of this memory uses a per-boot key and a 10-bit whitening value that is unique to the address and cache line. This prevents simple oracles or reuse across resets/reboots.
There's still wiggle room for an encryption oracle here: we need an encryption oracle with a specific whitening value and just find an encryption oracle. Luckily, the encryption oracle is built into the Hypervisor with the HvxEncrypted set of APIs. For the whitening value, we need a known value for those that we can compare against for part of the contents. This means we have a complete oracle!
Encrypting arbitrary data with the whitening value matching allows one to edit the encrypted memory. First, they tried editing the malloc and free pointers - this didn't work because of cache-line issues. Instead, they overwrote the dec_output_buffer (output of the decompression process) pointer to get a controlled write to another unintended location. This gives a 0x8000 write primitive with uncontrolled data into the HyperVisor.
To turn this into code execution, they had to win a race condition and be able to execute it multiple times - the second of these made it much more difficult to do in practice, since it removed many interesting targets. From within one of the writable bootloader code segments, they found a stb/blr pair that gave them an arbitrary write primitive that could be written at the end of a system call within the Hypervisor.
This is inherently racy and wasn't very consistent. When the race condition is combined with the brute force of the whitening value, the exploit takes too long. To make this more consistent, they experimented with thread prioritization and monitoring of the code. With their current payload, the attack thread got the malicious ciphertext flushed to RAM the XKE payload was already done running. To fix this, they put the attack on hw thread 0 and the payload thread on hw thread 1 and put both of these on core 0. There are more details on winning the race but it's over my head.
This exploit is still inconsistent and time-consuming. However, the means of winning the race more often and modifying encrypted memory are still good insights into complex exploit development. The testing strategies used was also interesting to me. Good work!