本文通过动态调试方式,深入分析Windows系统中,TPM(TPM2.0)解封BitLocker密钥过程。
本次BitLocker + TPM磁盘加密的PCR为PCR 7,11(启用了SecureBoot的默认配置)。
调试环境搭建
调试环境使用IDA + GDB + VMware远程调试方法,配置方法参考之前写的Blog文章Bitlocker密钥提取之bootmgfw调试
开始前,需要从VMware虚拟机中的Windows系统中,导出一份待分析bootmgfw.efi模块文件,文件路径如下:
\EFI\Microsoft\Boot\bootmgfw.efi
后续将静态分析该文件,找到需要断点的位置。
然后需要同时开启2个IDA环境,一个用于负责静态分析bootmgfw.efi模块,一个负责动态调试跟踪bootmgfw.efi模块的运行。
因为动态GDB调试下,IDA中不显示符号,不方便查看调试代码,因此需要一个静态分析的环境,结合偏移地址来动态调试、查看内存数据。
分析发送TPM命令的函数
通过分析得到发送TPM命令的函数如下图:

函数参数如下图:

参数内容如下:

参考开源代码:ntos-boot
设置TPM发送命令断点
先将虚拟机启动到如下界面位置(启动虚拟机系统时,按F2),在此状态下,bootmgfw.efi模块尚未加载运行。
然后在负责动态调试的IDA中,附加(Attach)远程GDB调试。

根据上一步分析得到的函数EfiTreeSubmitCommand的地址,配置IDA调试环境下,添加调试断点,如下图所示,选择硬件断点(Hardware)

设置调试配置选项,禁用ASLR功能,这样保持静态分析的地址和动态调试的内存地址相同,方便跟踪查看调用堆栈和内存数据,配置如下图:

一切设置完成后,按F9运行继续运行,在VMware虚拟机中选择"Boot Normal"启动Windows系统,很快停在IDA的断点处。
设置查看内存数据
在Hex View-1中设置同步R8寄存器中的值(即参数a3),用于查看发送的TPM命令具体的数据内容,设置方法如下:

同时,记录下a5参数(TPM响应数据)地址,按Ctrl + F7执行到函数返回,查看TPM响应数据。
下图是按Ctrl + F7执行到函数返回时的参数a5,即TPM命令执行后的响应数据。

格式化TPM命令和响应
上一步得到是TPM的命令和响应数据的二进制数据,不方便查看,这里推荐使用tpmstream工具解释TPM二进制交互数据。
也可在线使用tpmstream工具进行查看,分别粘贴TPM命令和响应数据,该在线工具将自动识别、解释数据内容,如下图所示:

TPM解封过程
通过调试分析得到的主要TPM交互流程。
TPM_CC.PCR_Read SHA256 PCR0~7
bash
Command
TPMI_ST_COMMAND_TAG | .tag 8001 TPMI_ST_COMMAND_TAG.NO_SESSIONS
UINT32 | .commandSize 00000014 20
TPM_CC | .commandCode 0000017e TPM_CC.PCR_Read
TPMS_COMMAND_HANDLES_PCR_READ | .handles
TPMS_COMMAND_PARAMS_PCR_READ | .parameters
TPML_PCR_SELECTION | | .pcrSelectionIn
UINT32 | | | .count 00000001 1
TPMS_PCR_SELECTION | | | .pcrSelections[0]
TPMI_ALG_HASH | | | | .hash 000b TPMI_ALG_HASH.SHA256
UINT8 | | | | .sizeofSelect 03 3
list[BYTE] | | | | .pcrSelect ff0000 ...
Response
TPM_ST | .tag 8001 TPM_ST.NO_SESSIONS
UINT32 | .responseSize 0000012c 300
TPM_RC | .responseCode 00000000 TPM_RC.SUCCESS
TPMS_RESPONSE_HANDLES_PCR_READ | .handles
TPMS_RESPONSE_PARAMS_PCR_READ | .parameters
UINT32 | | .pcrUpdateCounter 00000060 96
TPML_PCR_SELECTION | | .pcrSelectionOut
UINT32 | | | .count 00000001 1
TPMS_PCR_SELECTION | | | .pcrSelections[0]
TPMI_ALG_HASH | | | | .hash 000b TPMI_ALG_HASH.SHA256
UINT8 | | | | .sizeofSelect 03 3
list[BYTE] | | | | .pcrSelect ff0000 ...
TPML_DIGEST | | .pcrValues
UINT32 | | | .count 00000008 8
TPM2B_DIGEST | | | .digests[0]
UINT16 | | | | .size 0020 32
list[BYTE] | | | | .buffer 1e95a64323960a3e88157eafb63fb23189ecbc60a7b06170e47aaabdd895c294 ...C#..>..~..?.1...`..ap.z......
TPM2B_DIGEST | | | .digests[1]
UINT16 | | | | .size 0020 32
list[BYTE] | | | | .buffer 3d458cfe55cc03ea1f443f1562beec8df51c75e14a9fcf9a7234a13f198e7969 =E..U....D?.b.....u.J...r4.?..yi
TPM2B_DIGEST | | | .digests[2]
UINT16 | | | | .size 0020 32
list[BYTE] | | | | .buffer 3d458cfe55cc03ea1f443f1562beec8df51c75e14a9fcf9a7234a13f198e7969 =E..U....D?.b.....u.J...r4.?..yi
TPM2B_DIGEST | | | .digests[3]
UINT16 | | | | .size 0020 32
list[BYTE] | | | | .buffer 3d458cfe55cc03ea1f443f1562beec8df51c75e14a9fcf9a7234a13f198e7969 =E..U....D?.b.....u.J...r4.?..yi
TPM2B_DIGEST | | | .digests[4]
UINT16 | | | | .size 0020 32
list[BYTE] | | | | .buffer 5fb38f2d1eb31dd33b0981718bec502207f335b0fcb0fee9cea9efa4f78a830a _..-....;..q..P"..5.............
TPM2B_DIGEST | | | .digests[5]
UINT16 | | | | .size 0020 32
list[BYTE] | | | | .buffer af86209361c45b455a3b1a8765af470df7c00545965e0daee40cf0a5cf0d2271 .. .a.[EZ;..e.G....E.^........"q
TPM2B_DIGEST | | | .digests[6]
UINT16 | | | | .size 0020 32
list[BYTE] | | | | .buffer 3d458cfe55cc03ea1f443f1562beec8df51c75e14a9fcf9a7234a13f198e7969 =E..U....D?.b.....u.J...r4.?..yi
TPM2B_DIGEST | | | .digests[7]
UINT16 | | | | .size 0020 32
list[BYTE] | | | | .buffer baee51c2e2e40e18641abdb8827b3bd9524d8a77719ec43c239c0c5a91cd1cf8 ..Q.....d....{;.RM.wq..<#..Z....
这一步主要关注PCR7的值。
TPM_CC.PCR_Read PCR11 SHA256
bash
Command
TPMI_ST_COMMAND_TAG | .tag 8001 TPMI_ST_COMMAND_TAG.NO_SESSIONS
UINT32 | .commandSize 00000014 20
TPM_CC | .commandCode 0000017e TPM_CC.PCR_Read
TPMS_COMMAND_HANDLES_PCR_READ | .handles
TPMS_COMMAND_PARAMS_PCR_READ | .parameters
TPML_PCR_SELECTION | | .pcrSelectionIn
UINT32 | | | .count 00000001 1
TPMS_PCR_SELECTION | | | .pcrSelections[0]
TPMI_ALG_HASH | | | | .hash 000b TPMI_ALG_HASH.SHA256
UINT8 | | | | .sizeofSelect 03 3
list[BYTE] | | | | .pcrSelect 000800 ...
Response
TPM_ST | .tag 8001 TPM_ST.NO_SESSIONS
UINT32 | .responseSize 0000003e 62
TPM_RC | .responseCode 00000000 TPM_RC.SUCCESS
TPMS_RESPONSE_HANDLES_PCR_READ | .handles
TPMS_RESPONSE_PARAMS_PCR_READ | .parameters
UINT32 | | .pcrUpdateCounter 0000008a 138
TPML_PCR_SELECTION | | .pcrSelectionOut
UINT32 | | | .count 00000001 1
TPMS_PCR_SELECTION | | | .pcrSelections[0]
TPMI_ALG_HASH | | | | .hash 000b TPMI_ALG_HASH.SHA256
UINT8 | | | | .sizeofSelect 03 3
list[BYTE] | | | | .pcrSelect 000800 ...
TPML_DIGEST | | .pcrValues
UINT32 | | | .count 00000001 1
TPM2B_DIGEST | | | .digests[0]
UINT16 | | | | .size 0020 32
list[BYTE] | | | | .buffer 0000000000000000000000000000000000000000000000000000000000000000 ................................
PCR11的初始值0。
TPM_CC.ReadPublic
bash
Command
TPMI_ST_COMMAND_TAG | .tag 8001 TPMI_ST_COMMAND_TAG.NO_SESSIONS
UINT32 | .commandSize 0000000e 14
TPM_CC | .commandCode 00000173 TPM_CC.ReadPublic
TPMS_COMMAND_HANDLES_READ_PUBLIC | .handles
TPMI_DH_OBJECT | | .objectHandle 81000001 TPM_HR.PERSISTENT.000001
TPMS_COMMAND_PARAMS_READ_PUBLIC | .parameters
Response
TPM_ST | .tag 8001 TPM_ST.NO_SESSIONS
UINT32 | .responseSize 0000016e 366
TPM_RC | .responseCode 00000000 TPM_RC.SUCCESS
TPMS_RESPONSE_HANDLES_READ_PUBLIC | .handles
TPMS_RESPONSE_PARAMS_READ_PUBLIC | .parameters
TPM2B_PUBLIC | | .outPublic
UINT16 | | | .size 011a 282
TPMT_PUBLIC | | | .publicArea
TPMI_ALG_PUBLIC | | | | .type 0001 TPMI_ALG_PUBLIC.RSA
TPMI_ALG_HASH | | | | .nameAlg 000b TPMI_ALG_HASH.SHA256
TPMA_OBJECT | | | | .objectAttributes 00030472 TPMA_OBJECT.fixedTPM | TPMA_OBJECT.fixedParent | TPMA_OBJECT.sensitiveDataOrigin | TPMA_OBJECT.userWithAuth | TPMA_OBJECT.noDA | TPMA_OBJECT.restricted | TPMA_OBJECT.decrypt
| | | | | .reserved ...............................0
| | | | | .fixedTPM ..............................1.
| | | | | .stClear .............................0..
| | | | | .reserved0 ............................0...
| | | | | .fixedParent ...........................1....
| | | | | .sensitiveDataOrigin ..........................1.....
| | | | | .userWithAuth .........................1......
| | | | | .adminWithPolicy ........................0.......
| | | | | .reserved1 ......................00........
| | | | | .noDA .....................1..........
| | | | | .encryptedDuplication ....................0...........
| | | | | .reserved2 ................0000............
| | | | | .restricted ...............1................
| | | | | .decrypt ..............1.................
| | | | | .sign_decrypt .............0..................
| | | | | .sign ............0...................
| | | | | .reserved3 000000000000....................
TPM2B_DIGEST | | | | .authPolicy
UINT16 | | | | | .size 0000 0
list[BYTE] | | | | | .buffer
TPMU_PUBLIC_PARMS | | | | .parameters
TPMS_RSA_PARMS | | | | | .rsaDetail
TPMT_SYM_DEF_OBJECT | | | | | | .symmetric
TPMI_ALG_SYM_OBJECT | | | | | | | .algorithm 0006 TPMI_ALG_SYM_OBJECT.AES
TPMU_SYM_KEY_BITS | | | | | | | .keyBits
TPMI_AES_KEY_BITS | | | | | | | | .aes 0080 128
TPMU_SYM_MODE | | | | | | | .mode
TPMI_ALG_SYM_MODE | | | | | | | | .aes 0043 TPMI_ALG_SYM_MODE.CFB
TPMU_SYM_DETAILS | | | | | | | .details
TPMT_RSA_SCHEME | | | | | | .scheme
TPMI_ALG_RSA_SCHEME | | | | | | | .scheme 0010 TPMI_ALG_RSA_SCHEME.NULL
TPMU_ASYM_SCHEME | | | | | | | .details
TPMI_RSA_KEY_BITS | | | | | | .keyBits 0800 2048
UINT32 | | | | | | .exponent 00000000 0
TPMU_PUBLIC_ID | | | | .unique
TPM2B_PUBLIC_KEY_RSA | | | | | .rsa
UINT16 | | | | | | .size 0100 256
list[BYTE] | | | | | | .buffer a56abe2c8e0c4c822ac519cce8623fbb2adb03b261718985c8f62e4641eddb2600cc743061b0aafe50d0e1f57f1fbc10faff00f6a7918128ff399b7ae89a23e22afc4a85d13106c8a92fbac349e031cf824173e414416baa09b5385285ed38615ddd88b8c9f7308374bf9f5815d2d18ff9e74345d2ae56603e5a549368b356070297ccf001289487deda2060838b249ef9bea48a863c9af05e873300f4f0545509564dd8f21decc779b55f0b7d1a316cc2cb3690e110c590b9a6aefb21ae331e86b5a9326e0f57743e98677c76fc2e0328ed5cbe71fd3f90ad49320aed7277aeb10a984a3535c15ad55f50de6e9b32014efeee26167c9b8ebe54b3c2b9b00705 .j.,..L.*....b?.*...aq.....FA..&..t0a...P..............(.9.z..#.*.J..1.../..I.1..As..Ak...8R..8a].....0.t..X......CE..V`>ZT.h.V......(.... `..$......<..^.3...TU.VM.....y._.}.1l..6.........!.3....2n.Wt>.g|v...(.\.q.?..I2..rw....J55.Z._P.n.2.N..&.|...T......
TPM2B_NAME | | .name
UINT16 | | | .size 0022 34
list[BYTE] | | | .name 000b51a358da397554d553530cd7cbac45f16a7a92e8a7602b217ccfb804f3950cde ..Q.X.9uT.SS....E.jz...`+!|.......
TPM2B_NAME | | .qualifiedName
UINT16 | | | .size 0022 34
list[BYTE] | | | .name 000beabcdbd48e0f4a74c1087768825a06a9580a3b625fc2ac1896682d477adb7871 ........Jt..wh.Z..X.;b_....h-Gz.xq
TPM_CC.Load
bash
Command
TPMI_ST_COMMAND_TAG | .tag 8002 TPMI_ST_COMMAND_TAG.SESSIONS
UINT32 | .commandSize 000000f7 247
TPM_CC | .commandCode 00000157 TPM_CC.Load
TPMS_COMMAND_HANDLES_LOAD | .handles
TPMI_DH_OBJECT | | .parentHandle 81000001 TPM_HR.PERSISTENT.000001
UINT32 | .authSize 00000009 9
TPMS_AUTH_COMMAND | .authorizationArea[0]
TPMI_SH_AUTH_SESSION | | .sessionHandle 40000009 TPM_RS.PW
TPM2B_NONCE | | .nonce
UINT16 | | | .size 0000 0
list[BYTE] | | | .buffer
TPMA_SESSION | | .sessionAttributes 00
| | | .continueSession .......0
| | | .auditExclusive ......0.
| | | .auditReset .....0..
| | | .reserved ...00...
| | | .decrypt ..0.....
| | | .encrypt .0......
| | | .audit 0.......
TPM2B_AUTH | | .hmac
UINT16 | | | .size 0000 0
list[BYTE] | | | .buffer
TPMS_COMMAND_PARAMS_LOAD | .parameters
TPM2B_PRIVATE | | .inPrivate
UINT16 | | | .size 008a 138
list[BYTE] | | | .buffer 00208f1af15b326555eca1dc2e00cf59588bc9efaaa8a6024d45d6e78902214e68a60010b13b2ad956912d4f4db7666f5f951355ab5b3e230bf9bcaf83143a3fa834bd8765dbc68b1153a262ad3a137e5db458d02df04b1c20795ba1483af1571052b617302492b1054134055fd884327c2266e4389e83163ec19cd626945706edf5b61761cfbca80bf4 . ...[2eU......YX.......ME....!Nh....;*.V.-OM.fo_..U.[>#......:?.4..e....S.b.:.~].X.-.K. y[.H:.W.R..0$...A4._..2|"f.8...>...&.W.....a.....
TPM2B_PUBLIC | | .inPublic
UINT16 | | | .size 004e 78
TPMT_PUBLIC | | | .publicArea
TPMI_ALG_PUBLIC | | | | .type 0008 TPMI_ALG_PUBLIC.KEYEDHASH
TPMI_ALG_HASH | | | | .nameAlg 000b TPMI_ALG_HASH.SHA256
TPMA_OBJECT | | | | .objectAttributes 00000412 TPMA_OBJECT.fixedTPM | TPMA_OBJECT.fixedParent | TPMA_OBJECT.noDA
| | | | | .reserved ...............................0
| | | | | .fixedTPM ..............................1.
| | | | | .stClear .............................0..
| | | | | .reserved0 ............................0...
| | | | | .fixedParent ...........................1....
| | | | | .sensitiveDataOrigin ..........................0.....
| | | | | .userWithAuth .........................0......
| | | | | .adminWithPolicy ........................0.......
| | | | | .reserved1 ......................00........
| | | | | .noDA .....................1..........
| | | | | .encryptedDuplication ....................0...........
| | | | | .reserved2 ................0000............
| | | | | .restricted ...............0................
| | | | | .decrypt ..............0.................
| | | | | .sign_decrypt .............0..................
| | | | | .sign ............0...................
| | | | | .reserved3 000000000000....................
TPM2B_DIGEST | | | | .authPolicy
UINT16 | | | | | .size 0020 32
list[BYTE] | | | | | .buffer 2e9ad77b67646d96a9e274803fcd8a0346c12594e3303a27ff40a221353e87d2 ...{gdm...t.?...F.%..0:'.@.!5>..
TPMU_PUBLIC_PARMS | | | | .parameters
TPMS_KEYEDHASH_PARMS | | | | | .keyedHashDetail
TPMT_KEYEDHASH_SCHEME | | | | | | .scheme
TPMI_ALG_KEYEDHASH_SCHEME | | | | | | | .scheme 0010 TPMI_ALG_KEYEDHASH_SCHEME.NULL
TPMU_SCHEME_KEYEDHASH | | | | | | | .details
TPMU_PUBLIC_ID | | | | .unique
TPM2B_DIGEST | | | | | .keyedHash
UINT16 | | | | | | .size 0020 32
list[BYTE] | | | | | | .buffer e44e22a60876b729df6e05c39a145f8db4aead7b3d6114a7b0823eca48604a8e .N"..v.).n...._....{=a....>.H`J.
Response
TPM_ST | .tag 8002 TPM_ST.SESSIONS
UINT32 | .responseSize 0000003b 59
TPM_RC | .responseCode 00000000 TPM_RC.SUCCESS
TPMS_RESPONSE_HANDLES_LOAD | .handles
TPM_HANDLE | | .objectHandle 80000001 TPM_HR.TRANSIENT.000001
UINT32 | .parameterSize 00000024 36
TPMS_RESPONSE_PARAMS_LOAD | .parameters
TPM2B_NAME | | .name
UINT16 | | | .size 0022 34
list[BYTE] | | | .name 000bd19e0d691c24bed8a7193219380575c57ebc047303bf4365d3a9ae5a1690af54 .....i.$....2.8.u.~..s..Ce...Z...T
list[TPMS_AUTH_RESPONSE] | .authorizationArea
TPMS_AUTH_RESPONSE | .authorizationArea[0]
TPM2B_NONCE | | .nonce
UINT16 | | | .size 0000 0
list[BYTE] | | | .buffer
TPMA_SESSION | | .sessionAttributes 01 TPMA_SESSION.continueSession
| | | .continueSession .......1
| | | .auditExclusive ......0.
| | | .auditReset .....0..
| | | .reserved ...00...
| | | .decrypt ..0.....
| | | .encrypt .0......
| | | .audit 0.......
TPM2B_AUTH | | .hmac
UINT16 | | | .size 0000 0
list[BYTE] | | | .buffer
以上相关数据可以在加密磁盘的元数据中找到,如下图所示:

TPM_CC.GetRandom
bash
Command
TPMI_ST_COMMAND_TAG | .tag 8001 TPMI_ST_COMMAND_TAG.NO_SESSIONS
UINT32 | .commandSize 0000000c 12
TPM_CC | .commandCode 0000017b TPM_CC.GetRandom
TPMS_COMMAND_HANDLES_GET_RANDOM | .handles
TPMS_COMMAND_PARAMS_GET_RANDOM | .parameters
UINT16 | | .bytesRequested 0020 32
Response
TPM_ST | .tag 8001 TPM_ST.NO_SESSIONS
UINT32 | .responseSize 0000002c 44
TPM_RC | .responseCode 00000000 TPM_RC.SUCCESS
TPMS_RESPONSE_HANDLES_GET_RANDOM | .handles
TPMS_RESPONSE_PARAMS_GET_RANDOM | .parameters
TPM2B_DIGEST | | .randomBytes
UINT16 | | | .size 0020 32
list[BYTE] | | | .buffer 80ec76f41e75e1c445bc519981a8154b3f97b9a5a1cd5c81f9e279a941b24d3c ..v..u..E.Q....K?.....\...y.A.M<
TPM_CC.StartAuthSession
bash
Command
TPMI_ST_COMMAND_TAG | .tag 8001 TPMI_ST_COMMAND_TAG.NO_SESSIONS
UINT32 | .commandSize 0000003b 59
TPM_CC | .commandCode 00000176 TPM_CC.StartAuthSession
TPMS_COMMAND_HANDLES_START_AUTH_SESSION | .handles
TPMI_DH_OBJECT | | .tpmKey 40000007 TPM_RH.NULL
TPMI_DH_ENTITY | | .bind 40000007 TPM_RH.NULL
TPMS_COMMAND_PARAMS_START_AUTH_SESSION | .parameters
TPM2B_NONCE | | .nonceCaller
UINT16 | | | .size 0020 32
list[BYTE] | | | .buffer 80ec76f41e75e1c445bc519981a8154b3f97b9a5a1cd5c81f9e279a941b24d3c ..v..u..E.Q....K?.....\...y.A.M<
TPM2B_ENCRYPTED_SECRET | | .encryptedSalt
UINT16 | | | .size 0000 0
list[BYTE] | | | .secret
TPM_SE | | .sessionType 01 TPM_SE.POLICY
TPMT_SYM_DEF | | .symmetric
TPMI_ALG_SYM | | | .algorithm 0010 TPMI_ALG_SYM.NULL
TPMU_SYM_KEY_BITS | | | .keyBits
TPMU_SYM_MODE | | | .mode
TPMU_SYM_DETAILS | | | .details
TPMI_ALG_HASH | | .authHash 000b TPMI_ALG_HASH.SHA256
Response
TPM_ST | .tag 8001 TPM_ST.NO_SESSIONS
UINT32 | .responseSize 00000030 48
TPM_RC | .responseCode 00000000 TPM_RC.SUCCESS
TPMS_RESPONSE_HANDLES_START_AUTH_SESSION | .handles
TPMI_SH_AUTH_SESSION | | .sessionHandle 03000000 TPM_HR.POLICY_SESSION.000000
TPMS_RESPONSE_PARAMS_START_AUTH_SESSION | .parameters
TPM2B_NONCE | | .nonceTPM
UINT16 | | | .size 0020 32
list[BYTE] | | | .buffer 629d2be6c23a0506ef1a0ba4434c998e345b581abeeeb2528d501c171c66104f b.+..:......CL..4[X....R.P...f.O
开启一个用于解封密钥的会话对象0x03000000。
TPM_CC.GetRandom
bash
Command
TPMI_ST_COMMAND_TAG | .tag 8001 TPMI_ST_COMMAND_TAG.NO_SESSIONS
UINT32 | .commandSize 0000000c 12
TPM_CC | .commandCode 0000017b TPM_CC.GetRandom
TPMS_COMMAND_HANDLES_GET_RANDOM | .handles
TPMS_COMMAND_PARAMS_GET_RANDOM | .parameters
UINT16 | | .bytesRequested 0020 32
Response
TPM_ST | .tag 8001 TPM_ST.NO_SESSIONS
UINT32 | .responseSize 0000002c 44
TPM_RC | .responseCode 00000000 TPM_RC.SUCCESS
TPMS_RESPONSE_HANDLES_GET_RANDOM | .handles
TPMS_RESPONSE_PARAMS_GET_RANDOM | .parameters
TPM2B_DIGEST | | .randomBytes
UINT16 | | | .size 0020 32
list[BYTE] | | | .buffer a2f1347ea35539e81bc06232df4f88e8972338e31faa6ff2ec9e8ef9a9322152 ..4~.U9...b2.O...#8...o......2!R
TPM_CC.PolicyAuthValue
bash
Command
TPMI_ST_COMMAND_TAG | .tag 8001 TPMI_ST_COMMAND_TAG.NO_SESSIONS
UINT32 | .commandSize 0000000e 14
TPM_CC | .commandCode 0000016b TPM_CC.PolicyAuthValue
TPMS_COMMAND_HANDLES_POLICY_AUTH_VALUE | .handles
TPMI_SH_POLICY | | .policySession 03000000 TPM_HR.POLICY_SESSION.000000
TPMS_COMMAND_PARAMS_POLICY_AUTH_VALUE | .parameters
Response
TPM_ST | .tag 8001 TPM_ST.NO_SESSIONS
UINT32 | .responseSize 0000000a 10
TPM_RC | .responseCode 00000000 TPM_RC.SUCCESS
TPMS_RESPONSE_HANDLES_POLICY_AUTH_VALUE | .handles
TPMS_RESPONSE_PARAMS_POLICY_AUTH_VALUE | .parameters
设置会话通信不加密。
TPM_CC.PolicyPCR
bash
Command
TPMI_ST_COMMAND_TAG | .tag 8001 TPMI_ST_COMMAND_TAG.NO_SESSIONS
UINT32 | .commandSize 0000003a 58
TPM_CC | .commandCode 0000017f TPM_CC.PolicyPCR
TPMS_COMMAND_HANDLES_POLICY_PCR | .handles
TPMI_SH_POLICY | | .policySession 03000000 TPM_HR.POLICY_SESSION.000000
TPMS_COMMAND_PARAMS_POLICY_PCR | .parameters
TPM2B_DIGEST | | .pcrDigest
UINT16 | | | .size 0020 32
list[BYTE] | | | .buffer 3ec3f989f21ae77ad85cbcc6533598337d05dbcf47f7b0379da0d5cfbd1c18a5 >......z.\..S5.3}...G..7........
TPML_PCR_SELECTION | | .pcrs
UINT32 | | | .count 00000001 1
TPMS_PCR_SELECTION | | | .pcrSelections[0]
TPMI_ALG_HASH | | | | .hash 000b TPMI_ALG_HASH.SHA256
UINT8 | | | | .sizeofSelect 03 3
list[BYTE] | | | | .pcrSelect 800800 ...
Response
TPM_ST | .tag 8001 TPM_ST.NO_SESSIONS
UINT32 | .responseSize 0000000a 10
TPM_RC | .responseCode 00000000 TPM_RC.SUCCESS
TPMS_RESPONSE_HANDLES_POLICY_PCR | .handles
TPMS_RESPONSE_PARAMS_POLICY_PCR | .parameters
这一步比较重要,用于校验各个PCR是否发生变化,即系统是否被修改过。
其中的3ec3f989f21ae77ad85cbcc6533598337d05dbcf47f7b0379da0d5cfbd1c18a5存储在加密磁盘的元数据中,如下图所示:

该值在启用Bitlock + TPM加密系统盘密封VMK时生成,并保存在加密磁盘的元数据头中。
在BitLocker密封VMK密钥到TPM时,同时提交了PCRs的哈希值给TPM,然后TPM返回3ec3f989f21ae77ad85cbcc6533598337d05dbcf47f7b0379da0d5cfbd1c18a5,用于解封VMK时校验PCRs是否发生修改。
启用BitLocker磁盘加密时,PCR7,PCR11的值分别为:
baee51c2e2e40e18641abdb8827b3bd9524d8a77719ec43c239c0c5a91cd1cf8
0000000000000000000000000000000000000000000000000000000000000000
SHA256(PCR7 || PCR11):
3ec3f989f21ae77ad85cbcc6533598337d05dbcf47f7b0379da0d5cfbd1c18a5
密封过程如下图:

解封校验PCRs过程如下图:

由之前的过程可知,系统启动时,读取了PCR7,11中的值,分别为以下值:
baee51c2e2e40e18641abdb8827b3bd9524d8a77719ec43c239c0c5a91cd1cf8
0000000000000000000000000000000000000000000000000000000000000000
这和BitLocker加密时,密封密钥时使用的PCR7,11的值相同,通过计算得到相同的校验值
3ec3f989f21ae77ad85cbcc6533598337d05dbcf47f7b0379da0d5cfbd1c18a5
校验值相同,则本过程PolicyPCR返回成功,否则本过程失败!
密封详细内容参考:Bitlocker密钥提取之深入分析TPM密封VMK过程
TPM_CC.Unseal
bash
Command
TPMI_ST_COMMAND_TAG | .tag 8002 TPMI_ST_COMMAND_TAG.SESSIONS
UINT32 | .commandSize 0000005b 91
TPM_CC | .commandCode 0000015e TPM_CC.Unseal
TPMS_COMMAND_HANDLES_UNSEAL | .handles
TPMI_DH_OBJECT | | .itemHandle 80000001 TPM_HR.TRANSIENT.000001
UINT32 | .authSize 00000049 73
TPMS_AUTH_COMMAND | .authorizationArea[0]
TPMI_SH_AUTH_SESSION | | .sessionHandle 03000000 TPM_HR.POLICY_SESSION.000000
TPM2B_NONCE | | .nonce
UINT16 | | | .size 0020 32
list[BYTE] | | | .buffer a2f1347ea35539e81bc06232df4f88e8972338e31faa6ff2ec9e8ef9a9322152 ..4~.U9...b2.O...#8...o......2!R
TPMA_SESSION | | .sessionAttributes 00
| | | .continueSession .......0
| | | .auditExclusive ......0.
| | | .auditReset .....0..
| | | .reserved ...00...
| | | .decrypt ..0.....
| | | .encrypt .0......
| | | .audit 0.......
TPM2B_AUTH | | .hmac
UINT16 | | | .size 0020 32
list[BYTE] | | | .buffer 688848606fe2d5ad45c4f821e79503e11723ce7d9889842f3d37186cd298f748 h.H`o...E..!.....#.}.../=7.l...H
TPMS_COMMAND_PARAMS_UNSEAL | .parameters
Response
TPM_ST | .tag 8002 TPM_ST.SESSIONS
UINT32 | .responseSize 00000081 129
TPM_RC | .responseCode 00000000 TPM_RC.SUCCESS
TPMS_RESPONSE_HANDLES_UNSEAL | .handles
UINT32 | .parameterSize 0000002e 46
TPMS_RESPONSE_PARAMS_UNSEAL | .parameters
TPM2B_SENSITIVE_DATA | | .outData
UINT16 | | | .size 002c 44
list[BYTE] | | | .buffer 2c0005000100000003200000b468267d6801e284b473f9f2886a5e6ca48c9baa708e5f941b769f6f671eecfd ,........ ...h&}h....s...j^l....p._..v.og...
list[TPMS_AUTH_RESPONSE] | .authorizationArea
TPMS_AUTH_RESPONSE | .authorizationArea[0]
TPM2B_NONCE | | .nonce
UINT16 | | | .size 0020 32
list[BYTE] | | | .buffer 592fc49e407d0e8cd255106530143899d82b80df8e5db4db1ca1c13ac9d27de9 Y/..@}...U.e0.8..+...].....:..}.
TPMA_SESSION | | .sessionAttributes 00
| | | .continueSession .......0
| | | .auditExclusive ......0.
| | | .auditReset .....0..
| | | .reserved ...00...
| | | .decrypt ..0.....
| | | .encrypt .0......
| | | .audit 0.......
TPM2B_AUTH | | .hmac
UINT16 | | | .size 0020 32
list[BYTE] | | | .buffer 08398b1631c8993e876dd8d534664e6ef2d70dfb52a7406538a980f7ba1819da .9..1..>.m..4fNn....R.@e8.......
得到VMK密钥数据:
2c0005000100000003200000b468267d6801e284b473f9f2886a5e6ca48c9baa708e5f941b769f6f671eecfd
TPM_CC.FlushContext
bash
Command
TPMI_ST_COMMAND_TAG | .tag 8001 TPMI_ST_COMMAND_TAG.NO_SESSIONS
UINT32 | .commandSize 0000000e 14
TPM_CC | .commandCode 00000165 TPM_CC.FlushContext
TPMS_COMMAND_HANDLES_FLUSH_CONTEXT | .handles
TPMI_DH_CONTEXT | | .flushHandle 80000001 TPM_HR.TRANSIENT.000001
TPMS_COMMAND_PARAMS_FLUSH_CONTEXT | .parameters
Response
TPM_ST | .tag 8001 TPM_ST.NO_SESSIONS
UINT32 | .responseSize 0000000a 10
TPM_RC | .responseCode 00000000 TPM_RC.SUCCESS
TPMS_RESPONSE_HANDLES_FLUSH_CONTEXT | .handles
TPMS_RESPONSE_PARAMS_FLUSH_CONTEXT | .parameters
扩展 PCR11
当密钥解封成功后,需要扩展(修改)PCR11的值,防止恶意程序通过TPM命令再次解封密钥。
扩展PCR11的值操作共出现2次。
首次扩展PCR11的值在bootmgfw.efi中,分析得到调用顺序如下:

从流程图来看,最终通过函数TreeProtocol.HashLogExtendEvent扩展(修改)了PCR11寄存器的值,该函数原型及说明如下图所示,参考ntos-boot源代码

在函数SipEarlyExtendBitLockerCap中,第一个参数0x10就是本次计算PCR11 SHA256的哈希值原数据,共计算4个字节,即: 10 00 00 00

计算结果:SHA256(10 00 00 00) = 097328E8C957DE2428283954F6A1EE8FF7AD7DEF12E100A600178407F5DECF24
扩展PCR11值的方法:PCR11 = SHA256(PCR11 || NewSHA256),最后得到PCR11扩展后的值为:7366E3E017F2A466C909C2F4C2419B0A1587F07B3085218FC5790181786D6C4A
通过动态调试方法读取得到PCR11中的值也是该值(PCR11在被扩展修改值后,后续并没有再次读取PCR11值的行为,需要在后续某次与TPM交互时,强制修改内存中TPM指令数据,实现读取PCR11目的,如:后续有个扩展PCR12的操作,强制修改该操作的内存指令为读取PCR11的指令"8001000000140000017e00000001000b03000B00"等),如下图所示:

再次扩展PCR11的值在加载\Windows\System32\Winload.efi模块中,流程如下:

在函数SipRecordEnvironmentCapEventWorker中,第一参数v10指定要计算SHA256的原数据,这里时0xFFFF,攻击计算4个字节,即:FF FF 00 00

计算结果:SHA256(FF FF 00 00) = 08EFEA1C0957A5A1FE019E6EDB21FDC9FBE5DE2213487EAB7A05E06ECA1C9784
同样的方法扩展PCR11值的方法:PCR11 = SHA256(PCR11 || NewSHA256),最后得到PCR11扩展后的值为:0FE6E8F2110D5D53935C9E7D6F6BF722598B550595AABDC6E4FD2ECDF310F980
动态调试得到的结果如下(方法同上):

通过2次对PCR11的扩展,最终得到PCR11实际值就是:0FE6E8F2110D5D53935C9E7D6F6BF722598B550595AABDC6E4FD2ECDF310F980
如何验证该值的正确性呢?可以通过开机登录系统,使用Windows自动的TpmTool.exe打印PCR值,如下图所示:

到此,PCR11被扩展修改后,后续在同一个系统上,想通过TPM命令交互再次解封提取VMK密钥时,几乎是不可能的了,除非你能找到一个X值,并且X值满足以下条件:
PCR11 = SHA256( PCR11 || SHA256(X) ) = 0000000000000000000000000000000000000000000000000000000000000000求X值?
幻想中的攻击场景
假设物理接触目标电脑,启动目标机到恢复模式(命令行环境),因为PCR7的值是通过校验机器环境得来的,在目标机上,没有修改任何配置的情况下,可以通过TPM命令读取到正确的PCR7的值。接着,假设你得到了X这样的值,通过TPM的PCR_Extend扩展命令,将PCR11的值成功修改为了0,那么,在进行TPM_CC.PolicyPCR时,你将成功通过TPM的审核,进而取得密钥!
祝你好运!