@@ -22,6 +22,8 @@ def __init__(self):
22
22
self .pin :str = None
23
23
self .pin_raw :bytes = None
24
24
self .cardinfo = None
25
+ self .aes_key128 = None
26
+ self .aes_key256 = None
25
27
26
28
def __str__ (self ):
27
29
t = '\t == Kerberos ==\n '
@@ -39,7 +41,10 @@ def __str__(self):
39
41
t += '\t \t \t ReaderName: %s\n ' % self .cardinfo ['ReaderName' ]
40
42
t += '\t \t \t ContainerName: %s\n ' % self .cardinfo ['ContainerName' ]
41
43
t += '\t \t \t CSPName: %s\n ' % self .cardinfo ['CSPName' ]
42
-
44
+ if self .aes_key128 :
45
+ t += '\t \t AES128 Key: %s\n ' % self .aes_key128 .hex ()
46
+ if self .aes_key256 :
47
+ t += '\t \t AES256 Key: %s\n ' % self .aes_key256 .hex ()
43
48
# TODO: check if users actually need this.
44
49
# I think it's not useful to print out the kerberos ticket data as string, as noone uses it directly.
45
50
# It is better to use the -k flag an export the tickets
@@ -62,14 +67,18 @@ def to_dict(self):
62
67
t ['tickets' ] = []
63
68
for ticket in self .tickets :
64
69
t ['tickets' ] = ticket .to_dict ()
65
-
70
+ if self .aes_key128 :
71
+ t ['aes128' ] = self .aes_key128 .hex ()
72
+ if self .aes_key256 :
73
+ t ['aes256' ] = self .aes_key256 .hex ()
66
74
return t
67
75
68
76
69
77
class KerberosDecryptor (PackageDecryptor ):
70
- def __init__ (self , reader , decryptor_template , lsa_decryptor , sysinfo ):
78
+ def __init__ (self , reader , decryptor_template , lsa_decryptor , sysinfo , with_tickets = True ):
71
79
super ().__init__ ('Kerberos' , lsa_decryptor , sysinfo , reader )
72
80
self .decryptor_template = decryptor_template
81
+ self .with_tickets = with_tickets
73
82
self .credentials = []
74
83
75
84
self .current_ticket_type = None
@@ -83,10 +92,8 @@ async def find_first_entry(self):
83
92
84
93
async def handle_ticket (self , kerberos_ticket ):
85
94
try :
86
- #input(kerberos_ticket)
87
95
kt = await KerberosTicket .aparse (kerberos_ticket , self .reader , self .decryptor_template .sysinfo , self .current_ticket_type )
88
96
self .current_cred .tickets .append (kt )
89
- #print(str(kt))
90
97
except Exception as e :
91
98
raise e
92
99
@@ -131,100 +138,65 @@ async def process_session(self, kerberos_logon_session):
131
138
132
139
self .current_cred .username = await kerberos_logon_session .credentials .UserName .read_string (self .reader )
133
140
self .current_cred .domainname = await kerberos_logon_session .credentials .Domaine .read_string (self .reader )
134
- pwdata = await kerberos_logon_session .credentials .Password .read_maxdata (self .reader )
135
- self .current_cred .password , self .current_cred .password_raw = self .decrypt_password (pwdata )
136
-
137
- if kerberos_logon_session .SmartcardInfos .value != 0 :
138
- csp_info = await kerberos_logon_session .SmartcardInfos .read (self .reader , override_finaltype = self .decryptor_template .csp_info_struct )
139
- pin_enc = await csp_info .PinCode .read_maxdata (self .reader )
140
- self .current_cred .pin , raw_dec = self .decrypt_password (pin_enc )
141
- if csp_info .CspDataLength != 0 :
142
- self .current_cred .cardinfo = csp_info .CspData .get_infos ()
143
141
144
142
#### key list (still in session) this is not a linked list (thank god!)
145
143
if kerberos_logon_session .pKeyList .value != 0 :
146
144
key_list = await kerberos_logon_session .pKeyList .read (self .reader , override_finaltype = self .decryptor_template .keys_list_struct )
147
- #print(key_list.cbItem)
148
145
await key_list .read (self .reader , self .decryptor_template .hash_password_struct )
146
+
149
147
for key in key_list .KeyEntries :
150
- pass
151
- ### GOOD
152
- #keydata_enc = key.generic.Checksump.read_raw(self.reader, key.generic.Size)
153
- #print(keydata_enc)
154
- #keydata, raw_dec = self.decrypt_password(keydata_enc, bytes_expected=True)
155
- #print(keydata_enc.hex())
156
- #input('KEY?')
157
-
148
+ if key .generic .Size > 0 :
149
+ if key .generic .Size <= 24 : # AES128
150
+ keydata = await key .generic .Checksump .read_raw (self .reader , key .generic .Size )
151
+ if keydata :
152
+ dec_key , _ = self .decrypt_password (keydata , bytes_expected = True )
153
+ if dec_key :
154
+ self .current_cred .aes_key128 = dec_key
155
+ elif key .generic .Size <= 32 : # AES256
156
+ keydata = await key .generic .Checksump .read_raw (self .reader , key .generic .Size )
157
+ if keydata :
158
+ dec_key , _ = self .decrypt_password (keydata , bytes_expected = True )
159
+ if dec_key :
160
+ self .current_cred .aes_key256 = dec_key
158
161
159
- #print(key.generic.Checksump.value)
160
-
161
- #self.log_ptr(key.generic.Checksump.value, 'Checksump', datasize = key.generic.Size)
162
- #if self.reader.reader.sysinfo.BuildNumber < WindowsBuild.WIN_10_1507.value and key.generic.Size > LSAISO_DATA_BLOB.size:
163
- # if key.generic.Size <= LSAISO_DATA_BLOB.size + (len("KerberosKey") - 1) + 32: #AES_256_KEY_LENGTH
164
- # input('1')
165
- # data_blob = key.generic.Checksump.read(self.reader, override_finaltype = LSAISO_DATA_BLOB)
166
- # data_blob.read(self.reader, key.generic.Size - LSAISO_DATA_BLOB.size)
167
- #
168
- # input('data blob end')
169
- # """
170
- # kprintf(L"\n\t * LSA Isolated Data: %.*S", blob->typeSize, blob->data);
171
- # kprintf(L"\n\t Unk-Key : "); kull_m_string_wprintf_hex(blob->unkKeyData, sizeof(blob->unkKeyData), 0);
172
- # kprintf(L"\n\t Encrypted: "); kull_m_string_wprintf_hex(blob->data + blob->typeSize, blob->origSize, 0);
173
- # kprintf(L"\n\t\t SS:%u, TS:%u, DS:%u", blob->structSize, blob->typeSize, blob->origSize);
174
- # 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);
175
- # kull_m_string_wprintf_hex(blob->unkData2, sizeof(blob->unkData2), 0); kprintf(L", 5:0x%x", blob->unk5);
176
- # """
177
- # else:
178
- # input('2')
179
- # key.generic.Checksump.read(self.reader, override_finaltype = LSAISO_DATA_BLOB)
180
- # print('unkData1 : %s' % data_struct.unkData1.hex())
181
- # print('unkData2 : %s' % data_struct.unkData2.hex())
182
- # print('Encrypted : %s' % data_struct.data.hex()) #another extra struct should wrap this data! ENC_LSAISO_DATA_BLOB
183
- #
184
- #else:
185
- #
186
- # if self.reader.reader.sysinfo.BuildNumber < WindowsBuild.WIN_VISTA.value:
187
- # input('3')
188
- # key.generic.Checksump.read(self.reader, override_finaltype = LSAISO_DATA_BLOB)
189
- # print('unkData1 : %s' % data_struct.unkData1.hex())
190
- # print('unkData2 : %s' % data_struct.unkData2.hex())
191
- # print('Encrypted : %s' % data_struct.data.hex()) #another extra struct should wrap this data! ENC_LSAISO_DATA_BLOB
192
- #
193
- # else:
194
- # input('4')
195
- # #we need to decrypt as well!
196
- # self.reader.move(key.generic.Checksump.value)
197
- # enc_data = self.reader.read(key.generic.Size)
198
- # print(hexdump(enc_data))
199
- # dec_data = self.lsa_decryptor.decrypt(enc_data)
200
- # print(hexdump(dec_data))
201
- # t_reader = GenericReader(dec_data)
202
- # data_struct = LSAISO_DATA_BLOB(t_reader)
203
- # print('unkData1 : %s' % data_struct.unkData1.hex())
204
- # print('unkData2 : %s' % data_struct.unkData2.hex())
205
- # print('Encrypted : %s' % data_struct.data.hex()) #another extra struct should wrap this data! ENC_LSAISO_DATA_BLOB
206
- #
207
- #input()
208
162
163
+ if kerberos_logon_session .credentials .Password .Length != 0 :
164
+ pwdata = await kerberos_logon_session .credentials .Password .read_maxdata (self .reader )
165
+ if self .current_cred .username .endswith ('$' ) is True :
166
+ self .current_cred .password , self .current_cred .password_raw = self .decrypt_password (pwdata , bytes_expected = True )
167
+ if self .current_cred .password is not None :
168
+ self .current_cred .password = self .current_cred .password .hex ()
169
+ else :
170
+ self .current_cred .password , self .current_cred .password_raw = self .decrypt_password (pwdata )
209
171
210
- if kerberos_logon_session .Tickets_1 .Flink .value != 0 and \
211
- kerberos_logon_session .Tickets_1 .Flink .value != kerberos_logon_session .Tickets_1 .Flink .location and \
212
- kerberos_logon_session .Tickets_1 .Flink .value != kerberos_logon_session .Tickets_1 .Flink .location - 4 :
213
- self .current_ticket_type = KerberosTicketType .TGS
214
- await self .walk_list (kerberos_logon_session .Tickets_1 .Flink , self .handle_ticket , override_ptr = self .decryptor_template .kerberos_ticket_struct )
172
+ if kerberos_logon_session .SmartcardInfos .value != 0 :
173
+ csp_info = await kerberos_logon_session .SmartcardInfos .read (self .reader , override_finaltype = self .decryptor_template .csp_info_struct )
174
+ pin_enc = await csp_info .PinCode .read_maxdata (self .reader )
175
+ self .current_cred .pin , raw_dec = self .decrypt_password (pin_enc )
176
+ if csp_info .CspDataLength != 0 :
177
+ self .current_cred .cardinfo = csp_info .CspData .get_infos ()
178
+
215
179
216
- if kerberos_logon_session .Tickets_2 .Flink .value != 0 and \
217
- kerberos_logon_session .Tickets_2 .Flink .value != kerberos_logon_session .Tickets_2 .Flink .location and \
218
- kerberos_logon_session .Tickets_2 .Flink .value != kerberos_logon_session .Tickets_2 .Flink .location - 4 :
219
- self .current_ticket_type = KerberosTicketType .CLIENT
220
- await self .walk_list (kerberos_logon_session .Tickets_2 .Flink ,self .handle_ticket , override_ptr = self .decryptor_template .kerberos_ticket_struct )
180
+ if self .with_tickets is True :
181
+ if kerberos_logon_session .Tickets_1 .Flink .value != 0 and \
182
+ kerberos_logon_session .Tickets_1 .Flink .value != kerberos_logon_session .Tickets_1 .Flink .location and \
183
+ kerberos_logon_session .Tickets_1 .Flink .value != kerberos_logon_session .Tickets_1 .Flink .location - 4 :
184
+ self .current_ticket_type = KerberosTicketType .TGS
185
+ await self .walk_list (kerberos_logon_session .Tickets_1 .Flink , self .handle_ticket , override_ptr = self .decryptor_template .kerberos_ticket_struct )
186
+
187
+ if kerberos_logon_session .Tickets_2 .Flink .value != 0 and \
188
+ kerberos_logon_session .Tickets_2 .Flink .value != kerberos_logon_session .Tickets_2 .Flink .location and \
189
+ kerberos_logon_session .Tickets_2 .Flink .value != kerberos_logon_session .Tickets_2 .Flink .location - 4 :
190
+ self .current_ticket_type = KerberosTicketType .CLIENT
191
+ await self .walk_list (kerberos_logon_session .Tickets_2 .Flink ,self .handle_ticket , override_ptr = self .decryptor_template .kerberos_ticket_struct )
192
+
193
+ if kerberos_logon_session .Tickets_3 .Flink .value != 0 and \
194
+ kerberos_logon_session .Tickets_3 .Flink .value != kerberos_logon_session .Tickets_3 .Flink .location and \
195
+ kerberos_logon_session .Tickets_3 .Flink .value != kerberos_logon_session .Tickets_3 .Flink .location - 4 :
196
+ self .current_ticket_type = KerberosTicketType .TGT
197
+ await self .walk_list (kerberos_logon_session .Tickets_3 .Flink ,self .handle_ticket , override_ptr = self .decryptor_template .kerberos_ticket_struct )
198
+ self .current_ticket_type = None
221
199
222
- if kerberos_logon_session .Tickets_3 .Flink .value != 0 and \
223
- kerberos_logon_session .Tickets_3 .Flink .value != kerberos_logon_session .Tickets_3 .Flink .location and \
224
- kerberos_logon_session .Tickets_3 .Flink .value != kerberos_logon_session .Tickets_3 .Flink .location - 4 :
225
- self .current_ticket_type = KerberosTicketType .TGT
226
- await self .walk_list (kerberos_logon_session .Tickets_3 .Flink ,self .handle_ticket , override_ptr = self .decryptor_template .kerberos_ticket_struct )
227
- self .current_ticket_type = None
228
200
self .credentials .append (self .current_cred )
229
201
230
202
0 commit comments