@@ -21,6 +21,8 @@ def __init__(self):
21
21
self .pin :str = None
22
22
self .pin_raw :bytes = None
23
23
self .cardinfo = None
24
+ self .aes_key128 = None
25
+ self .aes_key256 = None
24
26
25
27
def __str__ (self ):
26
28
t = '\t == Kerberos ==\n '
@@ -38,6 +40,10 @@ def __str__(self):
38
40
t += '\t \t \t ReaderName: %s\n ' % self .cardinfo ['ReaderName' ]
39
41
t += '\t \t \t ContainerName: %s\n ' % self .cardinfo ['ContainerName' ]
40
42
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 ()
41
47
42
48
# TODO: check if users actually need this.
43
49
# 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):
61
67
t ['tickets' ] = []
62
68
for ticket in self .tickets :
63
69
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 ()
65
74
return t
66
75
67
76
@@ -130,13 +139,40 @@ def process_session(self, kerberos_logon_session):
130
139
131
140
self .current_cred .username = kerberos_logon_session .credentials .UserName .read_string (self .reader )
132
141
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
+ )
140
176
141
177
if kerberos_logon_session .SmartcardInfos .value != 0 :
142
178
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):
145
181
if csp_info .CspDataLength != 0 :
146
182
self .current_cred .cardinfo = csp_info .CspData .get_infos ()
147
183
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
-
213
184
if self .with_tickets is True :
214
185
if kerberos_logon_session .Tickets_1 .Flink .value != 0 and \
215
186
kerberos_logon_session .Tickets_1 .Flink .value != kerberos_logon_session .Tickets_1 .Flink .location and \
0 commit comments