debugging 以程序设计方式在多执行绪64比特应用程序上设定中断点

kpbpu008  于 2022-11-14  发布在  其他
关注(0)|答案(1)|浏览(109)

我从其他来源(主要是here)改编了一些代码,但在我的环境中没有任何用处。我正在连接一个64位的应用程序,在任何给定的时间都有100个线程。我有两个问题,有点不相关:
1.只要代码命中DebugActiveProcess(pid),附加的应用程序就会冻结。
1.我的代码只在主线程上设置了一个断点,但我需要在多个线程上设置断点--最好是在所有线程上。
我已经确认,当代码命中SetThreadContext(hThread, &ctx)时,dr0dr7寄存器会按预期进行更改,因此没有问题。我现在看到的唯一问题是进程冻结和设置多个断点(我想对每个线程进行迭代,但当它进入while循环时,显然会出现问题,并且非常消耗资源)。我还应该注意到,我可以将CheatEngine调试器连接到应用程序,断点工作正常,没有任何问题。下面是我使用的代码:

DWORD GetProcessThreadID(DWORD dwProcessID)
{
    THREADENTRY32 te = { sizeof(THREADENTRY32) };
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);

    if (Thread32First(hSnapshot, &te))
        while (Thread32Next(hSnapshot, &te))
            if (te.th32OwnerProcessID == dwProcessID)
                return te.th32ThreadID;

    return NULL;
}

BOOL SetDebugPrivilege(BOOL State)
{
    HANDLE hToken;
    TOKEN_PRIVILEGES token_privileges;
    DWORD dwSize;

    ZeroMemory(&token_privileges, sizeof(token_privileges));
    token_privileges.PrivilegeCount = 1;

    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken))
        return FALSE;

    if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &token_privileges.Privileges[0].Luid))
    {
        CloseHandle(hToken);
        return FALSE;
    }

    if (State)
        token_privileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    else
        token_privileges.Privileges[0].Attributes = SE_PRIVILEGE_REMOVED;

    if (!AdjustTokenPrivileges(hToken, FALSE, &token_privileges, 0, NULL, &dwSize))
    {
        CloseHandle(hToken);
        return FALSE;
    }

    return CloseHandle(hToken);
}

void CreateBreakpoint(DWORD pid, DWORD64 addr) {

    DebugActiveProcess(pid);
    DebugSetProcessKillOnExit(false);

    DWORD_PTR dwThreadID = GetProcessThreadID(pid);
    std::cout << std::hex << dwThreadID << std::endl;

    HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, dwThreadID);

    SetDebugPrivilege(true);

    CONTEXT ctx = { 0 };
    ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS | CONTEXT_INTEGER;
    ctx.Dr0 = addr;
    ctx.Dr7 = 0x00000001;

    SetThreadContext(hThread, &ctx);

    DEBUG_EVENT dbgEvent;
    while (true) {
        if (WaitForDebugEvent(&dbgEvent, INFINITE) == 0)
            break;

        if (dbgEvent.dwDebugEventCode == EXCEPTION_DEBUG_EVENT &&
            dbgEvent.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP) // EXCEPTION_BREAKPOINT
        {
            if (dbgEvent.u.Exception.ExceptionRecord.ExceptionAddress == (LPVOID)addr)
            {
                GetThreadContext(hThread, &ctx);
                std::cout << ctx.Rax << "\n";
                ctx.Dr7 = 0;
                SetThreadContext(hThread, &ctx);
            }
        }
        ContinueDebugEvent(dbgEvent.dwProcessId, dbgEvent.dwThreadId, DBG_CONTINUE);
    }
}

值得注意的是,这是一个Python脚本的C扩展,但这应该不是真正相关的,即使我单独运行代码,也会遇到同样的问题。另外,我不是CMaven,所以如果有任何误解,我道歉。

uurity8g

uurity8g1#

我同意Taekahn的观点,除非你给予更多关于你要做什么的信息,为什么不使用一个普通的调试器呢?如果你只是想读取寄存器,任何调试器都可以做到。你甚至可以在反汇编或随机地址中设置断点,或者设置数据断点。
关于gdb的IDK,但是即使在visual studio中,你也可以在断点上设置条件和动作。它没有c++代码那么强大,但是再次,没有更多的信息...
如果你想修改应用程序的行为,我们不是这样做的,使用调试器实际上会导致问题。

相关问题