def test_RpcEnumPrinters(self): dce, rpctransport = self.connect() request = rprn.RpcEnumPrinters() request['Flags'] = rprn.PRINTER_ENUM_LOCAL request['Name'] = NULL request['pPrinterEnum'] = NULL request['Level'] = 1 request.dump() bytesNeeded = 0 try: resp = dce.request(request) resp.dump() except rprn.DCERPCSessionError as e: if str(e).find('ERROR_INSUFFICIENT_BUFFER') < 0: raise bytesNeeded = e.get_packet()['pcbNeeded'] request = rprn.RpcEnumPrinters() request['Flags'] = rprn.PRINTER_ENUM_LOCAL request['Name'] = NULL request['Level'] = 1 request['cbBuf'] = bytesNeeded request['pPrinterEnum'] = b'a' * bytesNeeded request.dump() resp = dce.request(request) resp.dump() hexdump(resp['pPrinterEnum'])
def setUp(self): # Turn test case mode on ntlm.TEST_CASE = True self.user = "******" self.domain = "Domain" self.password = "******" self.serverName = "Server" self.workstationName = "COMPUTER" self.randomSessionKey = "U" * 16 self.time = "\x00" * 8 self.clientChallenge = "\xaa" * 8 self.serverChallenge = "\x01\x23\x45\x67\x89\xab\xcd\xef" self.flags = ntlm.NTLMSSP_NEGOTIATE_KEY_EXCH | ntlm.NTLMSSP_NEGOTIATE_56 | ntlm.NTLMSSP_NEGOTIATE_128 | ntlm.NTLMSSP_NEGOTIATE_VERSION | ntlm.NTLMSSP_TARGET_TYPE_SERVER | ntlm.NTLMSSP_NEGOTIATE_ALWAYS_SIGN | ntlm.NTLMSSP_NEGOTIATE_NTLM | ntlm.NTLMSSP_NEGOTIATE_SEAL | ntlm.NTLMSSP_NEGOTIATE_SIGN | ntlm.NTLM_NEGOTIATE_OEM | ntlm.NTLMSSP_NEGOTIATE_UNICODE self.seqNum = 0 self.nonce = '\x00' * 4 self.plaintext = 'Plaintext'.encode('utf-16le') print("## BEFORE RUNNING THESE TESTS") print( "Don't forget to set up aTime = '\\x00'*8 in computeResponseNTLMv2 otherwise the results won't be right. " ) print( "Look for that in ntlm.py and uncomment the lines, comment the other ones and don't forget to revert everything back whenever finished testing" ) print("Flags") hexdump(struct.pack('<L', self.flags))
def test_RpcEnumPrinters(self): dce, rpctransport = self.connect() request = rprn.RpcEnumPrinters() request['Flags'] = rprn.PRINTER_ENUM_LOCAL request['Name'] = NULL request['pPrinterEnum'] = NULL request['Level'] = 1 request.dump() with assertRaisesRegex(self, rprn.DCERPCSessionError, "ERROR_INSUFFICIENT_BUFFER") as cm: dce.request(request) bytesNeeded = cm.exception.get_packet()['pcbNeeded'] request = rprn.RpcEnumPrinters() request['Flags'] = rprn.PRINTER_ENUM_LOCAL request['Name'] = NULL request['Level'] = 1 request['cbBuf'] = bytesNeeded request['pPrinterEnum'] = b'a' * bytesNeeded request.dump() resp = dce.request(request) resp.dump() hexdump(b''.join(resp['pPrinterEnum']))
def test_RpcEnumPrinters(self): dce, rpctransport = self.connect() request = rprn.RpcEnumPrinters() request['Flags'] = rprn.PRINTER_ENUM_LOCAL request['Name'] = NULL request['pPrinterEnum'] = NULL request['Level'] = 1 request.dump() bytesNeeded = 0 try: resp = dce.request(request) resp.dump() except rprn.DCERPCSessionError as e: if str(e).find('ERROR_INSUFFICIENT_BUFFER') < 0: raise bytesNeeded = e.get_packet()['pcbNeeded'] request = rprn.RpcEnumPrinters() request['Flags'] = rprn.PRINTER_ENUM_LOCAL request['Name'] = NULL request['Level'] = 1 request['cbBuf'] = bytesNeeded request['pPrinterEnum'] = b'a'*bytesNeeded request.dump() resp = dce.request(request) resp.dump() hexdump(resp['pPrinterEnum'])
def __pack_and_parse(self, message, expected): data = message.getData() hexdump(data) self.assertEqual(data, expected) parsed = ntlm.NTLMAuthNegotiate() parsed.fromString(data) return parsed
def test_hLsarQuerySecurityObject_hLsarSetSecurityObject(self): dce, rpctransport, policyHandle = self.connect() resp = lsad.hLsarQuerySecurityObject(dce, policyHandle, lsad.OWNER_SECURITY_INFORMATION) hexdump(resp) resp = lsad.hLsarSetSecurityObject(dce, policyHandle, lsad.OWNER_SECURITY_INFORMATION,resp) resp.dump()
def test_hLsarQuerySecurityObject_hLsarSetSecurityObject(self): dce, rpctransport, policyHandle = self.connect() resp = lsad.hLsarQuerySecurityObject(dce, policyHandle, lsad.OWNER_SECURITY_INFORMATION) hexdump(resp) resp = lsad.hLsarSetSecurityObject(dce, policyHandle, lsad.OWNER_SECURITY_INFORMATION,resp) resp.dump()
def test_encodedecodename(self): name = 'THISISAVERYLONGLONGNAME' encoded = nmb.encode_name(name,nmb.TYPE_SERVER,None) hexdump(encoded) decoded = nmb.decode_name(encoded) hexdump(decoded[1]) #self.assertTrue(nmb.TYPE_SERVER==decoded[0]) self.assertTrue(name[:15]==decoded[1].strip())
def test_encodedecodename(self): name = 'THISISAVERYLONGLONGNAME' encoded = nmb.encode_name(name,nmb.TYPE_SERVER,None) hexdump(encoded) decoded = nmb.decode_name(encoded) hexdump(bytearray(decoded[1],'utf-8')) #self.assertTrue(nmb.TYPE_SERVER==decoded[0]) self.assertTrue(name[:15]==decoded[1].strip())
def test_encodedecodename(self): name = 'THISISAVERYLONGLONGNAME' encoded = nmb.encode_name(name, nmb.TYPE_SERVER, None) hexdump(encoded) decoded = nmb.decode_name(encoded) hexdump(bytearray(decoded[1], 'utf-8')) #self.assertEqual(nmb.TYPE_SERVER, decoded[0]) self.assertEqual(name[:15], decoded[1].strip())
def dump(self): print("[VAULT_VPOL_KEYS]") if self['Key1']['Size'] > 0x24: print('Key1:') hexdump(self['Key1']['bKeyBlob']) print('Key2:') hexdump(self['Key2']['bKeyBlob']) else: print('Key1: 0x%s' % self['Key1']['bKeyBlob']['bKey'].hex()) print('Key2: 0x%s' % self['Key2']['bKeyBlob']['bKey'].hex()) print()
def dump(self): print("[VAULT_VPOL_KEYS]") if self['Key1']['Size'] > 0x24: print('Key1:') hexdump(self['Key1']['bKeyBlob']) print('Key2:') hexdump(self['Key2']['bKeyBlob']) else: print('Key1: 0x%s' % hexlify(self['Key1']['bKeyBlob']['bKey']).decode('latin-1')) print('Key2: 0x%s' % hexlify(self['Key2']['bKeyBlob']['bKey']).decode('latin-1')) print()
def dump(self): print("[VAULT_VPOL_KEYS]") if self['Key1']['Size'] > 0x24: print('Key1:') hexdump(self['Key1']['bKeyBlob']) print('Key2:') hexdump(self['Key2']['bKeyBlob']) else: print('Key1: 0x%s' % hexlify(self['Key1']['bKeyBlob']['bKey']).decode('latin-1')) print('Key2: 0x%s' % hexlify(self['Key2']['bKeyBlob']['bKey']).decode('latin-1')) print()
def test_EvtRpcRegisterLogQuery_EvtRpcQueryNext(self): dce, rpctransport = self.connect(2) request = even6.EvtRpcRegisterLogQuery() request['Path'] = 'Security\x00' request['Query'] = '*\x00' request['Flags'] = even6.EvtQueryChannelName | even6.EvtReadNewestToOldest request.dump() try: resp = dce.request(request) resp.dump() except Exception as e: return log_handle = resp['Handle'] request = even6.EvtRpcQueryNext() request['LogQuery'] = log_handle request['NumRequestedRecords'] = 5 request['TimeOutEnd'] = 1000 request['Flags'] = 0 request.dump() try: resp = dce.request(request) resp.dump() except Exception as e: return for i in range(resp['NumActualRecords']): event_offset = resp['EventDataIndices'][i]['Data'] event_size = resp['EventDataSizes'][i]['Data'] event = resp['ResultBuffer'][event_offset:event_offset + event_size] buff = b''.join(event) print(hexdump(buff))
def test_hEvtRpcRegisterLogQuery_hEvtRpcQueryNext(self): dce, rpctransport = self.connect(2) try: resp = even6.hEvtRpcRegisterLogQuery( dce, 'Security\x00', '*\x00', even6.EvtQueryChannelName | even6.EvtReadNewestToOldest) resp.dump() except Exception as e: return log_handle = resp['Handle'] try: resp = even6.EvtRpcQueryNext(dce, log_handle, 5, 1000, 0) resp.dump() except Exception as e: return for i in range(resp['NumActualRecords']): event_offset = resp['EventDataIndices'][i]['Data'] event_size = resp['EventDataSizes'][i]['Data'] event = resp['ResultBuffer'][event_offset:event_offset + event_size] buff = ''.join([x.encode('hex') for x in event]).decode('hex') print(hexdump(buff))
def setUp(self): # Turn test case mode on ntlm.TEST_CASE = True self.user = "******" self.domain = "Domain" self.password = "******" self.serverName = "Server" self.workstationName = "COMPUTER" self.randomSessionKey = b("U" * 16) self.time = b('\x00' * 8) self.clientChallenge = b("\xaa" * 8) self.serverChallenge = b("\x01\x23\x45\x67\x89\xab\xcd\xef") self.flags = ntlm.NTLMSSP_NEGOTIATE_KEY_EXCH | ntlm.NTLMSSP_NEGOTIATE_56 | ntlm.NTLMSSP_NEGOTIATE_128 | ntlm.NTLMSSP_NEGOTIATE_VERSION | ntlm.NTLMSSP_TARGET_TYPE_SERVER | ntlm.NTLMSSP_NEGOTIATE_ALWAYS_SIGN | ntlm.NTLMSSP_NEGOTIATE_NTLM | ntlm.NTLMSSP_NEGOTIATE_SEAL | ntlm.NTLMSSP_NEGOTIATE_SIGN | ntlm.NTLM_NEGOTIATE_OEM | ntlm.NTLMSSP_NEGOTIATE_UNICODE self.seqNum = 0 self.nonce = b('\x00' * 16) self.plaintext = 'Plaintext'.encode('utf-16le') print("Flags") hexdump(struct.pack('<L', self.flags))
def printValue(self, valueType, valueData): if valueType == REG_SZ or valueType == REG_EXPAND_SZ: if type(valueData) is int: print('NULL') else: print("%s" % (valueData.decode('utf-16le'))) elif valueType == REG_BINARY: print('') hexdump(valueData, self.indent) elif valueType == REG_DWORD: print("%d" % valueData) elif valueType == REG_QWORD: print("%d" % (unpack('<Q', valueData)[0])) elif valueType == REG_NONE: try: if len(valueData) > 1: print('') hexdump(valueData, self.indent) else: print(" NULL") except: print(" NULL") elif valueType == REG_MULTISZ: print("%s" % (valueData.decode('utf-16le'))) else: print("Unknown Type 0x%x!" % valueType) hexdump(valueData)
def printValue(self, valueType, valueData): if valueType == REG_SZ or valueType == REG_EXPAND_SZ: if type(valueData) is int: print('NULL') else: print("%s" % (valueData.decode('utf-16le'))) elif valueType == REG_BINARY: print('') hexdump(valueData, self.indent) elif valueType == REG_DWORD: print("%d" % valueData) elif valueType == REG_QWORD: print("%d" % (unpack('<Q',valueData)[0])) elif valueType == REG_NONE: try: if len(valueData) > 1: print('') hexdump(valueData, self.indent) else: print(" NULL") except: print(" NULL") elif valueType == REG_MULTISZ: print("%s" % (valueData.decode('utf-16le'))) else: print("Unknown Type 0x%x!" % valueType) hexdump(valueData)
def __parse_lp_data(valueType, valueData): try: if valueType == rrp.REG_SZ or valueType == rrp.REG_EXPAND_SZ: if type(valueData) is int: print('NULL') else: print("%s" % (valueData.decode('utf-16le')[:-1])) elif valueType == rrp.REG_BINARY: print('') hexdump(valueData, '\t') elif valueType == rrp.REG_DWORD: print("0x%x" % (unpack('<L', valueData)[0])) elif valueType == rrp.REG_QWORD: print("0x%x" % (unpack('<Q', valueData)[0])) elif valueType == rrp.REG_NONE: try: if len(valueData) > 1: print('') hexdump(valueData, '\t') else: print(" NULL") except: print(" NULL") elif valueType == rrp.REG_MULTI_SZ: print("%s" % (valueData.decode('utf-16le')[:-2])) else: print("Unknown Type 0x%x!" % valueType) hexdump(valueData) except Exception as e: logging.debug('Exception thrown when printing reg value %s', str(e)) print('Invalid data') pass
def __parse_lp_data(valueType, valueData): try: if valueType == rrp.REG_SZ or valueType == rrp.REG_EXPAND_SZ: if type(valueData) is int: print('NULL') else: print("%s" % (valueData.decode('utf-16le')[:-1])) elif valueType == rrp.REG_BINARY: print('') hexdump(valueData, '\t') elif valueType == rrp.REG_DWORD: print("0x%x" % (unpack('<L', valueData)[0])) elif valueType == rrp.REG_QWORD: print("0x%x" % (unpack('<Q', valueData)[0])) elif valueType == rrp.REG_NONE: try: if len(valueData) > 1: print('') hexdump(valueData, '\t') else: print(" NULL") except: print(" NULL") elif valueType == rrp.REG_MULTI_SZ: print("%s" % (valueData.decode('utf-16le')[:-2])) else: print("Unknown Type 0x%x!" % valueType) hexdump(valueData) except Exception as e: logging.debug('Exception thrown when printing reg value %s', str(e)) print('Invalid data') pass
def setUp(self): # Turn test case mode on ntlm.TEST_CASE = True self.user = "******" self.domain = "Domain" self.password = "******" self.serverName = "Server" self.workstationName = "COMPUTER" self.randomSessionKey = "U"*16 self.time = "\x00"*8 self.clientChallenge = "\xaa"*8 self.serverChallenge = "\x01\x23\x45\x67\x89\xab\xcd\xef" self.flags = ntlm.NTLMSSP_NEGOTIATE_KEY_EXCH | ntlm.NTLMSSP_NEGOTIATE_56 | ntlm.NTLMSSP_NEGOTIATE_128 | ntlm.NTLMSSP_NEGOTIATE_VERSION | ntlm.NTLMSSP_TARGET_TYPE_SERVER | ntlm.NTLMSSP_NEGOTIATE_ALWAYS_SIGN | ntlm.NTLMSSP_NEGOTIATE_NTLM | ntlm.NTLMSSP_NEGOTIATE_SEAL | ntlm.NTLMSSP_NEGOTIATE_SIGN | ntlm.NTLM_NEGOTIATE_OEM | ntlm.NTLMSSP_NEGOTIATE_UNICODE self.seqNum = 0 self.nonce = '\x00' * 4 self.plaintext = 'Plaintext'.encode('utf-16le') print("## BEFORE RUNNING THESE TESTS") print("Don't forget to set up aTime = '\\x00'*8 in computeResponseNTLMv2 otherwise the results won't be right. ") print("Look for that in ntlm.py and uncomment the lines, comment the other ones and don't forget to revert everything back whenever finished testing") print("Flags") hexdump(struct.pack('<L',self.flags))
def test_hEvtRpcRegisterLogQuery_hEvtRpcQueryNext(self): dce, rpctransport = self.connect(2) try: resp = even6.hEvtRpcRegisterLogQuery(dce, 'Security\x00', '*\x00', even6.EvtQueryChannelName | even6.EvtReadNewestToOldest) resp.dump() except Exception as e: return log_handle = resp['Handle'] try: resp = even6.EvtRpcQueryNext(dce, log_handle, 5, 1000, 0) resp.dump() except Exception as e: return for i in range(resp['NumActualRecords']): event_offset = resp['EventDataIndices'][i]['Data'] event_size = resp['EventDataSizes'][i]['Data'] event = resp['ResultBuffer'][event_offset:event_offset + event_size] buff = ''.join([x.encode('hex') for x in event]).decode('hex') print(hexdump(buff))
def test_ntlmv2(self): print("####### 4.2.4 NTLMv2 Authentication") ntlm.USE_NTLMv2 = True serverName = b( '\x02\x00\x0c\x00\x44\x00\x6f\x00\x6d\x00\x61\x00\x69\x00\x6e\x00\x01\x00\x0c\x00\x53\x00\x65\x00\x72\x00\x76\x00\x65\x00\x72\x00\x00\x00\x00\x00' ) # Still the aTime won't be set to zero. that must be changed in ntlm.computeResponseNTLM2. Gotta make this more automated flags = ntlm.NTLMSSP_NEGOTIATE_KEY_EXCH | ntlm.NTLMSSP_NEGOTIATE_56 | ntlm.NTLMSSP_NEGOTIATE_128 | \ ntlm.NTLMSSP_NEGOTIATE_VERSION | ntlm.NTLMSSP_NEGOTIATE_TARGET_INFO | \ ntlm.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY | ntlm.NTLMSSP_TARGET_TYPE_SERVER | \ ntlm.NTLMSSP_NEGOTIATE_ALWAYS_SIGN | ntlm.NTLMSSP_NEGOTIATE_NTLM | ntlm.NTLMSSP_NEGOTIATE_SEAL | \ ntlm.NTLMSSP_NEGOTIATE_SIGN | ntlm.NTLM_NEGOTIATE_OEM | ntlm.NTLMSSP_NEGOTIATE_UNICODE print("Flags") hexdump(struct.pack('<L', flags)) print("\n") print("4.2.4.1.1 NTOWFv2 and LMOWFv2") res = ntlm.NTOWFv2(self.user, self.password, self.domain) hexdump(res) self.assertTrue(res == bytearray( b'\x0c\x86\x8a@;\xfdz\x93\xa3\x00\x1e\xf2.\xf0.?')) print("\n") print("\n") print("4.2.4.1.2 Session Base Key") ntResponse, lmResponse, sessionBaseKey = ntlm.computeResponseNTLMv2( flags, self.serverChallenge, self.clientChallenge, serverName, self.domain, self.user, self.password, '', '') hexdump(sessionBaseKey) self.assertTrue(sessionBaseKey == bytearray( b'\x8d\xe4\x0c\xca\xdb\xc1\x4a\x82\xf1\x5c\xb0\xad\x0d\xe9\x5c\xa3' )) print("\n") print("4.2.4.2.1 LMv2 Response") hexdump(lmResponse) self.assertTrue(lmResponse == bytearray( b'\x86\xc3P\x97\xac\x9c\xec\x10%TvJW\xcc\xcc\x19\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa' )) print("\n") print("4.2.4.2.2 NTLMv2 Response") hexdump(ntResponse[:16]) self.assertTrue(ntResponse[:16] == bytearray( b'\x68\xcd\x0a\xb8\x51\xe5\x1c\x96\xaa\xbc\x92\x7b\xeb\xef\x6a\x1c' )) print("\n") print("4.2.4.2.3 Encrypted Session Key") keyExchangeKey = ntlm.KXKEY(flags, sessionBaseKey, lmResponse, self.serverChallenge, self.password, '', '') encryptedSessionKey = ntlm.generateEncryptedSessionKey( keyExchangeKey, self.randomSessionKey) hexdump(encryptedSessionKey) self.assertTrue(encryptedSessionKey == bytearray( b'\xC5\xDA\xD2\x54\x4F\xC9\x79\x90\x94\xCE\x1C\xE9\x0B\xC9\xD0\x3E' )) print("\n") print("AUTHENTICATE MESSAGE") encryptedSessionKey = ntlm.generateEncryptedSessionKey( keyExchangeKey, self.randomSessionKey) ntlmChallengeResponse = ntlm.NTLMAuthChallengeResponse( self.user, self.password, self.serverChallenge) ntlmChallengeResponse['flags'] = flags ntlmChallengeResponse['host_name'] = self.workstationName.encode( 'utf-16le') ntlmChallengeResponse['domain_name'] = self.domain.encode('utf-16le') ntlmChallengeResponse['lanman'] = lmResponse ntlmChallengeResponse['ntlm'] = ntResponse ntlmChallengeResponse['session_key'] = encryptedSessionKey hexdump(ntlmChallengeResponse.getData()) self.assertTrue(ntlmChallengeResponse.getData() == bytearray( b'NTLMSSP\x00\x03\x00\x00\x00\x18\x00\x18\x00|\x00\x00\x00T\x00T\x00\x94\x00\x00\x00\x0c\x00\x0c\x00X\x00\x00\x00\x08\x00\x08\x00d\x00\x00\x00\x10\x00\x10\x00l\x00\x00\x00\x10\x00\x10\x00\xe8\x00\x00\x003\x82\x8a\xe2D\x00o\x00m\x00a\x00i\x00n\x00U\x00s\x00e\x00r\x00C\x00O\x00M\x00P\x00U\x00T\x00E\x00R\x00\x86\xc3P\x97\xac\x9c\xec\x10%TvJW\xcc\xcc\x19\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaah\xcd\n\xb8Q\xe5\x1c\x96\xaa\xbc\x92{\xeb\xefj\x1c\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\x00\x00\x00\x00\x02\x00\x0c\x00D\x00o\x00m\x00a\x00i\x00n\x00\x01\x00\x0c\x00S\x00e\x00r\x00v\x00e\x00r\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc5\xda\xd2TO\xc9y\x90\x94\xce\x1c\xe9\x0b\xc9\xd0>' )) print("\n") print("4.2.4.4 GSS_WrapEx") print("Plaintext") hexdump(self.plaintext) print("\n") print("Output of SEAL()") exportedSessionKey = self.randomSessionKey clientSigningKey = ntlm.SIGNKEY(flags, exportedSessionKey) clientSealingKey = ntlm.SEALKEY(flags, exportedSessionKey) from Cryptodome.Cipher import ARC4 cipher2 = ARC4.new(clientSealingKey) client_sealing_h = cipher2.encrypt print("SEALKEY()") hexdump(clientSealingKey) self.assertTrue(clientSealingKey == bytearray( b'Y\xf6\x00\x97<\xc4\x96\n%H\n|\x19nLX')) print("\n") print("SIGNKEY()") hexdump(clientSigningKey) self.assertTrue(clientSigningKey == bytearray( b'G\x88\xdc\x86\x1bG\x82\xf3]C\xfd\x98\xfe\x1a-9')) print("\n") print("Sealed Data") sealedMsg, signature = ntlm.SEAL(flags, clientSealingKey, clientSigningKey, self.plaintext, self.plaintext, self.seqNum, client_sealing_h) #signature = ntlm.SIGN(flags, clientSigningKey, plaintext, seqNum, client_sealing_h) hexdump(sealedMsg) self.assertTrue(sealedMsg == bytearray( b'T\xe5\x01e\xbf\x196\xdc\x99` \xc1\x81\x1b\x0f\x06\xfb_')) print("\n") print("Signature") hexdump(signature.getData()) self.assertTrue(signature.getData() == bytearray( b'\x01\x00\x00\x00\x00\xc1a\xa1\x1e@\x03\x9f\x00\x00\x00\x00')) #print (repr(bytearray(str(signature)))) #raise print("\n")
def run(self): if self.options.action.upper() == 'MASTERKEY': fp = open(options.file, 'rb') data = fp.read() mkf = MasterKeyFile(data) mkf.dump() data = data[len(mkf):] if mkf['MasterKeyLen'] > 0: mk = MasterKey(data[:mkf['MasterKeyLen']]) data = data[len(mk):] if mkf['BackupKeyLen'] > 0: bkmk = MasterKey(data[:mkf['BackupKeyLen']]) data = data[len(bkmk):] if mkf['CredHistLen'] > 0: ch = CredHist(data[:mkf['CredHistLen']]) data = data[len(ch):] if mkf['DomainKeyLen'] > 0: dk = DomainKey(data[:mkf['DomainKeyLen']]) data = data[len(dk):] if self.options.system and self.options.security and self.options.sid is None: # We have hives, let's try to decrypt with them self.getLSA() decryptedKey = mk.decrypt(self.dpapiSystem['UserKey']) if decryptedKey: print('Decrypted key with UserKey') print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1')) return decryptedKey = mk.decrypt(self.dpapiSystem['MachineKey']) if decryptedKey: print('Decrypted key with MachineKey') print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1')) return decryptedKey = bkmk.decrypt(self.dpapiSystem['UserKey']) if decryptedKey: print('Decrypted Backup key with UserKey') print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1')) return decryptedKey = bkmk.decrypt(self.dpapiSystem['MachineKey']) if decryptedKey: print('Decrypted Backup key with MachineKey') print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1')) return elif self.options.system and self.options.security: # Use SID + hash # We have hives, let's try to decrypt with them self.getLSA() key1, key2 = self.deriveKeysFromUserkey( self.options.sid, self.dpapiSystem['UserKey']) decryptedKey = mk.decrypt(key1) if decryptedKey: print('Decrypted key with UserKey + SID') print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1')) return decryptedKey = bkmk.decrypt(key1) if decryptedKey: print('Decrypted Backup key with UserKey + SID') print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1')) return decryptedKey = mk.decrypt(key2) if decryptedKey: print('Decrypted key with UserKey + SID') print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1')) return decryptedKey = bkmk.decrypt(key2) if decryptedKey: print('Decrypted Backup key with UserKey + SID') print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1')) return elif self.options.key and self.options.sid: key = unhexlify(self.options.key[2:]) key1, key2 = self.deriveKeysFromUserkey(self.options.sid, key) decryptedKey = mk.decrypt(key1) if decryptedKey: print('Decrypted key with key provided + SID') print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1')) return decryptedKey = mk.decrypt(key2) if decryptedKey: print('Decrypted key with key provided + SID') print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1')) return elif self.options.key: key = unhexlify(self.options.key[2:]) decryptedKey = mk.decrypt(key) if decryptedKey: print('Decrypted key with key provided') print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1')) return elif self.options.pvk and dk: pvkfile = open(self.options.pvk, 'rb').read() key = PRIVATE_KEY_BLOB(pvkfile[len(PVK_FILE_HDR()):]) private = privatekeyblob_to_pkcs1(key) cipher = PKCS1_v1_5.new(private) decryptedKey = cipher.decrypt(dk['SecretData'][::-1], None) if decryptedKey: domain_master_key = DPAPI_DOMAIN_RSA_MASTER_KEY( decryptedKey) key = domain_master_key[ 'buffer'][:domain_master_key['cbMasterKey']] print('Decrypted key with domain backup key provided') print('Decrypted key: 0x%s' % hexlify(key).decode('latin-1')) return elif self.options.sid and self.options.key is None: # Do we have a password? if self.options.password is None: # Nope let's ask it from getpass import getpass password = getpass("Password:"******"Password:"******"Password:"******"G$BCKUPKEY_PREFERRED", "G$BCKUPKEY_P"): buffer = crypto.decryptSecret( connection.getSessionKey(), lsad.hLsarRetrievePrivateData(dce, resp['PolicyHandle'], keyname)) guid = bin_to_string(buffer) name = "G$BCKUPKEY_{}".format(guid) secret = crypto.decryptSecret( connection.getSessionKey(), lsad.hLsarRetrievePrivateData(dce, resp['PolicyHandle'], name)) keyVersion = struct.unpack('<L', secret[:4])[0] if keyVersion == 1: # legacy key backup_key = P_BACKUP_KEY(secret) backupkey = backup_key['Data'] if self.options.export: logging.debug( "Exporting key to file {}".format(name + ".key")) open(name + ".key", 'wb').write(backupkey) else: print("Legacy key:") print("0x%s" % hexlify(backupkey).decode('latin-1')) print("\n") elif keyVersion == 2: # preferred key backup_key = PREFERRED_BACKUP_KEY(secret) pvk = backup_key['Data'][:backup_key['KeyLength']] cert = backup_key['Data'][ backup_key['KeyLength']:backup_key['KeyLength'] + backup_key['CertificateLength']] # build pvk header (PVK_MAGIC, PVK_FILE_VERSION_0, KeySpec, PVK_NO_ENCRYPT, 0, cbPvk) header = PVK_FILE_HDR() header['dwMagic'] = 0xb0b5f11e header['dwVersion'] = 0 header['dwKeySpec'] = 1 header['dwEncryptType'] = 0 header['cbEncryptData'] = 0 header['cbPvk'] = backup_key['KeyLength'] backupkey_pvk = header.getData() + pvk # pvk blob backupkey = backupkey_pvk if self.options.export: logging.debug( "Exporting certificate to file {}".format(name + ".der")) open(name + ".der", 'wb').write(cert) logging.debug( "Exporting private key to file {}".format(name + ".pvk")) open(name + ".pvk", 'wb').write(backupkey) else: print("Preferred key:") header.dump() print("PRIVATEKEYBLOB:{%s}" % (hexlify(backupkey).decode('latin-1'))) print("\n") return elif self.options.action.upper() == 'CREDENTIAL': fp = open(options.file, 'rb') data = fp.read() cred = CredentialFile(data) blob = DPAPI_BLOB(cred['Data']) if self.options.key is not None: key = unhexlify(self.options.key[2:]) decrypted = blob.decrypt(key) if decrypted is not None: creds = CREDENTIAL_BLOB(decrypted) creds.dump() return else: # Just print the data blob.dump() elif self.options.action.upper() == 'VAULT': if options.vcrd is None and options.vpol is None: print( 'You must specify either -vcrd or -vpol parameter. Type --help for more info' ) return if options.vcrd is not None: fp = open(options.vcrd, 'rb') data = fp.read() blob = VAULT_VCRD(data) if self.options.key is not None: key = unhexlify(self.options.key[2:]) cleartext = None for i, entry in enumerate(blob.attributesLen): if entry > 28: attribute = blob.attributes[i] if 'IV' in attribute.fields and len( attribute['IV']) == 16: cipher = AES.new(key, AES.MODE_CBC, iv=attribute['IV']) else: cipher = AES.new(key, AES.MODE_CBC) cleartext = cipher.decrypt(attribute['Data']) if cleartext is not None: # Lookup schema Friendly Name and print if we find one if blob['FriendlyName'].decode( 'utf-16le')[:-1] in VAULT_KNOWN_SCHEMAS: # Found one. Cast it and print vault = VAULT_KNOWN_SCHEMAS[ blob['FriendlyName'].decode('utf-16le')[:-1]]( cleartext) vault.dump() else: # otherwise hexdump(cleartext) return else: blob.dump() elif options.vpol is not None: fp = open(options.vpol, 'rb') data = fp.read() vpol = VAULT_VPOL(data) vpol.dump() if self.options.key is not None: key = unhexlify(self.options.key[2:]) blob = vpol['Blob'] data = blob.decrypt(key) if data is not None: keys = VAULT_VPOL_KEYS(data) keys.dump() return elif self.options.action.upper() == 'UNPROTECT': fp = open(options.file, 'rb') data = fp.read() blob = DPAPI_BLOB(data) if self.options.key is not None: key = unhexlify(self.options.key[2:]) if self.options.entropy_file is not None: fp2 = open(self.options.entropy_file, 'rb') entropy = fp2.read() fp2.close() elif self.options.entropy is not None: entropy = b(self.options.entropy) else: entropy = None decrypted = blob.decrypt(key, entropy) if decrypted is not None: print('Successfully decrypted data') hexdump(decrypted) return else: # Just print the data blob.dump() print('Cannot decrypt (specify -key or -sid whenever applicable) ')
def dump(self): print("KeyWord : %s" % (self['KeyWord'].decode('utf-16le'))) #print("Flags : %8x (%s)" % (self['Flags'], getFlags(CREDENTIAL_FLAGS, self['Flags']))) print("Data : ") hexdump(self['Data'])
def dump(self): baseOffset = len(self.record) self.record.dump() tags = self.data[-4*self.record['FirstAvailablePageTag']:] print("FLAGS: ") self.printFlags() print() for i in range(self.record['FirstAvailablePageTag']): tag = tags[-4:] if self.__DBHeader['Version'] == 0x620 and self.__DBHeader['FileFormatRevision'] > 11 and self.__DBHeader['PageSize'] > 8192: valueSize = unpack('<H', tag[:2])[0] & 0x7fff valueOffset = unpack('<H',tag[2:])[0] & 0x7fff hexdump((self.data[baseOffset+valueOffset:][:6])) pageFlags = ord(self.data[baseOffset+valueOffset:][1]) >> 5 #print "TAG FLAG: 0x%x " % (unpack('<L', self.data[baseOffset+valueOffset:][:4]) ) >> 5 #print "TAG FLAG: 0x " , ord(self.data[baseOffset+valueOffset:][0]) else: valueSize = unpack('<H', tag[:2])[0] & 0x1fff pageFlags = (unpack('<H', tag[2:])[0] & 0xe000) >> 13 valueOffset = unpack('<H',tag[2:])[0] & 0x1fff print("TAG %-8d offset:0x%-6x flags:0x%-4x valueSize:0x%x" % (i,valueOffset,pageFlags,valueSize)) #hexdump(self.getTag(i)[1]) tags = tags[:-4] if self.record['PageFlags'] & FLAGS_ROOT > 0: rootHeader = ESENT_ROOT_HEADER(self.getTag(0)[1]) rootHeader.dump() elif self.record['PageFlags'] & FLAGS_LEAF == 0: # Branch Header flags, data = self.getTag(0) branchHeader = ESENT_BRANCH_HEADER(data) branchHeader.dump() else: # Leaf Header flags, data = self.getTag(0) if self.record['PageFlags'] & FLAGS_SPACE_TREE > 0: # Space Tree spaceTreeHeader = ESENT_SPACE_TREE_HEADER(data) spaceTreeHeader.dump() else: leafHeader = ESENT_LEAF_HEADER(data) leafHeader.dump() # Print the leaf/branch tags for tagNum in range(1,self.record['FirstAvailablePageTag']): flags, data = self.getTag(tagNum) if self.record['PageFlags'] & FLAGS_LEAF == 0: # Branch page branchEntry = ESENT_BRANCH_ENTRY(flags, data) branchEntry.dump() elif self.record['PageFlags'] & FLAGS_LEAF > 0: # Leaf page if self.record['PageFlags'] & FLAGS_SPACE_TREE > 0: # Space Tree spaceTreeEntry = ESENT_SPACE_TREE_ENTRY(data) #spaceTreeEntry.dump() elif self.record['PageFlags'] & FLAGS_INDEX > 0: # Index Entry indexEntry = ESENT_INDEX_ENTRY(data) #indexEntry.dump() elif self.record['PageFlags'] & FLAGS_LONG_VALUE > 0: # Long Page Value raise Exception('Long value still not supported') else: # Table Value leafEntry = ESENT_LEAF_ENTRY(flags, data) dataDefinitionHeader = ESENT_DATA_DEFINITION_HEADER(leafEntry['EntryData']) dataDefinitionHeader.dump() catalogEntry = ESENT_CATALOG_DATA_DEFINITION_ENTRY(leafEntry['EntryData'][len(dataDefinitionHeader):]) catalogEntry.dump() hexdump(leafEntry['EntryData'])
def dump(self): baseOffset = len(self.record) self.record.dump() tags = self.data[-4 * self.record['FirstAvailablePageTag']:] print("FLAGS: ") self.printFlags() print() for i in range(self.record['FirstAvailablePageTag']): tag = tags[-4:] if self.__DBHeader['Version'] == 0x620 and self.__DBHeader[ 'FileFormatRevision'] > 11 and self.__DBHeader[ 'PageSize'] > 8192: valueSize = unpack('<H', tag[:2])[0] & 0x7fff valueOffset = unpack('<H', tag[2:])[0] & 0x7fff hexdump((self.data[baseOffset + valueOffset:][:6])) pageFlags = ord(self.data[baseOffset + valueOffset:][1]) >> 5 #print "TAG FLAG: 0x%x " % (unpack('<L', self.data[baseOffset+valueOffset:][:4]) ) >> 5 #print "TAG FLAG: 0x " , ord(self.data[baseOffset+valueOffset:][0]) else: valueSize = unpack('<H', tag[:2])[0] & 0x1fff pageFlags = (unpack('<H', tag[2:])[0] & 0xe000) >> 13 valueOffset = unpack('<H', tag[2:])[0] & 0x1fff print("TAG %-8d offset:0x%-6x flags:0x%-4x valueSize:0x%x" % (i, valueOffset, pageFlags, valueSize)) #hexdump(self.getTag(i)[1]) tags = tags[:-4] if self.record['PageFlags'] & FLAGS_ROOT > 0: rootHeader = ESENT_ROOT_HEADER(self.getTag(0)[1]) rootHeader.dump() elif self.record['PageFlags'] & FLAGS_LEAF == 0: # Branch Header flags, data = self.getTag(0) branchHeader = ESENT_BRANCH_HEADER(data) branchHeader.dump() else: # Leaf Header flags, data = self.getTag(0) if self.record['PageFlags'] & FLAGS_SPACE_TREE > 0: # Space Tree spaceTreeHeader = ESENT_SPACE_TREE_HEADER(data) spaceTreeHeader.dump() else: leafHeader = ESENT_LEAF_HEADER(data) leafHeader.dump() # Print the leaf/branch tags for tagNum in range(1, self.record['FirstAvailablePageTag']): flags, data = self.getTag(tagNum) if self.record['PageFlags'] & FLAGS_LEAF == 0: # Branch page branchEntry = ESENT_BRANCH_ENTRY(flags, data) branchEntry.dump() elif self.record['PageFlags'] & FLAGS_LEAF > 0: # Leaf page if self.record['PageFlags'] & FLAGS_SPACE_TREE > 0: # Space Tree spaceTreeEntry = ESENT_SPACE_TREE_ENTRY(data) #spaceTreeEntry.dump() elif self.record['PageFlags'] & FLAGS_INDEX > 0: # Index Entry indexEntry = ESENT_INDEX_ENTRY(data) #indexEntry.dump() elif self.record['PageFlags'] & FLAGS_LONG_VALUE > 0: # Long Page Value raise Exception('Long value still not supported') else: # Table Value leafEntry = ESENT_LEAF_ENTRY(flags, data) dataDefinitionHeader = ESENT_DATA_DEFINITION_HEADER( leafEntry['EntryData']) dataDefinitionHeader.dump() catalogEntry = ESENT_CATALOG_DATA_DEFINITION_ENTRY( leafEntry['EntryData'][len(dataDefinitionHeader):]) catalogEntry.dump() hexdump(leafEntry['EntryData'])
def run(self): if self.options.action.upper() == 'MASTERKEY': fp = open(options.file, 'rb') data = fp.read() mkf = MasterKeyFile(data) mkf.dump() data = data[len(mkf):] if mkf['MasterKeyLen'] > 0: mk = MasterKey(data[:mkf['MasterKeyLen']]) data = data[len(mk):] if mkf['BackupKeyLen'] > 0: bkmk = MasterKey(data[:mkf['BackupKeyLen']]) data = data[len(bkmk):] if mkf['CredHistLen'] > 0: ch = CredHist(data[:mkf['CredHistLen']]) data = data[len(ch):] if mkf['DomainKeyLen'] > 0: dk = DomainKey(data[:mkf['DomainKeyLen']]) data = data[len(dk):] if self.options.system and self.options.security: # We have hives, let's try to decrypt with them self.getLSA() decryptedKey = mk.decrypt(self.dpapiSystem['UserKey']) if decryptedKey: print('Decrypted key with UserKey') print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1')) return decryptedKey = mk.decrypt(self.dpapiSystem['MachineKey']) if decryptedKey: print('Decrypted key with MachineKey') print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1')) return decryptedKey = bkmk.decrypt(self.dpapiSystem['UserKey']) if decryptedKey: print('Decrypted Backup key with UserKey') print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1')) return decryptedKey = bkmk.decrypt(self.dpapiSystem['MachineKey']) if decryptedKey: print('Decrypted Backup key with MachineKey') print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1')) return elif self.options.key: key = unhexlify(self.options.key[2:]) decryptedKey = mk.decrypt(key) if decryptedKey: print('Decrypted key with key provided') print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1')) return elif self.options.sid and self.options.key is None: # Do we have a password? if self.options.password is None: # Nope let's ask it from getpass import getpass password = getpass("Password:") else: password = options.password key1, key2, key3 = self.deriveKeysFromUser( self.options.sid, password) # if mkf['flags'] & 4 ? SHA1 : MD4 decryptedKey = mk.decrypt(key3) if decryptedKey: print('Decrypted key with User Key (MD4 protected)') print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1')) return decryptedKey = mk.decrypt(key2) if decryptedKey: print('Decrypted key with User Key (MD4)') print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1')) return decryptedKey = mk.decrypt(key1) if decryptedKey: print('Decrypted key with User Key (SHA1)') print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1')) return decryptedKey = bkmk.decrypt(key3) if decryptedKey: print('Decrypted Backup key with User Key (MD4 protected)') print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1')) return decryptedKey = bkmk.decrypt(key2) if decryptedKey: print('Decrypted Backup key with User Key (MD4)') print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1')) return decryptedKey = bkmk.decrypt(key1) if decryptedKey: print('Decrypted Backup key with User Key (SHA1)') print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1')) return else: # Just print key's data if mkf['MasterKeyLen'] > 0: mk.dump() if mkf['BackupKeyLen'] > 0: bkmk.dump() if mkf['CredHistLen'] > 0: ch.dump() if mkf['DomainKeyLen'] > 0: dk.dump() elif self.options.action.upper() == 'CREDENTIAL': fp = open(options.file, 'rb') data = fp.read() cred = CredentialFile(data) blob = DPAPI_BLOB(cred['Data']) if self.options.key is not None: key = unhexlify(self.options.key[2:]) decrypted = blob.decrypt(key) if decrypted is not None: creds = CREDENTIAL_BLOB(decrypted) creds.dump() return else: # Just print the data blob.dump() elif self.options.action.upper() == 'VAULT': if options.vcrd is None and options.vpol is None: print( 'You must specify either -vcrd or -vpol parameter. Type --help for more info' ) return if options.vcrd is not None: fp = open(options.vcrd, 'rb') data = fp.read() blob = VAULT_VCRD(data) if self.options.key is not None: key = unhexlify(self.options.key[2:]) cleartext = None for i, entry in enumerate(blob.attributesLen): if entry > 28: attribute = blob.attributes[i] if 'IV' in attribute.fields and len( attribute['IV']) == 16: cipher = AES.new(key, AES.MODE_CBC, iv=attribute['IV']) else: cipher = AES.new(key, AES.MODE_CBC) cleartext = cipher.decrypt(attribute['Data']) if cleartext is not None: # Lookup schema Friendly Name and print if we find one if blob['FriendlyName'].decode( 'utf-16le')[:-1] in VAULT_KNOWN_SCHEMAS: # Found one. Cast it and print vault = VAULT_KNOWN_SCHEMAS[ blob['FriendlyName'].decode('utf-16le')[:-1]]( cleartext) vault.dump() else: # otherwise hexdump(cleartext) return else: blob.dump() elif options.vpol is not None: fp = open(options.vpol, 'rb') data = fp.read() vpol = VAULT_VPOL(data) vpol.dump() if self.options.key is not None: key = unhexlify(self.options.key[2:]) blob = vpol['Blob'] data = blob.decrypt(key) if data is not None: keys = VAULT_VPOL_KEYS(data) keys.dump() return print('Cannot decrypt (specify -key or -sid whenever applicable) ')
def dump(self): print("KeyWord : %s" % (self['KeyWord'].decode('utf-16le'))) #print("Flags : %8x (%s)" % (self['Flags'], getFlags(CREDENTIAL_FLAGS, self['Flags']))) print("Data : ") hexdump(self['Data'])
def run(self): if self.options.action.upper() == 'MASTERKEY': fp = open(options.file, 'rb') data = fp.read() mkf= MasterKeyFile(data) mkf.dump() data = data[len(mkf):] if mkf['MasterKeyLen'] > 0: mk = MasterKey(data[:mkf['MasterKeyLen']]) data = data[len(mk):] if mkf['BackupKeyLen'] > 0: bkmk = MasterKey(data[:mkf['BackupKeyLen']]) data = data[len(bkmk):] if mkf['CredHistLen'] > 0: ch = CredHist(data[:mkf['CredHistLen']]) data = data[len(ch):] if mkf['DomainKeyLen'] > 0: dk = DomainKey(data[:mkf['DomainKeyLen']]) data = data[len(dk):] if self.options.system and self.options.security: # We have hives, let's try to decrypt with them self.getLSA() decryptedKey = mk.decrypt(self.dpapiSystem['UserKey']) if decryptedKey: print('Decrypted key with UserKey') print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1')) return decryptedKey = mk.decrypt(self.dpapiSystem['MachineKey']) if decryptedKey: print('Decrypted key with MachineKey') print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1')) return decryptedKey = bkmk.decrypt(self.dpapiSystem['UserKey']) if decryptedKey: print('Decrypted Backup key with UserKey') print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1')) return decryptedKey = bkmk.decrypt(self.dpapiSystem['MachineKey']) if decryptedKey: print('Decrypted Backup key with MachineKey') print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1')) return elif self.options.key: key = unhexlify(self.options.key[2:]) decryptedKey = mk.decrypt(key) if decryptedKey: print('Decrypted key with key provided') print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1')) return elif self.options.pvk and dk: pvkfile = open(self.options.pvk, 'rb').read() key = PRIVATE_KEY_BLOB(pvkfile[len(PVK_FILE_HDR()):]) private = privatekeyblob_to_pkcs1(key) cipher = PKCS1_v1_5.new(private) decryptedKey = cipher.decrypt(dk['SecretData'][::-1], None) if decryptedKey: domain_master_key = DPAPI_DOMAIN_RSA_MASTER_KEY(decryptedKey) key = domain_master_key['buffer'][:domain_master_key['cbMasterKey']] print('Decrypted key with domain backup key provided') print('Decrypted key: 0x%s' % hexlify(key).decode('latin-1')) return elif self.options.sid and self.options.key is None: # Do we have a password? if self.options.password is None: # Nope let's ask it from getpass import getpass password = getpass("Password:"******"Password:"******"G$BCKUPKEY_PREFERRED", "G$BCKUPKEY_P"): buffer = crypto.decryptSecret(connection.getSessionKey(), lsad.hLsarRetrievePrivateData(dce, resp['PolicyHandle'], keyname)) guid = bin_to_string(buffer) name = "G$BCKUPKEY_{}".format(guid) secret = crypto.decryptSecret(connection.getSessionKey(), lsad.hLsarRetrievePrivateData(dce, resp['PolicyHandle'], name)) keyVersion = struct.unpack('<L', secret[:4])[0] if keyVersion == 1: # legacy key backup_key = P_BACKUP_KEY(secret) backupkey = backup_key['Data'] if self.options.export: logging.debug("Exporting key to file {}".format(name + ".key")) open(name + ".key", 'wb').write(backupkey) else: print("Legacy key:") print("0x%s" % hexlify(backupkey).decode('latin-1')) print("\n") elif keyVersion == 2: # preferred key backup_key = PREFERRED_BACKUP_KEY(secret) pvk = backup_key['Data'][:backup_key['KeyLength']] cert = backup_key['Data'][backup_key['KeyLength']:backup_key['KeyLength'] + backup_key['CertificateLength']] # build pvk header (PVK_MAGIC, PVK_FILE_VERSION_0, KeySpec, PVK_NO_ENCRYPT, 0, cbPvk) header = PVK_FILE_HDR() header['dwMagic'] = 0xb0b5f11e header['dwVersion'] = 0 header['dwKeySpec'] = 1 header['dwEncryptType'] = 0 header['cbEncryptData'] = 0 header['cbPvk'] = backup_key['KeyLength'] backupkey_pvk = header.getData() + pvk # pvk blob backupkey = backupkey_pvk if self.options.export: logging.debug("Exporting certificate to file {}".format(name + ".der")) open(name + ".der", 'wb').write(cert) logging.debug("Exporting private key to file {}".format(name + ".pvk")) open(name + ".pvk", 'wb').write(backupkey) else: print("Preferred key:") header.dump() print("PRIVATEKEYBLOB:{%s}" % (hexlify(backupkey).decode('latin-1'))) print("\n") return elif self.options.action.upper() == 'CREDENTIAL': fp = open(options.file, 'rb') data = fp.read() cred = CredentialFile(data) blob = DPAPI_BLOB(cred['Data']) if self.options.key is not None: key = unhexlify(self.options.key[2:]) decrypted = blob.decrypt(key) if decrypted is not None: creds = CREDENTIAL_BLOB(decrypted) creds.dump() return else: # Just print the data blob.dump() elif self.options.action.upper() == 'VAULT': if options.vcrd is None and options.vpol is None: print('You must specify either -vcrd or -vpol parameter. Type --help for more info') return if options.vcrd is not None: fp = open(options.vcrd, 'rb') data = fp.read() blob = VAULT_VCRD(data) if self.options.key is not None: key = unhexlify(self.options.key[2:]) cleartext = None for i, entry in enumerate(blob.attributesLen): if entry > 28: attribute = blob.attributes[i] if 'IV' in attribute.fields and len(attribute['IV']) == 16: cipher = AES.new(key, AES.MODE_CBC, iv=attribute['IV']) else: cipher = AES.new(key, AES.MODE_CBC) cleartext = cipher.decrypt(attribute['Data']) if cleartext is not None: # Lookup schema Friendly Name and print if we find one if blob['FriendlyName'].decode('utf-16le')[:-1] in VAULT_KNOWN_SCHEMAS: # Found one. Cast it and print vault = VAULT_KNOWN_SCHEMAS[blob['FriendlyName'].decode('utf-16le')[:-1]](cleartext) vault.dump() else: # otherwise hexdump(cleartext) return else: blob.dump() elif options.vpol is not None: fp = open(options.vpol, 'rb') data = fp.read() vpol = VAULT_VPOL(data) vpol.dump() if self.options.key is not None: key = unhexlify(self.options.key[2:]) blob = vpol['Blob'] data = blob.decrypt(key) if data is not None: keys = VAULT_VPOL_KEYS(data) keys.dump() return print('Cannot decrypt (specify -key or -sid whenever applicable) ')
def test_ntlmv1(self): print("####### 4.2.2 NTLMv1 Authentication") ntlm.USE_NTLMv2 = False print("4.2.2.1 LMOWFv1()") res = ntlm.LMOWFv1(self.password) print(repr(res)) hexdump(res) self.assertTrue(res==bytearray(b'\xe5,\xacgA\x9a\x9a"J;\x10\x8f?\xa6\xcbm')) print("\n") print("4.2.2.1.2 NTOWFv1()") res = ntlm.NTOWFv1(self.password) hexdump(res) self.assertTrue(res==bytearray(b'\xa4\xf4\x9c\x40\x65\x10\xbd\xca\xb6\x82\x4e\xe7\xc3\x0f\xd8\x52')) print("\n") print("4.2.2.1.3 Session Base Key and Key Exchange Key") ntResponse, lmResponse, sessionBaseKey = ntlm.computeResponseNTLMv1(int(self.flags), self.serverChallenge, self.clientChallenge, self.serverName, self.domain, self.user, self.password, '', '') hexdump(sessionBaseKey) self.assertTrue(sessionBaseKey==bytearray(b'\xD8\x72\x62\xB0\xCD\xE4\xB1\xCB\x74\x99\xBE\xCC\xCD\xF1\x07\x84')) print("\n") print("4.2.2.2.1 NTLMv1 Response") hexdump(ntResponse) self.assertTrue(ntResponse==bytearray(b'\x67\xC4\x30\x11\xF3\x02\x98\xA2\xAD\x35\xEC\xE6\x4F\x16\x33\x1C\x44\xBD\xBE\xD9\x27\x84\x1F\x94')) print("\n") print("4.2.2.2.2 LMv1 Response") hexdump(lmResponse) self.assertTrue(lmResponse==bytearray(b'\x98\xDE\xF7\xB8\x7F\x88\xAA\x5D\xAF\xE2\xDF\x77\x96\x88\xA1\x72\xde\xf1\x1c\x7d\x5c\xcd\xef\x13')) print("\n") print("4.2.2.2.2 LMv1 Response with NTLMSSP_NEGOTIATE_LM_KEY set") flags2 = self.flags #flags2 = flags | ntlm.NTLMSSP_LM_KEY #hexdump(struct.pack('<L',flags2)) ntResponse, lmResponse, sessionBaseKey = ntlm.computeResponseNTLMv1(int(flags2), self.serverChallenge, self.clientChallenge, self.serverName, self.domain, self.user, self.password, '', '') hexdump(lmResponse) print("\n") print("4.2.2.2.3 Encrypted Session Key ") ntResponse, lmResponse, sessionBaseKey = ntlm.computeResponseNTLMv1(int(self.flags), self.serverChallenge, self.clientChallenge, self.serverName, self.domain, self.user, self.password, '', '') keyExchangeKey = ntlm.KXKEY(self.flags, sessionBaseKey, lmResponse, self.serverChallenge, self.password,'','') encryptedSessionKey = ntlm.generateEncryptedSessionKey(keyExchangeKey,self.randomSessionKey) hexdump(encryptedSessionKey) self.assertTrue(encryptedSessionKey==bytearray(b'\x51\x88\x22\xB1\xB3\xF3\x50\xC8\x95\x86\x82\xEC\xBB\x3E\x3C\xB7')) print("\n") print("4.2.2.2.3 Encrypted Session Key (NTLMSSP_NON_NT_KEY)") flags2 = self.flags | ntlm.NTLMSSP_REQUEST_NON_NT_SESSION_KEY keyExchangeKey = ntlm.KXKEY(flags2, sessionBaseKey, lmResponse, self.serverChallenge, self.password,'','') encryptedSessionKey = ntlm.generateEncryptedSessionKey(keyExchangeKey,self.randomSessionKey) hexdump(encryptedSessionKey) #ToDo Fix this #self.assertTrue(encryptedSessionKey==bytearray(b'\x74\x52\xca\x55\xc2\x25\xa1\xca\x04\xb4\x8f\xae\x32\xcf\x56\xfc')) print("\n") print("4.2.2.2.3 Encrypted Session Key (NTLMSSP_LM_KEY)") flags2 = self.flags | ntlm.NTLMSSP_NEGOTIATE_LM_KEY #hexdump(struct.pack('<L',flags2)) keyExchangeKey = ntlm.KXKEY(flags2, sessionBaseKey, lmResponse, self.serverChallenge, self.password,'','') encryptedSessionKey = ntlm.generateEncryptedSessionKey(keyExchangeKey,self.randomSessionKey) hexdump(encryptedSessionKey) #ToDo Fix this #self.assertTrue(encryptedSessionKey==bytearray(b'\x4c\xd7\xbb\x57\xd6\x97\xef\x9b\x54\x9f\x02\xb8\xf9\xb3\x78\x64') print("\n") print("4.2.2.3 AUTHENTICATE MESSAGE") ntResponse, lmResponse, sessionBaseKey = ntlm.computeResponseNTLMv1(int(self.flags), self.serverChallenge, self.clientChallenge, self.serverName, self.domain, self.user, self.password, '', '') keyExchangeKey = ntlm.KXKEY(self.flags, sessionBaseKey, lmResponse, self.serverChallenge, self.password,'','') encryptedSessionKey = ntlm.generateEncryptedSessionKey(keyExchangeKey,self.randomSessionKey) ntlmChallengeResponse = ntlm.NTLMAuthChallengeResponse(self.user, self.password, self.serverChallenge) ntlmChallengeResponse['flags'] = flags2 ntlmChallengeResponse['host_name'] = self.workstationName.encode('utf-16le') ntlmChallengeResponse['domain_name'] = self.domain.encode('utf-16le') ntlmChallengeResponse['lanman'] = lmResponse ntlmChallengeResponse['ntlm'] = ntResponse ntlmChallengeResponse['session_key'] = encryptedSessionKey hexdump(ntlmChallengeResponse.getData()) self.assertTrue(ntlmChallengeResponse.getData()==bytearray(b'NTLMSSP\x00\x03\x00\x00\x00\x18\x00\x18\x00|\x00\x00\x00\x18\x00\x18\x00\x94\x00\x00\x00\x0c\x00\x0c\x00X\x00\x00\x00\x08\x00\x08\x00d\x00\x00\x00\x10\x00\x10\x00l\x00\x00\x00\x10\x00\x10\x00\xac\x00\x00\x00\xb3\x82\x02\xe2D\x00o\x00m\x00a\x00i\x00n\x00U\x00s\x00e\x00r\x00C\x00O\x00M\x00P\x00U\x00T\x00E\x00R\x00\x98\xde\xf7\xb8\x7f\x88\xaa]\xaf\xe2\xdfw\x96\x88\xa1r\xde\xf1\x1c}\\\xcd\xef\x13g\xc40\x11\xf3\x02\x98\xa2\xad5\xec\xe6O\x163\x1cD\xbd\xbe\xd9\'\x84\x1f\x94Q\x88"\xb1\xb3\xf3P\xc8\x95\x86\x82\xec\xbb><\xb7')) print("\n") print("4.2.2.4 GSS_WrapEx") print("Output of SEAL()") from Crypto.Cipher import ARC4 cipher = ARC4.new(self.randomSessionKey) handle = cipher.encrypt print("Plaintext") hexdump(self.plaintext) print("\n") sealedMsg, signature = ntlm.SEAL(self.flags, self.nonce, self.nonce, self.plaintext, self.plaintext, self.seqNum, handle) #signature = ntlm.SIGN(flags, nonce, plaintext, seqNum, handle) hexdump(sealedMsg) self.assertTrue(sealedMsg==bytearray(b'V\xfe\x04\xd8a\xf91\x9a\xf0\xd7#\x8a.;ME\x7f\xb8')) print("\n") hexdump(signature.getData()) self.assertTrue(signature.getData()==bytearray(b'\x01\x00\x00\x00\x00\x00\x00\x00\t\xdc\xd1\xdf.E\x9d6')) print("\n") print("####### 4.2.3 NTLMv1 with Client Challenge") flags = ntlm.NTLMSSP_NEGOTIATE_56 | ntlm.NTLMSSP_NEGOTIATE_VERSION | ntlm.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY \ | ntlm.NTLMSSP_TARGET_TYPE_SERVER | ntlm.NTLMSSP_NEGOTIATE_ALWAYS_SIGN | ntlm.NTLMSSP_NEGOTIATE_NTLM |\ ntlm.NTLMSSP_NEGOTIATE_SEAL | ntlm.NTLMSSP_NEGOTIATE_SIGN | ntlm.NTLM_NEGOTIATE_OEM | ntlm.NTLMSSP_NEGOTIATE_UNICODE print("Flags") hexdump(struct.pack('<L',flags)) print("\n") print("4.2.3.1.1 NTOWFv1(password)") hexdump(ntlm.NTOWFv1(self.password)) print("\n") print("4.2.3.1.2 Session Base Key") ntResponse, lmResponse, sessionBaseKey = ntlm.computeResponseNTLMv1(int(flags), self.serverChallenge, self.clientChallenge, self.serverName, self.domain, self.user, self.password, '', '') hexdump(sessionBaseKey) self.assertTrue(sessionBaseKey==bytearray(b'\xd8rb\xb0\xcd\xe4\xb1\xcbt\x99\xbe\xcc\xcd\xf1\x07\x84')) print("\n") print("4.2.3.1.3 Key Exchange Key") keyExchangeKey = ntlm.KXKEY(flags, sessionBaseKey, lmResponse, self.serverChallenge, self.password,'','') hexdump(keyExchangeKey) # ToDo: Fix this #self.assertTrue(keyExchangeKey==bytearray(b'\xeb\x93\x42\x9a\x8b\xd9\x52\xf8\xb8\x9c\x55\xb8\x7f\x47\x5e\xdc')) print("\n") print("4.2.3.2.1 LMv1 Response") hexdump(lmResponse) #self.assertTrue(lmResponse==bytearray(b'\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')) print("\n") print("4.2.3.2.2 NTLMv1 Response") hexdump(ntResponse) # ToDo: Fix this #self.assertTrue(ntResponse==bytearray(b'\x75\x37\xf8\x03\xae\x36\x71\x28\xca\x45\x82\x04\xbd\xe7\xca\xf8\x1e\x97\xed\x26\x83\x26\x72\x32')) print("\n") print("AUTHENTICATE MESSAGE") encryptedSessionKey = ntlm.generateEncryptedSessionKey(keyExchangeKey,self.randomSessionKey) ntlmChallengeResponse = ntlm.NTLMAuthChallengeResponse(self.user, self.password, self.serverChallenge) ntlmChallengeResponse['flags'] = flags2 ntlmChallengeResponse['host_name'] = self.workstationName.encode('utf-16le') ntlmChallengeResponse['domain_name'] = self.domain.encode('utf-16le') ntlmChallengeResponse['lanman'] = lmResponse ntlmChallengeResponse['ntlm'] = ntResponse hexdump(ntlmChallengeResponse.getData()) self.assertTrue(ntlmChallengeResponse.getData()==bytearray(b'NTLMSSP\x00\x03\x00\x00\x00\x18\x00\x18\x00|\x00\x00\x00\x18\x00\x18\x00\x94\x00\x00\x00\x0c\x00\x0c\x00X\x00\x00\x00\x08\x00\x08\x00d\x00\x00\x00\x10\x00\x10\x00l\x00\x00\x00\x00\x00\x00\x00\xac\x00\x00\x00\xb3\x82\x02\xe2D\x00o\x00m\x00a\x00i\x00n\x00U\x00s\x00e\x00r\x00C\x00O\x00M\x00P\x00U\x00T\x00E\x00R\x00\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00u7\xf8\x03\xae6q(\xcaE\x82\x04\xbd\xe7\xca\xf8\x1e\x97\xed&\x83&r2')) print("\n") print("4.2.3.4 GSS_WrapEx") print("Plaintext") hexdump(self.plaintext) print("\n") print("Output of SEAL()") exportedSessionKey = keyExchangeKey clientSigningKey = ntlm.SIGNKEY(flags, exportedSessionKey) serverSigningKey = ntlm.SIGNKEY(flags, exportedSessionKey, "Server") clientSealingKey = ntlm.SEALKEY(flags, exportedSessionKey) serverSealingKey = ntlm.SEALKEY(flags, exportedSessionKey, "Server") from Crypto.Cipher import ARC4 cipher = ARC4.new(clientSigningKey) client_signing_h = cipher.encrypt cipher2 = ARC4.new(clientSealingKey) client_sealing_h = cipher2.encrypt print("SEALKEY()") hexdump(clientSealingKey) print("\n") print("SIGNKEY()") hexdump(clientSigningKey) print("\n") print("Sealed Data") sealedMsg, signature = ntlm.SEAL(flags, clientSealingKey, clientSigningKey, self.plaintext, self.plaintext, self.seqNum, client_sealing_h) #signature = ntlm.SIGN(flags, clientSigningKey, plaintext, seqNum, client_sealing_h) hexdump(sealedMsg) # ToDo: Fix this #self.assertTrue(ntResponse==bytearray(b'\xa0\x23\x72\xf6\x53\x02\x73\xf3\xaa\x1e\xb9\x01\x90\xce\x52\x00\xc9\x9d')) print("\n") print("Signature") hexdump(signature.getData()) # ToDo: Fix this #self.assertTrue(ntResponse==bytearray(b'\x01\x00\x00\x00\xff\x2a\xeb\x52\xf6\x81\x79\x3a\x00\x00\x00\x00') print("\n")
def test_ntlmv2(self): print("####### 4.2.4 NTLMv2 Authentication") ntlm.USE_NTLMv2 = True serverName = '\x02\x00\x0c\x00\x44\x00\x6f\x00\x6d\x00\x61\x00\x69\x00\x6e\x00\x01\x00\x0c\x00\x53\x00\x65\x00\x72\x00\x76\x00\x65\x00\x72\x00\x00\x00\x00\x00' # Still the aTime won't be set to zero. that must be changed in ntlm.computeResponseNTLM2. Gotta make this more automated flags = ntlm.NTLMSSP_NEGOTIATE_KEY_EXCH | ntlm.NTLMSSP_NEGOTIATE_56 | ntlm.NTLMSSP_NEGOTIATE_128 | \ ntlm.NTLMSSP_NEGOTIATE_VERSION | ntlm.NTLMSSP_NEGOTIATE_TARGET_INFO | \ ntlm.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY | ntlm.NTLMSSP_TARGET_TYPE_SERVER | \ ntlm.NTLMSSP_NEGOTIATE_ALWAYS_SIGN | ntlm.NTLMSSP_NEGOTIATE_NTLM | ntlm.NTLMSSP_NEGOTIATE_SEAL | \ ntlm.NTLMSSP_NEGOTIATE_SIGN | ntlm.NTLM_NEGOTIATE_OEM | ntlm.NTLMSSP_NEGOTIATE_UNICODE print("Flags") hexdump(struct.pack('<L',flags)) print("\n") print("4.2.4.1.1 NTOWFv2 and LMOWFv2") res = ntlm.NTOWFv2(self.user,self.password,self.domain) hexdump(res) self.assertTrue(res==bytearray(b'\x0c\x86\x8a@;\xfdz\x93\xa3\x00\x1e\xf2.\xf0.?')) print("\n") print("\n") print("4.2.4.1.2 Session Base Key") ntResponse, lmResponse, sessionBaseKey = ntlm.computeResponseNTLMv2(flags, self.serverChallenge, self.clientChallenge, serverName, self.domain, self.user, self.password, '', '' ) hexdump(sessionBaseKey) self.assertTrue(sessionBaseKey==bytearray(b'\x8d\xe4\x0c\xca\xdb\xc1\x4a\x82\xf1\x5c\xb0\xad\x0d\xe9\x5c\xa3')) print("\n") print("4.2.4.2.1 LMv2 Response") hexdump(lmResponse) self.assertTrue(lmResponse==bytearray(b'\x86\xc3P\x97\xac\x9c\xec\x10%TvJW\xcc\xcc\x19\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa')) print("\n") print("4.2.4.2.2 NTLMv2 Response") hexdump(ntResponse[:16]) self.assertTrue(ntResponse[:16]==bytearray(b'\x68\xcd\x0a\xb8\x51\xe5\x1c\x96\xaa\xbc\x92\x7b\xeb\xef\x6a\x1c')) print("\n") print("4.2.4.2.3 Encrypted Session Key") keyExchangeKey = ntlm.KXKEY(flags, sessionBaseKey, lmResponse, self.serverChallenge, self.password,'','') encryptedSessionKey = ntlm.generateEncryptedSessionKey(keyExchangeKey,self.randomSessionKey) hexdump(encryptedSessionKey) self.assertTrue(encryptedSessionKey==bytearray(b'\xC5\xDA\xD2\x54\x4F\xC9\x79\x90\x94\xCE\x1C\xE9\x0B\xC9\xD0\x3E')) print("\n") print("AUTHENTICATE MESSAGE") encryptedSessionKey = ntlm.generateEncryptedSessionKey(keyExchangeKey,self.randomSessionKey) ntlmChallengeResponse = ntlm.NTLMAuthChallengeResponse(self.user, self.password, self.serverChallenge) ntlmChallengeResponse['flags'] = flags ntlmChallengeResponse['host_name'] = self.workstationName.encode('utf-16le') ntlmChallengeResponse['domain_name'] = self.domain.encode('utf-16le') ntlmChallengeResponse['lanman'] = lmResponse ntlmChallengeResponse['ntlm'] = ntResponse ntlmChallengeResponse['session_key'] = encryptedSessionKey hexdump(ntlmChallengeResponse.getData()) self.assertTrue(ntlmChallengeResponse.getData()==bytearray(b'NTLMSSP\x00\x03\x00\x00\x00\x18\x00\x18\x00|\x00\x00\x00T\x00T\x00\x94\x00\x00\x00\x0c\x00\x0c\x00X\x00\x00\x00\x08\x00\x08\x00d\x00\x00\x00\x10\x00\x10\x00l\x00\x00\x00\x10\x00\x10\x00\xe8\x00\x00\x003\x82\x8a\xe2D\x00o\x00m\x00a\x00i\x00n\x00U\x00s\x00e\x00r\x00C\x00O\x00M\x00P\x00U\x00T\x00E\x00R\x00\x86\xc3P\x97\xac\x9c\xec\x10%TvJW\xcc\xcc\x19\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaah\xcd\n\xb8Q\xe5\x1c\x96\xaa\xbc\x92{\xeb\xefj\x1c\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\x00\x00\x00\x00\x02\x00\x0c\x00D\x00o\x00m\x00a\x00i\x00n\x00\x01\x00\x0c\x00S\x00e\x00r\x00v\x00e\x00r\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc5\xda\xd2TO\xc9y\x90\x94\xce\x1c\xe9\x0b\xc9\xd0>')) print("\n") print("4.2.4.4 GSS_WrapEx") print("Plaintext") hexdump(self.plaintext) print("\n") print("Output of SEAL()") exportedSessionKey = self.randomSessionKey clientSigningKey = ntlm.SIGNKEY(flags, exportedSessionKey) serverSigningKey = ntlm.SIGNKEY(flags, exportedSessionKey, "Server") clientSealingKey = ntlm.SEALKEY(flags, exportedSessionKey) serverSealingKey = ntlm.SEALKEY(flags, exportedSessionKey, "Server") from Crypto.Cipher import ARC4 cipher = ARC4.new(clientSigningKey) client_signing_h = cipher.encrypt cipher2 = ARC4.new(clientSealingKey) client_sealing_h = cipher2.encrypt print("SEALKEY()") hexdump(clientSealingKey) self.assertTrue(clientSealingKey==bytearray(b'Y\xf6\x00\x97<\xc4\x96\n%H\n|\x19nLX')) print("\n") print("SIGNKEY()") hexdump(clientSigningKey) self.assertTrue(clientSigningKey==bytearray(b'G\x88\xdc\x86\x1bG\x82\xf3]C\xfd\x98\xfe\x1a-9')) print("\n") print("Sealed Data") sealedMsg, signature = ntlm.SEAL(flags, clientSealingKey, clientSigningKey, self.plaintext, self.plaintext, self.seqNum, client_sealing_h) #signature = ntlm.SIGN(flags, clientSigningKey, plaintext, seqNum, client_sealing_h) hexdump(sealedMsg) self.assertTrue(sealedMsg==bytearray(b'T\xe5\x01e\xbf\x196\xdc\x99` \xc1\x81\x1b\x0f\x06\xfb_')) print("\n") print("Signature") hexdump(signature.getData()) self.assertTrue(signature.getData()==bytearray(b'\x01\x00\x00\x00\x00\xc1a\xa1\x1e@\x03\x9f\x00\x00\x00\x00')) #print (repr(bytearray(str(signature)))) #raise print("\n")
def test_ntlmv1(self): print("####### 4.2.2 NTLMv1 Authentication") ntlm.USE_NTLMv2 = False print("4.2.2.1 LMOWFv1()") res = ntlm.LMOWFv1(self.password) hexdump(res) self.assertTrue( res == bytearray(b'\xe5,\xacgA\x9a\x9a"J;\x10\x8f?\xa6\xcbm')) print("\n") print("4.2.2.1.2 NTOWFv1()") res = ntlm.NTOWFv1(self.password) hexdump(res) self.assertTrue(res == bytearray( b'\xa4\xf4\x9c\x40\x65\x10\xbd\xca\xb6\x82\x4e\xe7\xc3\x0f\xd8\x52' )) print("\n") print("4.2.2.1.3 Session Base Key and Key Exchange Key") ntResponse, lmResponse, sessionBaseKey = ntlm.computeResponseNTLMv1( int(self.flags), self.serverChallenge, self.clientChallenge, self.serverName, self.domain, self.user, self.password, '', '') hexdump(sessionBaseKey) self.assertTrue(sessionBaseKey == bytearray( b'\xD8\x72\x62\xB0\xCD\xE4\xB1\xCB\x74\x99\xBE\xCC\xCD\xF1\x07\x84' )) print("\n") print("4.2.2.2.1 NTLMv1 Response") hexdump(ntResponse) self.assertTrue(ntResponse == bytearray( b'\x67\xC4\x30\x11\xF3\x02\x98\xA2\xAD\x35\xEC\xE6\x4F\x16\x33\x1C\x44\xBD\xBE\xD9\x27\x84\x1F\x94' )) print("\n") print("4.2.2.2.2 LMv1 Response") hexdump(lmResponse) self.assertTrue(lmResponse == bytearray( b'\x98\xDE\xF7\xB8\x7F\x88\xAA\x5D\xAF\xE2\xDF\x77\x96\x88\xA1\x72\xde\xf1\x1c\x7d\x5c\xcd\xef\x13' )) print("\n") print("4.2.2.2.2 LMv1 Response with NTLMSSP_NEGOTIATE_LM_KEY set") flags2 = self.flags #flags2 = flags | ntlm.NTLMSSP_LM_KEY #hexdump(struct.pack('<L',flags2)) ntResponse, lmResponse, sessionBaseKey = ntlm.computeResponseNTLMv1( int(flags2), self.serverChallenge, self.clientChallenge, self.serverName, self.domain, self.user, self.password, '', '') hexdump(lmResponse) print("\n") print("4.2.2.2.3 Encrypted Session Key ") ntResponse, lmResponse, sessionBaseKey = ntlm.computeResponseNTLMv1( int(self.flags), self.serverChallenge, self.clientChallenge, self.serverName, self.domain, self.user, self.password, '', '') keyExchangeKey = ntlm.KXKEY(self.flags, sessionBaseKey, lmResponse, self.serverChallenge, self.password, '', '') encryptedSessionKey = ntlm.generateEncryptedSessionKey( keyExchangeKey, self.randomSessionKey) hexdump(encryptedSessionKey) self.assertTrue(encryptedSessionKey == bytearray( b'\x51\x88\x22\xB1\xB3\xF3\x50\xC8\x95\x86\x82\xEC\xBB\x3E\x3C\xB7' )) print("\n") print("4.2.2.2.3 Encrypted Session Key (NTLMSSP_NON_NT_KEY)") flags2 = self.flags | ntlm.NTLMSSP_REQUEST_NON_NT_SESSION_KEY keyExchangeKey = ntlm.KXKEY(flags2, sessionBaseKey, lmResponse, self.serverChallenge, self.password, '', '') encryptedSessionKey = ntlm.generateEncryptedSessionKey( keyExchangeKey, self.randomSessionKey) hexdump(encryptedSessionKey) #ToDo Fix this #self.assertTrue(encryptedSessionKey==bytearray(b'\x74\x52\xca\x55\xc2\x25\xa1\xca\x04\xb4\x8f\xae\x32\xcf\x56\xfc')) print("\n") print("4.2.2.2.3 Encrypted Session Key (NTLMSSP_LM_KEY)") flags2 = self.flags | ntlm.NTLMSSP_NEGOTIATE_LM_KEY #hexdump(struct.pack('<L',flags2)) keyExchangeKey = ntlm.KXKEY(flags2, sessionBaseKey, lmResponse, self.serverChallenge, self.password, '', '') encryptedSessionKey = ntlm.generateEncryptedSessionKey( keyExchangeKey, self.randomSessionKey) hexdump(encryptedSessionKey) #ToDo Fix this #self.assertTrue(encryptedSessionKey==bytearray(b'\x4c\xd7\xbb\x57\xd6\x97\xef\x9b\x54\x9f\x02\xb8\xf9\xb3\x78\x64') print("\n") print("4.2.2.3 AUTHENTICATE MESSAGE") ntResponse, lmResponse, sessionBaseKey = ntlm.computeResponseNTLMv1( int(self.flags), self.serverChallenge, self.clientChallenge, self.serverName, self.domain, self.user, self.password, '', '') keyExchangeKey = ntlm.KXKEY(self.flags, sessionBaseKey, lmResponse, self.serverChallenge, self.password, '', '') encryptedSessionKey = ntlm.generateEncryptedSessionKey( keyExchangeKey, self.randomSessionKey) ntlmChallengeResponse = ntlm.NTLMAuthChallengeResponse( self.user, self.password, self.serverChallenge) ntlmChallengeResponse['flags'] = flags2 ntlmChallengeResponse['host_name'] = self.workstationName.encode( 'utf-16le') ntlmChallengeResponse['domain_name'] = self.domain.encode('utf-16le') ntlmChallengeResponse['lanman'] = lmResponse ntlmChallengeResponse['ntlm'] = ntResponse ntlmChallengeResponse['session_key'] = encryptedSessionKey hexdump(ntlmChallengeResponse.getData()) self.assertTrue(ntlmChallengeResponse.getData() == bytearray( b'NTLMSSP\x00\x03\x00\x00\x00\x18\x00\x18\x00|\x00\x00\x00\x18\x00\x18\x00\x94\x00\x00\x00\x0c\x00\x0c\x00X\x00\x00\x00\x08\x00\x08\x00d\x00\x00\x00\x10\x00\x10\x00l\x00\x00\x00\x10\x00\x10\x00\xac\x00\x00\x00\xb3\x82\x02\xe2D\x00o\x00m\x00a\x00i\x00n\x00U\x00s\x00e\x00r\x00C\x00O\x00M\x00P\x00U\x00T\x00E\x00R\x00\x98\xde\xf7\xb8\x7f\x88\xaa]\xaf\xe2\xdfw\x96\x88\xa1r\xde\xf1\x1c}\\\xcd\xef\x13g\xc40\x11\xf3\x02\x98\xa2\xad5\xec\xe6O\x163\x1cD\xbd\xbe\xd9\'\x84\x1f\x94Q\x88"\xb1\xb3\xf3P\xc8\x95\x86\x82\xec\xbb><\xb7' )) print("\n") print("4.2.2.4 GSS_WrapEx") print("Output of SEAL()") from Cryptodome.Cipher import ARC4 cipher = ARC4.new(self.randomSessionKey) handle = cipher.encrypt print("Plaintext") hexdump(self.plaintext) print("\n") sealedMsg, signature = ntlm.SEAL(self.flags, self.nonce, self.nonce, self.plaintext, self.plaintext, self.seqNum, handle) #signature = ntlm.SIGN(flags, nonce, plaintext, seqNum, handle) hexdump(sealedMsg) self.assertTrue(sealedMsg == bytearray( b'V\xfe\x04\xd8a\xf91\x9a\xf0\xd7#\x8a.;ME\x7f\xb8')) print("\n") hexdump(signature.getData()) self.assertTrue(signature.getData() == bytearray( b'\x01\x00\x00\x00\x00\x00\x00\x00\t\xdc\xd1\xdf.E\x9d6')) print("\n") print("####### 4.2.3 NTLMv1 with Client Challenge") flags = ntlm.NTLMSSP_NEGOTIATE_56 | ntlm.NTLMSSP_NEGOTIATE_VERSION | ntlm.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY \ | ntlm.NTLMSSP_TARGET_TYPE_SERVER | ntlm.NTLMSSP_NEGOTIATE_ALWAYS_SIGN | ntlm.NTLMSSP_NEGOTIATE_NTLM |\ ntlm.NTLMSSP_NEGOTIATE_SEAL | ntlm.NTLMSSP_NEGOTIATE_SIGN | ntlm.NTLM_NEGOTIATE_OEM | ntlm.NTLMSSP_NEGOTIATE_UNICODE print("Flags") hexdump(struct.pack('<L', flags)) print("\n") print("4.2.3.1.1 NTOWFv1(password)") hexdump(ntlm.NTOWFv1(self.password)) print("\n") print("4.2.3.1.2 Session Base Key") ntResponse, lmResponse, sessionBaseKey = ntlm.computeResponseNTLMv1( int(flags), self.serverChallenge, self.clientChallenge, self.serverName, self.domain, self.user, self.password, '', '') hexdump(sessionBaseKey) self.assertTrue(sessionBaseKey == bytearray( b'\xd8rb\xb0\xcd\xe4\xb1\xcbt\x99\xbe\xcc\xcd\xf1\x07\x84')) print("\n") print("4.2.3.1.3 Key Exchange Key") keyExchangeKey = ntlm.KXKEY(flags, sessionBaseKey, lmResponse, self.serverChallenge, self.password, '', '') hexdump(keyExchangeKey) # ToDo: Fix this #self.assertTrue(keyExchangeKey==bytearray(b'\xeb\x93\x42\x9a\x8b\xd9\x52\xf8\xb8\x9c\x55\xb8\x7f\x47\x5e\xdc')) print("\n") print("4.2.3.2.1 LMv1 Response") hexdump(lmResponse) #self.assertTrue(lmResponse==bytearray(b'\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')) print("\n") print("4.2.3.2.2 NTLMv1 Response") hexdump(ntResponse) # ToDo: Fix this #self.assertTrue(ntResponse==bytearray(b'\x75\x37\xf8\x03\xae\x36\x71\x28\xca\x45\x82\x04\xbd\xe7\xca\xf8\x1e\x97\xed\x26\x83\x26\x72\x32')) print("\n") print("AUTHENTICATE MESSAGE") ntlm.generateEncryptedSessionKey(keyExchangeKey, self.randomSessionKey) ntlmChallengeResponse = ntlm.NTLMAuthChallengeResponse( self.user, self.password, self.serverChallenge) ntlmChallengeResponse['flags'] = flags2 ntlmChallengeResponse['host_name'] = self.workstationName.encode( 'utf-16le') ntlmChallengeResponse['domain_name'] = self.domain.encode('utf-16le') ntlmChallengeResponse['lanman'] = lmResponse ntlmChallengeResponse['ntlm'] = ntResponse hexdump(ntlmChallengeResponse.getData()) self.assertTrue(ntlmChallengeResponse.getData() == bytearray( b'NTLMSSP\x00\x03\x00\x00\x00\x18\x00\x18\x00|\x00\x00\x00\x18\x00\x18\x00\x94\x00\x00\x00\x0c\x00\x0c\x00X\x00\x00\x00\x08\x00\x08\x00d\x00\x00\x00\x10\x00\x10\x00l\x00\x00\x00\x00\x00\x00\x00\xac\x00\x00\x00\xb3\x82\x02\xe2D\x00o\x00m\x00a\x00i\x00n\x00U\x00s\x00e\x00r\x00C\x00O\x00M\x00P\x00U\x00T\x00E\x00R\x00\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00u7\xf8\x03\xae6q(\xcaE\x82\x04\xbd\xe7\xca\xf8\x1e\x97\xed&\x83&r2' )) print("\n") print("4.2.3.4 GSS_WrapEx") print("Plaintext") hexdump(self.plaintext) print("\n") print("Output of SEAL()") exportedSessionKey = keyExchangeKey clientSigningKey = ntlm.SIGNKEY(flags, exportedSessionKey) clientSealingKey = ntlm.SEALKEY(flags, exportedSessionKey) from Cryptodome.Cipher import ARC4 cipher = ARC4.new(clientSigningKey) cipher2 = ARC4.new(clientSealingKey) client_sealing_h = cipher2.encrypt print("SEALKEY()") hexdump(clientSealingKey) print("\n") print("SIGNKEY()") hexdump(clientSigningKey) print("\n") print("Sealed Data") sealedMsg, signature = ntlm.SEAL(flags, clientSealingKey, clientSigningKey, self.plaintext, self.plaintext, self.seqNum, client_sealing_h) #signature = ntlm.SIGN(flags, clientSigningKey, plaintext, seqNum, client_sealing_h) hexdump(sealedMsg) # ToDo: Fix this #self.assertTrue(ntResponse==bytearray(b'\xa0\x23\x72\xf6\x53\x02\x73\xf3\xaa\x1e\xb9\x01\x90\xce\x52\x00\xc9\x9d')) print("\n") print("Signature") hexdump(signature.getData()) # ToDo: Fix this #self.assertTrue(ntResponse==bytearray(b'\x01\x00\x00\x00\xff\x2a\xeb\x52\xf6\x81\x79\x3a\x00\x00\x00\x00') print("\n")
def test_hRpcEnumPrinters(self): dce, rpctransport = self.connect() resp = rprn.hRpcEnumPrinters(dce, rprn.PRINTER_ENUM_LOCAL, NULL, 1) hexdump(resp['pPrinterEnum'])
def test_hRpcEnumPrinters(self): dce, rpctransport = self.connect() resp = rprn.hRpcEnumPrinters(dce, rprn.PRINTER_ENUM_LOCAL, NULL, 1) hexdump(resp['pPrinterEnum'])
def run(self): if self.options.action.upper() == 'MASTERKEY': fp = open(options.file, 'rb') data = fp.read() mkf= MasterKeyFile(data) mkf.dump() data = data[len(mkf):] if mkf['MasterKeyLen'] > 0: mk = MasterKey(data[:mkf['MasterKeyLen']]) data = data[len(mk):] if mkf['BackupKeyLen'] > 0: bkmk = MasterKey(data[:mkf['BackupKeyLen']]) data = data[len(bkmk):] if mkf['CredHistLen'] > 0: ch = CredHist(data[:mkf['CredHistLen']]) data = data[len(ch):] if mkf['DomainKeyLen'] > 0: dk = DomainKey(data[:mkf['DomainKeyLen']]) data = data[len(dk):] if self.options.system and self.options.security: # We have hives, let's try to decrypt with them self.getLSA() decryptedKey = mk.decrypt(self.dpapiSystem['UserKey']) if decryptedKey: print('Decrypted key with UserKey') print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1')) return decryptedKey = mk.decrypt(self.dpapiSystem['MachineKey']) if decryptedKey: print('Decrypted key with MachineKey') print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1')) return decryptedKey = bkmk.decrypt(self.dpapiSystem['UserKey']) if decryptedKey: print('Decrypted Backup key with UserKey') print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1')) return decryptedKey = bkmk.decrypt(self.dpapiSystem['MachineKey']) if decryptedKey: print('Decrypted Backup key with MachineKey') print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1')) return elif self.options.key: key = unhexlify(self.options.key[2:]) decryptedKey = mk.decrypt(key) if decryptedKey: print('Decrypted key with key provided') print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1')) return elif self.options.pvk and dk: pvkfile = open(self.options.pvk, 'rb').read() key = PRIVATE_KEY_BLOB(pvkfile[len(PVK_FILE_HDR()):]) private = privatekeyblob_to_pkcs1(key) cipher = PKCS1_v1_5.new(private) decryptedKey = cipher.decrypt(dk['SecretData'][::-1], None) if decryptedKey: domain_master_key = DPAPI_DOMAIN_RSA_MASTER_KEY(decryptedKey) key = domain_master_key['buffer'][:domain_master_key['cbMasterKey']] print('Decrypted key with domain backup key provided') print('Decrypted key: 0x%s' % hexlify(key).decode('latin-1')) return elif self.options.sid and self.options.key is None: # Do we have a password? if self.options.password is None: # Nope let's ask it from getpass import getpass password = getpass("Password:"******"Password:"******"G$BCKUPKEY_PREFERRED", "G$BCKUPKEY_P"): buffer = crypto.decryptSecret(connection.getSessionKey(), lsad.hLsarRetrievePrivateData(dce, resp['PolicyHandle'], keyname)) guid = bin_to_string(buffer) name = "G$BCKUPKEY_{}".format(guid) secret = crypto.decryptSecret(connection.getSessionKey(), lsad.hLsarRetrievePrivateData(dce, resp['PolicyHandle'], name)) keyVersion = struct.unpack('<L', secret[:4])[0] if keyVersion == 1: # legacy key backup_key = P_BACKUP_KEY(secret) backupkey = backup_key['Data'] if self.options.export: logging.debug("Exporting key to file {}".format(name + ".key")) open(name + ".key", 'wb').write(backupkey) else: print("Legacy key:") print("0x%s" % hexlify(backupkey)) print("\n") elif keyVersion == 2: # preferred key backup_key = PREFERRED_BACKUP_KEY(secret) pvk = backup_key['Data'][:backup_key['KeyLength']] cert = backup_key['Data'][backup_key['KeyLength']:backup_key['KeyLength'] + backup_key['CertificateLength']] # build pvk header (PVK_MAGIC, PVK_FILE_VERSION_0, KeySpec, PVK_NO_ENCRYPT, 0, cbPvk) header = PVK_FILE_HDR() header['dwMagic'] = 0xb0b5f11e header['dwVersion'] = 0 header['dwKeySpec'] = 1 header['dwEncryptType'] = 0 header['cbEncryptData'] = 0 header['cbPvk'] = backup_key['KeyLength'] backupkey_pvk = header.getData() + pvk # pvk blob backupkey = backupkey_pvk if self.options.export: logging.debug("Exporting certificate to file {}".format(name + ".der")) open(name + ".der", 'wb').write(cert) logging.debug("Exporting private key to file {}".format(name + ".pvk")) open(name + ".pvk", 'wb').write(backupkey) else: print("Preferred key:") header.dump() print("PRIVATEKEYBLOB:{%s}" % (hexlify(backupkey))) print("\n") return elif self.options.action.upper() == 'CREDENTIAL': fp = open(options.file, 'rb') data = fp.read() cred = CredentialFile(data) blob = DPAPI_BLOB(cred['Data']) if self.options.key is not None: key = unhexlify(self.options.key[2:]) decrypted = blob.decrypt(key) if decrypted is not None: creds = CREDENTIAL_BLOB(decrypted) creds.dump() return else: # Just print the data blob.dump() elif self.options.action.upper() == 'VAULT': if options.vcrd is None and options.vpol is None: print('You must specify either -vcrd or -vpol parameter. Type --help for more info') return if options.vcrd is not None: fp = open(options.vcrd, 'rb') data = fp.read() blob = VAULT_VCRD(data) if self.options.key is not None: key = unhexlify(self.options.key[2:]) cleartext = None for i, entry in enumerate(blob.attributesLen): if entry > 28: attribute = blob.attributes[i] if 'IV' in attribute.fields and len(attribute['IV']) == 16: cipher = AES.new(key, AES.MODE_CBC, iv=attribute['IV']) else: cipher = AES.new(key, AES.MODE_CBC) cleartext = cipher.decrypt(attribute['Data']) if cleartext is not None: # Lookup schema Friendly Name and print if we find one if blob['FriendlyName'].decode('utf-16le')[:-1] in VAULT_KNOWN_SCHEMAS: # Found one. Cast it and print vault = VAULT_KNOWN_SCHEMAS[blob['FriendlyName'].decode('utf-16le')[:-1]](cleartext) vault.dump() else: # otherwise hexdump(cleartext) return else: blob.dump() elif options.vpol is not None: fp = open(options.vpol, 'rb') data = fp.read() vpol = VAULT_VPOL(data) vpol.dump() if self.options.key is not None: key = unhexlify(self.options.key[2:]) blob = vpol['Blob'] data = blob.decrypt(key) if data is not None: keys = VAULT_VPOL_KEYS(data) keys.dump() return print('Cannot decrypt (specify -key or -sid whenever applicable) ')