
A little more reverse engineering of UEFI PEI modules with another useful example
Hello again, dear habrachitateli.
As part of the struggle for the possibility of modifying UEFI on HP laptops, another defense had to be broken, this time more modern. Apparently, the firmware development department at HP realized that the previous protection was not so hot , and therefore they decided to radically improve it, so the method of bypassing the protection of the DXE volume from the previous article stopped working, and again I needed to arm with a disassembler, develop a converter from TE to PE and answer the same questions: where is the digital signature located, who exactly checks it and how to make sure that the verification always ends in success.
If you are interested in answers and a description of the process of their search - please, under cat.
The protection, the breaking of which will be discussed in this text, was introduced by HP about a year and a half ago, and (as far as I know) was still considered reliable. Users of HP laptops with UEFI protected by it periodically visited the bios-mods.com forum in the hope of help in getting rid of white lists of equipment or opening hidden UEFI Setup settings, but they received an answer at the same frequency - the protection is stable and nothing can be done. In early summer 2014, one of the bios-mods administratorsit was tired and he decided to take the initiative for hacking into his own hands. The process began, but it was extremely slow, and the public result has not yet appeared, and it is very necessary for repairmen who would be happy to put other processors / video cards / modems on these laptops, but they can not, because for their proper operation, modification of DXE drivers is needed, and after it the firmware does not start. As a result, I was tired of this nonsense and I decided to break off the protection myself, since, as it turned out, they could not come up with anything radically more difficult than the previous HP protection.
If you do not understand what is happening here, read the previous article , there is a brief introduction to the course of work and a list of tools used.
There is an HP laptop, which responds to any change in the DXE volume first by rebooting almost immediately after turning it on, and then falls into an endless cycle, while blinking light on the keyboard. There is also a dump of its firmware and kind repair guys who are ready to spend time trying to check the next modified firmware for performance.
The final goal is that the firmware should work after modifications.
Open the firmware again in UEFITool and look at the Messages panel. Thanks to the experience gained in the previous article, the utility is now able to display non-standard data in the tree (i.e. it is not necessary now to unpack the entire DXE to get to them) and saves them when the volume is rebuilt:

As last time, the suspicious the data is at the very end of the DXE volume, but now you can get it directly from the tree, which is what we do, we get the key.bin file , which we then open in the Hex editor:

And again, an unknown piece of data of 100h size appears (it looks like RSA2048 public key), but now it has a signature cheers - $ hss. As I already wrote, data of this kind can be found either by the signature, or by the offset within the volume, or by the absolute address (given the fact that the last byte of the SPI-flash chip is at startup at the address FFFFFFFFh). First, check the first option, using the text search in UEFITool:

Find 4 occurrences of the search string, one of which we have already looked at (the one inside Non-UEFI data), we need to deal with the rest. The first appears in the DXE driver by the name of BiosImageInterface, but it is located in the volume it is intended to check, so the presence of the main check there is very unlikely. If we do not find in other places, it will be necessary to return to it.
The last two entries indicate two copies of the same PEI module, the first of which is in the packed copy of the PEI volume (it can be used to automatically repair the damaged PEI volume), and the other in the “real” PEI volume. Here is our suspect, everything indicates that it is he who checks the integrity, and you need to get its contents into the hss.bin file for further analysis.
Last time, at this place, we uploaded the file to the IDA and began to analyze it, but in this case only IDA 6.7 and above owners can do this, because it was in 6.7 that native support for the Terse Executable format appeared, in which our PEI module is stored. This format was developed by the authors of the UEFI PI specification to save space in the processor cache, in fact it is PE32 with a very trimmed header, from which only the fields vital for the correct image loading are left. Moreover, most manufacturers use the extremely primitive executable file loader in the PEI phase, which does not support relocation, and therefore its base address must match the physical address. All this is wonderful, of course, but we do not need incomprehensible TE, but understandable PE32, so we had to write a converter from TE to PE, which is trying to restore the header of the PE file from the data that it turned out to be found in the TE file. The utility was written in half an hour and for a specific file, so I can not vouch for the correctness of converting any previously set TE-image.
Now we have the pe.bin file and you can open it in the IDA and analyze it. This time we will go a little different way and we will start not from the entry point, but from the place where the $ HSS signature is found . Go to Search -> Text ... (or press Alt + T), enter $ HSS, check the box Find all occurences and ... find nothing. We think a little and understand that we have a LittleEndian machine, and $ HSS when loaded into the register will look like SSH $ or 53534824h. We are looking for this option and voila, one occurrence:

We double-click on the message and get here:

And here is a check that the address from EBX is 53534824h, and if it really is there - EBX + 20h is stored in the variable on the stack, i.e. just the address of the first byte of the key, and if it does not, 10h is added to the EBX and checked again. It is also seen that from another branch of the code, the value FFF3DF00h, which is the physical address of the first byte of the key, can fall into the same variable. You can check this, for which it is enough to subtract FFF3DF00h from 100000000h and back off the received C2100h bytes from the end of the file - as expected, we find ourselves at the very beginning of the block with the key. Whether the key is found by signature or absolute address depends on BootMode. If the current mode is 20h, i.e. BOOT_IN_RECOVERY_MODE - the key will be found at the absolute address, otherwise - by signature.
We look further:

And then there is a function call from some specific HP PPI , which performs the check. If this function returned 0 (i.e. EFI_SUCCESS), then we go down from this screen to return, if the verification fails, everything again depends on BootMode, in the case of BOOT_IN_RECOVERY_MODE, a function is called from another PPI (which, I suspect, will try to restore the DXE volume from the Recovery image). Then, independently of BootMode, another function from the second PPI is called, after which 6 and 0CF9h are pushed onto the stack and a short function is called, in our case it looks like this:
If you suddenly did not recognize in makeup - this is the most common way to hard reset now through IO ports. And if the reset did not happen suddenly, there will be an endless cycle, which immediately follows it.
Well, we figured out the reasons for the reset, now we need to get around it, and in order to return EFI_SUCCESS to EAX from the function in which it all happens. In my opinion, the easiest way to achieve what you want is to change the first test eax, eax to xor eax, eax , as a result, 0 will appear in EAX and JGE will work 100% of the time, and the reset will become dead code.
UPD by popular demand from drugs: to quickly find a place for the patch, you need to get the executable section from the file with GUID 86D70125-BAA3-4296-A62F-602BEBBB9081 (it can be either TE or PE, I met both options), open it in the Hex editor, find line $ HSS and find the first occurrence of the pattern 85 C0 after $ HSS - with a very high probability this is the place for the patch. If not, you have to look for it yourself.
No sooner said than done, patch 85 C0 -> 31 C0, collect the firmware (not forgetting that we have two copies of this file and we need to replace both) and send it to our repairmen for testing. After 5 minutes, a message arrives: "it starts and works, thank you very much." Now you can sit down again and write an article about cool vendor defenses, which first last a year and a half, and then are removed in an hour and a half.
Thank you for your attention, successful firmware and modifications.
As part of the struggle for the possibility of modifying UEFI on HP laptops, another defense had to be broken, this time more modern. Apparently, the firmware development department at HP realized that the previous protection was not so hot , and therefore they decided to radically improve it, so the method of bypassing the protection of the DXE volume from the previous article stopped working, and again I needed to arm with a disassembler, develop a converter from TE to PE and answer the same questions: where is the digital signature located, who exactly checks it and how to make sure that the verification always ends in success.
If you are interested in answers and a description of the process of their search - please, under cat.
Brief Background
The protection, the breaking of which will be discussed in this text, was introduced by HP about a year and a half ago, and (as far as I know) was still considered reliable. Users of HP laptops with UEFI protected by it periodically visited the bios-mods.com forum in the hope of help in getting rid of white lists of equipment or opening hidden UEFI Setup settings, but they received an answer at the same frequency - the protection is stable and nothing can be done. In early summer 2014, one of the bios-mods administratorsit was tired and he decided to take the initiative for hacking into his own hands. The process began, but it was extremely slow, and the public result has not yet appeared, and it is very necessary for repairmen who would be happy to put other processors / video cards / modems on these laptops, but they can not, because for their proper operation, modification of DXE drivers is needed, and after it the firmware does not start. As a result, I was tired of this nonsense and I decided to break off the protection myself, since, as it turned out, they could not come up with anything radically more difficult than the previous HP protection.
There will be no educational program
If you do not understand what is happening here, read the previous article , there is a brief introduction to the course of work and a list of tools used.
What is given and what is required to find
There is an HP laptop, which responds to any change in the DXE volume first by rebooting almost immediately after turning it on, and then falls into an endless cycle, while blinking light on the keyboard. There is also a dump of its firmware and kind repair guys who are ready to spend time trying to check the next modified firmware for performance.
The final goal is that the firmware should work after modifications.
Search
Open the firmware again in UEFITool and look at the Messages panel. Thanks to the experience gained in the previous article, the utility is now able to display non-standard data in the tree (i.e. it is not necessary now to unpack the entire DXE to get to them) and saves them when the volume is rebuilt:

As last time, the suspicious the data is at the very end of the DXE volume, but now you can get it directly from the tree, which is what we do, we get the key.bin file , which we then open in the Hex editor:

And again, an unknown piece of data of 100h size appears (it looks like RSA2048 public key), but now it has a signature cheers - $ hss. As I already wrote, data of this kind can be found either by the signature, or by the offset within the volume, or by the absolute address (given the fact that the last byte of the SPI-flash chip is at startup at the address FFFFFFFFh). First, check the first option, using the text search in UEFITool:

Find 4 occurrences of the search string, one of which we have already looked at (the one inside Non-UEFI data), we need to deal with the rest. The first appears in the DXE driver by the name of BiosImageInterface, but it is located in the volume it is intended to check, so the presence of the main check there is very unlikely. If we do not find in other places, it will be necessary to return to it.
The last two entries indicate two copies of the same PEI module, the first of which is in the packed copy of the PEI volume (it can be used to automatically repair the damaged PEI volume), and the other in the “real” PEI volume. Here is our suspect, everything indicates that it is he who checks the integrity, and you need to get its contents into the hss.bin file for further analysis.
Last time, at this place, we uploaded the file to the IDA and began to analyze it, but in this case only IDA 6.7 and above owners can do this, because it was in 6.7 that native support for the Terse Executable format appeared, in which our PEI module is stored. This format was developed by the authors of the UEFI PI specification to save space in the processor cache, in fact it is PE32 with a very trimmed header, from which only the fields vital for the correct image loading are left. Moreover, most manufacturers use the extremely primitive executable file loader in the PEI phase, which does not support relocation, and therefore its base address must match the physical address. All this is wonderful, of course, but we do not need incomprehensible TE, but understandable PE32, so we had to write a converter from TE to PE, which is trying to restore the header of the PE file from the data that it turned out to be found in the TE file. The utility was written in half an hour and for a specific file, so I can not vouch for the correctness of converting any previously set TE-image.
Now we have the pe.bin file and you can open it in the IDA and analyze it. This time we will go a little different way and we will start not from the entry point, but from the place where the $ HSS signature is found . Go to Search -> Text ... (or press Alt + T), enter $ HSS, check the box Find all occurences and ... find nothing. We think a little and understand that we have a LittleEndian machine, and $ HSS when loaded into the register will look like SSH $ or 53534824h. We are looking for this option and voila, one occurrence:

We double-click on the message and get here:

And here is a check that the address from EBX is 53534824h, and if it really is there - EBX + 20h is stored in the variable on the stack, i.e. just the address of the first byte of the key, and if it does not, 10h is added to the EBX and checked again. It is also seen that from another branch of the code, the value FFF3DF00h, which is the physical address of the first byte of the key, can fall into the same variable. You can check this, for which it is enough to subtract FFF3DF00h from 100000000h and back off the received C2100h bytes from the end of the file - as expected, we find ourselves at the very beginning of the block with the key. Whether the key is found by signature or absolute address depends on BootMode. If the current mode is 20h, i.e. BOOT_IN_RECOVERY_MODE - the key will be found at the absolute address, otherwise - by signature.
We look further:

And then there is a function call from some specific HP PPI , which performs the check. If this function returned 0 (i.e. EFI_SUCCESS), then we go down from this screen to return, if the verification fails, everything again depends on BootMode, in the case of BOOT_IN_RECOVERY_MODE, a function is called from another PPI (which, I suspect, will try to restore the DXE volume from the Recovery image). Then, independently of BootMode, another function from the second PPI is called, after which 6 and 0CF9h are pushed onto the stack and a short function is called, in our case it looks like this:
mov al, 6
mov dx, 0CF9h
out dx, al
If you suddenly did not recognize in makeup - this is the most common way to hard reset now through IO ports. And if the reset did not happen suddenly, there will be an endless cycle, which immediately follows it.
Well, we figured out the reasons for the reset, now we need to get around it, and in order to return EFI_SUCCESS to EAX from the function in which it all happens. In my opinion, the easiest way to achieve what you want is to change the first test eax, eax to xor eax, eax , as a result, 0 will appear in EAX and JGE will work 100% of the time, and the reset will become dead code.
UPD by popular demand from drugs: to quickly find a place for the patch, you need to get the executable section from the file with GUID 86D70125-BAA3-4296-A62F-602BEBBB9081 (it can be either TE or PE, I met both options), open it in the Hex editor, find line $ HSS and find the first occurrence of the pattern 85 C0 after $ HSS - with a very high probability this is the place for the patch. If not, you have to look for it yourself.
Testing and conclusion
No sooner said than done, patch 85 C0 -> 31 C0, collect the firmware (not forgetting that we have two copies of this file and we need to replace both) and send it to our repairmen for testing. After 5 minutes, a message arrives: "it starts and works, thank you very much." Now you can sit down again and write an article about cool vendor defenses, which first last a year and a half, and then are removed in an hour and a half.
Thank you for your attention, successful firmware and modifications.
PS As a bonus, a little photo of a running laptop with a replaced Boot Logo stored in a DXE volume. Indicates that the protection is indeed removed.
