319 lines
15 KiB
C
319 lines
15 KiB
C
/* Benjamin DELPY `gentilkiwi`
|
|
http://blog.gentilkiwi.com
|
|
benjamin@gentilkiwi.com
|
|
Licence : https://creativecommons.org/licenses/by/4.0/
|
|
*/
|
|
#include "kull_m_key.h"
|
|
|
|
PKULL_M_KEY_CAPI_BLOB kull_m_key_capi_create(PVOID data/*, DWORD size*/)
|
|
{
|
|
PKULL_M_KEY_CAPI_BLOB capiKey = NULL;
|
|
if(capiKey = (PKULL_M_KEY_CAPI_BLOB) LocalAlloc(LPTR, sizeof(KULL_M_KEY_CAPI_BLOB)))
|
|
{
|
|
RtlCopyMemory(capiKey, data, FIELD_OFFSET(KULL_M_KEY_CAPI_BLOB, pName));
|
|
capiKey->pName = (PSTR) ((PBYTE) data + FIELD_OFFSET(KULL_M_KEY_CAPI_BLOB, pName));
|
|
capiKey->pHash = (PBYTE) capiKey->pName + capiKey->dwNameLen;
|
|
capiKey->pSiPublicKey = (PBYTE) capiKey->pHash + capiKey->dwHashLen;
|
|
capiKey->pSiPrivateKey = (PBYTE) capiKey->pSiPublicKey + capiKey->dwSiPublicKeyLen;
|
|
capiKey->pSiExportFlag = (PBYTE) capiKey->pSiPrivateKey + capiKey->dwSiPrivateKeyLen;
|
|
capiKey->pExPublicKey = (PBYTE) capiKey->pSiExportFlag + capiKey->dwSiExportFlagLen;
|
|
capiKey->pExPrivateKey = (PBYTE) capiKey->pExPublicKey + capiKey->dwExPublicKeyLen;
|
|
capiKey->pExExportFlag = (PBYTE) capiKey->pExPrivateKey + capiKey->dwExPrivateKeyLen;
|
|
|
|
kull_m_string_ptr_replace(&capiKey->pName, capiKey->dwNameLen);
|
|
kull_m_string_ptr_replace(&capiKey->pHash, capiKey->dwHashLen);
|
|
kull_m_string_ptr_replace(&capiKey->pSiPublicKey, capiKey->dwSiPublicKeyLen);
|
|
kull_m_string_ptr_replace(&capiKey->pSiPrivateKey, capiKey->dwSiPrivateKeyLen);
|
|
kull_m_string_ptr_replace(&capiKey->pSiExportFlag, capiKey->dwSiExportFlagLen);
|
|
kull_m_string_ptr_replace(&capiKey->pExPublicKey, capiKey->dwExPublicKeyLen);
|
|
kull_m_string_ptr_replace(&capiKey->pExPrivateKey, capiKey->dwExPrivateKeyLen);
|
|
kull_m_string_ptr_replace(&capiKey->pExExportFlag, capiKey->dwExExportFlagLen);
|
|
}
|
|
return capiKey;
|
|
}
|
|
|
|
void kull_m_key_capi_delete(PKULL_M_KEY_CAPI_BLOB capiKey)
|
|
{
|
|
if(capiKey)
|
|
{
|
|
if(capiKey->pName)
|
|
LocalFree(capiKey->pName);
|
|
if(capiKey->pHash)
|
|
LocalFree(capiKey->pHash);
|
|
if(capiKey->pSiPublicKey)
|
|
LocalFree(capiKey->pSiPublicKey);
|
|
if(capiKey->pSiPrivateKey)
|
|
LocalFree(capiKey->pSiPrivateKey);
|
|
if(capiKey->pSiExportFlag)
|
|
LocalFree(capiKey->pSiExportFlag);
|
|
if(capiKey->pExPublicKey)
|
|
LocalFree(capiKey->pExPublicKey);
|
|
if(capiKey->pExPrivateKey)
|
|
LocalFree(capiKey->pExPrivateKey);
|
|
if(capiKey->pExExportFlag)
|
|
LocalFree(capiKey->pExExportFlag);
|
|
LocalFree(capiKey);
|
|
}
|
|
}
|
|
|
|
void kull_m_key_capi_descr(DWORD level, PKULL_M_KEY_CAPI_BLOB capiKey)
|
|
{
|
|
kprintf(L"%*s" L"**KEY (capi)**\n", level << 1, L"");
|
|
if(capiKey)
|
|
{
|
|
kprintf(L"%*s" L" dwVersion : %08x - %u\n", level << 1, L"", capiKey->dwVersion, capiKey->dwVersion);
|
|
kprintf(L"%*s" L" dwUniqueNameLen : %08x - %u\n", level << 1, L"", capiKey->dwNameLen, capiKey->dwNameLen);
|
|
kprintf(L"%*s" L" dwSiPublicKeyLen : %08x - %u\n", level << 1, L"", capiKey->dwSiPublicKeyLen, capiKey->dwSiPublicKeyLen);
|
|
kprintf(L"%*s" L" dwSiPrivateKeyLen : %08x - %u\n", level << 1, L"", capiKey->dwSiPrivateKeyLen, capiKey->dwSiPrivateKeyLen);
|
|
kprintf(L"%*s" L" dwExPublicKeyLen : %08x - %u\n", level << 1, L"", capiKey->dwExPublicKeyLen, capiKey->dwExPublicKeyLen);
|
|
kprintf(L"%*s" L" dwExPrivateKeyLen : %08x - %u\n", level << 1, L"", capiKey->dwExPrivateKeyLen, capiKey->dwExPrivateKeyLen);
|
|
kprintf(L"%*s" L" dwHashLen : %08x - %u\n", level << 1, L"", capiKey->dwHashLen, capiKey->dwHashLen);
|
|
kprintf(L"%*s" L" dwSiExportFlagLen : %08x - %u\n", level << 1, L"", capiKey->dwSiExportFlagLen, capiKey->dwSiExportFlagLen);
|
|
kprintf(L"%*s" L" dwExExportFlagLen : %08x - %u\n", level << 1, L"", capiKey->dwExExportFlagLen, capiKey->dwExExportFlagLen);
|
|
|
|
|
|
kprintf(L"%*s" L" pUniqueName : ", level << 1, L""); kprintf(L"%S\n", capiKey->pName);
|
|
kprintf(L"%*s" L" pHash : ", level << 1, L""); kull_m_string_wprintf_hex(capiKey->pHash, capiKey->dwHashLen, 0); kprintf(L"\n");
|
|
kprintf(L"%*s" L" pSiPublicKey : ", level << 1, L""); kull_m_string_wprintf_hex(capiKey->pSiPublicKey, capiKey->dwSiPublicKeyLen, 0); kprintf(L"\n");
|
|
kprintf(L"%*s" L" pSiPrivateKey :\n", level << 1, L"");
|
|
if(capiKey->pSiPrivateKey && capiKey->dwSiPrivateKeyLen)
|
|
kull_m_dpapi_blob_quick_descr(level + 1, capiKey->pSiPrivateKey); /*kull_m_string_wprintf_hex(capiKey->pPrivateKey, capiKey->dwPrivateKeyLen, 0);*/
|
|
kprintf(L"%*s" L" pSiExportFlag :\n", level << 1, L"");
|
|
if(capiKey->pSiExportFlag && capiKey->dwSiExportFlagLen)
|
|
kull_m_dpapi_blob_quick_descr(level + 1, capiKey->pSiExportFlag); /*kull_m_string_wprintf_hex(capiKey->pExportFlag, capiKey->dwExportFlagLen, 0);*/
|
|
kprintf(L"%*s" L" pExPublicKey : ", level << 1, L""); kull_m_string_wprintf_hex(capiKey->pExPublicKey, capiKey->dwExPublicKeyLen, 0); kprintf(L"\n");
|
|
kprintf(L"%*s" L" pExPrivateKey :\n", level << 1, L"");
|
|
if(capiKey->pExPrivateKey && capiKey->dwExPrivateKeyLen)
|
|
kull_m_dpapi_blob_quick_descr(level + 1, capiKey->pExPrivateKey); /*kull_m_string_wprintf_hex(capiKey->pPrivateKey, capiKey->dwPrivateKeyLen, 0);*/
|
|
kprintf(L"%*s" L" pExExportFlag :\n", level << 1, L"");
|
|
if(capiKey->pExExportFlag && capiKey->dwExExportFlagLen)
|
|
kull_m_dpapi_blob_quick_descr(level + 1, capiKey->pExExportFlag); /*kull_m_string_wprintf_hex(capiKey->pExportFlag, capiKey->dwExportFlagLen, 0);*/
|
|
|
|
}
|
|
}
|
|
|
|
BOOL kull_m_key_capi_write(PKULL_M_KEY_CAPI_BLOB capiKey, PVOID *data, DWORD *size)
|
|
{
|
|
BOOL status = FALSE;
|
|
PBYTE ptr;
|
|
*size = FIELD_OFFSET(KULL_M_KEY_CAPI_BLOB, pName) + capiKey->dwNameLen + capiKey->dwHashLen + capiKey->dwSiPublicKeyLen + capiKey->dwSiPrivateKeyLen + capiKey->dwSiExportFlagLen + capiKey->dwExPublicKeyLen + capiKey->dwExPrivateKeyLen + capiKey->dwExExportFlagLen;
|
|
if(*data = LocalAlloc(LPTR, *size))
|
|
{
|
|
ptr = (PBYTE) *data;
|
|
RtlCopyMemory(ptr, capiKey, FIELD_OFFSET(KULL_M_KEY_CAPI_BLOB, pName));
|
|
ptr += FIELD_OFFSET(KULL_M_KEY_CAPI_BLOB, pName);
|
|
RtlCopyMemory(ptr, capiKey->pName, capiKey->dwNameLen);
|
|
ptr += capiKey->dwNameLen;
|
|
RtlCopyMemory(ptr, capiKey->pHash, capiKey->dwHashLen);
|
|
ptr += capiKey->dwHashLen;
|
|
RtlCopyMemory(ptr, capiKey->pSiPublicKey, capiKey->dwSiPublicKeyLen);
|
|
ptr += capiKey->dwSiPublicKeyLen;
|
|
RtlCopyMemory(ptr, capiKey->pSiPrivateKey, capiKey->dwSiPrivateKeyLen);
|
|
ptr += capiKey->dwSiPrivateKeyLen;
|
|
RtlCopyMemory(ptr, capiKey->pSiExportFlag, capiKey->dwSiExportFlagLen);
|
|
ptr += capiKey->dwSiExportFlagLen;
|
|
RtlCopyMemory(ptr, capiKey->pExPublicKey, capiKey->dwExPublicKeyLen);
|
|
ptr += capiKey->dwExPublicKeyLen;
|
|
RtlCopyMemory(ptr, capiKey->pExPrivateKey, capiKey->dwExPrivateKeyLen);
|
|
ptr += capiKey->dwExPrivateKeyLen;
|
|
RtlCopyMemory(ptr, capiKey->pExExportFlag, capiKey->dwExExportFlagLen);
|
|
status = TRUE;
|
|
}
|
|
return status;
|
|
}
|
|
|
|
BOOL kull_m_key_capi_decryptedkey_to_raw(LPCVOID decrypted, DWORD decryptedLen, PRSA_GENERICKEY_BLOB *blob, DWORD *blobLen)
|
|
{
|
|
BOOL status = FALSE;
|
|
DWORD keyLen;
|
|
PBYTE ptrDestination, ptrSource;
|
|
|
|
if(((PDWORD) decrypted)[0] == '2ASR')
|
|
{
|
|
keyLen = ((PDWORD) decrypted)[2];
|
|
*blobLen = sizeof(RSA_GENERICKEY_BLOB) + ((keyLen * 9) / 16);
|
|
if(*blob = (PRSA_GENERICKEY_BLOB) LocalAlloc(LPTR, *blobLen))
|
|
{
|
|
status = TRUE;
|
|
(*blob)->Header.bType = PRIVATEKEYBLOB;
|
|
(*blob)->Header.bVersion = CUR_BLOB_VERSION;
|
|
(*blob)->Header.reserved = 0;
|
|
(*blob)->Header.aiKeyAlg = CALG_RSA_KEYX;
|
|
|
|
(*blob)->RsaKey.magic = ((PDWORD) decrypted)[0];
|
|
(*blob)->RsaKey.bitlen = keyLen;
|
|
(*blob)->RsaKey.pubexp = ((PDWORD) decrypted)[4];
|
|
|
|
ptrDestination = ((PBYTE) (*blob)) + sizeof(RSA_GENERICKEY_BLOB);
|
|
ptrSource = (PBYTE) ((PDWORD) decrypted + 5);
|
|
|
|
RtlCopyMemory(ptrDestination, ptrSource, keyLen / 8);
|
|
ptrDestination += keyLen / 8;
|
|
ptrSource += (keyLen / 8) + 8;
|
|
RtlCopyMemory(ptrDestination, ptrSource, keyLen / 16);
|
|
ptrDestination += keyLen / 16;
|
|
ptrSource += (keyLen / 16) + 4;
|
|
RtlCopyMemory(ptrDestination, ptrSource, keyLen / 16);
|
|
ptrDestination += keyLen / 16;
|
|
ptrSource += (keyLen / 16) + 4;
|
|
RtlCopyMemory(ptrDestination, ptrSource, keyLen / 16);
|
|
ptrDestination += keyLen / 16;
|
|
ptrSource += (keyLen / 16) + 4;
|
|
RtlCopyMemory(ptrDestination, ptrSource, keyLen / 16);
|
|
ptrDestination += keyLen / 16;
|
|
ptrSource += (keyLen / 16) + 4;
|
|
RtlCopyMemory(ptrDestination, ptrSource, keyLen / 16);
|
|
ptrDestination += keyLen / 16;
|
|
ptrSource += (keyLen / 16) + 4;
|
|
RtlCopyMemory(ptrDestination, ptrSource, keyLen / 8);
|
|
}
|
|
}
|
|
return status;
|
|
}
|
|
|
|
PKULL_M_KEY_CNG_BLOB kull_m_key_cng_create(PVOID data/*, DWORD size*/)
|
|
{
|
|
PKULL_M_KEY_CNG_BLOB cngKey = NULL;
|
|
|
|
if(cngKey = (PKULL_M_KEY_CNG_BLOB) LocalAlloc(LPTR, sizeof(KULL_M_KEY_CNG_BLOB)))
|
|
{
|
|
RtlCopyMemory(cngKey, data, FIELD_OFFSET(KULL_M_KEY_CNG_BLOB, pName));
|
|
cngKey->pName = (PSTR) ((PBYTE) data + FIELD_OFFSET(KULL_M_KEY_CNG_BLOB, pName));
|
|
if(!kull_m_key_cng_properties_create((PBYTE) cngKey->pName + cngKey->dwNameLen, cngKey->dwPublicPropertiesLen, &cngKey->pPublicProperties, &cngKey->cbPublicProperties))
|
|
PRINT_ERROR(L"kull_m_key_cng_properties_create (public)\n");
|
|
cngKey->pPrivateProperties = (PBYTE) cngKey->pName + cngKey->dwNameLen + cngKey->dwPublicPropertiesLen;
|
|
cngKey->pPrivateKey = (PBYTE) cngKey->pPrivateProperties + cngKey->dwPrivatePropertiesLen;
|
|
kull_m_string_ptr_replace(&cngKey->pName, cngKey->dwNameLen);
|
|
kull_m_string_ptr_replace(&cngKey->pPrivateProperties, cngKey->dwPrivatePropertiesLen);
|
|
kull_m_string_ptr_replace(&cngKey->pPrivateKey, cngKey->dwPrivateKeyLen);
|
|
}
|
|
return cngKey;
|
|
}
|
|
|
|
void kull_m_key_cng_delete(PKULL_M_KEY_CNG_BLOB cngKey)
|
|
{
|
|
if(cngKey)
|
|
{
|
|
if(cngKey->pName)
|
|
LocalFree(cngKey->pName);
|
|
if(cngKey->cbPublicProperties && cngKey->pPublicProperties)
|
|
kull_m_key_cng_properties_delete(cngKey->pPublicProperties, cngKey->cbPublicProperties);
|
|
if(cngKey->pPrivateProperties)
|
|
LocalFree(cngKey->pPrivateProperties);
|
|
if(cngKey->pPrivateKey)
|
|
LocalFree(cngKey->pPrivateKey);
|
|
LocalFree(cngKey);
|
|
}
|
|
}
|
|
|
|
void kull_m_key_cng_descr(DWORD level, PKULL_M_KEY_CNG_BLOB cngKey)
|
|
{
|
|
kprintf(L"%*s" L"**KEY (cng)**\n", level << 1, L"");
|
|
if(cngKey)
|
|
{
|
|
kprintf(L"%*s" L" dwVersion : %08x - %u\n", level << 1, L"", cngKey->dwVersion, cngKey->dwVersion);
|
|
kprintf(L"%*s" L" unk : %08x - %u\n", level << 1, L"", cngKey->unk, cngKey->unk);
|
|
kprintf(L"%*s" L" dwNameLen : %08x - %u\n", level << 1, L"", cngKey->dwNameLen, cngKey->dwNameLen);
|
|
kprintf(L"%*s" L" type : %08x - %u\n", level << 1, L"", cngKey->type, cngKey->type);
|
|
kprintf(L"%*s" L" dwPublicPropertiesLen : %08x - %u\n", level << 1, L"", cngKey->dwPublicPropertiesLen, cngKey->dwPublicPropertiesLen);
|
|
kprintf(L"%*s" L" dwPrivatePropertiesLen: %08x - %u\n", level << 1, L"", cngKey->dwPrivatePropertiesLen, cngKey->dwPrivatePropertiesLen);
|
|
kprintf(L"%*s" L" dwPrivateKeyLen : %08x - %u\n", level << 1, L"", cngKey->dwPrivateKeyLen, cngKey->dwPrivateKeyLen);
|
|
kprintf(L"%*s" L" unkArray[16] : ", level << 1, L""); kull_m_string_wprintf_hex(cngKey->unkArray, sizeof(cngKey->unkArray), 0); kprintf(L"\n");
|
|
kprintf(L"%*s" L" pName : ", level << 1, L""); kprintf(L"%.*s\n", cngKey->dwNameLen / sizeof(wchar_t), cngKey->pName);
|
|
kprintf(L"%*s" L" pPublicProperties : ", level << 1, L""); kull_m_key_cng_properties_descr(level + 1, cngKey->pPublicProperties, cngKey->cbPublicProperties);
|
|
kprintf(L"%*s" L" pPrivateProperties :\n", level << 1, L"");
|
|
if(cngKey->pPrivateProperties && cngKey->dwPrivatePropertiesLen)
|
|
kull_m_dpapi_blob_quick_descr(level + 1, cngKey->pPrivateProperties); /*kull_m_string_wprintf_hex(cngKey->pPrivateProperties, cngKey->dwPrivatePropertiesLen, 0);*/
|
|
kprintf(L"%*s" L" pPrivateKey :\n", level << 1, L"");
|
|
if(cngKey->pPrivateKey && cngKey->dwPrivateKeyLen)
|
|
kull_m_dpapi_blob_quick_descr(level + 1, cngKey->pPrivateKey); /*kull_m_string_wprintf_hex(cngKey->pPrivateKey, cngKey->dwPrivateKeyLen, 0);*/
|
|
}
|
|
}
|
|
|
|
PKULL_M_KEY_CNG_PROPERTY kull_m_key_cng_property_create(PVOID data/*, DWORD size*/)
|
|
{
|
|
PKULL_M_KEY_CNG_PROPERTY cngProperty = NULL;
|
|
if(cngProperty = (PKULL_M_KEY_CNG_PROPERTY) LocalAlloc(LPTR, sizeof(KULL_M_KEY_CNG_PROPERTY)))
|
|
{
|
|
RtlCopyMemory(cngProperty, data, FIELD_OFFSET(KULL_M_KEY_CNG_PROPERTY, pName));
|
|
cngProperty->pName = (PSTR) ((PBYTE) data + FIELD_OFFSET(KULL_M_KEY_CNG_PROPERTY, pName));
|
|
cngProperty->pProperty = (PBYTE) cngProperty->pName + cngProperty->dwNameLen;
|
|
kull_m_string_ptr_replace(&cngProperty->pName, cngProperty->dwNameLen);
|
|
kull_m_string_ptr_replace(&cngProperty->pProperty, cngProperty->dwPropertyLen);
|
|
}
|
|
return cngProperty;
|
|
}
|
|
|
|
void kull_m_key_cng_property_delete(PKULL_M_KEY_CNG_PROPERTY property)
|
|
{
|
|
if(property)
|
|
{
|
|
if(property->pName)
|
|
LocalFree(property->pName);
|
|
if(property->pProperty)
|
|
LocalFree(property->pProperty);
|
|
LocalFree(property);
|
|
}
|
|
}
|
|
|
|
void kull_m_key_cng_property_descr(DWORD level, PKULL_M_KEY_CNG_PROPERTY property)
|
|
{
|
|
kprintf(L"%*s" L"**KEY CNG PROPERTY**\n", level << 1, L"");
|
|
if(property)
|
|
{
|
|
kprintf(L"%*s" L" dwStructLen : %08x - %u\n", level << 1, L"", property->dwStructLen, property->dwStructLen);
|
|
kprintf(L"%*s" L" type : %08x - %u\n", level << 1, L"", property->type, property->type);
|
|
kprintf(L"%*s" L" unk : %08x - %u\n", level << 1, L"", property->unk, property->unk);
|
|
kprintf(L"%*s" L" dwNameLen : %08x - %u\n", level << 1, L"", property->dwNameLen, property->dwNameLen);
|
|
kprintf(L"%*s" L" dwPropertyLen : %08x - %u\n", level << 1, L"", property->dwPropertyLen, property->dwPropertyLen);
|
|
kprintf(L"%*s" L" pName : ", level << 1, L""); kprintf(L"%.*s\n", property->dwNameLen / sizeof(wchar_t), property->pName);
|
|
kprintf(L"%*s" L" pProperty : ", level << 1, L""); kull_m_string_wprintf_hex(property->pProperty, property->dwPropertyLen, 0); kprintf(L"\n\n");
|
|
}
|
|
}
|
|
|
|
BOOL kull_m_key_cng_properties_create(PVOID data, DWORD size, PKULL_M_KEY_CNG_PROPERTY **properties, DWORD *count)
|
|
{
|
|
BOOL status = FALSE;
|
|
DWORD i, j;
|
|
|
|
for(i = 0, *count = 0; i < size; i += ((PKULL_M_KEY_CNG_PROPERTY) ((PBYTE) data + i))->dwStructLen, (*count)++);
|
|
|
|
if((*properties) = (PKULL_M_KEY_CNG_PROPERTY *) LocalAlloc(LPTR, *count * sizeof(PKULL_M_KEY_CNG_PROPERTY)))
|
|
{
|
|
for(i = 0, j = 0, status = TRUE; (i < (*count)) && status; i++)
|
|
{
|
|
if((*properties)[i] = kull_m_key_cng_property_create((PBYTE) data + j))
|
|
j += (*properties)[i]->dwStructLen;
|
|
else status = FALSE;
|
|
}
|
|
}
|
|
if(!status)
|
|
{
|
|
kull_m_key_cng_properties_delete(*properties, *count);
|
|
*properties = NULL;
|
|
*count = 0;
|
|
}
|
|
return status;
|
|
}
|
|
|
|
void kull_m_key_cng_properties_delete(PKULL_M_KEY_CNG_PROPERTY *properties, DWORD count)
|
|
{
|
|
DWORD i;
|
|
if(properties)
|
|
{
|
|
for(i = 0; i < count; i++)
|
|
kull_m_key_cng_property_delete(properties[i]);
|
|
LocalFree(properties);
|
|
}
|
|
}
|
|
|
|
void kull_m_key_cng_properties_descr(DWORD level, PKULL_M_KEY_CNG_PROPERTY *properties, DWORD count)
|
|
{
|
|
DWORD i;
|
|
if(count && properties)
|
|
{
|
|
kprintf(L"%u field(s)\n", count);
|
|
for(i = 0; i < count; i++)
|
|
kull_m_key_cng_property_descr(level, properties[i]);
|
|
}
|
|
} |