PC Hacking! Lenovo ThinkPad X220 BIOS
Maybe you know my efforts on hacking gaming consoles. Recently I have not used them at all, but still I love hacking. In this morning, I have tried to hack my own PC, Lenovo ThinkPad X220. I’ll write down the experience.
SMM
SMM is the most privileged state in PC. I found an explanation on a very simplevulnerability, and ported the exploit to X220.
The vulnerability is quite a simple. A SMI refers to a pointer for
LocateProtocol
function in EFI_BOOT_SERVICES
. EFI_BOOT_SERVICES
is not
located in SMRAM, accessible only for SMM, but in an area accessible for the OS.
So I could exploit it just by finding the two value: the address where the pointer is located in, and the SMI number.
The pointer is lost in the OS environment since EFI_BOOT_SERVICES
is freed
and no longer exists. But it was easy to extract the address with EFI shell
as the article says.
Finding the SMI number is a little tricky. The vulnerable module,
SystemSmmAhciAspiLegacyRt
registers the SMI handler in somewhere free. The
article tells to try handlers from 0 to 255, but in X220 the target was
registered in 7 while X220 had broken handlers also in 1 and 2. It was a little
confusing. Maybe SMI 1 and 2 are also vulnerable, but it’s not my aim.
I modified the Python PoC according to those values, and it allowed to run a function in SMM without any difficulty.
S3 Boot Script and FLOCKDN
I came up with an idea to flash coreboot without hard modding. I’m not really good at hardware modding, so I have been awaiting an emergence of a vulnerability allowing to flash BIOS.
To accomplish the aim, I investigated the BIOS lock with chipsec.
The BIOS lock is done by write protect of PR0 (Protected Region 0), and it was
locked by FLOCKDN
bit of HSFS
register. Resetting device is necessary to
disable FLOCKDN
.
The S3 boot script to restore the context had an instruction to restore HSFS
register, so I thought it can be disabled by modifying the script. It was done
just with the following command.
chipsec_main -m tools.uefi.s3script_modify -a replace_op,mmio_wr,0xFED1F804,0x00006009
However, it doesn’t disable FLOCKDN
. It actually found the instruction, and
succeeded in overwriting.
I found another fact that the PR0 register is not set by the script, but it’s still kept. I have also tried to dump the firmware, but it results in a dump whose ME region is filled with 0xFF, which is conflicting with what the PR0 register indicates. I may need a further investigation, but I simply gave up.