x64 Windows 10 中的简单调试器和硬件断点

逆向工程 调试器 断点
2021-06-17 22:59:36

我已经为 x64 编写了一个非常简单的调试器,我目前使用的是 Win10。

我正在尝试将一些硬件断点设置为由我的调试器循环捕获,如下所示:

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);
}
}

我正在调用 ThreadsLoop(pi.dwProcessId);哪里 pi 是从我的初始调用返回的 PROCESS_INFORMATION 结构:

CreateProcess(pname, NULL, NULL, NULL, false, DEBUG_ONLY_THIS_PROCESS, NULL,NULL, &si, &pi);

没有一个硬件断点被命中。我做了几次尝试更改 DR0-DR7(以及上面的条件和长度变量)设置,但没有成功。对 SetThreadContext 的所有调用都成功返回。

我通过以下代码对软件断点进行了相同的测试,并且运行良好:

BYTE p[] = { 0xcc }; 
SIZE_T d = 0;
WriteProcessMemory(pi.hProcess, (void*)addr, p, sizeof(p), &d);

此代码/方法可能有什么问题?

谢谢

1个回答

有些问题你必须解决

  1. 请看一下其中解释了在硬件断点情况下触发了哪个事件。您必须DebuggerThreadProc()函数中添加EXCEPTION_SINGLE_STEP

  2. 您需要附加到目标进程才能对其进行调试。为此,您需要使用DebugActiveProcess

  3. 这是一个相当大的语义错误。当您在同一个应用程序中创建目标进程时,您已经拥有该进程和主线程的打开句柄,因此无需创建快照和搜索目标!这是完全多余的。请删除所有这些部分并将句柄作为输入传递给这些函数。

  4. 始终牢记关闭您打开的手柄。