Bitlocker密钥提取之深入分析TPM解封VMK过程

本文通过动态调试方式,深入分析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的审核,进而取得密钥!

祝你好运!