-
Notifications
You must be signed in to change notification settings - Fork 279
How does it work?
Since me_cleaner modifies a very fundamental part of an Intel system, it is reasonable to be worried about such modification. Here I'm explaining what this script does, and how.
The basic informations about Intel ME firmwares were provided by:
- me.bios.info
- Igor Skochinsky - Rootkit in your laptop - Breakpoint 2012
- Igor Skochinsky - Intel ME Secrets - RECON 2014
- me-tools
- MEAnalyzer
Our work started when we found, on the coreboot Mailing List, a message from Trammel Hudson in which he shared his recent discovers about Intel ME firmwares. Then we tried by ourself and replicated the results: to make things simpler I created a Python script to modify the firmware automatically and we published it on the coreboot Mailing List and later on GitHub.
As you can see in me.bios.info, the firmware is divided in partitions and every partition can contain one or more modules. At the beginning of the image there is the FPT (Firmware Partition Table), a region where all the partitions are indexed. The FPT region is NOT signed and can be freely modified (but it has a checksum, offset 0x1b).
Each partition is individually signed, therefore all the non-fundamental partitions can be removed without breaking anything (as we are removing the partitions, but also the signatures).
It seems that the only fundamental partition is the FTPR (Factory Partition), as every other partition (with the respective entry in the FPT) can be removed. The firmware still contains some code, but:
- The network stack (partition NFTP) has been removed
- The PAVP (partition MDMV, module JCOM) has been removed
- And more...
Based on the results on Trammel Hudson (again, on the coreboot ML) I improved me_cleaner by removing also the LZMA-compressed modules in the FTPR partition (more or less half of the modules in the partition). This also removes the Intel Antitheft module (module TDT), and leaves only 4-5 Huffman-compressed modules. According to Igor's 2014 presentation, slide 17, these modules do the basic ME initialization:
- ROMP (not always present)
- BUP - Bringup (hardware initialization/configuration)
- KERNEL - Scheduler, low-level APIs for other modules
- POLICY - Secondary init tasks, some high-level APIs
- FTCS
After a while I updated me_cleaner to remove also most of the Huffman-compressed modules, leaving only:
- ROMP (not always present)
- BUP - Bringup (hardware initialization/configuration)
Since the TXE firmwares are very similar to the ME ones, I also adapted me_cleaner to work on them.
A month later I finally realized how to move the partitions; in this way the empty space before the FTPR partition can be recovered, and the final size of the Intel ME image is ~80 kB.
We can never be sure about this, but, thanks to the Igor's 2014 presentation (slide 18), we can suppose that the code inside the internal ROM is just the code responsible for the very basic initialization of Intel ME.
Since there isn't any official documentation of the Intel ME firmwares, a short explanation of how me_cleaner works is mandatory. At first it detects if the image is a "pure" ME image (magic $FPT at offset 0x10) or a full BIOS dump (magic 5a a5 f0 0f at offset 0x10). If it is a "pure" ME image it uses the whole file as ME image, otherwise it finds the ME region by reading the values inside the Intel Flash Descriptor.
Then it searches for the basic ME informations: presence of the FPT region, version of the firmware, number of partitions and offset and size of the FTPR partition. Now it has all the informations it needs, and it can start the "cleaning" process by:
- dumping the original FTPR entry in the FPT
- filling the whole image with 0xff, except for the first 0x30 bytes (the start of the FPT) and the FTPR partition
- restoring the FTPR entry in the FPT
- removing the EFFS presence flag
- correcting the FPT checksum
Now the ME image contains only the FTPR partition, as every other partition has been overwritten by 0xff.
For pre-Skylake images, the internal structure of the partitions is known, and also most of the modules can be removed.
The LZMA modules are placed after the Huffman data (after the LLUT) and their positions are clearly saved inside the manifests, so they can easily be removed.
The Huffman modules are more tricky to remove, as the module manifests does not contain directly an offset. The Huffman modules are indexed by "chunks": each "chunk" represent a fixed-size block (usually 1024 bytes of uncompressed data) and it contains an offset to the Huffman stream and a flag. Each module manifest contains the base loading address of that module (that sets the starting chunk, first_chunk = (module_base - overall_base) / chunk_size
) and the uncompressed module size (that sets the number of chunks, last_chunk = first_chunk + module_size / chunk_size
). Once we have the chunk indexes we can construct a whitelist of unremovable blocks and remove the others.
Moving a partition is not straightforward, as additional steps are needed:
- correct the partition's FPT offset (bytes 0x8:0xc)
- fix the LLUT absolute offset (bytes 0xc:0x10 of the LLUT, minus bytes 0x9:0xb)
- adjust the absolute Huffman offset in the LLUT (bytes 0x14:0x18)
- correct the offset of each Huffman chunk
This is the simplified structure of a partition header:
As you can see the partition is not signed directly, instead all the modules are hashed and the modules manifests (that contain the hashes) are signed. This means that modify a module doesn't invalidate the signature, but only its hash.
Luckily for us, Intel ME doesn't check all the hashes at once, but only when it needs to execute them. Moreover the system is allowed to boot after the execution of the first module (BUP).
Therefore Intel ME:
- checks the partition signature: valid
- finds the BUP module and checks its hash: valid
- executes BUP
- at this point the system can boot correctly, without the 30-min window
- finds the following module (probably KERNEL) and checks its hash: INVALID
- stops the execution
You're right, you should never trust a random guy on the Internet, but you don't have to trust me, you can check the code by yourself.
And, by the way
- most of the
me_cleaner
code is "find x and overwrite it with 0xff". - Intel ME doesn't accept unsigned code and, unfortunately, I don't own the Intel ME key
Before flashing the modified image you should understand the implications of such modification. First you should understand that this tool does not reimplement anything, it only wipes parts of a basic component of your processor, so keep in mind:
- Currently
me_cleaner
DOES NOT work on platforms with Intel Boot Guard inverified boot
mode, see here - Even if this tool has been tested with your system, it does not mean that this modification is safe, so be prepared for a brick!
- Intel ME doesn't only provide some services (that you may or may not use), but it also does low-level stuff (like silicon workaround, thermal management, fan control...). Luckily, no user has reported any side effect so far (as many of these features aren't used anymore or they are implemented by something else).
- Often the ME region is not writeable by software: in these cases you need an external programmer to write the modified firmware.
Even if it sounds dangerous, once you have a valid backup of your ROM and a way to reprogram it (external flasher, dual BIOS...), you should be safe.
Great! You can follow this guide if you want to try it.
Please report the success on #3 (even if it's already listed in the status page).
You can use intelmetool
from the coreboot repository:
$ git clone --depth=1 http://review.coreboot.org/p/coreboot
$ cd coreboot/util/intelmetool
$ make
$ sudo ./intelmetool -s
On my platform (Thinkpad X220T with coreboot) it shows this.