@@ -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
@@ -125,13 +134,40 @@ def process_session(self, kerberos_logon_session):
125
134
126
135
self .current_cred .username = kerberos_logon_session .credentials .UserName .read_string (self .reader )
127
136
self .current_cred .domainname = kerberos_logon_session .credentials .Domaine .read_string (self .reader )
128
- #if self.current_cred.username.endswith('$') is True:
129
- # self.current_cred.password, self.current_cred.password_raw = self.decrypt_password(kerberos_logon_session.credentials.Password.read_maxdata(self.reader), bytes_expected=True)
130
- # if self.current_cred.password is not None:
131
- # self.current_cred.password = self.current_cred.password.hex()
132
- #else:
133
- # self.current_cred.password, self.current_cred.password_raw = self.decrypt_password(kerberos_logon_session.credentials.Password.read_maxdata(self.reader))
134
- self .current_cred .password , self .current_cred .password_raw = self .decrypt_password (kerberos_logon_session .credentials .Password .read_maxdata (self .reader ))
137
+
138
+ # Extract keys from pKeyList
139
+ if kerberos_logon_session .pKeyList .value != 0 :
140
+ key_list = kerberos_logon_session .pKeyList .read (self .reader , override_finaltype = self .decryptor_template .keys_list_struct )
141
+ key_list .read (self .reader , self .decryptor_template .hash_password_struct )
142
+
143
+ for key in key_list .KeyEntries :
144
+ if key .generic .Size > 0 :
145
+ if key .generic .Size <= 24 : # AES128
146
+ keydata = key .generic .Checksump .read_raw (self .reader , key .generic .Size )
147
+ if keydata :
148
+ dec_key , _ = self .decrypt_password (keydata , bytes_expected = True )
149
+ if dec_key :
150
+ self .current_cred .aes_key128 = dec_key
151
+ elif key .generic .Size <= 32 : # AES256
152
+ keydata = key .generic .Checksump .read_raw (self .reader , key .generic .Size )
153
+ if keydata :
154
+ dec_key , _ = self .decrypt_password (keydata , bytes_expected = True )
155
+ if dec_key :
156
+ self .current_cred .aes_key256 = dec_key
157
+
158
+ # Process normal password if present
159
+ if kerberos_logon_session .credentials .Password .Length != 0 :
160
+ if self .current_cred .username .endswith ('$' ) is True :
161
+ self .current_cred .password , self .current_cred .password_raw = self .decrypt_password (
162
+ kerberos_logon_session .credentials .Password .read_maxdata (self .reader ),
163
+ bytes_expected = True
164
+ )
165
+ if self .current_cred .password is not None :
166
+ self .current_cred .password = self .current_cred .password .hex ()
167
+ else :
168
+ self .current_cred .password , self .current_cred .password_raw = self .decrypt_password (
169
+ kerberos_logon_session .credentials .Password .read_maxdata (self .reader )
170
+ )
135
171
136
172
if kerberos_logon_session .SmartcardInfos .value != 0 :
137
173
csp_info = kerberos_logon_session .SmartcardInfos .read (self .reader , override_finaltype = self .decryptor_template .csp_info_struct )
@@ -140,71 +176,6 @@ def process_session(self, kerberos_logon_session):
140
176
if csp_info .CspDataLength != 0 :
141
177
self .current_cred .cardinfo = csp_info .CspData .get_infos ()
142
178
143
- #### key list (still in session) this is not a linked list (thank god!)
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
- #print(key_list.cbItem)
147
- key_list .read (self .reader , self .decryptor_template .hash_password_struct )
148
- for key in key_list .KeyEntries :
149
- pass
150
- ### GOOD
151
- #keydata_enc = key.generic.Checksump.read_raw(self.reader, key.generic.Size)
152
- #print(keydata_enc)
153
- #keydata, raw_dec = self.decrypt_password(keydata_enc, bytes_expected=True)
154
- #print(keydata_enc.hex())
155
- #input('KEY?')
156
-
157
-
158
- #print(key.generic.Checksump.value)
159
-
160
- #self.log_ptr(key.generic.Checksump.value, 'Checksump', datasize = key.generic.Size)
161
- #if self.reader.reader.sysinfo.BuildNumber < WindowsBuild.WIN_10_1507.value and key.generic.Size > LSAISO_DATA_BLOB.size:
162
- # if key.generic.Size <= LSAISO_DATA_BLOB.size + (len("KerberosKey") - 1) + 32: #AES_256_KEY_LENGTH
163
- # input('1')
164
- # data_blob = key.generic.Checksump.read(self.reader, override_finaltype = LSAISO_DATA_BLOB)
165
- # data_blob.read(self.reader, key.generic.Size - LSAISO_DATA_BLOB.size)
166
- #
167
- # input('data blob end')
168
- # """
169
- # kprintf(L"\n\t * LSA Isolated Data: %.*S", blob->typeSize, blob->data);
170
- # kprintf(L"\n\t Unk-Key : "); kull_m_string_wprintf_hex(blob->unkKeyData, sizeof(blob->unkKeyData), 0);
171
- # kprintf(L"\n\t Encrypted: "); kull_m_string_wprintf_hex(blob->data + blob->typeSize, blob->origSize, 0);
172
- # kprintf(L"\n\t\t SS:%u, TS:%u, DS:%u", blob->structSize, blob->typeSize, blob->origSize);
173
- # 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);
174
- # kull_m_string_wprintf_hex(blob->unkData2, sizeof(blob->unkData2), 0); kprintf(L", 5:0x%x", blob->unk5);
175
- # """
176
- # else:
177
- # input('2')
178
- # key.generic.Checksump.read(self.reader, override_finaltype = LSAISO_DATA_BLOB)
179
- # print('unkData1 : %s' % data_struct.unkData1.hex())
180
- # print('unkData2 : %s' % data_struct.unkData2.hex())
181
- # print('Encrypted : %s' % data_struct.data.hex()) #another extra struct should wrap this data! ENC_LSAISO_DATA_BLOB
182
- #
183
- #else:
184
- #
185
- # if self.reader.reader.sysinfo.BuildNumber < WindowsBuild.WIN_VISTA.value:
186
- # input('3')
187
- # key.generic.Checksump.read(self.reader, override_finaltype = LSAISO_DATA_BLOB)
188
- # print('unkData1 : %s' % data_struct.unkData1.hex())
189
- # print('unkData2 : %s' % data_struct.unkData2.hex())
190
- # print('Encrypted : %s' % data_struct.data.hex()) #another extra struct should wrap this data! ENC_LSAISO_DATA_BLOB
191
- #
192
- # else:
193
- # input('4')
194
- # #we need to decrypt as well!
195
- # self.reader.move(key.generic.Checksump.value)
196
- # enc_data = self.reader.read(key.generic.Size)
197
- # print(hexdump(enc_data))
198
- # dec_data = self.lsa_decryptor.decrypt(enc_data)
199
- # print(hexdump(dec_data))
200
- # t_reader = GenericReader(dec_data)
201
- # data_struct = LSAISO_DATA_BLOB(t_reader)
202
- # print('unkData1 : %s' % data_struct.unkData1.hex())
203
- # print('unkData2 : %s' % data_struct.unkData2.hex())
204
- # print('Encrypted : %s' % data_struct.data.hex()) #another extra struct should wrap this data! ENC_LSAISO_DATA_BLOB
205
- #
206
- #input()
207
-
208
179
if self .with_tickets is True :
209
180
if kerberos_logon_session .Tickets_1 .Flink .value != 0 and \
210
181
kerberos_logon_session .Tickets_1 .Flink .value != kerberos_logon_session .Tickets_1 .Flink .location and \
0 commit comments