mimikatz/modules/kull_m_cred.c

666 lines
27 KiB
C

/* Benjamin DELPY `gentilkiwi`
https://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : https://creativecommons.org/licenses/by/4.0/
*/
#include "kull_m_cred.h"
const wchar_t KULL_M_CRED_ENTROPY_CRED_DER[37] = L"\x0184\x0188\x0194\x00c8\x00e0\x00d8\x00e4\x0198\x00b4\x00e4\x0188\x00d0\x00dc\x00b4\x00d0\x018c\x0190\x00e4\x00b4\x0184\x00cc\x00d4\x00e0\x00b4\x018c\x00c8\x00c8\x00e4\x00c0\x00d0\x0190\x0188\x0184\x00dc\x0198\x00dc";
const wchar_t KULL_M_CRED_ENTROPYDOM_CRED_DER[37] = L"\x00e0\x00c8\x0108\x0110\x00c0\x0114\x00d8\x00dc\x00b4\x00e4\x0118\x0114\x0104\x00b4\x00d0\x00dc\x00d0\x00e0\x00b4\x00e0\x00d8\x00dc\x00c8\x00b4\x0110\x00d4\x0114\x0118\x0114\x00d4\x0108\x00dc\x00dc\x00e4\x0108\x00c0";
//wchar_t entropyCred[] = L"abe2869f-9b47-4cd9-a358-c22904dba7f7";
//wchar_t entropyDomCred[] = L"82BD0E67-9FEA-4748-8672-D5EFE5B779B0";
//DWORD i;
//for(i = 0; i < ARRAYSIZE(entropyCred); i++)
// entropyCred[i] <<= 2;
//for(i = 0; i < ARRAYSIZE(entropyDomCred); i++)
// entropyDomCred[i] <<= 2;
PKULL_M_CRED_BLOB kull_m_cred_create(PVOID data/*, DWORD size*/)
{
PKULL_M_CRED_BLOB cred = NULL;
if(cred = (PKULL_M_CRED_BLOB) LocalAlloc(LPTR, sizeof(KULL_M_CRED_BLOB)))
{
RtlCopyMemory(cred, data, FIELD_OFFSET(KULL_M_CRED_BLOB, TargetName));
cred->TargetName = (LPWSTR) ((PBYTE) data + FIELD_OFFSET(KULL_M_CRED_BLOB, TargetName));
cred->dwUnkData = *(PDWORD) ((PBYTE) cred->TargetName + cred->dwTargetName);
cred->UnkData = (LPWSTR) ((PBYTE) cred->TargetName + cred->dwTargetName + sizeof(DWORD));
cred->dwComment = *(PDWORD) ((PBYTE) cred->UnkData + cred->dwUnkData);
cred->Comment = (LPWSTR) ((PBYTE) cred->UnkData + cred->dwUnkData + sizeof(DWORD));
cred->dwTargetAlias = *(PDWORD) ((PBYTE) cred->Comment + cred->dwComment);
cred->TargetAlias = (LPWSTR) ((PBYTE) cred->Comment + cred->dwComment + sizeof(DWORD));
cred->dwUserName = *(PDWORD) ((PBYTE) cred->TargetAlias + cred->dwTargetAlias);
cred->UserName = (LPWSTR) ((PBYTE) cred->TargetAlias + cred->dwTargetAlias + sizeof(DWORD));
cred->CredentialBlobSize = *(PDWORD) ((PBYTE) cred->UserName + cred->dwUserName);
cred->CredentialBlob = (PBYTE) cred->UserName + cred->dwUserName + sizeof(DWORD);
if(cred->AttributeCount)
kull_m_cred_attributes_create(((PBYTE) cred->CredentialBlob + cred->CredentialBlobSize + (cred->CredentialBlobSize & 1)), &cred->Attributes, cred->AttributeCount);
kull_m_string_ptr_replace(&cred->TargetName, cred->dwTargetName);
kull_m_string_ptr_replace(&cred->TargetAlias, cred->dwTargetAlias);
kull_m_string_ptr_replace(&cred->Comment, cred->dwComment);
kull_m_string_ptr_replace(&cred->UnkData, cred->dwUnkData);
kull_m_string_ptr_replace(&cred->UserName, cred->dwUserName);
kull_m_string_ptr_replace(&cred->CredentialBlob, cred->CredentialBlobSize);
}
return cred;
}
void kull_m_cred_delete(PKULL_M_CRED_BLOB cred)
{
if(cred)
{
if(cred->TargetName)
LocalFree(cred->TargetName);
if(cred->UnkData)
LocalFree(cred->UnkData);
if(cred->Comment)
LocalFree(cred->Comment);
if(cred->TargetAlias)
LocalFree(cred->TargetAlias);
if(cred->UserName)
LocalFree(cred->UserName);
if(cred->CredentialBlob)
LocalFree(cred->CredentialBlob);
if(cred->Attributes)
kull_m_cred_attributes_delete(cred->Attributes, cred->AttributeCount);
LocalFree(cred);
}
}
void kull_m_cred_descr(DWORD level, PKULL_M_CRED_BLOB cred)
{
kprintf(L"%*s" L"**CREDENTIAL**\n", level << 1, L"");
if(cred)
{
kprintf(L"%*s" L" credFlags : %08x - %u\n", level << 1, L"", cred->credFlags, cred->credFlags);
kprintf(L"%*s" L" credSize : %08x - %u\n", level << 1, L"", cred->credSize, cred->credSize);
kprintf(L"%*s" L" credUnk0 : %08x - %u\n\n", level << 1, L"", cred->credUnk0, cred->credUnk0);
kprintf(L"%*s" L" Type : %08x - %u - %s\n", level << 1, L"", cred->Type, cred->Type, kull_m_cred_CredType(cred->Type));
kprintf(L"%*s" L" Flags : %08x - %u\n", level << 1, L"", cred->Flags, cred->Flags);
kprintf(L"%*s" L" LastWritten : ", level << 1, L""); kull_m_string_displayFileTime(&cred->LastWritten); kprintf(L"\n");
kprintf(L"%*s" L" unkFlagsOrSize : %08x - %u\n", level << 1, L"", cred->unkFlagsOrSize, cred->unkFlagsOrSize);
kprintf(L"%*s" L" Persist : %08x - %u - %s\n", level << 1, L"", cred->Persist, cred->Persist, kull_m_cred_CredPersist(cred->Persist));
kprintf(L"%*s" L" AttributeCount : %08x - %u\n", level << 1, L"", cred->AttributeCount, cred->AttributeCount);
kprintf(L"%*s" L" unk0 : %08x - %u\n", level << 1, L"", cred->unk0, cred->unk0);
kprintf(L"%*s" L" unk1 : %08x - %u\n", level << 1, L"", cred->unk1, cred->unk1);
kprintf(L"%*s" L" TargetName : %s\n", level << 1, L"", cred->TargetName);
kprintf(L"%*s" L" UnkData : %s\n", level << 1, L"", cred->UnkData);
kprintf(L"%*s" L" Comment : %s\n", level << 1, L"", cred->Comment);
kprintf(L"%*s" L" TargetAlias : %s\n", level << 1, L"", cred->TargetAlias);
kprintf(L"%*s" L" UserName : %s\n", level << 1, L"", cred->UserName);
kprintf(L"%*s" L" CredentialBlob : ", level << 1, L"");
kull_m_string_printSuspectUnicodeString(cred->CredentialBlob, cred->CredentialBlobSize);
kprintf(L"\n");
kprintf(L"%*s" L" Attributes : %u\n", level << 1, L"", cred->AttributeCount);
kull_m_cred_attributes_descr(level + 1, cred->Attributes, cred->AttributeCount);
}
}
BOOL kull_m_cred_attributes_create(PVOID data, PKULL_M_CRED_ATTRIBUTE **Attributes, DWORD count)
{
BOOL status = FALSE;
DWORD i, j;
if((*Attributes) = (PKULL_M_CRED_ATTRIBUTE *) LocalAlloc(LPTR, count * sizeof(PKULL_M_CRED_ATTRIBUTE)))
{
for(i = 0, j = 0, status = TRUE; (i < count) && status; i++)
{
if((*Attributes)[i] = kull_m_cred_attribute_create((PBYTE) data + j))
j += sizeof(KULL_M_CRED_ATTRIBUTE) - 2 * sizeof(PVOID) + (*Attributes)[i]->dwKeyword + (*Attributes)[i]->ValueSize;
else status = FALSE;
}
}
if(!status)
{
kull_m_cred_attributes_delete(*Attributes, count);
*Attributes = NULL;
}
return status;
}
void kull_m_cred_attributes_delete(PKULL_M_CRED_ATTRIBUTE *Attributes, DWORD count)
{
DWORD i;
if(Attributes)
{
for(i = 0; i < count; i++)
kull_m_cred_attribute_delete(Attributes[i]);
LocalFree(Attributes);
}
}
void kull_m_cred_attributes_descr(DWORD level, PKULL_M_CRED_ATTRIBUTE *Attributes, DWORD count)
{
DWORD i;
if(count && Attributes)
for(i = 0; i < count; i++)
kull_m_cred_attribute_descr(level, Attributes[i]);
}
PKULL_M_CRED_ATTRIBUTE kull_m_cred_attribute_create(PVOID data/*, DWORD size*/)
{
PKULL_M_CRED_ATTRIBUTE Attribute = NULL;
if(Attribute = (PKULL_M_CRED_ATTRIBUTE) LocalAlloc(LPTR, sizeof(KULL_M_CRED_ATTRIBUTE)))
{
RtlCopyMemory(Attribute, data, FIELD_OFFSET(KULL_M_CRED_ATTRIBUTE, Keyword));
Attribute->Keyword = (LPWSTR) ((PBYTE) data + FIELD_OFFSET(KULL_M_CRED_ATTRIBUTE, Keyword));
Attribute->ValueSize = *(PDWORD) ((PBYTE) Attribute->Keyword + Attribute->dwKeyword);
Attribute->Value = (PBYTE) Attribute->Keyword + Attribute->dwKeyword + sizeof(DWORD);
kull_m_string_ptr_replace(&Attribute->Keyword, Attribute->dwKeyword);
kull_m_string_ptr_replace(&Attribute->Value, Attribute->ValueSize);
}
return Attribute;
}
void kull_m_cred_attribute_delete(PKULL_M_CRED_ATTRIBUTE Attribute)
{
if(Attribute)
{
if(Attribute->Keyword)
LocalFree(Attribute->Keyword);
if(Attribute->Value)
LocalFree(Attribute->Value);
LocalFree(Attribute);
}
}
void kull_m_cred_attribute_descr(DWORD level, PKULL_M_CRED_ATTRIBUTE Attribute)
{
kprintf(L"%*s" L"**ATTRIBUTE**\n", level << 1, L"");
if(Attribute)
{
kprintf(L"%*s" L" Flags : %08x - %u\n", level << 1, L"", Attribute->Flags, Attribute->Flags);
kprintf(L"%*s" L" Keyword : %s\n", level << 1, L"", Attribute->Keyword);
kprintf(L"%*s" L" Value : ", level << 1, L"");
kull_m_string_printSuspectUnicodeString(Attribute->Value, Attribute->ValueSize);
kprintf(L"\n");
}
}
PKULL_M_CRED_LEGACY_CREDS_BLOB kull_m_cred_legacy_creds_create(PVOID data/*, DWORD size*/)
{
PKULL_M_CRED_LEGACY_CREDS_BLOB creds = NULL;
DWORD i;
PBYTE curPtr;
if(creds = (PKULL_M_CRED_LEGACY_CREDS_BLOB) LocalAlloc(LPTR, sizeof(KULL_M_CRED_LEGACY_CREDS_BLOB)))
{
RtlCopyMemory(creds, data, FIELD_OFFSET(KULL_M_CRED_LEGACY_CREDS_BLOB, __count));
for(curPtr = (PBYTE) data + FIELD_OFFSET(KULL_M_CRED_LEGACY_CREDS_BLOB, __count); curPtr < ((PBYTE) data + creds->structSize); curPtr += *(PDWORD) curPtr, creds->__count++);
if(creds->__count)
if(creds->Credentials = (PKULL_M_CRED_LEGACY_CRED_BLOB *) LocalAlloc(LPTR, creds->__count * sizeof(PKULL_M_CRED_LEGACY_CRED_BLOB)))
for(i = 0, curPtr = (PBYTE) data + FIELD_OFFSET(KULL_M_CRED_LEGACY_CREDS_BLOB, __count); (i < creds->__count) && (curPtr < ((PBYTE) data + creds->structSize)); i++, curPtr += *(PDWORD) curPtr)
creds->Credentials[i] = kull_m_cred_legacy_cred_create(curPtr);
}
return creds;
}
void kull_m_cred_legacy_creds_delete(PKULL_M_CRED_LEGACY_CREDS_BLOB creds)
{
DWORD i;
if(creds)
{
if(creds->Credentials)
{
for(i = 0; i < creds->__count; i++)
kull_m_cred_legacy_cred_delete(creds->Credentials[i]);
LocalFree(creds->Credentials);
}
LocalFree(creds);
}
}
void kull_m_cred_legacy_creds_descr(DWORD level, PKULL_M_CRED_LEGACY_CREDS_BLOB creds)
{
DWORD i;
kprintf(L"%*s" L"**LEGACY CREDENTIALS GROUP**\n", level << 1, L"");
if(creds)
{
kprintf(L"%*s" L" dwVersion : %08x - %u\n", level << 1, L"", creds->dwVersion, creds->dwVersion);
kprintf(L"%*s" L" structSize : %08x - %u\n", level << 1, L"", creds->structSize, creds->structSize);
kprintf(L"%*s" L" Credentials : %u\n", level << 1, L"", creds->__count);
for(i = 0; i < creds->__count; i++)
kull_m_cred_legacy_cred_descr(level + 1, creds->Credentials[i]);
}
}
PKULL_M_CRED_LEGACY_CRED_BLOB kull_m_cred_legacy_cred_create(PVOID data/*, DWORD size*/)
{
PKULL_M_CRED_LEGACY_CRED_BLOB cred = NULL;
if(cred = (PKULL_M_CRED_LEGACY_CRED_BLOB) LocalAlloc(LPTR, sizeof(KULL_M_CRED_LEGACY_CRED_BLOB)))
{
RtlCopyMemory(cred, data, FIELD_OFFSET(KULL_M_CRED_LEGACY_CRED_BLOB, TargetName));
cred->TargetName = (LPWSTR) ((PBYTE) data + FIELD_OFFSET(KULL_M_CRED_LEGACY_CRED_BLOB, TargetName));
cred->dwComment = *(PDWORD) ((PBYTE) cred->TargetName + cred->dwTargetName);
cred->Comment = (LPWSTR) ((PBYTE) cred->TargetName + cred->dwTargetName + sizeof(DWORD));
cred->dwTargetAlias = *(PDWORD) ((PBYTE) cred->Comment + cred->dwComment);
cred->TargetAlias = (LPWSTR) ((PBYTE) cred->Comment + cred->dwComment + sizeof(DWORD));
cred->dwUserName = *(PDWORD) ((PBYTE) cred->TargetAlias + cred->dwTargetAlias);
cred->UserName = (LPWSTR) ((PBYTE) cred->TargetAlias + cred->dwTargetAlias + sizeof(DWORD));
cred->CredentialBlobSize = *(PDWORD) ((PBYTE) cred->UserName + cred->dwUserName);
cred->CredentialBlob = (PBYTE) cred->UserName + cred->dwUserName + sizeof(DWORD);
if(cred->AttributeCount)
kull_m_cred_attributes_create(((PBYTE) cred->CredentialBlob + cred->CredentialBlobSize + (cred->CredentialBlobSize & 1)), &cred->Attributes, cred->AttributeCount);
kull_m_string_ptr_replace(&cred->TargetName, cred->dwTargetName);
kull_m_string_ptr_replace(&cred->Comment, cred->dwComment);
kull_m_string_ptr_replace(&cred->TargetAlias, cred->dwTargetAlias);
kull_m_string_ptr_replace(&cred->UserName, cred->dwUserName);
kull_m_string_ptr_replace(&cred->CredentialBlob, cred->CredentialBlobSize);
}
return cred;
}
void kull_m_cred_legacy_cred_delete(PKULL_M_CRED_LEGACY_CRED_BLOB cred)
{
if(cred)
{
if(cred->TargetName)
LocalFree(cred->TargetName);
if(cred->Comment)
LocalFree(cred->Comment);
if(cred->TargetAlias)
LocalFree(cred->TargetAlias);
if(cred->UserName)
LocalFree(cred->UserName);
if(cred->CredentialBlob)
LocalFree(cred->CredentialBlob);
if(cred->Attributes)
kull_m_cred_attributes_delete(cred->Attributes, cred->AttributeCount);
LocalFree(cred);
}
}
void kull_m_cred_legacy_cred_descr(DWORD level, PKULL_M_CRED_LEGACY_CRED_BLOB cred)
{
kprintf(L"%*s" L"**LEGACY CREDENTIAL**\n", level << 1, L"");
if(cred)
{
kprintf(L"%*s" L" credSize : %08x - %u\n\n", level << 1, L"", cred->credSize, cred->credSize);
kprintf(L"%*s" L" Flags : %08x - %u\n", level << 1, L"", cred->Flags, cred->Flags);
kprintf(L"%*s" L" Type : %08x - %u - %s\n", level << 1, L"", cred->Type, cred->Type, kull_m_cred_CredType(cred->Type));
kprintf(L"%*s" L" LastWritten : ", level << 1, L""); kull_m_string_displayFileTime(&cred->LastWritten); kprintf(L"\n");
kprintf(L"%*s" L" unkFlagsOrSize : %08x - %u\n", level << 1, L"", cred->unkFlagsOrSize, cred->unkFlagsOrSize);
kprintf(L"%*s" L" Persist : %08x - %u - %s\n", level << 1, L"", cred->Persist, cred->Persist, kull_m_cred_CredPersist(cred->Persist));
kprintf(L"%*s" L" AttributeCount : %08x - %u\n", level << 1, L"", cred->AttributeCount, cred->AttributeCount);
kprintf(L"%*s" L" unk0 : %08x - %u\n", level << 1, L"", cred->unk0, cred->unk0);
kprintf(L"%*s" L" unk1 : %08x - %u\n", level << 1, L"", cred->unk1, cred->unk1);
kprintf(L"%*s" L" TargetName : %s\n", level << 1, L"", cred->TargetName);
kprintf(L"%*s" L" Comment : %s\n", level << 1, L"", cred->Comment);
kprintf(L"%*s" L" TargetAlias : %s\n", level << 1, L"", cred->TargetAlias);
kprintf(L"%*s" L" UserName : %s\n", level << 1, L"", cred->UserName);
kprintf(L"%*s" L" CredentialBlob : ", level << 1, L"");
kull_m_string_printSuspectUnicodeString(cred->CredentialBlob, cred->CredentialBlobSize);
kprintf(L"\n");
kprintf(L"%*s" L" Attributes : %u\n", level << 1, L"", cred->AttributeCount);
kull_m_cred_attributes_descr(level + 1, cred->Attributes, cred->AttributeCount);
}
}
const PCWCHAR kull_m_cred_CredTypeToStrings[] = {
L"?", L"generic", L"domain_password", L"domain_certificate",
L"domain_visible_password", L"generic_certificate", L"domain_extended"
};
PCWCHAR kull_m_cred_CredType(DWORD type)
{
if(type >= ARRAYSIZE(kull_m_cred_CredTypeToStrings))
type = 0;
return kull_m_cred_CredTypeToStrings[type];
}
const PCWCHAR kull_m_cred_CredPersistToStrings[] = {L"none", L"session", L"local_machine", L"enterprise"};
PCWCHAR kull_m_cred_CredPersist(DWORD persist)
{
if(persist < ARRAYSIZE(kull_m_cred_CredPersistToStrings))
return kull_m_cred_CredPersistToStrings[persist];
else return L"?";
}
PKULL_M_CRED_VAULT_POLICY kull_m_cred_vault_policy_create(PVOID data/*, DWORD size*/)
{
PKULL_M_CRED_VAULT_POLICY policy = NULL;
if(policy = (PKULL_M_CRED_VAULT_POLICY) LocalAlloc(LPTR, sizeof(KULL_M_CRED_VAULT_POLICY)))
{
RtlCopyMemory(policy, data, FIELD_OFFSET(KULL_M_CRED_VAULT_POLICY, Name));
policy->Name = (LPWSTR) ((PBYTE) data + FIELD_OFFSET(KULL_M_CRED_VAULT_POLICY, Name));
RtlCopyMemory(&policy->unk0, (PBYTE) policy->Name + policy->dwName, FIELD_OFFSET(KULL_M_CRED_VAULT_POLICY, key) - FIELD_OFFSET(KULL_M_CRED_VAULT_POLICY, unk0));
policy->key = kull_m_cred_vault_policy_key_create((PBYTE) policy->Name + policy->dwName + FIELD_OFFSET(KULL_M_CRED_VAULT_POLICY, key) - FIELD_OFFSET(KULL_M_CRED_VAULT_POLICY, unk0));
kull_m_string_ptr_replace(&policy->Name, policy->dwName);
}
return policy;
}
void kull_m_cred_vault_policy_delete(PKULL_M_CRED_VAULT_POLICY policy)
{
if(policy)
{
if(policy->Name)
LocalFree(policy->Name);
if(policy->key)
kull_m_cred_vault_policy_key_delete(policy->key);
LocalFree(policy);
}
}
void kull_m_cred_vault_policy_descr(DWORD level, PKULL_M_CRED_VAULT_POLICY policy)
{
kprintf(L"%*s" L"**VAULT POLICY**\n", level << 1, L"");
if(policy)
{
kprintf(L"%*s" L" version : %08x - %u\n", level << 1, L"", policy->version, policy->version);
kprintf(L"%*s" L" vault : ", level << 1, L""); kull_m_string_displayGUID(&policy->vault); kprintf(L"\n");
kprintf(L"%*s" L" Name : %s\n", level << 1, L"", policy->Name);
kprintf(L"%*s" L" unk0/1/2: %08x/%08x/%08x\n", level << 1, L"", policy->unk0, policy->unk1, policy->unk2);
if(policy->key)
kull_m_cred_vault_policy_key_descr(level + 1, policy->key);
kprintf(L"\n");
}
}
PKULL_M_CRED_VAULT_POLICY_KEY kull_m_cred_vault_policy_key_create(PVOID data/*, DWORD size*/)
{
PKULL_M_CRED_VAULT_POLICY_KEY key = NULL;
if(key = (PKULL_M_CRED_VAULT_POLICY_KEY) LocalAlloc(LPTR, sizeof(KULL_M_CRED_VAULT_POLICY_KEY)))
{
RtlCopyMemory(key, data, FIELD_OFFSET(KULL_M_CRED_VAULT_POLICY_KEY, KeyBlob));
key->KeyBlob = (PBYTE) data + FIELD_OFFSET(KULL_M_CRED_VAULT_POLICY_KEY, KeyBlob);
kull_m_string_ptr_replace(&key->KeyBlob, key->dwKeyBlob);
}
return key;
}
void kull_m_cred_vault_policy_key_delete(PKULL_M_CRED_VAULT_POLICY_KEY key)
{
if(key)
{
if(key->KeyBlob)
LocalFree(key->KeyBlob);
LocalFree(key);
}
}
void kull_m_cred_vault_policy_key_descr(DWORD level, PKULL_M_CRED_VAULT_POLICY_KEY key)
{
kprintf(L"%*s" L"**VAULT POLICY KEY**\n", level << 1, L"");
if(key)
{
kprintf(L"%*s" L" unk0 : ", level << 1, L""); kull_m_string_displayGUID(&key->unk0); kprintf(L"\n");
kprintf(L"%*s" L" unk1 : ", level << 1, L""); kull_m_string_displayGUID(&key->unk1); kprintf(L"\n");
kull_m_dpapi_blob_quick_descr(level + 1, key->KeyBlob);
kprintf(L"\n");
}
}
BOOL kull_m_cred_vault_policy_key(PVOID data, DWORD size, BYTE aes128[AES_128_KEY_SIZE], BYTE aes256[AES_256_KEY_SIZE])
{
BOOL status = FALSE;
DWORD keySize128, keySize256;
PBYTE ptr = (PBYTE) data;
PKULL_M_CRED_VAULT_POLICY_KEY_MBDK pMbdk;
PKIWI_BCRYPT_KEY pBcrypt;
keySize128 = *(PDWORD) ptr;
if(keySize128 >= 0x24)
{
if(*(PDWORD) (ptr + 3 * sizeof(DWORD)) == 'MBDK')
{
pMbdk = (PKULL_M_CRED_VAULT_POLICY_KEY_MBDK) ptr;
if(status = ((pMbdk->type == 2) && (pMbdk->key.cbSecret == AES_128_KEY_SIZE)))
RtlCopyMemory(aes128, pMbdk->key.data, AES_128_KEY_SIZE);
}
else if(*(PDWORD) (ptr + 4 * sizeof(DWORD)) == 'MSSK')
{
pBcrypt = (PKIWI_BCRYPT_KEY) (ptr + 3 * sizeof(DWORD));
if(status = ((pBcrypt->bits == 128) && (pBcrypt->hardkey.cbSecret == AES_128_KEY_SIZE)))
RtlCopyMemory(aes128, pBcrypt->hardkey.data, AES_128_KEY_SIZE);
}
if(status)
{
status = FALSE;
ptr += sizeof(DWORD) + keySize128;
keySize256 = *(PDWORD) ptr;
if(keySize256 >= 0x34)
{
if(*(PDWORD) (ptr + 3 * sizeof(DWORD)) == 'MBDK')
{
pMbdk = (PKULL_M_CRED_VAULT_POLICY_KEY_MBDK) ptr;
if(status = ((pMbdk->type == 1) && (pMbdk->key.cbSecret == AES_256_KEY_SIZE)))
RtlCopyMemory(aes256, pMbdk->key.data, AES_256_KEY_SIZE);
}
else if(*(PDWORD) (ptr + 4 * sizeof(DWORD)) == 'MSSK')
{
pBcrypt = (PKIWI_BCRYPT_KEY) (ptr + 3 * sizeof(DWORD));
if(status = ((pBcrypt->bits == 256) && (pBcrypt->hardkey.cbSecret == AES_256_KEY_SIZE)))
RtlCopyMemory(aes256, pBcrypt->hardkey.data, AES_256_KEY_SIZE);
}
}
}
}
return status;
}
PKULL_M_CRED_VAULT_CREDENTIAL kull_m_cred_vault_credential_create(PVOID data/*, DWORD size*/)
{
PKULL_M_CRED_VAULT_CREDENTIAL credential = NULL;
PKULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE attribute;
PBYTE ptr;
DWORD i;
if(credential = (PKULL_M_CRED_VAULT_CREDENTIAL) LocalAlloc(LPTR, sizeof(KULL_M_CRED_VAULT_CREDENTIAL)))
{
RtlCopyMemory(credential, data, FIELD_OFFSET(KULL_M_CRED_VAULT_CREDENTIAL, FriendlyName));
credential->FriendlyName = (LPWSTR) ((PBYTE) data + FIELD_OFFSET(KULL_M_CRED_VAULT_CREDENTIAL, FriendlyName));
credential->dwAttributesMapSize = *(PDWORD) ((PBYTE) credential->FriendlyName + credential->dwFriendlyName);
credential->attributesMap = (PKULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE_MAP) ((PBYTE) credential->FriendlyName + credential->dwFriendlyName + sizeof(DWORD));
kull_m_string_ptr_replace(&credential->FriendlyName, credential->dwFriendlyName);
kull_m_string_ptr_replace(&credential->attributesMap, credential->dwAttributesMapSize);
credential->__cbElements = credential->dwAttributesMapSize / sizeof(KULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE_MAP);
if(credential->attributes = (PKULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE * ) LocalAlloc(LPTR, (credential->__cbElements + ((credential->unk0 < 4) ? 1 : 0)) * sizeof(PKULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE)))
{
for(i = 0; i < credential->__cbElements; i++)
{
if(credential->attributes[i] = (PKULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE) LocalAlloc(LPTR, sizeof(KULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE)))
{
attribute = (PKULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE) ((PBYTE) data + credential->attributesMap[i].offset);
RtlCopyMemory(credential->attributes[i], attribute, FIELD_OFFSET(KULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE, szData));
ptr = (PBYTE) attribute;
if(attribute->id >= 100)
ptr += sizeof(DWORD); // boo!
ptr += FIELD_OFFSET(KULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE, szData);
kull_m_cred_vault_credential_create_attribute_from_data(ptr, credential->attributes[i]);
}
}
if(attribute && credential->unk0 < 4)
{
if(credential->attributes[i] = (PKULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE) LocalAlloc(LPTR, sizeof(KULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE)))
{
kull_m_cred_vault_credential_create_attribute_from_data((PBYTE) attribute + FIELD_OFFSET(KULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE, data) + attribute->szData + sizeof(USHORT), credential->attributes[i]);
credential->__cbElements++;
}
}
}
}
return credential;
}
void kull_m_cred_vault_credential_create_attribute_from_data(PBYTE ptr, PKULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE attribute)
{
BOOLEAN isIV;
if(attribute->szData = *(PDWORD) ptr)
{
attribute->szData--;
ptr += sizeof(DWORD);
isIV = *(PBOOLEAN) ptr;
ptr += sizeof(BOOLEAN);
if(isIV)
{
attribute->szData -= sizeof(DWORD);;
if(attribute->szIV = *(PDWORD) ptr)
{
attribute->szData -= attribute->szIV;
ptr += sizeof(DWORD);
attribute->IV = ptr;
ptr += attribute->szIV;
kull_m_string_ptr_replace(&attribute->IV, attribute->szIV);
}
}
attribute->data = ptr;
kull_m_string_ptr_replace(&attribute->data, attribute->szData);
}
}
void kull_m_cred_vault_credential_delete(PKULL_M_CRED_VAULT_CREDENTIAL credential)
{
DWORD i;
if(credential)
{
if(credential->FriendlyName)
LocalFree(credential->FriendlyName);
if(credential->attributesMap)
LocalFree(credential->attributesMap);
if(credential->attributes)
{
for(i = 0; i < credential->__cbElements; i++)
{
if(credential->attributes[i])
{
if(credential->attributes[i]->data)
LocalFree(credential->attributes[i]->data);
if(credential->attributes[i]->IV)
LocalFree(credential->attributes[i]->IV);
LocalFree(credential->attributes[i]);
}
}
LocalFree(credential->attributes);
}
LocalFree(credential);
}
}
void kull_m_cred_vault_credential_descr(DWORD level, PKULL_M_CRED_VAULT_CREDENTIAL credential)
{
DWORD i;
kprintf(L"%*s" L"**VAULT CREDENTIAL**\n", level << 1, L"");
if(credential)
{
kprintf(L"%*s" L" SchemaId : ", level << 1, L""); kull_m_string_displayGUID(&credential->SchemaId); kprintf(L"\n");
kprintf(L"%*s" L" unk0 : %08x - %u\n", level << 1, L"", credential->unk0, credential->unk0);
kprintf(L"%*s" L" LastWritten : ", level << 1, L""); kull_m_string_displayFileTime(&credential->LastWritten); kprintf(L"\n");
kprintf(L"%*s" L" unk1 : %08x - %u\n", level << 1, L"", credential->unk1, credential->unk1);
kprintf(L"%*s" L" unk2 : %08x - %u\n", level << 1, L"", credential->unk2, credential->unk2);
kprintf(L"%*s" L" FriendlyName : %s\n", level << 1, L"", credential->FriendlyName);
kprintf(L"%*s" L" dwAttributesMapSize : %08x - %u\n", level << 1, L"", credential->dwAttributesMapSize, credential->dwAttributesMapSize);
for(i = 0; i < (credential->dwAttributesMapSize / sizeof(KULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE_MAP)); i++)
kprintf(L"%*s" L" * Attribute %3u @ offset %08x - %u (unk %08x - %u)\n", level << 1, L"", credential->attributesMap[i].id, credential->attributesMap[i].offset, credential->attributesMap[i].offset, credential->attributesMap[i].unk, credential->attributesMap[i].unk);
for(i = 0; i < credential->__cbElements; i++)
kull_m_cred_vault_credential_attribute_descr(level + 1, credential->attributes[i]);
kprintf(L"\n");
}
}
void kull_m_cred_vault_credential_attribute_descr(DWORD level, PKULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE attribute)
{
kprintf(L"%*s" L"**VAULT CREDENTIAL ATTRIBUTE**\n", level << 1, L"");
if(attribute)
{
kprintf(L"%*s" L" id : %08x - %u\n", level << 1, L"", attribute->id, attribute->id);
kprintf(L"%*s" L" unk0/1/2: %08x/%08x/%08x\n", level << 1, L"", attribute->unk0, attribute->unk1, attribute->unk2);
if(attribute->szIV && attribute->IV)
{
kprintf(L"%*s" L" IV : ", level << 1, L"");
kull_m_string_wprintf_hex(attribute->IV, attribute->szIV, 0);
kprintf(L"\n");
}
if(attribute->szData && attribute->data)
{
kprintf(L"%*s" L" Data : ", level << 1, L"");
kull_m_string_wprintf_hex(attribute->data, attribute->szData, 0);
kprintf(L"\n");
}
}
}
PKULL_M_CRED_VAULT_CLEAR kull_m_cred_vault_clear_create(PVOID data/*, DWORD size*/)
{
PKULL_M_CRED_VAULT_CLEAR clear = NULL;
DWORD i, size;
PBYTE ptr;
if(clear = (PKULL_M_CRED_VAULT_CLEAR) LocalAlloc(LPTR, sizeof(KULL_M_CRED_VAULT_CLEAR)))
{
RtlCopyMemory(clear, data, FIELD_OFFSET(KULL_M_CRED_VAULT_CLEAR, entries));
if(clear->count && (clear->entries = (PKULL_M_CRED_VAULT_CLEAR_ENTRY *) LocalAlloc(LPTR, clear->count * sizeof(PKULL_M_CRED_VAULT_CLEAR_ENTRY))))
{
ptr = (PBYTE) data + FIELD_OFFSET(KULL_M_CRED_VAULT_CLEAR, entries);
for(i = 0; i < clear->count; i++)
{
size = FIELD_OFFSET(KULL_M_CRED_VAULT_CLEAR_ENTRY, data) + *(PDWORD) (ptr + FIELD_OFFSET(KULL_M_CRED_VAULT_CLEAR_ENTRY, size));
if(clear->entries[i] = (PKULL_M_CRED_VAULT_CLEAR_ENTRY) LocalAlloc(LPTR, size))
RtlCopyMemory(clear->entries[i], ptr, size);
ptr += size;
}
}
}
return clear;
}
void kull_m_cred_vault_clear_delete(PKULL_M_CRED_VAULT_CLEAR clear)
{
DWORD i;
if(clear)
{
if(clear->entries)
{
for(i = 0 ; i < clear->count; i++)
if(clear->entries[i])
LocalFree(clear->entries[i]);
LocalFree(clear->entries);
}
LocalFree(clear);
}
}
void kull_m_cred_vault_clear_descr(DWORD level, PKULL_M_CRED_VAULT_CLEAR clear)
{
DWORD i;
kprintf(L"%*s" L"**VAULT CREDENTIAL CLEAR ATTRIBUTES**\n", level << 1, L"");
if(clear)
{
kprintf(L"%*s" L" version: %08x - %u\n", level << 1, L"", clear->version, clear->version);
kprintf(L"%*s" L" count : %08x - %u\n", level << 1, L"", clear->count, clear->count);
kprintf(L"%*s" L" unk : %08x - %u\n", level << 1, L"", clear->unk, clear->unk);
if(clear->entries)
{
kprintf(L"\n");
for(i = 0; i < clear->count; i++)
{
kprintf(L"%*s" L" * ", level << 1, L"");
switch(clear->entries[i]->id)
{
case 1:
kprintf(L"ressource : ");
break;
case 2:
kprintf(L"identity : ");
break;
case 3:
kprintf(L"authenticator : ");
break;
default:
kprintf(L"property %3u : ", clear->entries[i]->id);
break;
}
kull_m_string_printSuspectUnicodeString(clear->entries[i]->data, clear->entries[i]->size);
kprintf(L"\n");
}
}
}
}