DPAPI vault IV for @dfirfpi

This commit is contained in:
Benjamin DELPY 2015-07-21 04:11:25 +02:00
parent 1265e86bfe
commit c00b9cfab3
4 changed files with 102 additions and 100 deletions

View File

@ -37,14 +37,14 @@ NTSTATUS kuhl_m_dpapi_vault(int argc, wchar_t * argv[])
{
PCWSTR inFilePolicy, inFileCred;
PVOID filePolicy, fileCred, out;
DWORD szFilePolicy, szFileCred, szOut, len, i;
DWORD szFilePolicy, szFileCred, szOut, len, i, mode = CRYPT_MODE_CBC;
BYTE aes128[AES_128_KEY_SIZE], aes256[AES_256_KEY_SIZE];
PKULL_M_CRED_VAULT_POLICY vaultPolicy;
PKULL_M_CRED_VAULT_CREDENTIAL vaultCredential;
PKULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE attribute;
PKULL_M_CRED_VAULT_CLEAR clear;
PVOID buffer;
BOOL isAttr;
HCRYPTPROV hProv;
HCRYPTKEY hKey;
@ -77,38 +77,21 @@ NTSTATUS kuhl_m_dpapi_vault(int argc, wchar_t * argv[])
if(attribute = vaultCredential->attributes[i])
{
kprintf(L" > Attribute %u : ", attribute->id);
if(attribute->id && (attribute->id < 100))
{
if(len = (attribute->attributeElement.simpleAttribute.size >= 1) ? (attribute->attributeElement.simpleAttribute.size - 1) : 0)
{
if(kull_m_crypto_hkey(hProv, CALG_AES_128, aes128, AES_128_KEY_SIZE, 0, &hKey, NULL))
if(attribute->data && (len = attribute->szData))
{
if(buffer = LocalAlloc(LPTR, len))
{
RtlCopyMemory(buffer, attribute->attributeElement.simpleAttribute.attributeData->data, len);
RtlCopyMemory(buffer, attribute->data, len);
if(kuhl_m_dpapi_vault_key_type(attribute, hProv, aes128, aes256, &hKey, &isAttr))
{
if(CryptDecrypt(hKey, 0, TRUE, 0, (PBYTE) buffer, &len))
{
if(isAttr)
{
kull_m_string_wprintf_hex(buffer, len, 0);
}
else PRINT_ERROR_AUTO(L"CryptDecrypt");
CryptDestroyKey(hKey);
LocalFree(buffer);
}
}
}
else kprintf(L"n/a");
}
else
{
if(len = (attribute->attributeElement.complexAttribute.size >= 5) ? (attribute->attributeElement.complexAttribute.size - 5) : 0)
{
if(kull_m_crypto_hkey(hProv, CALG_AES_256, aes256, AES_256_KEY_SIZE, 0, &hKey, NULL))
{
if(buffer = LocalAlloc(LPTR, len))
{
RtlCopyMemory(buffer, attribute->attributeElement.complexAttribute.attributeData->data, len);
if(CryptDecrypt(hKey, 0, TRUE, 0, (PBYTE) buffer, &len))
{
kprintf(L"\n");
if(!attribute->id || (attribute->id == 100))
@ -122,14 +105,12 @@ NTSTATUS kuhl_m_dpapi_vault(int argc, wchar_t * argv[])
else kull_m_string_wprintf_hex(buffer, len, 1 | (16 << 16));
kprintf(L"\n");
}
}
else PRINT_ERROR_AUTO(L"CryptDecrypt");
CryptDestroyKey(hKey);
}
LocalFree(buffer);
}
}
}
else kprintf(L"n/a");
}
kprintf(L"\n");
}
}
@ -154,3 +135,33 @@ NTSTATUS kuhl_m_dpapi_vault(int argc, wchar_t * argv[])
return STATUS_SUCCESS;
}
BOOL kuhl_m_dpapi_vault_key_type(PKULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE attribute, HCRYPTPROV hProv, BYTE aes128[AES_128_KEY_SIZE], BYTE aes256[AES_256_KEY_SIZE], HCRYPTKEY *hKey, BOOL *isAttr)
{
BOOL status = FALSE;
DWORD mode = CRYPT_MODE_CBC, calgId, keyLen;
LPCVOID key;
*isAttr = attribute->id && (attribute->id < 100);
if(*isAttr)
{
calgId = CALG_AES_128;
key = aes128;
keyLen = AES_128_KEY_SIZE;
}
else
{
calgId = CALG_AES_256;
key = aes256;
keyLen = AES_256_KEY_SIZE;
}
if(status = kull_m_crypto_hkey(hProv, calgId, key, keyLen, 0, hKey, NULL))
{
CryptSetKeyParam(*hKey, KP_MODE, (LPCBYTE) &mode, 0);
if(attribute->szIV && attribute->IV)
CryptSetKeyParam(*hKey, KP_IV, attribute->IV, 0);
}
return status;
}

View File

@ -16,4 +16,6 @@ typedef struct _KUHL_M_DPAPI_ENCRYPTED_CRED {
NTSTATUS kuhl_m_dpapi_cred(int argc, wchar_t * argv[]);
NTSTATUS kuhl_m_dpapi_vault(int argc, wchar_t * argv[]);
BOOL kuhl_m_dpapi_vault_key_type(PKULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE attribute, HCRYPTPROV hProv, BYTE aes128[AES_128_KEY_SIZE], BYTE aes256[AES_256_KEY_SIZE], HCRYPTKEY *hKey, BOOL *isAttr);
void kuhl_m_dpapi_vault_basic(PVOID data, DWORD size, GUID *schema);

View File

@ -317,6 +317,7 @@ PKULL_M_CRED_VAULT_CREDENTIAL kull_m_cred_vault_credential_create(PVOID data/*,
{
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)))
{
@ -336,29 +337,20 @@ PKULL_M_CRED_VAULT_CREDENTIAL kull_m_cred_vault_credential_create(PVOID data/*,
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, attributeElement));
if(attribute->id < 100)
{
RtlCopyMemory(&credential->attributes[i]->attributeElement.simpleAttribute, &attribute->attributeElement.simpleAttribute, FIELD_OFFSET(KULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE_SIMPLE, attributeData));
credential->attributes[i]->attributeElement.simpleAttribute.attributeData = (PKULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE_DATA) &attribute->attributeElement.simpleAttribute.attributeData;
kull_m_string_ptr_replace(&credential->attributes[i]->attributeElement.simpleAttribute.attributeData, credential->attributes[i]->attributeElement.simpleAttribute.size);
}
else
{
RtlCopyMemory(&credential->attributes[i]->attributeElement.complexAttribute, &attribute->attributeElement.complexAttribute, FIELD_OFFSET(KULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE_COMPLEX, attributeData));
credential->attributes[i]->attributeElement.complexAttribute.attributeData = (PKULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE_DATA) &attribute->attributeElement.complexAttribute.attributeData;
kull_m_string_ptr_replace(&credential->attributes[i]->attributeElement.complexAttribute.attributeData, credential->attributes[i]->attributeElement.complexAttribute.size);
}
}
}
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)))
{
RtlCopyMemory(&credential->attributes[i]->attributeElement.complexAttribute.size, (PBYTE) attribute + FIELD_OFFSET(KULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE, attributeElement) + FIELD_OFFSET(KULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE_SIMPLE, attributeData) + attribute->attributeElement.simpleAttribute.size + sizeof(USHORT), FIELD_OFFSET(KULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE_COMPLEX, attributeData) - FIELD_OFFSET(KULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE_COMPLEX, size));
credential->attributes[i]->attributeElement.complexAttribute.attributeData = (PKULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE_DATA) ((PBYTE) attribute + FIELD_OFFSET(KULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE, attributeElement) + FIELD_OFFSET(KULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE_SIMPLE, attributeData) + attribute->attributeElement.simpleAttribute.size + sizeof(USHORT) + (FIELD_OFFSET(KULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE_COMPLEX, attributeData) - FIELD_OFFSET(KULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE_COMPLEX, size)));
kull_m_string_ptr_replace(&credential->attributes[i]->attributeElement.complexAttribute.attributeData, credential->attributes[i]->attributeElement.complexAttribute.size);
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++;
}
}
@ -367,6 +359,32 @@ PKULL_M_CRED_VAULT_CREDENTIAL kull_m_cred_vault_credential_create(PVOID data/*,
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;
@ -383,16 +401,10 @@ void kull_m_cred_vault_credential_delete(PKULL_M_CRED_VAULT_CREDENTIAL credentia
{
if(credential->attributes[i])
{
if(credential->attributes[i]->id && (credential->attributes[i]->id < 100))
{
if(credential->attributes[i]->attributeElement.simpleAttribute.attributeData)
LocalFree(credential->attributes[i]->attributeElement.simpleAttribute.attributeData);
}
else
{
if(credential->attributes[i]->attributeElement.complexAttribute.attributeData)
LocalFree(credential->attributes[i]->attributeElement.complexAttribute.attributeData);
}
if(credential->attributes[i]->data)
LocalFree(credential->attributes[i]->data);
if(credential->attributes[i]->IV)
LocalFree(credential->attributes[i]->IV);
LocalFree(credential->attributes[i]);
}
}
@ -430,26 +442,20 @@ void kull_m_cred_vault_credential_attribute_descr(DWORD level, PKULL_M_CRED_VAUL
{
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->id && (attribute->id < 100))
if(attribute->szIV && attribute->IV)
{
if((attribute->attributeElement.simpleAttribute.size >= 1) && attribute->attributeElement.simpleAttribute.attributeData)
{
kprintf(L"%*s" L" Simple data (%02x): ", level << 1, L"", attribute->attributeElement.simpleAttribute.attributeData->unkByte);
kull_m_string_wprintf_hex(attribute->attributeElement.simpleAttribute.attributeData->data, attribute->attributeElement.simpleAttribute.size - 1, 0);
kprintf(L"%*s" L" IV : ", level << 1, L"");
kull_m_string_wprintf_hex(attribute->IV, attribute->szIV, 0);
kprintf(L"\n");
}
}
else
if(attribute->szData && attribute->data)
{
if((attribute->attributeElement.complexAttribute.size >= (4 + 1)) && attribute->attributeElement.complexAttribute.attributeData)
{
kprintf(L"%*s" L" Complex data : (%08x - %08x - %02x) - ", level << 1, L"", attribute->attributeElement.complexAttribute.unk0, attribute->attributeElement.complexAttribute.unk1, attribute->attributeElement.complexAttribute.attributeData->unkByte);
kull_m_string_wprintf_hex(attribute->attributeElement.complexAttribute.attributeData->data, attribute->attributeElement.complexAttribute.size - (4 + 1), 0);
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*/)
{
@ -497,7 +503,6 @@ void kull_m_cred_vault_clear_descr(DWORD level, PKULL_M_CRED_VAULT_CLEAR clear)
kprintf(L"%*s" L"**VAULT CREDENTIAL CLEAR ATTRIBUTES**\n", level << 1, L"");
if(clear)
{
kprintf(L"%*s" L" unkArray : ", level << 1, L""); kull_m_string_wprintf_hex(clear->unkArray, sizeof(clear->unkArray), 0); kprintf(L"\n");
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);

View File

@ -9,32 +9,16 @@
#include "kull_m_string.h"
#pragma pack(push, 1)
typedef struct _KULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE_DATA {
BYTE unkByte;
BYTE data[ANYSIZE_ARRAY];
} KULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE_DATA, *PKULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE_DATA;
typedef struct _KULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE_SIMPLE {
DWORD size; // inc bullshit
PKULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE_DATA attributeData;
} KULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE_SIMPLE, *PKULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE_SIMPLE;
typedef struct _KULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE_COMPLEX {
DWORD unk0;
DWORD size; // inc bullshit
DWORD unk1; // maybe flags;
PKULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE_DATA attributeData;
} KULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE_COMPLEX, *PKULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE_COMPLEX;
typedef struct _KULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE {
DWORD id;
DWORD unk0; // maybe flags
DWORD unk1; // maybe type
DWORD unk2; // 0a 00 00 00
union {
KULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE_SIMPLE simpleAttribute; // if id < 100
KULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE_COMPLEX complexAttribute;
} attributeElement;
//DWORD unkComplex; // only in complex (and 0, avoid it ?)
DWORD szData; // when parsing, inc bullshit... clean in structure
PBYTE data;
DWORD szIV;
PBYTE IV;
} KULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE, *PKULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE;
#pragma pack(pop)
@ -137,7 +121,6 @@ typedef struct _KULL_M_CRED_VAULT_CLEAR_ENTRY {
} KULL_M_CRED_VAULT_CLEAR_ENTRY, *PKULL_M_CRED_VAULT_CLEAR_ENTRY;
typedef struct _KULL_M_CRED_VAULT_CLEAR {
BYTE unkArray[16];
DWORD version;
DWORD count;
DWORD unk;
@ -166,6 +149,7 @@ void kull_m_cred_vault_policy_key_delete(PKULL_M_CRED_VAULT_POLICY_KEY key);
void kull_m_cred_vault_policy_key_descr(DWORD level, PKULL_M_CRED_VAULT_POLICY_KEY key);
PKULL_M_CRED_VAULT_CREDENTIAL kull_m_cred_vault_credential_create(PVOID data/*, DWORD size*/);
void kull_m_cred_vault_credential_create_attribute_from_data(PBYTE ptr, PKULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE attribute);
void kull_m_cred_vault_credential_delete(PKULL_M_CRED_VAULT_CREDENTIAL credential);
void kull_m_cred_vault_credential_descr(DWORD level, PKULL_M_CRED_VAULT_CREDENTIAL credential);
void kull_m_cred_vault_credential_attribute_descr(DWORD level, PKULL_M_CRED_VAULT_CREDENTIAL_ATTRIBUTE attribute);