def decrypt_hash(self, rid, hashobj, constant): key1, key2 = SAM.rid_to_key(rid) des1 = des(key1) des2 = des(key2) if isinstance(hashobj, SAM_HASH): rc4key = hashlib.md5( self.hashed_bootkey[:0x10] + int(rid, 16).to_bytes(4, 'little', signed=False) + constant).digest() key = RC4(rc4key).encrypt(hashobj.hash) else: key = b'' cipher = AESModeOfOperationCBC(self.hashed_bootkey[:0x10], iv=hashobj.salt) n = 16 for block in [ hashobj.data[i:i + n] for i in range(0, len(hashobj.data), n) ]: #terrible, terrible workaround key += cipher.decrypt(block) key = key[:16] dec_hash = des1.decrypt(key[:8]) + des2.decrypt(key[8:]) return dec_hash
def get_HBoot_key(self): logger.debug('SAM parsing hashed bootkey') QWERTY = b"!@#$%^&*()qwertyUIOPAzxcvbnmQQQQQQQQQQQQ)(*@&%\0" DIGITS = b"0123456789012345678901234567890123456789\0" F = self.hive.get_value(r'SAM\Domains\Account\F')[1] logger.log(1,'[SAM] F key value: %s' % F) domain_properties = DOMAIN_ACCOUNT_F.from_bytes(F) if isinstance(domain_properties.key_0, SAM_KEY_DATA): rc4_key = hashlib.md5(domain_properties.key_0.salt + QWERTY + self.bootkey +DIGITS).digest() self.hashed_bootkey = RC4(rc4_key).encrypt(domain_properties.key_0.key + domain_properties.key_0.checksum) checksum = hashlib.md5(self.hashed_bootkey[:16] + DIGITS + self.hashed_bootkey[:16] + QWERTY).digest() if checksum != self.hashed_bootkey[16:]: logger.error('[SAM] HBootkey checksum verification failed!') raise Exception('[SAM] HBootkey checksum verification failed!') elif isinstance(domain_properties.key_0, SAM_KEY_DATA_AES): self.hashed_bootkey = b'' cipher = AESModeOfOperationCBC(self.bootkey, iv = domain_properties.key_0.salt) n = 16 for block in [domain_properties.key_0.data[i:i+n] for i in range(0, len(domain_properties.key_0.data), n)]: #terrible, terrible workaround self.hashed_bootkey += cipher.decrypt(block) logger.debug('[SAM] HBootkey: %s' % self.hashed_bootkey.hex()) return self.hashed_bootkey
def setup(self): if self.mode == SYMMETRIC_MODE.ECB: self.ctx = AESModeOfOperationECB(self.key) elif self.mode == SYMMETRIC_MODE.CBC: self.ctx = AESModeOfOperationCBC(self.key, iv=self.iv) else: raise Exception('Unknown mode!')
def decrypt(self, encrypted): # TODO: NT version specific, move from here in subclasses. cleartext = '' size = len(encrypted) if size: if size % 8: if not self.aes_key or not self.iv: return cleartext cipher = AESModeOfOperationCBC(self.aes_key, iv=self.IV) else: if not self.des_key or not self.iv: return cleartext #cipher = DES3.new(self.des_key, DES3.MODE_CBC, self.iv[:8]) cipher = triple_des(self.des_key, CBC, self.iv[:8]) cleartext = cipher.decrypt(encrypted) return cleartext
def decrypt(self, encrypted): # TODO: NT version specific, move from here in subclasses. cleartext = b'' size = len(encrypted) if size: if size % 8: if not self.aes_key or not self.iv: return cleartext cipher = AESModeOfOperationCBC(self.aes_key, iv = self.iv) n = 16 for block in [encrypted[i:i+n] for i in range(0, len(encrypted), n)]: #terrible, terrible workaround cleartext += cipher.decrypt(block) else: if not self.des_key or not self.iv: return cleartext #cipher = DES3.new(self.des_key, DES3.MODE_CBC, self.iv[:8]) cipher = triple_des(self.des_key, CBC, self.iv[:8]) cleartext = cipher.decrypt(encrypted) return cleartext
class AES: def __init__(self, key, mode=SYMMETRIC_MODE.ECB, iv=None): self.key = key self.mode = mode self.iv = iv self.block_size = 16 self.ctx = None self.setup() def setup(self): if self.mode == SYMMETRIC_MODE.ECB: self.ctx = AESModeOfOperationECB(self.key) elif self.mode == SYMMETRIC_MODE.CBC: self.ctx = AESModeOfOperationCBC(self.key, iv=self.iv) else: raise Exception('Unknown mode!') def encrypt(self, data): if len(data) % self.block_size != 0: raise Exception('Data size not matching blocksize!') res = b'' for block in [ data[i:i + self.block_size] for i in range(0, len(data), self.block_size) ]: #terrible, terrible workaround res += self.ctx.encrypt(block) return res def decrypt(self, data): if len(data) % self.block_size != 0: raise Exception('Data size not matching blocksize!') res = b'' for block in [ data[i:i + self.block_size] for i in range(0, len(data), self.block_size) ]: #terrible, terrible workaround res += self.ctx.decrypt(block) return res
async def dump_dcc(self): logger.debug('[SECURITY] dump_dcc invoked') cache_reg = await self.hive.find_key('Cache', False) if cache_reg is None: logger.debug('[SECURITY] No DCC secrets found') return values = await self.hive.list_values(cache_reg) if values == []: logger.debug('[SECURITY] No DCC secrets found') return if b'NL$Control' in values: values.remove(b'NL$Control') if b'NL$IterationCount' in values: logger.debug('[SECURITY] DCC Setting iteration count') values.remove(b'NL$IterationCount') record = await self.hive.get_value('Cache\\NL$IterationCount') record = record[1] if record > 10240: self.dcc_iteration_count = record & 0xfffffc00 else: self.dcc_iteration_count = record * 1024 await self.get_lsa_key() await self.get_NKLM_key() for value in values: logger.debug('[SECURITY] DCC Checking value: %s' % value) record_data = await self.hive.get_value('Cache\\%s' % value.decode()) record_data = record_data[1] record = NL_RECORD.from_bytes(record_data) if record.IV != b'\x00' * 16: if record.Flags & 1 == 1: # Encrypted if self.lsa_secret_key_vista_type is True: plaintext = b'' cipher = AESModeOfOperationCBC(self.NKLM_key[16:32], iv=record.IV) n = 16 for block in [ record.EncryptedData[i:i + n] for i in range(0, len(record.EncryptedData), n) ]: #terrible, terrible workaround if len(block) < 16: block += b'\x00' * (16 - len(block)) plaintext += cipher.decrypt(block) else: key = hmac.new(self.NKLM_key, record.IV).digest() cipher = RC4(key) plaintext = cipher.decrypt(record.EncryptedData) else: # Plain! Until we figure out what this is, we skip it #plainText = record['EncryptedData'] logger.debug( '[SECURITY] DCC Skipping value %s, unknown formet' % value) continue dcc_hash = plaintext[:0x10] blob = io.BytesIO(plaintext[0x48:]) username = blob.read(record.UserLength).decode('utf-16-le') blob.seek( self.__pad(record.UserLength) + self.__pad(record.DomainNameLength)) domain = blob.read( record.DnsDomainNameLength).decode('utf-16-le') version = 2 if self.lsa_secret_key_vista_type is True else 1 secret = LSADCCSecret(version, domain, username, dcc_hash, iteration=self.dcc_iteration_count) self.dcc_hashes.append(secret) return self.dcc_hashes
def dump_dcc(self): cache_reg = self.hive.find_key('Cache') values = self.hive.list_values(cache_reg) if values == []: return if b'NL$Control' in values: values.remove(b'NL$Control') if b'NL$IterationCount' in values: values.remove(b'NL$IterationCount') record = self.getValue('Cache\\NL$IterationCount')[1] if record > 10240: self.dcc_iteration_count = record & 0xfffffc00 else: self.dcc_iteration_count = record * 1024 self.get_lsa_key() self.get_NKLM_key() print(self.lsa_key) print(self.NKLM_key) for value in values: print('Checking value: %s' % value) record_data = self.hive.get_value('Cache\\%s' % value.decode())[1] record = NL_RECORD.from_bytes(record_data) if record.IV != b'\x00' * 16: if record.Flags & 1 == 1: # Encrypted if self.lsa_secret_key_vista_type is True: plaintext = b'' cipher = AESModeOfOperationCBC(self.NKLM_key[16:32], iv=record.IV) n = 16 for block in [ record.EncryptedData[i:i + n] for i in range(0, len(record.EncryptedData), n) ]: #terrible, terrible workaround if len(block) < 16: block += b'\x00' * (16 - len(block)) plaintext += cipher.decrypt(block) else: key = hmac.new(self.NKLM_key, record.IV).digest() cipher = RC4(key) plaintext = cipher.decrypt(record.EncryptedData) else: # Plain! Until we figure out what this is, we skip it #plainText = record['EncryptedData'] continue dcc_hash = plaintext[:0x10] blob = io.BytesIO(plaintext[0x48:]) username = blob.read(record.UserLength).decode('utf-16-le') blob.seek( self.__pad(record.UserLength) + self.__pad(record.DomainNameLength)) domain = blob.read( record.DnsDomainNameLength).decode('utf-16-le') if self.lsa_secret_key_vista_type is True: ans = "%s/%s:$DCC2$%s#%s#%s" % (domain, username, self.dcc_iteration_count, username, dcc_hash.hex()) else: ans = "%s/%s:%s:%s" % (domain, username, dcc_hash.hex(), username) print(ans)