kkamagui / bitleaker

This tool can decrypt a BitLocker-locked partition with the TPM vulnerability
Other
187 stars 35 forks source link

V1 Steps? #3

Closed roboknight closed 4 years ago

roboknight commented 4 years ago

Hi. I was asking before about V1 code. I modified your code to use either the V1 or the V2 code depending on which key you press at boot time. I've been working on trying to get the script to work. I've been able to get most of the pieces, but I wanted to find out if there was a SHA1 that needed to be used for the signature? I've checked a few things (I monitored the LPC bus, and checked against the data you recovered). And I still seem to be missing something, as I get all the way to the Unseal command and it fails. I can't give you direct logs or anything now because I don't have the system available. Unfortunately, I don't have a compiler handy to compile PCRTool, which I believe would be helpful, but I can't find an executable, just source code (I can't compile on my target. No compiler). Also, it seems that there might be more things sent to the TPM than got logged. Maybe there is another way to check this Windows TPM logs?

This isn't really a bug, but there didn't seem like a better place to put this.

roboknight commented 4 years ago

kkamagui, Do you happen to have the python script that worked with V1 of the TPM spec? The Dell Inspiron that I have uses an fTPM that supports TPM 2.0, but the data is in the V1 format. I fixed the bitleaker-grub (well, you already had the code there), and I DO have a V1 setup somewhere I think, but I need to find it. I haven't looked through the git repo to see where the python script might have already supported V1.

kkamagui commented 4 years ago

Hi @roboknight , Unfortunately, I haven't added the V1 format support feature. First of all, I should find a machine that uses the V1 log format. If I have the machine, I will start the work. :) Thank you for your patience.

roboknight commented 4 years ago

@kkamagui, I've been working on it because everything I run across seems to support SHA1 instead of the SHA256 of the V2 log. Your code for SHA1 (that you have with the #ifdef) does seem to work. At least as far as I can tell. I'm mainly working on how to get it to work WITH that log. I MOSTLY have the support in python, but I'm running into a couple of issues. And now I've seemed to kill my test platform, so I'll have to attempt a rebuild tomorrow. I don't know how that happened, but I got the stupid DELL StartupAssist or SystemAssist or something and it doesn't boot Windows. I have another device, so I'm going to pull files from that and see what I can do.

roboknight commented 4 years ago

I should also add that I also converted things to python3 because I use that (mainly because I don't know when python 2 support will die. Maybe never, but they keep trying to kill it).

roboknight commented 4 years ago

Okay, I'm finally getting to compare my TPM monitoring with what you produced. I have a question about TPM_Unseal. It appears, if I read my data correctly I have the following (note, all SHA1 hashes): Extend PCR7x5 Extend PCR0-7 (with the same hash) Extend PCR5 Extend PCR4 Extend PCR7 TPM_Get_compatibility PCR Read PCR8 (I have to double check which PCR it is, but it has a return value of all 0s, so I figure it has to be 8 because it is the only thing that makes sense) NV_Read NV_Increment NV_Read ReadClock NV_Read NV_Increment NV_Read ReadClock ReadPublic Load GetRandom StartAuthSession (Use random value here... I guess you just picked something for this) GetRandom PolicyAuthValue PolicyPCR Unseal (Use Random value here and some other hash that I don't recognize)

So, on the last Unseal command, do you NEED the random value do you know? Also, I can not figure out what the OTHER hash-like data is... The command looks like this:

80 02 00 00 00 43 00 00 01 5e 80 00 00 01 00 00 00 31 03 00 00 00 00 14 66 f9 f5 3a 9d 37 50 9b 0b 46 c3 b6 e5 fd 26 c0 02 ca 71 1e 00 00 14 3d 4c c8 c8 1f 08 e0 d0 eb 4e 23 31 83 a7 ce a5 a5 c6 e3 4e

The FIRST 0x14 byte value is the random value from the previous GetRandom. So I guess that doesn't matter. But what is the second 0x14 byte value? I think that MAY be where my unseal is failing. I've checked the remainder of my data, and it all appears to be good. I checked all the remaining data and it works okay. The only possibly problem I might have is that tpmtcticlient doesn't seem to work. I have resorted to using the actual TPM commands I need. I'm hoping they don't add anything to the TPM commands. I have been able to get your code to load and "watch" my fTPM (the info above was from another system using the SHA1 hashing scheme, and it seems like the steps are all the same. Just the data is different, of course). I was looking for another way to send raw TPM commands, but I can't find one other than tpmtcticlient. Anyway, I was hoping you might know what that other value is.

kkamagui commented 4 years ago

Hi, @roboknight , It's a little bit different from my test result. Maybe your system uses TPM 1.2. According to the TPM 1.2 spec, it seems the 9th parameter, parentAuth.

Screen Shot 2020-09-11 at 18 30 52

If then, is it also the static value, right? Because your parent handle is always the same value as 0x80000001 or 0x40000001. So, if your PCR values are the same as good PCR values and you succeeded to call TPM_PolicyPCR, then TPM_Unseal also should be succeeded.

Best regards,

Seunghun

roboknight commented 4 years ago

The example I'm working on right now is a DELL Inspiron 15" ... I don't have the model number available, but your tool for detecting the vulnerability works. I'm trying to figure out now what I need to generate a Bitlocker key. I haven't been working on it in the past month, but it definitely is something vulnerable. Actually, many of the devices I've run across all use the V1 log format (from what I can tell. Unless there is something wrong with the V2 code that causes a crash, but I don't think this is the case because I put in what you had for V1 (switching the

IFDEF) and it seems to work. I have a version that lets you choose with a

keypress at run time, but I figured out it is better to not use that version.

My problem currently is trying to make it work using a thumbdrive that appears "signed". I THINK everything runs okay, but I need to verify the TPM register values because I don't get a valid Bitlocker key. My goal is to have a Thumbdrive that is "signed" that can run all of the code to get the keys. I started with the Linux signed SHIM, but I think something goes wrong because on the DELL, it seems to detect no signing at some point and things don't always run and I end up in the Bitlocker Recovery Key state. I'm trying to figure out how to avoid this. But, after I get past this point, I still don't know all the proper values that Microsoft puts into the TPM to generate a Bitlocker key for V1. There is a fixed value that you have (I think it is the signed hash for the Microsoft bootloader) and I've been trying to figure out what it is for V1. But until I solve the boot problem, I can't determine the value. I would monitor this value (as I can monitor the LPCBus), but on the DELL it doesn't help because they use an fTPM (which, from the BlackHat talk this year, I'm guessing is an ARM processor inside the X86 chip. At least this is how AMD does it. I don't know if Intel does the same, or if they use some old x86 microcontroller architecture within their larger System On Chip (SoC)). At any rate, it means I cannot monitor the LPCBus on these chips.

Thanks for getting back to me, by the way. I'm sorry I cannot communicate back in your native language. I only know a bit of Spanish, some Italian, and a few German words. Your english is excellent, and I'm glad of that, but I can imagine that reading long english e-mails isn't always the best.

Hope you and your family are well. Best Regards,

Roboknight.

On Tue, Jul 28, 2020 at 1:15 AM Seunghun Han notifications@github.com wrote:

Hi @roboknight https://github.com/roboknight , Unfortunately, I haven't added the V1 format support feature. First of all, I should find a machine that uses the V1 log format. If I have the machine, I will start the work. :) Thank you for your patience.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/kkamagui/bitleaker/issues/3#issuecomment-664781584, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABQ757BSY2LDZCMSYC3WKTR5ZNFJANCNFSM4LGDUMBQ .

-- Those who can, do. Those who can't manage those who can.

Life is a Xerox copy. Quick someone add more toner!

roboknight commented 4 years ago

I have FINALLY been able to get bitleaker to boot a Bitlockered version of Windows. That was much harder than it should of been. I think I had made several stupid mistakes. Now that I have that worked out, I have an entire run of commands it should have sent to the TPM. I think I may have a slight issue though. I'm not entirely sure yet (and I'm not quite sure how I can track this down), but it might be possible that booting internally is different than booting from a thumbdrive. I did note, that while I was doing my first windows test, I recorded (with a webcam, since I didn't have an easier logger), several things. When I switched thumbdrives, I saw PCR 1, 4, and 7 change. 1 and 4 of course don't matter, but 7 does. I also notice that 11 doesn't really matter either (despite what bitlocker says) because 11 isn't set. I think 11 might be reserved for booting the recovery partition as bitleaker shows me a whole bunch of things get recorded to PCRs 11-15. Then I'm in the recovery (if bitlocker with TPM was flagged and I don't provide the recovery key). So I'm trying to nail down how you determined the last extend of PCR 7 was the SHA256 Cert value, because if I need a SHA1 cert value, I need to see which one. There are only 2 I can see, the PCA cert, and the other cert. There are several values that get played into PCR 7, but I only know the values when I booted through bitleaker, which might also change PCR 7. That's what I'm trying to narrow down. I think if I could get through that last bit, I might have everything nailed down for V1.

roboknight commented 4 years ago

Okay, my last boot gave me this value for extending PCR 7:

9f c7 13 b7 24 8d 99 a1 a0 db 3d 50 c1 4e b9 b4 ff 27 07 21

Is there any way I can check this against the bootmgfw.efi cert (assuming its a SHA1 hash of that)? I've been trying to check it, but nothing seems to match. I can actually verify this hash across devices (have done, actually) and that must be the hash. There are 5 constant hash results (I am presuming they are all sha1 hashes, they may not be) and 2 that are system dependent (presumably dependent based on some different measurement).

kkamagui commented 4 years ago

Hi @roboknight ,

I am very impressed with your work. You did a great job and almost succeeded! Actually, I found out that the last PCR 7 value was Microsoft Production PCA certificate due to reverse engineering of bootmgfw.efi. And if you got the PCR 7 with Bitleaker, the value might be a hash of the UEFI CA certificate, not the Microsoft Production PCA, since you booted with Shim and Bitleaker. Shim was signed by the UEFI CA certificate, so UEFI firmware verified it with UEFI CA and send a hash of it to the PCR 7.

If you want to have the sha1 hash of Microsoft Production PCA certificate, the easiest way is to boot with bootmgr.efi and get the measurement log from Microsoft Windows. Windows also has the measurement logs and saves them. You can get it with PCP toolkit made by Microsoft. As you know, Microsoft Production PCA certificate is everywhere that can support Secure Boot, so you can get it from other PCs. Additionally, the value is the same. :)

If you want to know detailed information on it, please check my Black Hat Europe 2019 presentation.

Best regards,

Seunghun

roboknight commented 4 years ago

Hey! Thanks for the info. I'll have to see if I can work out how to hash the value of the PCA cert. I actually have a different method of verifying the hash. I had a microsoft surface that I had clipped to the TPM on. It used the same TCG 1.2 that this Dell is using. It turns out that there are 7 hashes that get extended into PCR 7. 5 of them are the same between systems, I believe whether I boot the shim or not (the value I posted above was the same between the "clipped on" monitoring and bitleaker monitoring, so I think that one didn't matter. But there are 2 other hashes that might be an issue, as those differ between systems). I was using a webcam for monitoring because bitleaker conveniently puts out the ACTUAL command that is sent (just as if I was "hard monitoring" the TPM chip. I wanted to see the command formats because I think I'm going to need that later. The stupid issue I really kept running into with windows is that I wasn't properly setting the root variable for grub, so it couldn't find BCD. Once I fixed that, things booted. I'm unsure what the two hashes that actually change in PCR 7 are. But those I'm not worried about because I believe that your technique basically solves that issue. My problem now is that I need to try to fix up bitleaker so that it can hand TCG 1.2. This is where I'm not sure if TSS 2.0 is going to work or not. There were some tools you were using to send actual TPM commands (I believe, without modification), and I might have to use that. But now that I've verified the format, double checked the hashes and all of that, I think I might be able to do it.

roboknight commented 4 years ago

Okay, I have FINALLY been able to successfully compile (why they don't provide some executable for PCPTools is beyond me) PCPTools. I was having issues because I keep trying "PCPTool GetVersion" and that always returns an error code 0xd0000225, which I could not track down. It is apparently a "customer" error code according to the high bits. Anyway, it didn't matter. If I had just TRIED "PCPTool GetPCRs" it would have worked. It demonstrates that PCRs 0, 2, 3, 5, 6, and 7 all match up perfectly. PCRs 1 and 4 don't seem to match. PCR 4 might be because there MIGHT be an extra extend you are ignoring, but I need to really check that to be sure. Even so, I don't believe it matters. So that leaves it all down to those last few commands. So, I'll have to do a TPM1 Load. This changes because its shorter by a bit (0xd3 in length instead of 0xf7). TPM1 Start Session is only different in hash type, which I think is pretty easy. TPM1 PolicyAuthorize should be the same (identical). You mentioned that the second hash from PolicyPCR is likely to be fixed. So I'm going to go with that. That leaves one final unknown hash. The Unseal command has the random value from a previous GetRandom. But then it ALSO has a hash at the end that I cannot seem to determine. I need to find the "page" for TPM Unseal for TCG 1.2 to see what that parameter is supposed to be. But I believe that pretty much accounts for everything. So I believe, if I can figure out what that last hash is, then I should be generating keys for TCG 1.2 interfaces.

As a side note, I also updated your Python script to Python3. Now that I have a solid method for building LiveCDs though, I probably didn't need to do that.

roboknight commented 4 years ago

Okay, now I'm at a hard stop. I'm trying the first command "tpmtcticlient -i tpm1_load.bin" ... but I end up with an error 0x18b, which says "the handle is not correct for the use". It appears I only have PCR1 wrong. I don't know if I actually NEED PCR1 to be right in order to use the handle I want to use with the command (0x157 -- TPM Load). I originally had PCRs 1 & 4 incorrect, but there is a value that gets loaded after the LAST PCR7 value, so I loaded that into PCR4 and then PCR4 matched. But I don't actually know what "the handle is not correct for the use" means. If it means that PCR1 is wrong, then I have a problem because PCR1 ALWAYS seems to be wrong. I'll check to see if my "video" of the system booting will help, but I don't know if I'm out of luck.

roboknight commented 4 years ago

Okay, its been a long time getting my head wrapped around this, but I've been able to verify the policypcr hash value. It also appears all the "bits" in the policypcr check out. It looks like I really do have TPM2.0, but it is still using SHA1 instead of SHA256. So all of your steps seems about the same. I don't know why the "Load" command isn't working, but I think the error I'm getting trying to run the "load" is because I have to do a tpm2_createprimary. Once I do that, I may be able to load it. So all of your hard work seems should still apply directly, but until I can create everything and get that golden key, I'll have to keep plugging away. At least I've been able to verify the dislocker data agains the PCR replay. So I know it should work. I think I just have to figure out how to create the right object so I can load the data into it and unlock it.

roboknight commented 4 years ago

I don't know if I'm dead in the water or not. It looks like the registers in the Intel fTPM get "corrupted" when they get into that state. I tried sending tpm2_startup -c and tpm2_selftest -f but it doesn't seem to help. I don't know if they've added something to the code that makes it so you can't use any of the registers, but I noticed that when I run tpm2_nvreadpublic it doesn't allow me to look at any of the non-volatile registers after BitLeaker has run. Before BitLeaker runs, I can see and do a lot. Its almost as if the PCRs are reset, but the who fTPM itself didn't reset. But it isn't allowing me to load any data. I know I was able to play back the registers mostly correctly. There is a small issue with one of the registers (register 4) that also has some stuff. The only register I can't figure out is PCR1. I can't ever seem to make that one match, but I think that might be because I've booted from a Thumbdrive. But I can still use the TPM BEFORE I run BitLeaker.

roboknight commented 4 years ago

I've finally figured it out. It seems that the TPM had one last trick up its sleeve with the "orderly" flag. If the TPM clears this flag (which BitLeaker causes it to do), then you are pretty much hosed, unless of course you just shut the TPM down again. And it doesn't matter if the TPM restores a zero state. So I updated the script to accomplish this. I guess the TPM can now go off all drunk and disorderly and give up its secrets. Anyway, thanks kkamagui for taking the time to look at my posts. Sometimes it just helps to "type things out"...

kkamagui commented 4 years ago

Hi @roboknight ,

Congratulations! Finally, you made it! It's a long and thrilling journey and more than just changing sha256 to sha1. I also see your contribution, and I am reviewing your work. Thank you, and I will merge it after reviewing it.

Have a great day!

Seunghun

roboknight commented 4 years ago

I am fixing a few things at the end. I built a LiveCD with Cubic (an AWESOME tool! It let me take Ubuntu 18.04 and customize things). So I now have a thumbdrive needing no authorization, that I can plug into a system and it has ALL the Bitleaker things. Again, thanks for doing most of the heavy lifting on this. It is a really elegant Replay solution. I like "soft touch" solutions (though I have used "teardown solutions" many times). At any rate, I think I still output a bunch of junk that I don't want to output, so I'm still cleaning that up, but I figured you might like to look at it anyway.

On Tue, Oct 27, 2020 at 10:26 PM Seunghun Han notifications@github.com wrote:

Hi @roboknight https://github.com/roboknight ,

Congratulations! Finally, you made it! It's a long and thrilling journey and more than just changing sha256 to sha1. I also see your contribution, and I am reviewing your work. Thank you, and I will merge it after reviewing it.

Have a great day!

Seunghun

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/kkamagui/bitleaker/issues/3#issuecomment-717654237, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABQ757WRXGQMJNGTNHVSKTSM56N7ANCNFSM4LGDUMBQ .

-- Those who can, do. Those who can't manage those who can.

Life is a Xerox copy. Quick someone add more toner!