Jump to content

[UEFIPatch] UEFI patching utility


CodeRush
1,981 posts in this topic

Recommended Posts

No problem. It's in SbDxe module, InstallDxePchPlatformPolicy function, that calls GetSbSetupData function, which has built-in defaults (locks are disabled there), and tries to load defaults from Setup NVAR, where the settings are located.

mPchPolicyData.LockDownConfig->GlobalSmi    = gSbSetupData->SmiLock;
mPchPolicyData.LockDownConfig->GpioLockDown = gSbSetupData->GpioLock;

SB_SETUP_DATA stucture is big, but stable, and that settings are in the very beginning, so they are hardly be moved somewhere. On locked boards of Z87 and X79 platforms there are 0x01 on this bytes, on unlocked old BIOS versions - 0x00, so I think this is it, but it need further testing.

AMITSE is user interface module, so if there are no interface to that bytes, so it's useless to modify something there.

And yes, this protection was here from the very beginning, and it's not ASUS-specific at all.

 

UPD: corrected the code path.

---

BonBon6, change it manually, it's very simple. Offset 0x00180110, first 2 bytes, change from 0x01 0x01 to 0x00 0x00. Flash it and try using FPT 8.xx for writing.

post-1111314-0-45228400-1378635291_thumb.png

  • Like 3
Link to comment
Share on other sites

No problem. It's in SbDxe module, InstallDxePchPlatformPolicy function, that calls GetSbSetupData function, which has built-in defaults (locks are disabled there), and tries to load defaults from Setup NVAR, where the settings are located.

mPchPolicyData.LockDownConfig->GlobalSmi    = gSbSetupData->SmiLock;
mPchPolicyData.LockDownConfig->GpioLockDown = gSbSetupData->GpioLock;

SB_SETUP_DATA stucture is big, but stable, and that settings are in the very beginning, so they are hardly be moved somewhere. On locked boards of Z87 and X79 platforms there are 0x01 on this bytes, on unlocked old BIOS versions - 0x00, so I think this is it, but it need further testing.

AMITSE is user interface module, so if there are no interface to that bytes, so it's useless to modify something there.

And yes, this protection was here from the very beginning, and it's not ASUS-specific at all.

 

UPD: corrected the code path.

---

BonBon6, change it manually, it's very simple. Offset 0x00180110, first 2 bytes, change from 0x01 0x01 to 0x00 0x00. Flash it and try using FPT 8.xx for writing.

attachicon.gifChange.png

flashrom shows still the same:

flashrom -p internal
flashrom v0.9.7-r1711 on Darwin 13.0.0 (x86_64)
flashrom is free software, get the source code at http://www.flashrom.org

Calibrating delay loop... OK.
Mapping low megabyte at 0x0000000000000400, unaligned size 0xffc00.
Mapping low megabyte, 0xffc00 bytes at unaligned 0x0000000000000400.
Found chipset "Intel Z77". Enabling flash write... Warning: BIOS region SMM protection is enabled!
Warning: Setting Bios Control at 0xdc from 0x2a to 0x0b on Z77 failed.
New value is 0x2a.
Warning: SPI Configuration Lockdown activated.
PROBLEMS, continuing anyway
Found Winbond flash chip "W25Q64.V" (8192 kB, SPI) at physical address 0xff800000.
No operations were specified.

I'll try fpt now ;)

  • Like 1
Link to comment
Share on other sites

Cool, thanks for testing. It appears that some code is setting locks regardless of the NVRAM config. The setting code is located in somewhere in PchInitDxe or PchInitPeim, I will look for it now.

  • Like 2
Link to comment
Share on other sites

@BonBon6: Just a thought. Could it be possible that afuwin uses different flashing routines as Asus' tools, for example EzFlash, and does not perform a platform reset?

I used the built-in EzFlash when doing the tests, maybe it is worth giving it a try.

EDIT: Nevermind.

Edited by k3nny
Link to comment
Share on other sites

@BonBon6: Just a thought. Could it be possible that afuwin uses different flashing routines as Asus' tools, for example EzFlash, and does not perform a platform reset?

I used the built-in EzFlash when doing the tests, maybe it is worth giving it a try.

K3nny, the afudos for aptio does a platform reset for sure, everytime when I downgrade to 0401 which has writing option enabled the ME is downgraded an reset too.

EZflash does not accept bin files, only signed CAP files and I don't have a tool to sign the ROMs, so I flash from Intel FTK.

But I can definetely try to flash it again and do a global platform reset with fpt -greset.

I'll try it now.

Link to comment
Share on other sites

At first, we have the code that sets lock on SPI HSFS register, here in PchInitDxe

mov     edx, 8000h        ; Loading value with only bit 15 (B_PCH_SPI_HSFS_FLOCKDN) set
lea     ecx, [r14+3804h]  ; Loading address off r14 (RCBR)+ 0x3804 (R_PCH_SPI_HSFS)
call    sub_180009E48     ; Performing Or16 between parameters
  • Like 1
Link to comment
Share on other sites

 

At first, we have the code that sets lock on SPI HSFS register, here in PchInitDxe

mov     edx, 8000h        ; Loading value with only bit 15 (B_PCH_SPI_HSFS_FLOCKDN) set
lea     ecx, [r14+3804h]  ; Loading address off r14 (RCBR)+ 0x3804 (R_PCH_SPI_HSFS)
call    sub_180009E48     ; Performing Or16 between parameters

looks promising:

flashrom -p internal -V |grep HSFS
Mapping low megabyte at 0x0000000000000400, unaligned size 0xffc00.
Mapping low megabyte, 0xffc00 bytes at unaligned 0x0000000000000400.
Warning: BIOS region SMM protection is enabled!
Warning: Setting Bios Control at 0xdc from 0x2a to 0x0b on Z77 failed.
New value is 0x2a.
Warning: SPI Configuration Lockdown activated.
0x04: 0xe008 (HSFS)
HSFS: FDONE=0, FCERR=0, AEL=0, BERASE=1, SCIP=0, FDOPSS=1, FDV=1, FLOCKDN=1

FLOCKDN=1 is flashlockdown : ) you're on the right track

Link to comment
Share on other sites

Found the code that sets SMI lock. That is in PchInitDxe, here:

lea     rbx, [rdi+rsi+0F80A0h]   ; Loading address of rdi+rsi+0F80A0h (PciD31F0RegBase + R_PCH_LPC_ACPI_BASE)
mov     dl, 10h                  ; Loading value 0x10 (B_PCH_LPC_GEN_PMCON_SMI_LOCK) to DL
mov     rcx, rbx                 ; Copying loaded address from RBX to RCX
call    sub_180009DB4            ; Performing Or8 between parameters

But all this code can be suppressed by changing JZ to JMP, making the check if (PchPlatformPolicy->LockDownConfig->GlobalSmi == PCH_DEVICE_ENABLE) always false and the SMI lock effectively disabled no mater where it becomes enabled earlier.
The code that sets BiosInterfaceLock and BiosLock are right next to SmiLock, so I can patch it out by altering only one module - PchInitDxe.

BonBox6, here is the file to test:ASUSTeK P8Z77-V LX 2204_unlock.zip

Patched to remove SMILock, BIOSLock and BiosInterfaceLock. FLOCKDN register remains untoched.

  • Like 1
Link to comment
Share on other sites

Found the code that sets SMI lock. That is in PchInitDxe, here:

lea     rbx, [rdi+rsi+0F80A0h]   ; Loading address of rdi+rsi+0F80A0h (PciD31F0RegBase + R_PCH_LPC_ACPI_BASE)
mov     dl, 10h                  ; Loading value 0x10 (B_PCH_LPC_GEN_PMCON_SMI_LOCK) to DL
mov     rcx, rbx                 ; Copying loaded address from RBX to RCX
call    sub_180009DB4            ; Performing Or8 between parameters

But all this code can be suppressed by changing JZ to JMP, making the check if (PchPlatformPolicy->LockDownConfig->GlobalSmi == PCH_DEVICE_ENABLE) always false and the SMI lock effectively disabled no mater where it becomes enabled earlier.

The code that sets BiosInterfaceLock and BiosLock are right next to SmiLock, so I can patch it out by altering only one module - PchInitDxe.

 

BonBox6, here is the file to test:attachicon.gifASUSTeK P8Z77-V LX 2204_unlock.zip

Patched to remove SMILock, BIOSLock and BiosInterfaceLock. FLOCKDN register remains untoched.

flashrom shows:

flashrom -p internal -V |grep HSFS
Mapping low megabyte at 0x0000000000000400, unaligned size 0xffc00.
Mapping low megabyte, 0xffc00 bytes at unaligned 0x0000000000000400.
Warning: SPI Configuration Lockdown activated.
0x04: 0xe008 (HSFS)
HSFS: FDONE=0, FCERR=0, AEL=0, BERASE=1, SCIP=0, FDOPSS=1, FDV=1, FLOCKDN=1

from windows:

$>fpt -rewrite -f bios-unlocked.bin

Intel (R) Flash Programming Tool. Version:  8.1.10.1286
Copyright (c) 2007 - 2012, Intel Corporation. All rights reserved.

Platform: Intel(R) Z77 Express Chipset
Reading HSFSTS register... Flash Descriptor: Valid

    --- Flash Devices Found ---
    W25Q64BV    ID:0xEF4017    Size: 8192KB (65536Kb)

PDR Region does not exist.
GBE Region does not exist.

- Erasing Flash Block [0x800000] - 100% complete.
- Programming Flash [0x800000] 8192KB of 8192KB - 100% complete.
- Verifying Flash [0x800000] 8192KB of 8192KB - 100% complete.
RESULT: The data is identical.

FPT Operation Passed
Link to comment
Share on other sites

Show me the full log, please.

 

BIOS_CNTL = 0x09: BIOS Lock Enable: disabled, BIOS Write Enable: enabled ??

GCS = 0xc64: BIOS Interface Lock-Down: disabled, Boot BIOS Straps: 0x3 (SPI)
Top Swap : not enabled
SPIBAR = 0xfed1c000 + 0x3800
0x04: 0xe008 (HSFS)
HSFS: FDONE=0, FCERR=0, AEL=0, BERASE=1, SCIP=0, FDOPSS=1, FDV=1, FLOCKDN=1
  • Like 1
Link to comment
Share on other sites

I will test it on my Zotac Z77ITX a bit later and try to figure out, where the aditional locking code is and why setting NVRAM to zeroes is not working.

Perhaps there are some additional ASUS routines besides standart AMI ones.

 

BobBon6, appears to be working. :)

Try read the whole chip with flashrom -p internal -r dump.bin and then write it back with flashrom -p internal -w dump.bin.

  • Like 1
Link to comment
Share on other sites

I will test it on my Zotac Z77ITX a bit later and try to figure out, where the aditional locking code is and why setting NVRAM to zeroes is not working.

Perhaps there are some additional ASUS routines besides standart AMI ones.

 

BobBon6, appears to be working. :)

Try read the whole chip with flashrom -p internal -r dump.bin and then write it back with flashrom -p internal -w dump.bin.

looks good, I'll flash once again verbose to see what's going on.

 

YOU ARE A GENIUS:

flashrom -p internal -w P80401.bin
flashrom v0.9.7-r1711 on Darwin 13.0.0 (x86_64)
flashrom is free software, get the source code at http://www.flashrom.org

Calibrating delay loop... OK.
Mapping low megabyte at 0x0000000000000400, unaligned size 0xffc00.
Mapping low megabyte, 0xffc00 bytes at unaligned 0x0000000000000400.
Found chipset "Intel Z77". Enabling flash write... Warning: SPI Configuration Lockdown activated.
OK.
Found Winbond flash chip "W25Q64.V" (8192 kB, SPI) at physical address 0xff800000.
Reading old flash chip contents... done.
Erasing and writing flash chip... Erase/write done.
Verifying flash... VERIFIED.

  • Like 3
Link to comment
Share on other sites

Thank you both for help, guys. I'm glad it works. :thumbsup_anim:

Before I can make any automatic patcher, I must explain where and what to patch.

The module to patch is PchInitDxe (DE23ACEE-CF55-4FB6-AA77-984AB53DE823). The code of this module is written by Intel and updated recently, so every new BIOS can have slightly different module, which makes it hard to patch by automated tools. I will use the BonBon6's BIOS file as an example. All things will be done in Windows, because there are no tools for working with UEFI files in OS X, AFAIK.

1. Extract PchInitDxe (DE23ACEE-CF55-4FB6-AA77-984AB53DE823) module from BIOS file using MMTool or PhoenixTool and save it as PchInitDxe.bin. Do not be confused with PchInitPeim (DE23ACEE-CF55-4FB6-AA77-984AB53DE811) module, which has 11 on the end of GUID, where our module has 23.

 

2. Make a copy of it to modify later, and then remove all data in the beginning of the module, so the modified module begins with "MZ" signature:

post-1111314-0-66536600-1378708499_thumb.png

If there are more then 4 bytes, remove it anyway.

 

3. To disassemble the extracted module use dumpbin utility, that can be invoked easily by launching "Visual Studio Tools for Win64" shortcut, that is available after installing any edition of modern Visual Studio, including free Express one.

The command line is dumpbin /disasm /out:PchInitDxe.asm PchInitDxe.bin. If someone goes wrong - make sure that step 2 was done right.

The alternatives are objdump utility from binutils, but it produces less comprehensive disassembly, or IDA Pro 6.xx, that is extremely expensive for single hobbyists like us, so I personally prefer dumpbin.

PchInitDxe.asm.zip

 

4. Open the resulting asm file with your favorite editor and search for instruction with "+50h]" on the end, followed by "test" instruction.

The first occurrence of that pattern in our example is here:

0000000180001233: 4C 8B 5C 24 40     mov         r11,qword ptr [rsp+40h] ; Loading PchPlatformData variable address to R11
0000000180001238: 49 8B 43 50        mov         rax,qword ptr [r11+50h] ; Loading PchPlatformData->LockdownConfig to RAX  <--- HERE IS WHAT WE SEARCHED FOR
000000018000123C: 40 84 28           test        byte ptr [rax],bpl      ; Testing if the fisrt bit of LockdownConfig (GlobalSmi) is 0
                                                                         ; BPL register holds 0x01 here, and "test" instruction is actual "and" without storing the result 
000000018000123F: 74 69              je          00000001800012AA        ; Jump 0x69 bytes further if GlobalSmiLock is 0

The PchPlatformData structure can be changed in any update, but as far I have tested, LockdownConfig is and was at 50h offset from the beginning of it, lets hope it will always be so.

Patching JE instruction to JMP makes all the code that follows and sets the lock unreachable, disabling it completely.

The LockdownConfig structure is built that way:

typedef struct {
  UINT8  GlobalSmi      : 1; //test with 0x01
  UINT8  BiosInterface  : 1; //test with 0x02
  UINT8  GpioLockDown   : 1; //test with 0x04
  UINT8  RtcLock        : 1; //test with 0x08
  UINT8  BiosLock       : 1; //test with 0x10
  UINT8  Reserved       : 3;
  UINT8  PchBiosLockSwSmiNumber;
} PCH_LOCKDOWN_CONFIG;

It will help us identify, what checks must be patched.

Next occurrence is here:

00000001800012A5: 4C 8B 5C 24 40     mov         r11,qword ptr [rsp+40h] ; Loading PchPlatformData variable address to R11
00000001800012AA: 49 8B 43 50        mov         rax,qword ptr [r11+50h] ; Loading PchPlatformData->LockdownConfig to RAX  <--- HERE IS WHAT WE SEARCHED FOR
00000001800012AE: 40 84 30           test        byte ptr [rax],sil      ; Testing if the second bit of LockdownConfig (BiosInterface) is 0 
                                                                         ; SIL register holds 0x02 here, and "test" instruction is actual "and" without storing the result
00000001800012B1: 74 50              je          0000000180001303        ; Jump 0x50 bytes further if BiosInterface is 0

Can also be patched, but not required.

Next occurrence is here:

000000018000135E: 4C 8B 5C 24 40     mov         r11,qword ptr [rsp+40h] ; Loading PchPlatformData variable address to R11
0000000180001363: 49 8B 43 50        mov         rax,qword ptr [r11+50h] ; Loading PchPlatformData->LockdownConfig to RAX  <--- HERE IS WHAT WE SEARCHED FOR
0000000180001367: F6 00 04           test        byte ptr [rax],4        ; Testing if the third bit of LockdownConfig (GpioLockDown) is 0 
000000018000136A: 74 23              je          000000018000138F        ; Jump 0x23 bytes further if GpioLockDown is 0

Must not be patched normally.

Next occurrence is here:

00000001800013E2: 48 8B 4C 24 40     mov         rcx,qword ptr [rsp+40h] ; Loading PchPlatformData variable address to RCX
00000001800013E7: 80 39 03           cmp         byte ptr [rcx],3        ; Compare PchPlatformData->Revision with 3
00000001800013EA: 72 66              jb          0000000180001452        ; Jump 0ч66 bytes further if PchPlatformData->Revision is less then 3, which is false on modern boards 
00000001800013EC: 48 8B 41 50        mov         rax,qword ptr [rcx+50h] ; Loading PchPlatformData->LockdownConfig to RAX <--- HERE IS WHAT WE SEARCHED FOR
00000001800013F0: F6 00 08           test        byte ptr [rax],8        ; Testing if the fourth bit of LockdownConfig (RtcLock) is 0 
00000001800013F3: 74 2F              je          0000000180001424        ; Jump 0x2F bytes further if RtcLock is 0

Must not be patched normally.

The last interesting occurrence for us:

000000018000141F: 48 8B 4C 24 40     mov         rcx,qword ptr [rsp+40h] ; Loading PchPlatformData variable address to RCX
0000000180001424: 48 8B 41 50        mov         rax,qword ptr [rcx+50h] ; Loading PchPlatformData->LockdownConfig to RAX <--- HERE IS WHAT WE SEARCHED FOR
0000000180001428: F6 00 10           test        byte ptr [rax],10h      ; Testing if the fifth bit of LockdownConfig (BiosLock) is 0 
000000018000142B: 74 25              je          0000000180001452        ; Jump 0x25 bytes further if BiosLock is 0

Must be patched by replacing JE with JMP.

 

5. Knowing all bytes to patch, open the copied original PchInitDxe.bin, patch it using HexEditor, save and reintegrate back into BIOS file using MMTool or PhoenixTool.

You are done.

------

The problem with automated patching it that there are many variants of that code, and there be many more. Registers are changing, offsets are changing, a simple recompilation with slightly different options makes a new file, so I don't know when it be patched automatically.

The method is in your hands now. :)

  • Like 9
Link to comment
Share on other sites

flashing from windows:

 

 

$>fpt -rewrite -f bios-unlocked.bin

Intel ® Flash Programming Tool. Version:  8.1.10.1286
Copyright © 2007 - 2012, Intel Corporation. All rights reserved.

Platform: Intel® Z77 Express Chipset
Reading HSFSTS register... Flash Descriptor: Valid

    --- Flash Devices Found ---
    W25Q64BV    ID:0xEF4017    Size: 8192KB (65536Kb)


PDR Region does not exist.
GBE Region does not exist.


- Erasing Flash Block [0x800000] - 100% complete.
- Programming Flash [0x800000] 8192KB of 8192KB - 100% complete.
- Verifying Flash [0x800000] 8192KB of 8192KB - 100% complete.

RESULT: The data is identical.

FPT Operation Passed

  • Like 1
Link to comment
Share on other sites

Hi on the Zotac board (H87) I am having problems finding a flashing utility that will let me flash the patched UEFI bios. Tried FTK, AFUxxx but I cannot get past the "secure session" message. Can you link me a DOS flash utility that might work to force the flash?

Thanks again....

Link to comment
Share on other sites

MiniHack, use hardware SPI programmer or wait for someone brave who can break that protection.

If SMM is still vurnelable to cache spoofing, maybe we probably can try to disable protection even on unmodified BIOS by using normal DisableSpiProtection routine inside SMI handler.

Try FTK for DOS, if didn't tried earlier, but I think it won't work either.

Link to comment
Share on other sites

MiniHack, use hardware SPI programmer or wait for someone brave who can break that protection.

If SMM is still vurnelable to cache spoofing, maybe we probably can try to disable protection even on unmodified BIOS by using normal DisableSpiProtection routine inside SMI handler.

Try FTK for DOS, if didn't tried earlier, but I think it won't work either.

Well, that's beyond me. FTK for DOS tried already and failed so this definitely goes into the "too tough to bother about" category for the moment. Never mind, thanks anyway -maybe your contacts at Zotac would like to release a official patched bios. :)

Link to comment
Share on other sites

 

thanks a lot! CodeRush, I found out now the ME Region differs from original one.

So I'd suggest the changes can be done in ME, with

 

fwupdlcl -allowsv -f me.bin

 

those changes can be written back to unlock your hack, even for H/Q/Z87!

 

Anyone with Z77 board willing to flash ME only to test the unlock?

Link to comment
Share on other sites

×
×
  • Create New...