666 lines
27 KiB
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");
|
|
}
|
|
}
|
|
}
|
|
} |