argp         posts     research     bugs

Paper notes: Reverse engineering x86 processor microcode

Title: Reverse engineering x86 processor microcode
PDF: 133f02627cbd3771ad5d4b09729cfce7.pdf

A very interesting paper with technical details on the x86 microcode inner workings of AMD’s K8 and K10 CPUs. The reason for focusing on these old CPUs is that other/newer ones cryptographically protect their microcode updates, both for authenticity/integrity and confidentiality.

AMD’s K8 and K10 microcode updates are encoded (but not encrypted or signed) in a proprietary format which is only partly explained in the paper. The update process decodes the blob, which includes sets of microcode instructions (microinstructions) called triads, and values for match registers which are microcode-internal register-like locations that hold addresses of triads in microcode ROM. The new triads that the update carries are mapped in microcode RAM directly after the address space of the ROM, and the match register values are copied to their respective match registers. The match registers (which are eight by design) can be used to run the updated microcode triads by redirecting execution to the new addresses in RAM. The authors use this to hook CPU microcode triads and run their version of the div instruction for example. One limitation (apart from the only eight available match registers) is that instructions are separated into performance critical ones (called direct path instructions), and more complex ones (called vector path instructions). Match registers are used only for the latter. Since the microcode update is mapped into RAM, it’s not permanent, but is applied at each boot.

Using the above way to load arbitrary microcode triads via updates, the authors then proceeded to reverse the microcode instruction set by trial and error using a minimal operating system they developed. With some information from AMD’s patents and bruteforcing the microcode instruction fields, they observed the protection faults and CPU states their triads caused. This led to around 40% disassembling of existing microcode updates, which is an impressive feat.

The paper’s accompanying code includes a patch for the Linux kernel that applies a microcode update from file /lib/firmware/amd-ucode/myupdate.bin without any checks. It also includes various sample updates (in binary and encoded format, and microinstruction source) implementing instrumentation and backdoor PoCs described in the paper.

The references seem complete, apart from neglecting to cite Ben Hawkes’ notes on Intel microcode updates.