Files
maxDcb-C2Core/modules/ModuleCmd/hwbp.cpp
T
2025-04-05 13:22:52 -04:00

189 lines
3.7 KiB
C++

#include "hwbp.hpp"
#include "peb.hpp"
#if _WIN32
ULONG_PTR set_bits(
IN ULONG_PTR dw,
IN int lowBit,
IN int bits,
IN ULONG_PTR newValue)
{
ULONG_PTR mask = (1UL << bits) - 1UL;
dw = (dw & ~(mask << lowBit)) | (newValue << lowBit);
return dw;
}
BOOL enable_breakpoint(
OUT CONTEXT* ctx,
IN PVOID address,
IN int index)
{
switch (index)
{
case 0:
ctx->Dr0 = (ULONG_PTR)address;
break;
case 1:
ctx->Dr1 = (ULONG_PTR)address;
break;
case 2:
ctx->Dr2 = (ULONG_PTR)address;
break;
case 3:
ctx->Dr3 = (ULONG_PTR)address;
break;
default:
return FALSE;
}
ctx->Dr7 = set_bits(ctx->Dr7, 16, 16, 0);
ctx->Dr7 = set_bits(ctx->Dr7, (index * 2), 1, 1);
return TRUE;
}
typedef PVOID (WINAPI * RtlAddVectoredExceptionHandler_t)(
ULONG First,
exception_callback Handler
);
typedef PVOID (WINAPI * RtlRemoveVectoredExceptionHandler_t)(
PVOID Handle
);
VOID clear_breakpoint(
IN CONTEXT* ctx,
IN DWORD index)
{
// Clear the releveant hardware breakpoint
switch (index)
{
case 0:
ctx->Dr0 = 0;
break;
case 1:
ctx->Dr1 = 0;
break;
case 2:
ctx->Dr2 = 0;
break;
case 3:
ctx->Dr3 = 0;
break;
}
ctx->Dr7 = set_bits(ctx->Dr7, (index * 2), 1, 0);
ctx->Dr6 = 0;
ctx->EFlags = 0;
}
BOOL set_hwbp(
IN HANDLE hThread,
IN PVOID address,
IN exception_callback hwbp_handler,
IN UINT32 index,
OUT PHANDLE phHwBpHandler)
{
BOOL ret_val = FALSE;
NTSTATUS status = STATUS_UNSUCCESSFUL;
HANDLE hHwBpHandler = NULL;
CONTEXT threadCtx = { 0 };
memset(&threadCtx, 0, sizeof(threadCtx));
threadCtx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
RtlAddVectoredExceptionHandler_t RtlAddVectoredExceptionHandler = (RtlAddVectoredExceptionHandler_t)xGetProcAddress(xGetLibAddress((PCHAR)"ntdll", TRUE, NULL), (PCHAR)"RtlAddVectoredExceptionHandler", 0);
if (!RtlAddVectoredExceptionHandler)
{
goto Cleanup;
}
hHwBpHandler = RtlAddVectoredExceptionHandler(1, hwbp_handler);
if (!hHwBpHandler)
{
goto Cleanup;
}
status = GetThreadContext(hThread, &threadCtx);
if (!NT_SUCCESS(status))
{
goto Cleanup;
}
if (!enable_breakpoint(&threadCtx, address, index))
goto Cleanup;
status = SetThreadContext (hThread, &threadCtx);
if (!NT_SUCCESS(status))
{
goto Cleanup;
}
if (phHwBpHandler)
*phHwBpHandler = hHwBpHandler;
ret_val = TRUE;
Cleanup:
return ret_val;
}
VOID remove_hwbp_handler(
IN HANDLE hHwBpHandler)
{
if (!hHwBpHandler)
return;
RtlRemoveVectoredExceptionHandler_t RtlRemoveVectoredExceptionHandler = (RtlRemoveVectoredExceptionHandler_t)xGetProcAddress(xGetLibAddress((PCHAR)"ntdll", TRUE, NULL), (PCHAR)"RtlRemoveVectoredExceptionHandler", 0);
if (!RtlRemoveVectoredExceptionHandler)
{
return;
}
if (!RtlRemoveVectoredExceptionHandler(hHwBpHandler))
{
return;
}
}
VOID unset_hwbp(
IN HANDLE hThread,
IN UINT32 index)
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
CONTEXT threadCtx = { 0 };
memset(&threadCtx, 0, sizeof(threadCtx));
threadCtx.ContextFlags = CONTEXT_ALL;
status = GetThreadContext(hThread, &threadCtx);
if (!NT_SUCCESS(status))
{
goto cleanup;
}
clear_breakpoint(&threadCtx, index);
status = SetThreadContext (hThread, &threadCtx);
if (!NT_SUCCESS(status))
{
goto cleanup;
}
cleanup:
return;
}
#endif