I have coded a very simple Debugger for x64, I am using currently Win10.
I am trying to set some Hardware Breakpoints to be trapped by my Debugger Loop as follows:
inline void SETBITS(DWORD64 *dw, int lowBit, int bits, int newValue) {
int mask = (1 << bits) - 1;
*dw = (*dw & ~(mask << lowBit)) | (newValue << lowBit);
}
BOOL SetHardwareBP(HANDLE hThread, __int64 Address, DWORD Length, int Condition)
{
CONTEXT context = { CONTEXT_DEBUG_REGISTERS };
int i;
if (!GetThreadContext(hThread, &context)) return -1;
// find available hardware register
for (i = 0; i < 4; i++)
{
if ((context.Dr7 & (1 << (i * 2))) == 0)
{
*(&context.Dr0 + i) = Address;
SETBITS(&context.Dr7, 16 + i * 4, 2, Condition);
SETBITS(&context.Dr7, 18 + i * 4, 2, Length);
SETBITS(&context.Dr7, i * 2, 1, 1);
if (!SetThreadContext(hThread, &context))
return -1;
return i;
}
}
return -1;
}
int SetDebugPrivileges(void) {
TOKEN_PRIVILEGES priv = { 0 };
HANDLE hToken = NULL;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
priv.PrivilegeCount = 1;
priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &priv.Privileges[0].Luid)) {
if (AdjustTokenPrivileges(hToken, FALSE, &priv, 0, NULL, NULL) == 0) {
printf("AdjustTokenPrivilege Error! [%u]\n", GetLastError());
}
}
CloseHandle(hToken);
}
return GetLastError();
}
void ThreadsLoop(DWORD mPID) {
HANDLE hProcessSnap = NULL;
SetDebugPrivileges();
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (hProcessSnap == INVALID_HANDLE_VALUE) return;
else
{
THREADENTRY32 the;
the.dwSize = sizeof(THREADENTRY32);
BOOL bret = Thread32First(hProcessSnap, &the);
while (bret)
{
if (the.th32OwnerProcessID == mPID)
{
HANDLE hthread = OpenThread(THREAD_ALL_ACCESS, false, the.th32ThreadID);
SuspendThread(hthread);
//call with length and condition set to 0 for a Code Execution type
int hr = SetHardwareBP(hthread, addr, 0, 0);
ResumeThread(hthread);
CloseHandle(hthread);
}
bret = Thread32Next(hProcessSnap, &the);
}
CloseHandle(hProcessSnap);
}
}
I am calling
ThreadsLoop(pi.dwProcessId);
where pi is the the PROCESS_INFORMATION structure returned from my initial call:
CreateProcess(pname, NULL, NULL, NULL, false, DEBUG_ONLY_THIS_PROCESS, NULL,NULL, &si, &pi);
None of the Hardware Breakpoints is Hit. I did several attempts changing the DR0-DR7 (and condition and length variables above) setup without luck. All calls to SetThreadContext returned successfully.
I did the same test with a Software Breakpoint via the following code and works perfect:
BYTE p[] = { 0xcc };
SIZE_T d = 0;
WriteProcessMemory(pi.hProcess, (void*)addr, p, sizeof(p), &d);
What could be wrong in this code/approach?
Thanks