Intel (Converged Security) Management Engine: Drivers, Firmware and Tools (2-15)

This would be my fault. If the size of ME region is between 0x17D000 and 0x1FFFFF, I assumed it is ME 1.5 and cut it at 0x17D000, without checking if the rest is actually padding. This worked for the firmwares I had until now, so I was lazy to do a proper check. But now I added a check of the padding, to at least avoid cutting useful bytes and extract the full region if the padding is not empty. I should work on a proper size checking and extraction, but I remember that some ME firmwares have a different base for calculating the offset of modules, so that is why I ignored it for some time. Other ME firmwares are unaffected, because I extracted the entire region as is.

What is strange is that we have Skylake before a proper release of Broadwell. Have they screwed that bad or just not enough reasons (competition included) to release it in time? At least he have a chance to support Skylake from alpha stages.

@lordkag

Have you taken a look at the very-early Skylake ME11? It’s very different, structure-wise. I can’t even add it to ME Analyzer for now. ME Analyzer determines the SKU based on the actual $SKU manifest. This also prevents similar situations to what happened above, there is no way you can confuse 5MB firmware for 1.5MB and vice versa.

Capture.PNG



Also, Skylake is supposed to be released at the end of 2015 or something whereas desktop Broadwell in summer. The releases are close either way. Most probably this ME11 firmware is a very early build. The date is not even a month old!

EDIT: Could it be that the $MN2 manifest is now structured similarly to FPT? So, it shows the starting offset & length of the sub-regions to follow? Not sure because if I follow the offsets they don’t really make sense.

Capture2.PNG

The modules have sub-modules with a similar header as the main ME header?

ME_11.png


Ha,ha - we said the same thing. Check my edit.

Thing is, if you follow the offsets they lead "nowhere" sane.

Also, I could add ME Analyzer to your Extractor if you like. The way you have it now with "file mef"

I see you are using your mind reading ability again. Shame on you!

Now to being serious. It seems that way: name + offset + size + function + something else.

Edit: but they do. The base is the module start. Check again how the sub-modules are formed.

Here is an example:

ME_11_v2.png



No, ME Analyzer needs its special place. You worked hard on it. There is not point for me in doing the same thing (and doing it worse, for that matter). My only need is version, date is size.

It’s backwards, so it should be Name + something + offset + size

The length seems to always be the same (11 00 00 00) which is 0x000011 bytes.

For FTPRloadmgr, the offset should be 01 00 01 00 or 0x010001 but if you go there:

Capture.PNG



EDIT: Mmm, I didn’t see right. The size differs. Unless I messed something up.

EDIT2: Saw your previous edit, I got it the wrong way.

It seems to be name [0xC] + offset1 [4] + size1 [4] + reserved [4] + next [0xC] + offset2 [4] + size2 [4] + reserved [4] ?

Replace offset with pointer to be more accurate.

Actually I was talking about the offsets after $MN2 manifest. These ones are structured almost identically to FPT header. What you showed me is $CPD. Previously after $MN2 we would see $MEUpdate etc…

Oh, the .met are the ones that we are interested at. It’s confusing with all the text in between.

What’s the 2nd offset & 2nd size for?

EDIT: Yes, offset or pointer we mean the same thing here. :slight_smile:

By looking backwards, the second pointer is not needed.

ME_11_v3.png

After MN2 seems to be similar? Name [0xC or 0xE] + [FFFF or 0000FFFF] + size [4] + SHA256.

ME_11_v4.png



The size is the same as the one from the main module header.

MN2 yes. Before that: So for example, by going backwards: touch_fw.met points to BE 21 00 00 ? (before 2nd $MN2)

Capture.PNG



For me backwards or not, it looks the same. Some other .met are larger though.

Taking touch_fw.met as example:

- begins at start + 21BE, size = 10E.
- select block 1091BE - 1092CB.

You don’t need to go backwards literally. Of course they are parsed in order, but that was to point that each sub-module header takes 0x18 or 0x30 if they need the .met part.


Oh, start! I thought start was 0x0 (like FPT, what was I thinking…) but it’s $CPD - got it! :slight_smile:

Question now is how are going to find any meaningful info in there like SKU which is important.

EDIT: Only the 1st $MN2 keeps pointers, sizes etc. The 2nd looks like before.

Maybe plat_n_sku and bup_sku?


I searched for the string SKU as well but it’s different from the previous SKU formats. I’m not sure.

bup_sku = BringUp SKU

Mmm, where the sku strings are: I think each section starts after

Capture.PNG



So:

00 00 00 00 80 01 01 00 00 00 03 –> plat_n_sku
00 00 00 00 00 44 43 00 00 C0 13 01 00 00 00 03 –> bup_sku

I don’t know. Maybe plat_n_sku. I’ll check the length of the previous SKUs.

EDIT 1 : 04 00 00 00 C0 BA 11 F1 13 22 00 00 –> ME10 (size [4] etc)

EDIT 2 : Nah, the image is wrong. Doesn’t make sense.

EDIT 3 : Platform_SKU may be the FITC Emulation SKU (the drop-down list at the top) - just a guess

@Pacman @lordkag

I was wrong. The ME11 firmware is not ROM-Bypass, not Pre-Production but actually Production.

It seems that in the new ME firmware structure all partitions are accounted for at the Flash Partition Table ($FPT) header. However, those that are missing do not have a pointer or size. Also, the empty/missing partitions are signified by the 00 00 00 FF flag at the end. I don’t know why this flag is not set for the last empty partition though which is 00. Here:

Capture2.PNG



To be certain, I manually extracted & cut all partitions from the ME11 firmware to detect any remaining parts. Of course the resulting file is 315KB (0x4EE00) and consists of the $FPT header (0x190) and FF padding (0x4EC70). There is no ROMB inside and nothing else for that matter. The partitions that include data/code are FTPR, NFTP = FTUP & MFS. The partitions PSVN, IVBP, FLOG & UTOK exist but are empty (FF padding). The partitions DLMP, ROMB & ISHC are missing from the image (no pointers & size). All the files are attached below for anyone interested.

Capture4.PNG



Also, the $MN2 manifest headers have the Production-Signed flag of 00 00 00 00 so the image can be neither Pre-Production nor ROM-Bypass (00 00 00 80 flags respectively) as I originally claimed.

Capture3.PNG



ME Analyzer is now able to detect empty/missing ROMB partitions but it’s not released yet because I cannot figure out where the SKU is mentioned. I apologize for any misinformation given earlier. The structure is new so I wasn’t expecting that change.

Capture.PNG



Since the ME11 firmware we have is Production, it can be added to this thread as well.

Updates:

NEW! ME 11.0 Consumer Firmware v11.0.0.1120

Source: Station-Drivers

Warning: This firmware’s targeted platform is Skylake. Since Skylake is not even released yet, it’s provided here for research purposes.

Note: ME Analyzer has not been publicly updated to properly detect ME11 firmware yet. Any errors & notes reported are normal.

ME11_Partitions.rar (1.19 MB)

So there can be empty partitions and also present, filled with padding? I thought that this was a signed that the base for pointer is not the FPT header, but something else. I trust your judgement and analysis, though. This probably happens with all those images that I thought are using other base for pointer calculation.

One suggestion: the flag is not a byte [0x80], but a single bit = 0x80 - 0b10000000. So to test this and also be future-proof for any new property added to that byte, test with "if test_prod & 0x80 : is PRE/ROMB", where test_prod is that byte containing the flag.


We already had partitions that are present but filled with padding. A quick way to check that is to use Igor’s me_unpack tool for ME2-ME10.0 firmware. ME11 does not work due the different structure so I had to do it manually.

But I haven’t seen a missing (but mentioned at $FPT) partition before. The logical conclusion is that. Truth is, until we have a ME11 firmware that we know for sure that it’s Production, I may be wrong. But I don’t think so, the $MN2 flag at the header (which seems to be the only thing that hasn’t changed) also hopefully proves my point.

According to Igor’s notes/presentations, the ME firmware has a lot of jumps to code that is not available at the SPI image. Those jumps go to the bootrom, kernel or whatever is stored at the actual ME co-processor. To save space, the rest of the code is stored at the SPI flash image. The whole purpose of ROM-Bypass though is to keep all code (including the one inside the ME co-processor) at the SPI image due to early/buggy silicon. That way they can bypass any faulty hardware and test needed changes with ROMB firmware. So in theory ROMB does not have any jumps? I don’t know. When you mentioned "base for pointer calculation" those "jumps" came to mind but I highly doubt it has anything to do with what were are looking into right now ($FPT, $MN2 headers). Those jumps must be elsewhere and I don’t have the knowledge/experience to track them down. Thankfully we have Igor for that.


You lost me here. I assume you are talking about ME Analyzer and how it detects the PRD/PRE/BYP flag? We know that the flag consists of 4 hex bytes. The last one in which we are interested in (0x00 or 0x80) is a byte which when converted to 8 bits in binary we get 0b10000000 (or 10000000b). I assume you meant 0x80 = 0b10000000 and not subtraction (-). Still, how is that a bit?

The command you wrote, is it a different "if" format? My python knowledge is kind of crappy.

Keep in mind that the release flag is not the same for all $MN2 headers around the firmware. You may find at one $MN2 header a flag of 04 00 00 40, 00 00 00 C0 or something like that. However, the rule of thumb is that if you find a flag 00 00 00 00 the image is Production-signed whereas if you find 00 00 00 80 it’s Pre-Production or ROM-Bypass. This applies to whole firmware images no matter how many different $MN2 regions exist.

Then all those 4 bytes are used for image attributes, but only the last one is for production type. Yes, it should have been 0x80 = 0b10000000. But the thing is, only the first bit from the left or MSB is important for release type. So, when you test, you test that bit alone and ignore the full byte. Using bitwise operators you can target that bit alone. For MSB you use “ord(byte) & 0x80”, which results in 0x80 if MSB is 1, or 0 if MSB is 0.

0x40 & 0x80 = 0, 0xC0 & 0x80 = 0x80. It is still a regular “if …” statement, but any value different than 0 is considered true, while 0 is false.