mirror of
https://github.com/donnaskiez/ac.git
synced 2024-11-21 22:24:08 +01:00
refactor ept detection a bit
This commit is contained in:
parent
76d1cfee46
commit
45a23b7177
9 changed files with 171 additions and 62 deletions
|
@ -747,10 +747,6 @@ DriverEntry(
|
|||
return STATUS_FAILED_DRIVER_ENTRY;
|
||||
}
|
||||
|
||||
UNICODE_STRING string = RTL_CONSTANT_STRING(L"ExAllocatePoolWithTag");
|
||||
|
||||
DetectEptHooksInKeyFunctions();
|
||||
|
||||
DEBUG_LOG("DonnaAC Driver Entry Complete");
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
|
|
|
@ -1338,6 +1338,8 @@ MeasureReads(
|
|||
_enable();
|
||||
__writecr8(old_irql);
|
||||
|
||||
DEBUG_LOG("REad average: %llx", read_average);
|
||||
|
||||
return read_average / Count;
|
||||
}
|
||||
|
||||
|
@ -1362,23 +1364,16 @@ MeasureReads(
|
|||
STATIC
|
||||
NTSTATUS
|
||||
GetAverageReadTimeAtRoutine(
|
||||
_In_ PUNICODE_STRING RoutineName,
|
||||
_In_ PVOID RoutineAddress,
|
||||
_Inout_ PUINT64 AverageTime
|
||||
)
|
||||
{
|
||||
PVOID function_address = NULL;
|
||||
|
||||
if (!RoutineName || !AverageTime)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
function_address = MmGetSystemRoutineAddress(RoutineName);
|
||||
|
||||
if (!function_address)
|
||||
if (!RoutineAddress || !AverageTime)
|
||||
return STATUS_ABANDONED;
|
||||
|
||||
*AverageTime = MeasureReads(function_address, EPT_CHECK_NUM_ITERATIONS);
|
||||
*AverageTime = MeasureReads(RoutineAddress, EPT_CHECK_NUM_ITERATIONS);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
return *AverageTime == 0 ? STATUS_ABANDONED : STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1417,6 +1412,43 @@ WCHAR PROTECTED_FUNCTIONS[EPT_PROTECTED_FUNCTIONS_COUNT][EPT_MAX_FUNCTION_NAME_L
|
|||
L"MmCopyMemory"
|
||||
};
|
||||
|
||||
/*
|
||||
* For whatever reason MmGetSystemRoutineAddress only works once, then every call
|
||||
* thereafter fails. So will be storing the routine addresses in arrays.
|
||||
*/
|
||||
UINT64 CONTROL_FUNCTION_ADDRESSES[EPT_CONTROL_FUNCTIONS_COUNT];
|
||||
UINT64 PROTECTED_FUNCTION_ADDRESSES[EPT_PROTECTED_FUNCTIONS_COUNT];
|
||||
|
||||
STATIC
|
||||
NTSTATUS
|
||||
InitiateEptFunctionAddressArrays()
|
||||
{
|
||||
UNICODE_STRING current_function;
|
||||
|
||||
for (INT index = 0; index < EPT_CONTROL_FUNCTIONS_COUNT; index++)
|
||||
{
|
||||
RtlInitUnicodeString(¤t_function, CONTROL_FUNCTIONS[index]);
|
||||
CONTROL_FUNCTION_ADDRESSES[index] = MmGetSystemRoutineAddress(¤t_function);
|
||||
|
||||
if (!CONTROL_FUNCTION_ADDRESSES[index])
|
||||
return STATUS_ABANDONED;
|
||||
}
|
||||
|
||||
for (INT index = 0; index < EPT_PROTECTED_FUNCTIONS_COUNT; index++)
|
||||
{
|
||||
RtlInitUnicodeString(¤t_function, CONTROL_FUNCTIONS[index]);
|
||||
PROTECTED_FUNCTION_ADDRESSES[index] = MmGetSystemRoutineAddress(¤t_function);
|
||||
|
||||
if (!PROTECTED_FUNCTION_ADDRESSES[index])
|
||||
return STATUS_ABANDONED;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* This maybe needs to be dispatched from a system thread rather then a user mode thread.
|
||||
*/
|
||||
NTSTATUS
|
||||
DetectEptHooksInKeyFunctions()
|
||||
{
|
||||
|
@ -1425,50 +1457,54 @@ DetectEptHooksInKeyFunctions()
|
|||
UINT64 instruction_time = 0;
|
||||
UINT64 control_time_sum = 0;
|
||||
UINT64 control_average = 0;
|
||||
UNICODE_STRING current_function;
|
||||
|
||||
status = InitiateEptFunctionAddressArrays();
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
DEBUG_ERROR("InitiateEptFunctionAddressArrays failed with status %x", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
for (INT index = 0; index < EPT_CONTROL_FUNCTIONS_COUNT; index++)
|
||||
{
|
||||
RtlInitUnicodeString(¤t_function, CONTROL_FUNCTIONS[index]);
|
||||
|
||||
if (!current_function.Buffer)
|
||||
continue;
|
||||
|
||||
status = GetAverageReadTimeAtRoutine(
|
||||
¤t_function,
|
||||
CONTROL_FUNCTION_ADDRESSES[index],
|
||||
&instruction_time
|
||||
);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
DEBUG_ERROR("DetectEptPresentOnFunction failed with status %x", status);
|
||||
RtlZeroMemory(current_function.Buffer, current_function.Length);
|
||||
control_fails += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
control_time_sum += instruction_time;
|
||||
|
||||
RtlZeroMemory(current_function.Buffer, current_function.Length);
|
||||
}
|
||||
|
||||
if (!control_time_sum)
|
||||
DEBUG_LOG("Control time sum: %llx", control_time_sum);
|
||||
|
||||
if (control_time_sum == 0)
|
||||
{
|
||||
DEBUG_ERROR("Control time is null");
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
control_average = control_time_sum / (EPT_CONTROL_FUNCTIONS_COUNT - control_fails);
|
||||
|
||||
if (!control_average)
|
||||
DEBUG_LOG("Control average: %llx", control_average);
|
||||
|
||||
if (control_average == 0)
|
||||
{
|
||||
DEBUG_ERROR("Control average time is null");
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
for (INT index = 0; index < EPT_PROTECTED_FUNCTIONS_COUNT; index++)
|
||||
{
|
||||
RtlInitUnicodeString(¤t_function, PROTECTED_FUNCTIONS[index]);
|
||||
|
||||
if (!current_function.Buffer)
|
||||
continue;
|
||||
|
||||
status = GetAverageReadTimeAtRoutine(
|
||||
¤t_function,
|
||||
PROTECTED_FUNCTION_ADDRESSES[index],
|
||||
&instruction_time
|
||||
);
|
||||
|
||||
|
@ -1481,18 +1517,16 @@ DetectEptHooksInKeyFunctions()
|
|||
/* [+] EPT hook detected at function: ExAllocatePoolWithTag with execution time of: 149b7777777 */
|
||||
if (control_average * EPT_EXECUTION_TIME_MULTIPLIER < instruction_time)
|
||||
{
|
||||
DEBUG_LOG("EPT hook detected at function: %wZ with execution time of: %llx",
|
||||
current_function,
|
||||
DEBUG_LOG("EPT hook detected at function: %llx with execution time of: %llx",
|
||||
PROTECTED_FUNCTION_ADDRESSES[index],
|
||||
instruction_time);
|
||||
|
||||
/* close game etc. */
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG("No ept hook detected at function: %wZ", current_function);
|
||||
DEBUG_LOG("No ept hook detected at function: %llx", PROTECTED_FUNCTION_ADDRESSES[index]);
|
||||
}
|
||||
|
||||
RtlZeroMemory(current_function.Buffer, current_function.Length);
|
||||
}
|
||||
|
||||
return status;
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#define IOCTL_VALIDATE_PROCESS_LOADED_MODULE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x2015, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_REQUEST_HARDWARE_INFORMATION CTL_CODE(FILE_DEVICE_UNKNOWN, 0x2016, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_INITIATE_APC_OPERATION CTL_CODE(FILE_DEVICE_UNKNOWN, 0x2017, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_CHECK_FOR_EPT_HOOK CTL_CODE(FILE_DEVICE_UNKNOWN, 0x2018, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
#define APC_OPERATION_STACKWALK 0x1
|
||||
|
||||
|
@ -335,6 +336,25 @@ DeviceControl(
|
|||
|
||||
break;
|
||||
|
||||
case IOCTL_CHECK_FOR_EPT_HOOK:
|
||||
|
||||
/*
|
||||
* No need to wait on this thread as if it fails, program will be shut.
|
||||
*/
|
||||
status = PsCreateSystemThread(
|
||||
&handle,
|
||||
PROCESS_ALL_ACCESS,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
DetectEptHooksInKeyFunctions,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
DEBUG_ERROR("DetectEpthooksInKeyFunctions failed with status %x", status);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
DEBUG_ERROR("Invalid IOCTL passed to driver");
|
||||
|
|
|
@ -94,11 +94,14 @@ ValidateKPCRBThreads(
|
|||
{
|
||||
old_affinity = KeSetSystemAffinityThreadEx((KAFFINITY)(1ull << processor_index));
|
||||
|
||||
while (KeGetCurrentProcessorNumber() != processor_index)
|
||||
YieldProcessor();
|
||||
|
||||
kpcr = __readmsr(IA32_GS_BASE);
|
||||
kprcb = kpcr + KPRCB_OFFSET_FROM_GS_BASE;
|
||||
context.current_kpcrb_thread = *(UINT64*)(kprcb + KPCRB_CURRENT_THREAD);
|
||||
|
||||
DEBUG_LOG("Current thread: %llx", context.current_kpcrb_thread);
|
||||
DEBUG_LOG("Proc number: %lx, Current thread: %llx", processor_index, context.current_kpcrb_thread);
|
||||
|
||||
if (!context.current_kpcrb_thread)
|
||||
continue;
|
||||
|
@ -108,6 +111,8 @@ ValidateKPCRBThreads(
|
|||
&context
|
||||
);
|
||||
|
||||
DEBUG_LOG("Found in kthread: %lx, found in pspcid: %lx", (UINT32)context.thread_found_in_kthreadlist, (UINT32)context.thread_found_in_pspcidtable);
|
||||
|
||||
if (context.current_kpcrb_thread == FALSE || context.thread_found_in_pspcidtable == FALSE)
|
||||
{
|
||||
PHIDDEN_SYSTEM_THREAD_REPORT report =
|
||||
|
|
|
@ -527,6 +527,25 @@ VOID kernelmode::Driver::CheckForHiddenThreads()
|
|||
LOG_ERROR("failed to check for hidden threads %x", GetLastError());
|
||||
}
|
||||
|
||||
VOID kernelmode::Driver::CheckForEptHooks()
|
||||
{
|
||||
BOOLEAN status;
|
||||
|
||||
status = DeviceIoControl(
|
||||
this->driver_handle,
|
||||
IOCTL_CHECK_FOR_EPT_HOOK,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (status == NULL)
|
||||
LOG_ERROR("failed to check for ept hooks %x", GetLastError());
|
||||
}
|
||||
|
||||
VOID kernelmode::Driver::CheckDriverHeartbeat()
|
||||
{
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#define IOCTL_VALIDATE_PROCESS_LOADED_MODULE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x2015, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_REQUEST_HARDWARE_INFORMATION CTL_CODE(FILE_DEVICE_UNKNOWN, 0x2016, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_INITIATE_APC_OPERATION CTL_CODE(FILE_DEVICE_UNKNOWN, 0x2017, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_CHECK_FOR_EPT_HOOK CTL_CODE(FILE_DEVICE_UNKNOWN, 0x2018, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
#define MAX_REPORTS_PER_IRP 20
|
||||
|
||||
|
@ -76,6 +77,7 @@ namespace kernelmode
|
|||
VOID VerifyProcessLoadedModuleExecutableRegions();
|
||||
VOID SendClientHardwareInformation();
|
||||
VOID CheckForHiddenThreads();
|
||||
VOID CheckForEptHooks();
|
||||
BOOLEAN InitiateApcOperation( INT OperationId );
|
||||
};
|
||||
|
||||
|
|
|
@ -69,4 +69,9 @@ VOID kernelmode::KManager::InitiateApcStackwalkOperation()
|
|||
VOID kernelmode::KManager::CheckForHiddenThreads()
|
||||
{
|
||||
this->thread_pool->QueueJob([this]() { this->driver_interface->CheckForHiddenThreads(); });
|
||||
}
|
||||
|
||||
VOID kernelmode::KManager::CheckForEptHooks()
|
||||
{
|
||||
this->thread_pool->QueueJob([this]() { this->driver_interface->CheckForEptHooks(); });
|
||||
}
|
|
@ -30,6 +30,7 @@ namespace kernelmode
|
|||
VOID SendClientHardwareInformation();
|
||||
VOID InitiateApcStackwalkOperation();
|
||||
VOID CheckForHiddenThreads();
|
||||
VOID CheckForEptHooks();
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -43,39 +43,21 @@ DWORD WINAPI Init(HINSTANCE hinstDLL)
|
|||
|
||||
while (!GetAsyncKeyState(VK_DELETE))
|
||||
{
|
||||
int seed = (rand() % 9);
|
||||
int seed = (rand() % 3);
|
||||
|
||||
std::cout << "Seed: " << seed << std::endl;
|
||||
|
||||
switch (seed)
|
||||
{
|
||||
case 0:
|
||||
kmanager.EnumerateHandleTables();
|
||||
break;
|
||||
case 1:
|
||||
kmanager.PerformIntegrityCheck();
|
||||
break;
|
||||
case 2:
|
||||
kmanager.ScanPoolsForUnlinkedProcesses();
|
||||
break;
|
||||
case 3:
|
||||
kmanager.VerifySystemModules();
|
||||
break;
|
||||
case 4:
|
||||
kmanager.ValidateProcessModules();
|
||||
break;
|
||||
case 5:
|
||||
kmanager.RunNmiCallbacks();
|
||||
break;
|
||||
case 6:
|
||||
kmanager.CheckForAttachedThreads();
|
||||
break;
|
||||
case 7:
|
||||
kmanager.InitiateApcStackwalkOperation();
|
||||
break;
|
||||
case 8:
|
||||
case 1:
|
||||
kmanager.CheckForHiddenThreads();
|
||||
break;
|
||||
case 2:
|
||||
kmanager.CheckForEptHooks();
|
||||
break;
|
||||
}
|
||||
|
||||
kmanager.MonitorCallbackReports();
|
||||
|
@ -83,6 +65,51 @@ DWORD WINAPI Init(HINSTANCE hinstDLL)
|
|||
std::this_thread::sleep_for(std::chrono::seconds(10));
|
||||
}
|
||||
|
||||
//while (!GetAsyncKeyState(VK_DELETE))
|
||||
//{
|
||||
// int seed = (rand() % 10);
|
||||
|
||||
// std::cout << "Seed: " << seed << std::endl;
|
||||
|
||||
// switch (seed)
|
||||
// {
|
||||
// case 0:
|
||||
// kmanager.EnumerateHandleTables();
|
||||
// break;
|
||||
// case 1:
|
||||
// kmanager.PerformIntegrityCheck();
|
||||
// break;
|
||||
// case 2:
|
||||
// kmanager.ScanPoolsForUnlinkedProcesses();
|
||||
// break;
|
||||
// case 3:
|
||||
// kmanager.VerifySystemModules();
|
||||
// break;
|
||||
// case 4:
|
||||
// kmanager.ValidateProcessModules();
|
||||
// break;
|
||||
// case 5:
|
||||
// kmanager.RunNmiCallbacks();
|
||||
// break;
|
||||
// case 6:
|
||||
// kmanager.CheckForAttachedThreads();
|
||||
// break;
|
||||
// case 7:
|
||||
// kmanager.InitiateApcStackwalkOperation();
|
||||
// break;
|
||||
// case 8:
|
||||
// kmanager.CheckForHiddenThreads();
|
||||
// break;
|
||||
// case 9:
|
||||
// kmanager.CheckForEptHooks();
|
||||
// break;
|
||||
// }
|
||||
|
||||
// kmanager.MonitorCallbackReports();
|
||||
|
||||
// std::this_thread::sleep_for(std::chrono::seconds(10));
|
||||
//}
|
||||
|
||||
fclose(stdout);
|
||||
fclose(stdin);
|
||||
FreeConsole();
|
||||
|
|
Loading…
Reference in a new issue