CVE Wednesday - CVE-2021-39297


Welcome back to CVE Wednesday! Today we are going to look at CVE-2021-39297. CVE-2021-39297 was originally discovered and reported by Binarly and impacts certain HP PCs. A full write up, including a demonstration of a proof of concept, is available on the Binarly Website as BRLY-2021-003.

Additionally, HP provides a support document here

A Discussion regarding reproducing the vulnerability inspired me to write up this blog post.

Full credit for the discovery of this vulnerability is due to the team at Binarly. I had nothing to do with the discovery of this vulnerability


I reproduced this vulnerability using WSL2 on a Windows 11 laptop. You will need qemu-system and ovmf installed, and potentially ovmf-ia32.

First, I downloaded a firmware file from HP that the Binarly disclosure listed as vulnerable:

Next I used a script I wrote to extract the DXE firmware volume from the Q95_011400.bin file:

$ python3 Q95_011400.bin

This left me with a directory volume-0 that contains a directory with the module GUID:

$ ls volume-0/file-c988bded-6977-464d-b714-e61debd2de97/
file.obj  section1.ui

c988bded-6977-464d-b714-e61debd2de97 is listed in the original binarly advisory as being the vulnerable DXE driver GUID.

Now lets do a checksum:

$ md5sum volume-0/file-c988bded-6977-464d-b714-e61debd2de97/
f0f53a2f30f91feb32af7b6b8d73353d  volume-0/file-c988bded-6977-464d-b714-e61debd2de97/

The md5 hash f0f53a2f30f91feb32af7b6b8d73353d matches the hash listed for this firmware version in the Binarly Advisory. We have the vulnerable 0138.efi file at this point.


I then created a directory fs to use as my FAT32 ESP.

$ mkdir -p fs/EFI/boot
$ cp volume-0/file-c988bded-6977-464d-b714-e61debd2de97/ fs/0138.efi

Next, we can use OVMF with QEMU to launch into an EFI shell:

$ qemu-system-x86_64 -bios /usr/share/ovmf/OVMF.fd -hda fat:rw:fs -nographic -serial mon:stdio

I ran the EFI shell with QEMU from the CLI using -nographic because it made pasting in the EFI variable values easy.

From the EFI Shell we can then run 0138 and see the application launch:


The vulnerability stems from handling the EFI variables PlatformLang and Lang, so those need to be set to the values provided in the binarly advisory using the EFI command setvar.

It is important to note that the binarly advisory contains a video demonstrating successful exploitation of the vulnerability. However, the video does not capture which firmware file the 0138.efi file was extracted from. As such, the memory layout may differ between the various versions. This means when I attempted to exploit the vulnerability, I received a CPU exception:

!!!! X64 Exception Type - 0D(#GP - General Protection)  CPU Apic ID - 00000000 !!!!
ExceptionData - 0000000000000000
RIP  - 4C07E9E741BA079E, CS  - 0000000000000038, RFLAGS - 0000000000000206
RAX  - 0000000000000003, RCX - 0000000000000065, RDX - 0000000005F14A70
RBX  - 0000000007F10588, RSP - 0000000007F10440, RBP - 0000000007F10578
RSI  - 000000000614E018, RDI - E018B82850FF41C1
R8   - 0000000000000003, R9  - 000000000640531E, R10 - 00000000000005F2
R11  - 0000000000000001, R12 - 0000000000000000, R13 - 000000000614FA18
R14  - 000000000605DA00, R15 - 00000000060C2AE8
DS   - 0000000000000030, ES  - 0000000000000030, FS  - 0000000000000030
GS   - 0000000000000030, SS  - 0000000000000030
CR0  - 0000000080010033, CR2 - 0000000000000000, CR3 - 0000000007C01000
CR4  - 0000000000000668, CR8 - 0000000000000000
DR0  - 0000000000000000, DR1 - 0000000000000000, DR2 - 0000000000000000
DR3  - 0000000000000000, DR6 - 00000000FFFF0FF0, DR7 - 0000000000000400
GDTR - 00000000079DE000 0000000000000047, LDTR - 0000000000000000
IDTR - 0000000007471018 0000000000000FFF,   TR - 0000000000000000
FXSAVE_STATE - 0000000007F100A0

Next Steps

The next steps would be adjusting the exploit data to match up with the specific firmware version I am running against for this write up. If I have time and there is interest, I’ll write another blog post on how to do that later.