mirror of
https://github.com/HyperDbg/HyperDbg.git
synced 2026-07-18 13:34:37 +00:00
292 lines
8.1 KiB
C
292 lines
8.1 KiB
C
/**
|
|
* @file DpcRoutines.c
|
|
* @author Sina Karvandi (sina@hyperdbg.org)
|
|
* @brief All the dpc routines which relates to executing on a single core
|
|
* for multi-core you can use Broadcast.c
|
|
*
|
|
* @version 0.1
|
|
* @date 2020-04-29
|
|
*
|
|
* @copyright This project is released under the GNU Public License v3.
|
|
*
|
|
*/
|
|
#include "pch.h"
|
|
|
|
/**
|
|
* @brief lock for one core execution
|
|
*
|
|
*/
|
|
volatile LONG OneCoreLock;
|
|
|
|
/**
|
|
* @brief This function synchronize the function execution for a single core
|
|
* You should only used it for one core, not in multiple threads simultaneously
|
|
* The function that needs to use this feature (Routine parameter function) should
|
|
* have the when it ends :
|
|
*
|
|
* SpinlockUnlock(&OneCoreLock);
|
|
*
|
|
* @param CoreNumber core number that the target function should run on it
|
|
* @param Routine the target function that should be ran
|
|
* @param DeferredContext an optional parameter to Routine
|
|
* @return NTSTATUS
|
|
*/
|
|
NTSTATUS
|
|
DpcRoutineRunTaskOnSingleCore(UINT32 CoreNumber, PVOID Routine, PVOID DeferredContext)
|
|
{
|
|
PRKDPC Dpc;
|
|
ULONG ProcessorsCount;
|
|
|
|
ProcessorsCount = KeQueryActiveProcessorCount(0);
|
|
|
|
//
|
|
// Check if the core number is not invalid
|
|
//
|
|
if (CoreNumber >= ProcessorsCount)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// Allocate Memory for DPC
|
|
//
|
|
Dpc = PlatformMemAllocateZeroedNonPagedPool(sizeof(KDPC));
|
|
|
|
if (!Dpc)
|
|
{
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
//
|
|
// Creating a DPC that will run on the target process
|
|
//
|
|
KeInitializeDpc(Dpc, // Dpc
|
|
(PKDEFERRED_ROUTINE)Routine, // DeferredRoutine
|
|
DeferredContext // DeferredContext
|
|
);
|
|
|
|
//
|
|
// Set the target core
|
|
//
|
|
KeSetTargetProcessorDpc(Dpc, (CCHAR)CoreNumber);
|
|
|
|
//
|
|
// it's sure will be executed, but we want to free the above
|
|
// pool, so we have to wait on a spinlock that will be release
|
|
// by the DPC routine, actually Affinity Thread but that
|
|
// won't support more than 64 logical cores, I create a discussion
|
|
// here, and explained the problem, but no one answers
|
|
// link: https://community.osr.com/discussion/292064/putting-a-barrier-for-dpc-before-continuing-the-rest-of-code
|
|
// we also can't use the spinlock routine of Windows as this function
|
|
// raises the IRQL to DPC and we want to execute at DPC, means that
|
|
// If we're currently on the right core, we never find a chance to
|
|
// release the spinlock so a deadlock happens, all in all it's complicated :)
|
|
//
|
|
|
|
//
|
|
// Set the lock to be freed by the other DPC routine
|
|
//
|
|
if (!SpinlockTryLock(&OneCoreLock))
|
|
{
|
|
//
|
|
// We can't get the lock, probably sth goes wrong !
|
|
//
|
|
PlatformMemFreePool(Dpc);
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
//
|
|
// Fire the DPC
|
|
//
|
|
KeInsertQueueDpc(Dpc, NULL, NULL);
|
|
|
|
//
|
|
// spin on lock to be release, immediately after we get the lock, we'll
|
|
// release it for because there is no need to it anymore and DPC is finished
|
|
//
|
|
SpinlockLock(&OneCoreLock);
|
|
SpinlockUnlock(&OneCoreLock);
|
|
|
|
//
|
|
// Now it's safe to deallocate the bugger
|
|
//
|
|
PlatformMemFreePool(Dpc);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Broadcast msr write
|
|
*
|
|
* @param Dpc
|
|
* @param DeferredContext
|
|
* @param SystemArgument1
|
|
* @param SystemArgument2
|
|
* @return VOID
|
|
*/
|
|
VOID
|
|
DpcRoutinePerformWriteMsr(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2)
|
|
{
|
|
ULONG CurrentCore = KeGetCurrentProcessorNumberEx(NULL);
|
|
PROCESSOR_DEBUGGING_STATE * CurrentDebuggingState = &g_DbgState[CurrentCore];
|
|
|
|
UNREFERENCED_PARAMETER(Dpc);
|
|
UNREFERENCED_PARAMETER(DeferredContext);
|
|
UNREFERENCED_PARAMETER(SystemArgument1);
|
|
UNREFERENCED_PARAMETER(SystemArgument2);
|
|
|
|
//
|
|
// write on MSR
|
|
//
|
|
CpuWriteMsr((ULONG)CurrentDebuggingState->MsrState.Msr, CurrentDebuggingState->MsrState.Value);
|
|
|
|
//
|
|
// As this function is designed for a single,
|
|
// we have to release the synchronization lock here
|
|
//
|
|
SpinlockUnlock(&OneCoreLock);
|
|
}
|
|
|
|
/**
|
|
* @brief Broadcast msr read
|
|
*
|
|
* @param Dpc
|
|
* @param DeferredContext
|
|
* @param SystemArgument1
|
|
* @param SystemArgument2
|
|
* @return VOID
|
|
*/
|
|
VOID
|
|
DpcRoutinePerformReadMsr(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2)
|
|
{
|
|
ULONG CurrentCore = KeGetCurrentProcessorNumberEx(NULL);
|
|
PROCESSOR_DEBUGGING_STATE * CurrentDebuggingState = &g_DbgState[CurrentCore];
|
|
|
|
UNREFERENCED_PARAMETER(Dpc);
|
|
UNREFERENCED_PARAMETER(DeferredContext);
|
|
UNREFERENCED_PARAMETER(SystemArgument1);
|
|
UNREFERENCED_PARAMETER(SystemArgument2);
|
|
|
|
//
|
|
// read on MSR
|
|
//
|
|
CurrentDebuggingState->MsrState.Value = CpuReadMsr((ULONG)CurrentDebuggingState->MsrState.Msr);
|
|
|
|
//
|
|
// As this function is designed for a single,
|
|
// we have to release the synchronization lock here
|
|
//
|
|
SpinlockUnlock(&OneCoreLock);
|
|
}
|
|
|
|
/**
|
|
* @brief Broadcast Msr Write
|
|
*
|
|
* @param Dpc
|
|
* @param DeferredContext
|
|
* @param SystemArgument1
|
|
* @param SystemArgument2
|
|
* @return VOID
|
|
*/
|
|
VOID
|
|
DpcRoutineWriteMsrToAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2)
|
|
{
|
|
ULONG CurrentCore = KeGetCurrentProcessorNumberEx(NULL);
|
|
PROCESSOR_DEBUGGING_STATE * CurrentDebuggingState = &g_DbgState[CurrentCore];
|
|
|
|
UNREFERENCED_PARAMETER(Dpc);
|
|
UNREFERENCED_PARAMETER(DeferredContext);
|
|
|
|
//
|
|
// write on MSR
|
|
//
|
|
CpuWriteMsr((ULONG)CurrentDebuggingState->MsrState.Msr, CurrentDebuggingState->MsrState.Value);
|
|
|
|
// ------------------------------------------------------------------------------
|
|
// Synchronize the end of this routine with the caller
|
|
//
|
|
PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2);
|
|
}
|
|
|
|
/**
|
|
* @brief Broadcast Msr read
|
|
*
|
|
* @param Dpc
|
|
* @param DeferredContext
|
|
* @param SystemArgument1
|
|
* @param SystemArgument2
|
|
* @return VOID
|
|
*/
|
|
VOID
|
|
DpcRoutineReadMsrToAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2)
|
|
{
|
|
ULONG CurrentCore = KeGetCurrentProcessorNumberEx(NULL);
|
|
PROCESSOR_DEBUGGING_STATE * CurrentDebuggingState = &g_DbgState[CurrentCore];
|
|
|
|
UNREFERENCED_PARAMETER(Dpc);
|
|
UNREFERENCED_PARAMETER(DeferredContext);
|
|
|
|
//
|
|
// read msr
|
|
//
|
|
CurrentDebuggingState->MsrState.Value = CpuReadMsr((ULONG)CurrentDebuggingState->MsrState.Msr);
|
|
|
|
// ------------------------------------------------------------------------------
|
|
// Synchronize the end of this routine with the caller
|
|
//
|
|
PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2);
|
|
}
|
|
|
|
/**
|
|
* @brief vm-exit and halt the system
|
|
*
|
|
* @param Dpc
|
|
* @param DeferredContext
|
|
* @param SystemArgument1
|
|
* @param SystemArgument2
|
|
* @return VOID
|
|
*/
|
|
VOID
|
|
DpcRoutineVmExitAndHaltSystemAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2)
|
|
{
|
|
UNREFERENCED_PARAMETER(Dpc);
|
|
UNREFERENCED_PARAMETER(DeferredContext);
|
|
|
|
//
|
|
// vm-exit and halt current core
|
|
//
|
|
VmFuncVmxVmcall(DEBUGGER_VMCALL_VM_EXIT_HALT_SYSTEM, 0, 0, 0);
|
|
|
|
// ------------------------------------------------------------------------------
|
|
// Synchronize the end of this routine with the caller
|
|
//
|
|
PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2);
|
|
}
|
|
|
|
/**
|
|
* @brief Broadcast applying hardware debug register
|
|
*
|
|
* @param Dpc
|
|
* @param DeferredContext
|
|
* @param SystemArgument1
|
|
* @param SystemArgument2
|
|
* @return BOOLEAN
|
|
*/
|
|
BOOLEAN
|
|
DpcRoutineSetHardwareDebugRegisters(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2)
|
|
{
|
|
UNREFERENCED_PARAMETER(Dpc);
|
|
UNREFERENCED_PARAMETER(DeferredContext);
|
|
|
|
//
|
|
// Apply hardware debug registers
|
|
//
|
|
UdApplyHardwareDebugRegister(DeferredContext);
|
|
|
|
// ------------------------------------------------------------------------------
|
|
// Synchronize the end of this routine with the caller
|
|
//
|
|
PlatformBroadcastSynchronizeEndOfRoutine(SystemArgument1, SystemArgument2);
|
|
|
|
return TRUE;
|
|
}
|