@@ -21,6 +21,8 @@ def __init__(self):
2121 self .pin :str = None
2222 self .pin_raw :bytes = None
2323 self .cardinfo = None
24+ self .aes_key128 = None
25+ self .aes_key256 = None
2426
2527 def __str__ (self ):
2628 t = '\t == Kerberos ==\n '
@@ -38,6 +40,10 @@ def __str__(self):
3840 t += '\t \t \t ReaderName: %s\n ' % self .cardinfo ['ReaderName' ]
3941 t += '\t \t \t ContainerName: %s\n ' % self .cardinfo ['ContainerName' ]
4042 t += '\t \t \t CSPName: %s\n ' % self .cardinfo ['CSPName' ]
43+ if self .aes_key128 :
44+ t += '\t \t AES128 Key: %s\n ' % self .aes_key128 .hex ()
45+ if self .aes_key256 :
46+ t += '\t \t AES256 Key: %s\n ' % self .aes_key256 .hex ()
4147
4248 # TODO: check if users actually need this.
4349 # I think it's not useful to print out the kerberos ticket data as string, as noone uses it directly.
@@ -61,7 +67,10 @@ def to_dict(self):
6167 t ['tickets' ] = []
6268 for ticket in self .tickets :
6369 t ['tickets' ] = ticket .to_dict ()
64-
70+ if self .aes_key128 :
71+ t ['aes128' ] = self .aes_key128 .hex ()
72+ if self .aes_key256 :
73+ t ['aes256' ] = self .aes_key256 .hex ()
6574 return t
6675
6776
@@ -130,13 +139,40 @@ def process_session(self, kerberos_logon_session):
130139
131140 self .current_cred .username = kerberos_logon_session .credentials .UserName .read_string (self .reader )
132141 self .current_cred .domainname = kerberos_logon_session .credentials .Domaine .read_string (self .reader )
133- #if self.current_cred.username.endswith('$') is True:
134- # self.current_cred.password, self.current_cred.password_raw = self.decrypt_password(kerberos_logon_session.credentials.Password.read_maxdata(self.reader), bytes_expected=True)
135- # if self.current_cred.password is not None:
136- # self.current_cred.password = self.current_cred.password.hex()
137- #else:
138- # self.current_cred.password, self.current_cred.password_raw = self.decrypt_password(kerberos_logon_session.credentials.Password.read_maxdata(self.reader))
139- self .current_cred .password , self .current_cred .password_raw = self .decrypt_password (kerberos_logon_session .credentials .Password .read_maxdata (self .reader ))
142+
143+ # Extract keys from pKeyList
144+ if kerberos_logon_session .pKeyList .value != 0 :
145+ key_list = kerberos_logon_session .pKeyList .read (self .reader , override_finaltype = self .decryptor_template .keys_list_struct )
146+ key_list .read (self .reader , self .decryptor_template .hash_password_struct )
147+
148+ for key in key_list .KeyEntries :
149+ if key .generic .Size > 0 :
150+ if key .generic .Size <= 24 : # AES128
151+ keydata = key .generic .Checksump .read_raw (self .reader , key .generic .Size )
152+ if keydata :
153+ dec_key , _ = self .decrypt_password (keydata , bytes_expected = True )
154+ if dec_key :
155+ self .current_cred .aes_key128 = dec_key
156+ elif key .generic .Size <= 32 : # AES256
157+ keydata = key .generic .Checksump .read_raw (self .reader , key .generic .Size )
158+ if keydata :
159+ dec_key , _ = self .decrypt_password (keydata , bytes_expected = True )
160+ if dec_key :
161+ self .current_cred .aes_key256 = dec_key
162+
163+ # Process normal password if present
164+ if kerberos_logon_session .credentials .Password .Length != 0 :
165+ if self .current_cred .username .endswith ('$' ) is True :
166+ self .current_cred .password , self .current_cred .password_raw = self .decrypt_password (
167+ kerberos_logon_session .credentials .Password .read_maxdata (self .reader ),
168+ bytes_expected = True
169+ )
170+ if self .current_cred .password is not None :
171+ self .current_cred .password = self .current_cred .password .hex ()
172+ else :
173+ self .current_cred .password , self .current_cred .password_raw = self .decrypt_password (
174+ kerberos_logon_session .credentials .Password .read_maxdata (self .reader )
175+ )
140176
141177 if kerberos_logon_session .SmartcardInfos .value != 0 :
142178 csp_info = kerberos_logon_session .SmartcardInfos .read (self .reader , override_finaltype = self .decryptor_template .csp_info_struct )
@@ -145,71 +181,6 @@ def process_session(self, kerberos_logon_session):
145181 if csp_info .CspDataLength != 0 :
146182 self .current_cred .cardinfo = csp_info .CspData .get_infos ()
147183
148- #### key list (still in session) this is not a linked list (thank god!)
149- if kerberos_logon_session .pKeyList .value != 0 :
150- key_list = kerberos_logon_session .pKeyList .read (self .reader , override_finaltype = self .decryptor_template .keys_list_struct )
151- #print(key_list.cbItem)
152- #key_list.read(self.reader, self.decryptor_template.hash_password_struct)
153- #for key in key_list.KeyEntries:
154- #pass
155- ### GOOD
156- #keydata_enc = key.generic.Checksump.read_raw(self.reader, key.generic.Size)
157- #print(keydata_enc)
158- #keydata, raw_dec = self.decrypt_password(keydata_enc, bytes_expected=True)
159- #print(keydata_enc.hex())
160- #input('KEY?')
161-
162-
163- #print(key.generic.Checksump.value)
164-
165- #self.log_ptr(key.generic.Checksump.value, 'Checksump', datasize = key.generic.Size)
166- #if self.reader.reader.sysinfo.BuildNumber < WindowsBuild.WIN_10_1507.value and key.generic.Size > LSAISO_DATA_BLOB.size:
167- # if key.generic.Size <= LSAISO_DATA_BLOB.size + (len("KerberosKey") - 1) + 32: #AES_256_KEY_LENGTH
168- # input('1')
169- # data_blob = key.generic.Checksump.read(self.reader, override_finaltype = LSAISO_DATA_BLOB)
170- # data_blob.read(self.reader, key.generic.Size - LSAISO_DATA_BLOB.size)
171- #
172- # input('data blob end')
173- # """
174- # kprintf(L"\n\t * LSA Isolated Data: %.*S", blob->typeSize, blob->data);
175- # kprintf(L"\n\t Unk-Key : "); kull_m_string_wprintf_hex(blob->unkKeyData, sizeof(blob->unkKeyData), 0);
176- # kprintf(L"\n\t Encrypted: "); kull_m_string_wprintf_hex(blob->data + blob->typeSize, blob->origSize, 0);
177- # kprintf(L"\n\t\t SS:%u, TS:%u, DS:%u", blob->structSize, blob->typeSize, blob->origSize);
178- # kprintf(L"\n\t\t 0:0x%x, 1:0x%x, 2:0x%x, 3:0x%x, 4:0x%x, E:", blob->unk0, blob->unk1, blob->unk2, blob->unk3, blob->unk4);
179- # kull_m_string_wprintf_hex(blob->unkData2, sizeof(blob->unkData2), 0); kprintf(L", 5:0x%x", blob->unk5);
180- # """
181- # else:
182- # input('2')
183- # key.generic.Checksump.read(self.reader, override_finaltype = LSAISO_DATA_BLOB)
184- # print('unkData1 : %s' % data_struct.unkData1.hex())
185- # print('unkData2 : %s' % data_struct.unkData2.hex())
186- # print('Encrypted : %s' % data_struct.data.hex()) #another extra struct should wrap this data! ENC_LSAISO_DATA_BLOB
187- #
188- #else:
189- #
190- # if self.reader.reader.sysinfo.BuildNumber < WindowsBuild.WIN_VISTA.value:
191- # input('3')
192- # key.generic.Checksump.read(self.reader, override_finaltype = LSAISO_DATA_BLOB)
193- # print('unkData1 : %s' % data_struct.unkData1.hex())
194- # print('unkData2 : %s' % data_struct.unkData2.hex())
195- # print('Encrypted : %s' % data_struct.data.hex()) #another extra struct should wrap this data! ENC_LSAISO_DATA_BLOB
196- #
197- # else:
198- # input('4')
199- # #we need to decrypt as well!
200- # self.reader.move(key.generic.Checksump.value)
201- # enc_data = self.reader.read(key.generic.Size)
202- # print(hexdump(enc_data))
203- # dec_data = self.lsa_decryptor.decrypt(enc_data)
204- # print(hexdump(dec_data))
205- # t_reader = GenericReader(dec_data)
206- # data_struct = LSAISO_DATA_BLOB(t_reader)
207- # print('unkData1 : %s' % data_struct.unkData1.hex())
208- # print('unkData2 : %s' % data_struct.unkData2.hex())
209- # print('Encrypted : %s' % data_struct.data.hex()) #another extra struct should wrap this data! ENC_LSAISO_DATA_BLOB
210- #
211- #input()
212-
213184 if self .with_tickets is True :
214185 if kerberos_logon_session .Tickets_1 .Flink .value != 0 and \
215186 kerberos_logon_session .Tickets_1 .Flink .value != kerberos_logon_session .Tickets_1 .Flink .location and \
0 commit comments