<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:base="https://jbeekman.nl/">
  <id>https://jbeekman.nl/</id>
  <title>Reverse Engineering – Technology &amp; Policy</title>
  <updated>2015-03-09T00:00:00Z</updated>
  <link rel="alternate" href="https://jbeekman.nl/"/>
  <link rel="self" href="https://jbeekman.nl/blog/reverse-engineering/"/>
  <author>
    <name>Jethro Beekman</name>
    <uri>https://jbeekman.nl/blog</uri>
  </author>
  <icon>https://jbeekman.nl/favicon.ico</icon>
  <entry>
    <id>tag:jbeekman.nl,2015-03-08:/blog/2015/03/reverse-engineering-uefi-firmware/</id>
    <title type="html">Reverse Engineering UEFI Firmware – Technology &amp; Policy</title>
    <published>2015-03-09T00:00:00Z</published>
    <updated>2015-03-09T00:00:00Z</updated>
    <link rel="alternate" href="https://jbeekman.nl/blog/2015/03/reverse-engineering-uefi-firmware/"/>
    <content type="html">&lt;p&gt;In order to &lt;a href="/blog/2015/03/lenovo-thinkpad-hdd-password/"&gt;figure out how my BIOS drive password 
worked,&lt;/a&gt; I had to 
reverse-engineer the firmware that comes with my laptop. You can find the 
binary blobs on the update CD that Lenovo provides, and it turns out these 
blobs are actually UEFI images. UEFI firmware is made up of many different 
loadable modules (drivers, shared libraries, etc.), which are stored in the 
Portable Executable (PE) image format. These modules can be extracted from the 
image using Nikolaj Schlej’s excellent UEFIExtract (from 
&lt;a href="https://github.com/LongSoft/UEFITool"&gt;UEFITool&lt;/a&gt;). Once you have all the PE 
modules, the real reversing can begin.&lt;/p&gt;

&lt;p&gt;It helps to understand how UEFI works. The Internet contains a wealth of 
information, and here are two articles to get you started: &lt;a href="http://mjg59.dreamwidth.org/18773.html"&gt;Getting started 
with UEFI development&lt;/a&gt; and &lt;a href="http://x86asm.net/articles/uefi-programming-first-steps/"&gt;UEFI 
Programming - First 
Steps&lt;/a&gt;. The main 
problem that makes reverse engineering hard is that while the firmware consists 
of over 300 loadable modules, there is no dynamic linker. Instead, the entry 
point of a module gets passed an pointer to a “protocol” registry. A protocol 
is basically an interface, or in other words a struct of function pointers. The 
registry is keyed by Globally unique identifiers (GUIDs). To call into another 
module, you need to lookup a GUID in the registry and then call some function 
returned in the interface.&lt;/p&gt;

&lt;p&gt;My first strategy to get some insight into the firmware was to collect GUIDs 
from images and build a dependency graph. This turned out to be useless. The 
UEFI image contains &lt;em&gt;PEI dependency sections&lt;/em&gt; for each image, but the GUIDs 
that are listed seem to have no relation to actually required protocols. 
Furthermore, identifying GUIDs (also known as 16 random bytes) in binaries is 
hard, and even when I manged to identify a section that seemed to store GUIDs, 
there would be many GUIDs in such a section that were never referenced from 
code in that image.&lt;/p&gt;

&lt;p&gt;To figure out the dependencies, I decided to actually run the modules and see 
which protocols they lookup and which ones they register. &lt;em&gt;Wait what, run UEFI 
PE modules?&lt;/em&gt; Yes, &lt;a href="https://github.com/jethrogb/uefireverse/tree/master/efiperun"&gt;I wrote a tool called 
&lt;code&gt;efiperun&lt;/code&gt;&lt;/a&gt; that 
can load PE modules into memory and simulate enough of what an UEFI environment 
is supposed to look like to actually run them. Most modules will upon entry 
lookup some standard protocols, do some initialization, and register one or 
more protocols that other modules can use.&lt;/p&gt;

&lt;p&gt;With this information in hand, you can do more targeted reversing, trying to 
identify interfaces and function signatures. For example, 
&lt;code&gt;LenovoTranslateService.efi&lt;/code&gt; installs a protocol 
&lt;code&gt;e3abb023-b8b1-4696-98e1-8eedc3d3c63d&lt;/code&gt;. This protocol turns out to have the 
following interface:&lt;/p&gt;

&lt;div class="language-c highlighter-coderay"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;&lt;span style="color:#080;font-weight:bold"&gt;struct&lt;/span&gt; interface_e3abb023_b8b1_4696_98e1_8eedc3d3c63d
{
    &lt;span style="color:#088;font-weight:bold"&gt;void&lt;/span&gt;(EFIAPI *translate)(&lt;span style="color:#088;font-weight:bold"&gt;void&lt;/span&gt;* _this, &lt;span style="color:#088;font-weight:bold"&gt;const&lt;/span&gt; &lt;span style="color:#0a8;font-weight:bold"&gt;char&lt;/span&gt;* input, &lt;span style="color:#0a8;font-weight:bold"&gt;char&lt;/span&gt;* output, size_t length);
}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;With &lt;code&gt;efiperun&lt;/code&gt; you can actually write code that calls into loaded EFI modules, 
which makes it easy to test installed interfaces. Utilizing this functionality, 
I was able to determine that the &lt;code&gt;translate&lt;/code&gt; function above actually translates 
an ASCII string to keyboard scan codes.&lt;/p&gt;

&lt;p&gt;When doing reverse engineering, you always end up exploring branches that turn 
out to be less fruitful. But the knowledge obtained exploring such a branch can 
be useful in exploring other ideas. Now that I’ve setup the stage with the 
tools I’m going to use, I will describe the path that lead to the discovery of 
the algorithm. Keep in mind that this is a reconstruction and the order in 
which I actually figured parts out is different.&lt;/p&gt;

&lt;h4 id="graphical-entry-point"&gt;Graphical entry point&lt;/h4&gt;

&lt;p&gt;&lt;img src="/img/blog/reverse-engineering-uefi-firmware/hdp-prompt.png" alt="Lenovo HDP Prompt" align="right" /&gt;&lt;/p&gt;

&lt;p&gt;The Lenovo firmware does not make heavy use of graphical elements, but the Hard 
Drive Password prompt actually does display a small pictogram, pictured on the
right. Now, judging by the filenames, there are only a few modules that deal with graphics:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;SystemGraphicsConsoleDxe.efi&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;SystemHiiImageDisplayDxe.efi&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;SystemImageDecoderDxe.efi&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;SystemImageDisplayDxe.efi&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All these modules install a single protocol that don’t use a &lt;a href="https://github.com/jethrogb/uefireverse/blob/master/guiddb/efi_guid.c"&gt;well-known 
GUID&lt;/a&gt;, 
so let’s see what modules call them. As it turns out, only 
&lt;code&gt;SystemSplashDxe.efi&lt;/code&gt; calls &lt;code&gt;SystemHiiImageDisplayDxe.efi&lt;/code&gt; 
(96ce4c12-55e4-4a1c-bbf3-73a5055fb364) and only &lt;code&gt;LenovoPromptService.efi&lt;/code&gt; calls 
&lt;code&gt;SystemImageDisplayDxe.efi&lt;/code&gt; (71583a77-2789-4213-a83b-eef42afe85e0). 
&lt;code&gt;SystemSplashDxe.efi&lt;/code&gt; pretty much seems to be as advertised and even contains a 
GIF file with the ThinkPad splash image. Upon further inspection, 
&lt;code&gt;LenovoPromptService.efi&lt;/code&gt; contains 21 BMP files, all related to displaying 
password prompts. Bingo!&lt;/p&gt;

&lt;h4 id="password-control-program"&gt;Password control program&lt;/h4&gt;

&lt;p&gt;The Prompt service installs a single protocol 
56350810-2cb2-4aa0-96d2-66d1b8e1aac2 which is only called by 
&lt;code&gt;LenovoPasswordCp.efi&lt;/code&gt;. This module contains key code connecting various 
password-related modules, and I’ll assume Cp means “control progam”. Besides 
the prompt service (for text input), it also calls into 
&lt;code&gt;LenovoSoundService.efi&lt;/code&gt; (e01fc710-ba41-493b-a919-53583368f6d9, for beeping 
noises when you press an invalid key), &lt;code&gt;LenovoTranslateService.efi&lt;/code&gt; (described 
above) and &lt;code&gt;LenovoCryptService.efi&lt;/code&gt; (73e47354-b0c5-4e00-a714-9d0d5a4fdbfd, 
supposedly a crypto module—see next section).&lt;/p&gt;

&lt;p&gt;The password control program has an interesting function at offset &lt;code&gt;0x8cc&lt;/code&gt; that 
calls only &lt;code&gt;SetMem&lt;/code&gt;, &lt;code&gt;CopyMem&lt;/code&gt; and the Crypto and Translate services. Here’s 
roughly the code for this function:&lt;/p&gt;

&lt;div class="language-c highlighter-coderay"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;&lt;span style="color:#088;font-weight:bold"&gt;void&lt;/span&gt; _0x8cc(&lt;span style="color:#088;font-weight:bold"&gt;const&lt;/span&gt; CHAR16 in[&lt;span style="color:#00D"&gt;64&lt;/span&gt;], UINT8 out[&lt;span style="color:#00D"&gt;16&lt;/span&gt;])
{
    UINT8 ascii[&lt;span style="color:#00D"&gt;64&lt;/span&gt;], scancode[&lt;span style="color:#00D"&gt;64&lt;/span&gt;], hash[&lt;span style="color:#00D"&gt;32&lt;/span&gt;];
    BootServices-&amp;gt;SetMem(out,&lt;span style="color:#00D"&gt;16&lt;/span&gt;,&lt;span style="color:#00D"&gt;0&lt;/span&gt;);
    BootServices-&amp;gt;SetMem(ascii,&lt;span style="color:#00D"&gt;64&lt;/span&gt;,&lt;span style="color:#00D"&gt;0&lt;/span&gt;);
    BootServices-&amp;gt;SetMem(scancode,&lt;span style="color:#00D"&gt;64&lt;/span&gt;,&lt;span style="color:#00D"&gt;0&lt;/span&gt;);
    BootServices-&amp;gt;SetMem(hash,&lt;span style="color:#00D"&gt;32&lt;/span&gt;,&lt;span style="color:#00D"&gt;0&lt;/span&gt;);
    &lt;span style="color:#080;font-weight:bold"&gt;for&lt;/span&gt; (&lt;span style="color:#0a8;font-weight:bold"&gt;int&lt;/span&gt; i=&lt;span style="color:#00D"&gt;0&lt;/span&gt;;i&amp;lt;&lt;span style="color:#00D"&gt;64&lt;/span&gt;;i++)
    {
        ascii[i]=in[i];
    }
    &lt;span style="color:#080;font-weight:bold"&gt;if&lt;/span&gt; (TranslateService)
    {
        TranslateService-&amp;gt;Translate(TranslateService,ascii,scancode,&lt;span style="color:#00D"&gt;64&lt;/span&gt;);
        &lt;span style="color:#080;font-weight:bold"&gt;if&lt;/span&gt; (CryptService)
        {
            CryptService-&amp;gt;SHA256(CryptService,scancode,&lt;span style="color:#00D"&gt;64&lt;/span&gt;,hash);
            BootServices-&amp;gt;CopyMem(out,hash,&lt;span style="color:#00D"&gt;16&lt;/span&gt;);
        }
        BootServices-&amp;gt;SetMem(ascii,&lt;span style="color:#00D"&gt;64&lt;/span&gt;,&lt;span style="color:#00D"&gt;0&lt;/span&gt;);
        BootServices-&amp;gt;SetMem(scancode,&lt;span style="color:#00D"&gt;64&lt;/span&gt;,&lt;span style="color:#00D"&gt;0&lt;/span&gt;);
        BootServices-&amp;gt;SetMem(hash,&lt;span style="color:#00D"&gt;32&lt;/span&gt;,&lt;span style="color:#00D"&gt;0&lt;/span&gt;);
    }
    &lt;span style="color:#080;font-weight:bold"&gt;else&lt;/span&gt;
    {
        BootServices-&amp;gt;SetMem(ascii,&lt;span style="color:#00D"&gt;64&lt;/span&gt;,&lt;span style="color:#00D"&gt;0&lt;/span&gt;);
    }
}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;I’ll assume that this function is used to hash a password input by the user. 
There’s another interesting function at offset &lt;code&gt;0xa30&lt;/code&gt;, which checks whether the 
input &lt;code&gt;CHAR16&lt;/code&gt; is in the character class &lt;code&gt;[0-9A-Za-z ;]&lt;/code&gt;, which is used to limit 
the possible characters in the password input.&lt;/p&gt;

&lt;p&gt;I’ve made good progress identifying part of the path from password input to 
security unlock command, but here I’ve hit a dead end. It’s not really clear 
from where the password control program gets called and what happens to the 
hash it outputs. I’ll try a different approach next, but first let’s talk about 
the crypto service.&lt;/p&gt;

&lt;h4 id="crypto-service"&gt;Crypto service&lt;/h4&gt;

&lt;p&gt;The password control program calls a function in the Crypto service at offset 
&lt;code&gt;0x26e0&lt;/code&gt;, which references three GUIDs that I hadn’t seen before:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;69188a5f-6bbd-46c7-9c16-55f194befcdf&lt;/li&gt;
  &lt;li&gt;d0b3d668-16cf-4feb-95f5-1ca3693cfe56&lt;/li&gt;
  &lt;li&gt;6c48f74a-b4df-461f-80c4-5cae8a85b7ee&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These GUIDs do not appear in any &lt;code&gt;efiperun&lt;/code&gt; output. Instead, I just searched 
all images for appearances of these GUIDs, and they appear in 10 other images. 
A noteworthy appearance is in &lt;code&gt;SystemCryptSvcRt.efi&lt;/code&gt; at offset &lt;code&gt;0x1c70&lt;/code&gt;. Offset 
&lt;code&gt;0x1c70&lt;/code&gt; is referenced at offset &lt;code&gt;0x330&lt;/code&gt;, where it is immediately followed by 
the unicode string “SHA256”. This is followed by a jump table at offset 
&lt;code&gt;0x370&lt;/code&gt;, which points to 3 jumps at offset &lt;code&gt;0x33c0&lt;/code&gt; that jump to 3 functions at 
offsets &lt;code&gt;0x753c&lt;/code&gt;, &lt;code&gt;0x7570&lt;/code&gt; and &lt;code&gt;0x760c&lt;/code&gt;. The function at offset &lt;code&gt;0x753c&lt;/code&gt; 
references offset &lt;code&gt;0x2258&lt;/code&gt;, &lt;em&gt;which stores the &lt;a href="https://en.wikipedia.org/wiki/SHA-2#Pseudocode"&gt;hash initialization constants 
for SHA256&lt;/a&gt;&lt;/em&gt;! The rest of the 
&lt;code&gt;SystemCryptSvcRt.efi&lt;/code&gt; module also contains SHA256 round constants, and similar 
strings and constants for other algorithms.&lt;/p&gt;

&lt;p&gt;All in all this suggests that the Crypto service is a front for the 
cryptographic routines in &lt;code&gt;SystemCryptSvcRt.efi&lt;/code&gt; and that the password control 
program calls SHA256. I wrote a small test program for the &lt;a href="http://tianocore.sourceforge.net/wiki/Efi-shell"&gt;EFI shell&lt;/a&gt; that 
tests this:&lt;/p&gt;

&lt;div class="language-c highlighter-coderay"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;&lt;span style="color:#088;font-weight:bold"&gt;void&lt;/span&gt; buf2hexstr(VOID*buf,CHAR16*str,UINTN len)
{
    UINTN i;
    &lt;span style="color:#088;font-weight:bold"&gt;static&lt;/span&gt; CHAR16 hchars[&lt;span style="color:#00D"&gt;16&lt;/span&gt;]={&lt;span style="color:#D20"&gt;'0'&lt;/span&gt;,&lt;span style="color:#D20"&gt;'1'&lt;/span&gt;,&lt;span style="color:#D20"&gt;'2'&lt;/span&gt;,&lt;span style="color:#D20"&gt;'3'&lt;/span&gt;,&lt;span style="color:#D20"&gt;'4'&lt;/span&gt;,&lt;span style="color:#D20"&gt;'5'&lt;/span&gt;,&lt;span style="color:#D20"&gt;'6'&lt;/span&gt;,&lt;span style="color:#D20"&gt;'7'&lt;/span&gt;,&lt;span style="color:#D20"&gt;'8'&lt;/span&gt;,&lt;span style="color:#D20"&gt;'9'&lt;/span&gt;,&lt;span style="color:#D20"&gt;'a'&lt;/span&gt;,&lt;span style="color:#D20"&gt;'b'&lt;/span&gt;,&lt;span style="color:#D20"&gt;'c'&lt;/span&gt;,&lt;span style="color:#D20"&gt;'d'&lt;/span&gt;,&lt;span style="color:#D20"&gt;'e'&lt;/span&gt;,&lt;span style="color:#D20"&gt;'f'&lt;/span&gt;};
    UINT8* buf_=(UINT8*)buf;
    &lt;span style="color:#080;font-weight:bold"&gt;for&lt;/span&gt; (i=&lt;span style="color:#00D"&gt;0&lt;/span&gt;;i&amp;lt;len;i++)
    {
        *(str++)=hchars[*(buf_)  &amp;gt;&amp;gt;&lt;span style="color:#00D"&gt;4&lt;/span&gt;];
        *(str++)=hchars[*(buf_++)&amp;amp;&lt;span style="color:#02b"&gt;0xf&lt;/span&gt;];
    }
}

EFI_STATUS Initialize(...)
{
    ...
    EFI_GUID guid={&lt;span style="color:#02b"&gt;0x73e47354&lt;/span&gt;,&lt;span style="color:#02b"&gt;0xb0c5&lt;/span&gt;,&lt;span style="color:#02b"&gt;0x4e00&lt;/span&gt;,{&lt;span style="color:#02b"&gt;0xa7&lt;/span&gt;,&lt;span style="color:#02b"&gt;0x14&lt;/span&gt;,&lt;span style="color:#02b"&gt;0x9d&lt;/span&gt;,&lt;span style="color:#02b"&gt;0x0d&lt;/span&gt;,&lt;span style="color:#02b"&gt;0x5a&lt;/span&gt;,&lt;span style="color:#02b"&gt;0x4f&lt;/span&gt;,&lt;span style="color:#02b"&gt;0xdb&lt;/span&gt;,&lt;span style="color:#02b"&gt;0xfd&lt;/span&gt;}};
    &lt;span style="color:#088;font-weight:bold"&gt;void&lt;/span&gt;* intf;

    &lt;span style="color:#080;font-weight:bold"&gt;if&lt;/span&gt; (SystemTable-&amp;gt;BootServices-&amp;gt;LocateProtocol(&amp;amp;guid,&lt;span style="color:#069"&gt;NULL&lt;/span&gt;,&amp;amp;intf)==EFI_SUCCESS)
    {
        &lt;span style="color:#088;font-weight:bold"&gt;const&lt;/span&gt; &lt;span style="color:#0a8;font-weight:bold"&gt;char&lt;/span&gt;* in=&lt;span style="background-color:hsla(0,100%,50%,0.05)"&gt;&lt;span style="color:#710"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#D20"&gt;TEST&lt;/span&gt;&lt;span style="color:#710"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;;
        &lt;span style="color:#0a8;font-weight:bold"&gt;char&lt;/span&gt; out[&lt;span style="color:#00D"&gt;32&lt;/span&gt;]={};
        CHAR16 str[&lt;span style="color:#00D"&gt;13&lt;/span&gt;+(&lt;span style="color:#00D"&gt;32&lt;/span&gt;*&lt;span style="color:#00D"&gt;2&lt;/span&gt;)+&lt;span style="color:#00D"&gt;2&lt;/span&gt;]=L&lt;span style="background-color:hsla(0,100%,50%,0.05)"&gt;&lt;span style="color:#710"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#D20"&gt;SHA256 test: &lt;/span&gt;&lt;span style="color:#710"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;;
        ((&lt;span style="color:#088;font-weight:bold"&gt;void&lt;/span&gt;(*)(&lt;span style="color:#088;font-weight:bold"&gt;void&lt;/span&gt;*,&lt;span style="color:#088;font-weight:bold"&gt;const&lt;/span&gt; &lt;span style="color:#0a8;font-weight:bold"&gt;char&lt;/span&gt;*,UINTN,&lt;span style="color:#0a8;font-weight:bold"&gt;char&lt;/span&gt;*))(*(&lt;span style="color:#088;font-weight:bold"&gt;void&lt;/span&gt;**)intf))(intf,in,&lt;span style="color:#00D"&gt;4&lt;/span&gt;,out);
        buf2hexstr(out,str+&lt;span style="color:#00D"&gt;13&lt;/span&gt;,&lt;span style="color:#00D"&gt;32&lt;/span&gt;);
        str[&lt;span style="color:#00D"&gt;13&lt;/span&gt;+(&lt;span style="color:#00D"&gt;32&lt;/span&gt;*&lt;span style="color:#00D"&gt;2&lt;/span&gt;)]=&lt;span style="color:#D20"&gt;'\n'&lt;/span&gt;;
        SystemTable-&amp;gt;ConOut-&amp;gt;OutputString(SystemTable-&amp;gt;ConOut, str);
        SystemTable-&amp;gt;ConOut-&amp;gt;OutputString(SystemTable-&amp;gt;ConOut,
            L&lt;span style="background-color:hsla(0,100%,50%,0.05)"&gt;&lt;span style="color:#710"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#D20"&gt;Expected:    94ee059335e587e501cc4bf90613e0814f00a7b08bc7c648fd865a2af6a22cc2&lt;/span&gt;&lt;span style="color:#b0b"&gt;\n&lt;/span&gt;&lt;span style="color:#710"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
    }
    &lt;span style="color:#080;font-weight:bold"&gt;else&lt;/span&gt;
    {
        SystemTable-&amp;gt;ConOut-&amp;gt;OutputString(SystemTable-&amp;gt;ConOut,
            L&lt;span style="background-color:hsla(0,100%,50%,0.05)"&gt;&lt;span style="color:#710"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#D20"&gt;Unable to load CryptService protocol&lt;/span&gt;&lt;span style="color:#b0b"&gt;\n&lt;/span&gt;&lt;span style="color:#710"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
    }
    ...
}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Outputs:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;SHA256 test: 94ee059335e587e501cc4bf90613e0814f00a7b08bc7c648fd865a2af6a22cc2
Expected:    94ee059335e587e501cc4bf90613e0814f00a7b08bc7c648fd865a2af6a22cc2
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Success!&lt;/p&gt;

&lt;h4 id="hard-drive-communication"&gt;Hard-drive communication&lt;/h4&gt;

&lt;p&gt;As mentioned, I discovered how the input password got hashed, but it still 
needs to be sent to the drive. The UEFI standard defines the &lt;em&gt;ATA Pass Thru 
Protocol&lt;/em&gt;, which can be used to send raw ATA commands to a drive. This protocol 
is very likely to be used for sending ATA security commands. This protocol is 
not loaded upon initialization by any modules, but the GUID does appear in the 
following modules:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;FdiskOem.efi&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;LenovoHdpManagerDxe.efi&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;LenovoMfgBenchEventDxe.efi&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;SystemAhciAtaAtapiPassThruDxe.efi&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;SystemAhciBusDxe.efi&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;SystemAhciBusSmm.efi&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;SystemIdeAtaPassThruDxe.efi&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;SystemIdeBusDxe.efi&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Wait a minute, is that second module called &lt;em&gt;Lenovo Hard Drive Password 
Manager&lt;/em&gt;? Why yes, it is. There’s a bunch of code in this module, but I found
an interesting function call chain for you:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;offset &lt;code&gt;0xce0&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;offset &lt;code&gt;0x8a0&lt;/code&gt;
        &lt;ul&gt;
          &lt;li&gt;CryptService.SHA256&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;offset &lt;code&gt;0x144c&lt;/code&gt;
        &lt;ul&gt;
          &lt;li&gt;offset &lt;code&gt;0x232c&lt;/code&gt;
            &lt;ul&gt;
              &lt;li&gt;EFI_ATA_PASS_THRU_PROTOCOL.PassThru&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The input to the SHA256 function is a parameter to the function at offset 
&lt;code&gt;0xce0&lt;/code&gt;, and data from an EFI runtime variable “LenovoHddSecInfoVar”. The 
PassThru function is called with a ATA_OP_SECURITY_UNLOCK command block 
including the hash generated just before. I assume the input to the function at 
offset &lt;code&gt;0xce0&lt;/code&gt; is the password hash from the password control program, but what 
is the data in “LenovoHddSecInfoVar”? The &lt;code&gt;dmpstore&lt;/code&gt; utility in the &lt;a href="http://tianocore.sourceforge.net/wiki/Efi-shell"&gt;EFI shell&lt;/a&gt; 
that will dump runtime variables. Here’s mine:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Variable BS '2D8FBE63-3A04-4EF8-A8A4-77321DB5A9AB:LenovoHddSecInfoVar' DataSize = 8
  00000000: 98 7D BC B7 00 00 00 00-                         *........*
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;From the code I know that the value is being used as a memory address, so let’s 
use the &lt;code&gt;mem&lt;/code&gt; utility to dump that:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  B7BC7D98: .. .. .. .. .. .. .. ..-18 E0 0F B8 00 00 00 00           ........*
  B7BC7DA8: 98 DF 0F B8 00 00 00 00-.. .. .. .. .. .. .. ..  *........
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Those are two more memory addresses, let’s see what’s there:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  B80FDF98: 61 53 73 6D 6E 75 20 67-53 53 20 44 34 38 20 30  *aSsmnu gSS D48 0*
  B80FDFA8: 56 45 20 4F 30 35 47 30-20 42 20 20 20 20 20 20  *VE O05G0 B      *
  B80FDFB8: 20 20 20 20 20 20 20 20-.. .. .. .. .. .. .. ..  *        

  B80FE018: 31 53 48 44 53 4E 46 41-30 42 38 35 39 34 20 45  *1SHDSNFA0B8594 E*
  B80FE028: 20 20 20 20 .. .. .. ..-.. .. .. .. .. .. .. ..  *    
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you squint your eyes just right, those kind of read &lt;code&gt;Samsung SSD 840 EVO 
500GB&lt;/code&gt; and &lt;code&gt;S1DHNSAFB05849E&lt;/code&gt;, the Model Number and Serial Number for my SSD, 
respectively. Piecing all this together, you get the algorithm described in &lt;a href="/blog/2015/03/lenovo-thinkpad-hdd-password/"&gt;my 
other blog post&lt;/a&gt;.&lt;/p&gt;

&lt;h4 id="conclusion"&gt;Conclusion&lt;/h4&gt;

&lt;p&gt;As I mentioned, this story is the abridged version of how I found the password 
hashing algorithm. In reality, I looked at many other modules, including many 
hours spent looking at useless things. In the end though, I prevailed and found 
what I was looking for, developing &lt;a href="https://github.com/jethrogb/uefireverse"&gt;a bunch of 
tools&lt;/a&gt; in the process:&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;efiperun:&lt;/dt&gt;
  &lt;dd&gt;Load and run EFI PE image files in a regular OS environment.&lt;/dd&gt;
  &lt;dt&gt;guiddb:&lt;/dt&gt;
  &lt;dd&gt;Scan files for GUIDs and output them in C-source file format.&lt;/dd&gt;
  &lt;dt&gt;memdmp:&lt;/dt&gt;
  &lt;dd&gt;Dump UEFI memory using &lt;a href="http://tianocore.sourceforge.net/wiki/Efi-shell"&gt;EFI shell&lt;/a&gt;.&lt;/dd&gt;
  &lt;dt&gt;tree:&lt;/dt&gt;
  &lt;dd&gt;A Ruby abstraction for a firmware tree on your filesystem previously 
extracted by &lt;a href="https://github.com/LongSoft/UEFITool"&gt;UEFIExtract&lt;/a&gt;.&lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;I hope these tools are of use to anyone. Patches welcome. ☺️&lt;/p&gt;

</content>
    <summary type="html">&lt;p&gt;In order to &lt;a href="/blog/2015/03/lenovo-thinkpad-hdd-password/"&gt;figure out how my BIOS drive password 
worked,&lt;/a&gt; I had to 
reverse-engineer the firmware that comes with my laptop. You can find the 
binary blobs on the update CD that Lenovo provides, and it turns out these 
blobs are actually UEFI images. UEFI firmware is made up of many different 
loadable modules (drivers, shared libraries, etc.), which are stored in the 
Portable Executable (PE) image format. These modules can be extracted from the 
image using Nikolaj Schlej&amp;#x2019;s excellent UEFIExtract (from 
&lt;a href="https://github.com/LongSoft/UEFITool"&gt;UEFITool&lt;/a&gt;). Once you have all the PE 
modules, the real reversing can begin.&lt;/p&gt;</summary>
  </entry>
</feed>

