Hacking UEFI Variables

Plundervolt was a vulnerability found in Intel SGX (Software Guard Extensions) around mid-2019. It is relatively hard to exploit, as typical users don't use the SGX and the attack requires root privileges. Unfortunately, many manufacturers have patched the issue by disabling software undervolting, regardless of if the SGX is in use.

The good news: this is relatively easy to fix, and can be done without downgrading the BIOS. First, we take the BIOS update package and extract the individual firmware components using BIOSUtilities. My update package from Dell came in the form of a Windows executable, so I used the Dell PFS BIOS Extractor tool to dump its contents. The only file we are interested in from this set is 1 System BIOS with BIOS Guard v1.17.1.bin.

Next, we need to analyze the firmware to find the offsets of the locked variable. Open the extracted .bin in UEFITool, and search for the text Overclocking Lock. This finds a single PE32 image section. While we could modify this image and flash it, the whole point of this experiment is to avoid flashing the BIOS again, so we use UEFITool to Extract body and run it through yet another tool, the Universal IFR Extractor.

After all this trouble, we finally have a human-readable Internal Forms Representation of the BIOS Setup utility. Looking through the file, it is clear that much of the advanced configuration available on desktops is also present on laptops, but the Setup menus are hidden. Skipping down to the Overclocking Lock mentioned before, we see:

0x3A195         Form: View/Configure CPU Lock Options, FormId: 0x2732 {01 86 32 27 4A 01}
0x3A19B                 One Of: CFG Lock, VarStoreInfo (VarOffset/VarName): 0x4ED, VarStore: 0x1, QuestionId: 0x2BA, Size: 1, Min: 0x0, Max 0x1, Step: 0x0 {05 91 EF 02 F0 02 BA 02 01 00 ED 04 10 10 00 01 00}
0x3A1AC                         One Of Option: Disabled, Value (8 bit): 0x0 {09 07 04 00 00 00 00}
0x3A1B3                         One Of Option: Enabled, Value (8 bit): 0x1 (default) {09 07 03 00 30 00 01}
0x3A1BA                 End One Of {29 02}
0x3A1BC                 One Of: Overclocking Lock, VarStoreInfo (VarOffset/VarName): 0x59C, VarStore: 0x1, QuestionId: 0x2BB, Size: 1, Min: 0x0, Max 0x1, Step: 0x0 {05 91 EB 02 EC 02 BB 02 01 00 9C 05 10 10 00 01 00}
0x3A1CD                         One Of Option: Disabled, Value (8 bit): 0x0 {09 07 04 00 00 00 00}
0x3A1D4                         One Of Option: Enabled, Value (8 bit): 0x1 (default) {09 07 03 00 30 00 01}
0x3A1DB                 End One Of {29 02}
0x3A1DD         End Form {29 02}

Next to the Overclocking Lock is the CFG Lock, which needs to be disabled for Hackintosh machines to have correct native power management. We mark down the offsets of both, in this case 0x4ED and 0x59C. (It should be noted that these offsets are different on different machines. Using offsets for a different machine will write to an unexpected location, possibly bricking your machine!)

Now we might try to modify the EFI NVRAM by writing to the correct locations in efivarfs, but its restrictions are too limiting for our purposes. Luckily, a modded GRUB exists for this purpose. Assuming our EFI system partition is /boot/EFI, we simply place modGRUBShell.efi in that directory.

Although not really necessary, we can avoid a potentially wasted reboot due to a broken EFI application by testing with QEMU:

$ qemu-system-x86_64 \
    -enable-kvm \
    -cpu host \
    -bios /usr/share/edk2-ovmf/OVMF_CODE.fd \
    -drive file=/dev/sda,format=raw

At the UEFI shell:

Shell> FS0:
FS0:\> \EFI\modGRUBShell.efi

It works if you see the GRUB shell and setup_var is a valid command.

Before we are able to able to reboot into this shell, we need to add an entry for it in the EFI boot manager. This is one of the few variables efivarfs can write to, and efibootmgr is a simple frontend for manipulating it:

$ efibootmgr --create --loader '\EFI\modGRUBShell.efi'

We finally reboot into the modified GRUB and first check that the value at the offsets is indeed the expected 0x1, and then disable by writing a 0:

grub> setup_var_3 0x4ED
grub> setup_var_3 0x4ED 0x0
grub> setup_var_3 0x59C
grub> setup_var_3 0x59C 0x0
grub> reboot

If all went well, you can enjoy lower temps and quieter fans once again.