Based on the amazing me_cleaner, parses the required signed partition from an ME update file to generate a valid flashable ME binary.
This was written for Heads ROM to allow continuous integration reproducible builds for Lenovo xx20 models (X220, T420, T520, etc).
usage: me7_update_parser.py [-h] [-O output_file] file
positional arguments:
file ME/TXE image or full dump
optional arguments:
-h, --help show this help message and exit
-O output_file, --output output_file
save save file name other than the default
'flashregion_2_intel_me.bin'
- Download an intel ME update from Lenovo, the latest version as of November 2020 is
7.1.91.3272
contained in83rf46ww.exe
:
wget https://download.lenovo.com/ibmdl/pub/pc/pccbbs/mobiles/83rf46ww.exe
- Using innoextract, unpack
83rf46ww.exe
innoextract -I app/ME7_5M_UPD_Production.bin 83RF46WW.exe
- Run the script:
python me7_update_parser.py app/ME7_5M_UPD_Production.bin
The result is a file flashregion_2_intel_me.bin
- me_cleaner
- Igor Skochinsky - Rootkit in your laptop - Breakpoint 2012
- Igor Skochinsky - Intel ME Secrets - RECON 2014
- MEAnalyzer
- dump_me
- me.bios.io ME_blob_format (Wayback Machine link)
me_cleaner.py works by using the partition table to determine what information exists and what can be removed. Unfortunately, the ME 7.x update file only contains the data required to update; which does not include a partition table. Additionally, it modified the file directly. The locations of the partitions in the update file do not correspond to the stock file so add a partition table will not be enough.
We must work backwards. Using a valid ME partition from a stock BIOS,
me_cleaner.py
outputs a minified cleaned blob. Inspecting this blob, we see
there is only one remaining partition, FTPR
or "Factory Partition". In the
update binary, this partition is found at offset 0x00000
and has the same
length as the FTPR
in the ME partition from a stock BIOS, 0x76000
. While
the offset in the update file is 0x00000
, the offsets within this are
relative to the location in the stock file. The same functions that
me_cleaner.py
uses to strip the unnecessary parts and relocate required
remainder from a full ME blob have been copied and modified to work with an in
memory copy of the FTPR
partition and hard coded offsets to mimic a full ME.
Only the partitions are signed.The partition table is not signed and can
be generated. Between information found on me.bios.io ME_blob_format (Wayback Machine link), MEAnalyzer source code and Igor Skochinsky's presentations (Rootkit in your laptop - Breakpoint 2012
and Intel ME Secrets - RECON 2014) the values of the me_cleaner.py
output are
associated with fields. The values of fields, in combination with the output
from the modified me_cleaner functions, are written to a file. The value at
address 0x00039
is set to 0x00
, at which point the file now can pass the
verification function that was copied from me_cleaner.
Offset | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x00 | ROM BYPASS INSTR 0 | ROM BYPASS INSTR 1 | ROM BYPASS INSTR 2 | ROM BYPASS INSTR 3 | ||||||||||||
0x10 | "$FPT" | # of partitions | Version |
Entry Type |
Length |
Checksum |
Flash Cycle Life | Flash Cycle Limit | ||||||||
0x20 | UMA size | Flags | FIT Minor | FIT Major | FIT Hotfix | FIT build |
Offset | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x30 | Entry Name | Entry Owner | Entry Offset | Entry Length | ||||||||||||
0x40 | Start tokens | Max tokens | Scratch sectors | Entry Flags | ||||||||||||
0x50 - 0x400 | (blank filled with 0xFF) |
The remainder of the file is the cleaned signed and minified FTPR
partition.
ROM BYPASS INSTR 0
-ROM BYPASS INSTR 4
: unsure what these values do or if they are required. May try replacing with0x00
or0xFF
.Header flags
: unsure of what the correspond to.Entry Flags
: correlate to ExclBlockUse, Execute, Write, Read, DirectAccess. Not sure if any of these can be changed/disabled.- Why does the value at
0x00039
need to be changed to0x00
? That has been tested with multiple ME update versions.