Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 调试线程时执行无限循环_C++_Windows_Debugging_Reverse Engineering - Fatal编程技术网

C++ 调试线程时执行无限循环

C++ 调试线程时执行无限循环,c++,windows,debugging,reverse-engineering,C++,Windows,Debugging,Reverse Engineering,我试图将硬件断点附加到游戏进程,但我成功了。然后,我尝试循环遍历异常,等待我放入的异常,它也可以正常工作。问题是,在它发生后,它进入无限循环,我无法刹车。你能提出建议吗? 我这样做的原因是我想在这一点上停止线程,使用上下文读取EAX值,然后继续进程 h包含在这里调用的函数,它们都可以正常工作,因此我现在不包括它 #包括“Header.h” #包括 int main(){ SetDebugPrivilege(TRUE); DWORD dwProcessID=0; DWORD dwGame=0; p

我试图将硬件断点附加到游戏进程,但我成功了。然后,我尝试循环遍历异常,等待我放入的异常,它也可以正常工作。问题是,在它发生后,它进入无限循环,我无法刹车。你能提出建议吗? 我这样做的原因是我想在这一点上停止线程,使用上下文读取EAX值,然后继续进程

h包含在这里调用的函数,它们都可以正常工作,因此我现在不包括它

#包括“Header.h” #包括

int main(){

SetDebugPrivilege(TRUE);
DWORD dwProcessID=0;
DWORD dwGame=0;
printf(“寻找游戏过程…\n”);
while(dwProcessID==0){
dwProcessID=GetProcessID(L“PathOfExile.exe”);
如果(dwProcessID!=0)
dwGame=1;
睡眠(100);
}
printf(“dwProcessID=%p\n”,dwProcessID);
HANDLE snapshot=CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,dwProcessID);
模块Entry32模块;
module.dwSize=sizeof(MODULEENTRY32);
模块32第一个(快照和模块);
printf(“PoE基址=%p\n”,module.modBaseAddr);
hpChangeBreakpoint=(DWORD*)((char*)module.modBaseAddr+0x1AAD20);

std::cout您是否在收听/了解
恢复标志(RF)
?您需要将其设置为step over
DrX
brealpoint

所以代码必须是下一个

#define RESUME_FLAG 0x10000

CONTEXT Context = {};
Context.ContextFlags = CONTEXT_CONTROL;// not need CONTEXT_FULL here;
if (GetThreadContext(hThread, &Context))
{
    Context.EFlags |= RESUME_FLAG; // !!! this line is key point
    SetThreadContext(hThread, &Context);
}
这将是从win2003或windows vista开始的工作。不幸的是,XP不允许您在
上下文中设置此标志。因此,在这里您需要删除
Dr0
断点以跳过它(或修补程序XP内核-在ntoskrnl代码中搜索
0x003E0DD7
DWORD
,并将其替换为
0x003F0DD7
-这是
Eflags
掩码-在
恢复标志中不同)

另外,请给出一些优化建议-您不需要每次在
异常调试事件
时调用
OpenThread

首先,您已经有了这个线程句柄

HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, dwThreadID);
调用
SetThreadContext

异常只能在该线程的上下文中发生,所有其他线程不受此影响

在第二秒钟,您从未关闭在
异常\u调试\u事件中打开的线程句柄,所以您已经有了资源泄漏

调试器在
CREATE\u thread\u DEBUG\u EVENT
CREATE\u PROCESS\u DEBUG\u EVENT
上获得了线程句柄,并且必须关闭它(或者只是或通常维护它并关闭
EXIT\u thread\u DEBUG\u EVENT
EXIT\u PROCESS\u DEBUG\u EVENT

您无法处理
加载\u DLL\u调试\u事件,因此无法关闭文件句柄

您的代码有大量句柄泄漏

SuspendThread/ResumeThread-为了什么?!绝对没有意义-线程(以及进程中的所有线程)在这一点上已经挂起


struct CThread:LIST\u条目
{
句柄线程;
乌隆(ULONG)杜维德;;
CThread(HANDLE-hThread,ULONG-dwThreadId)
{
_hThread=hThread;
_dwThreadId=dwThreadId;
}
~CThread()
{
//CloseHandle(_hThread);//将在ContinuedBugEvent中关闭
}
静态CThread*get(ULONG dwThreadId,PLIST_条目threadlisthhead,CThread*phinthread)
{
if(pHintThread&&pHintThread->\u dwThreadId==dwThreadId)
{
返回非线程;
}
PLIST_ENTRY=螺纹列表头;
而((entry=entry->Flink)!=ThreadListHead)
{
pHintThread=静态转换(条目);
如果(pHintThread->_dwThreadId==dwThreadId)
{
返回非线程;
}
}
返回0;/??
}
静态void DeleteAll(PLIST\u入口螺纹列表头)
{
PLIST_ENTRY=ThreadListHead->Flink;
while(条目!=ThreadListHead)
{
CThread*pThread=static_cast(条目);
入口=入口->燧石;
删除pThread;
}
}
};
void RunDebuggerLoop()
{
BOOL bkuit=假;
列表\项目ThreadListHead={&ThreadListHead,&ThreadListHead};
CThread*pThread=0;
调试事件de;
布尔bFirst=TRUE;
while(!bguit&&WaitForDebugEvent(&de,无限))
{
NTSTATUS status=DBG\u CONTINUE;
开关(de.dwDebugEventCode)
{
案例异常\u调试\u事件:
如果(
!de.u.Exception.dwFirstChance
|| 
!(pThread=CThread::get(de.dwThreadId和线程列表头,pThread))
)
{
bkuit=TRUE;
继续;
}
状态=DBG\u异常未处理;
开关(de.u.Exception.ExceptionRecord.ExceptionCode)
{
案例状态\u断点:
案例状态\u WX86\u断点:
如果(bFirst)
{
bFirst=假;
状态=DBG_继续;
}
打破
案例状态\u单个步骤:
案例状态\u WX86\u单个步骤:
{
::CONTEXT ctx={};
ctx.ContextFlags=CONTEXT\u控件;
if(GetThreadContext(pThread->hThread,&ctx))
{
ctx.EFlags |=恢复标志;
SetThreadContext(pThread->hThread,&ctx);
}
}
打破
案例状态\访问\违规:
如果(de.u.Exception.ExceptionRecord.NumberParameters>1)
{
ULONG_PTR PTR=de.u.Exception.Exception记录。Exception信息[1];
}
打破
}
打破
案例创建\流程\调试\事件:
CloseHandle(de.u.CreateProcessInfo.hFile);
//CloseHandle(de.u.CreateProcessInfo.h
HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, dwThreadID);
struct CThread : LIST_ENTRY
{
    HANDLE _hThread;
    ULONG _dwThreadId;

    CThread(HANDLE hThread, ULONG dwThreadId)
    {
        _hThread = hThread;
        _dwThreadId = dwThreadId;
    }

    ~CThread()
    {
        //CloseHandle(_hThread);// will be closed in ContinueDebugEvent
    }

    static CThread* get(ULONG dwThreadId, PLIST_ENTRY ThreadListHead, CThread* pHintThread)
    {
        if (pHintThread && pHintThread->_dwThreadId == dwThreadId)
        {
            return pHintThread;
        }

        PLIST_ENTRY entry = ThreadListHead;

        while ((entry = entry->Flink) != ThreadListHead)
        {
            pHintThread = static_cast<CThread*>(entry);

            if (pHintThread->_dwThreadId == dwThreadId)
            {
                return pHintThread;
            }
        }

        return 0;//??
    }

    static void DeleteAll(PLIST_ENTRY ThreadListHead)
    {
        PLIST_ENTRY entry = ThreadListHead->Flink;

        while (entry != ThreadListHead)
        {
            CThread* pThread = static_cast<CThread*>(entry);

            entry = entry->Flink;

            delete pThread;
        }
    }
};


void RunDebuggerLoop()
{
    BOOL bQuit = FALSE;

    LIST_ENTRY ThreadListHead = { &ThreadListHead, &ThreadListHead };

    CThread* pThread = 0;

    DEBUG_EVENT de;

    BOOLEAN bFirst = TRUE;

    while (!bQuit && WaitForDebugEvent(&de, INFINITE))
    {
        NTSTATUS status = DBG_CONTINUE;

        switch(de.dwDebugEventCode)
        {
        case EXCEPTION_DEBUG_EVENT:
            if (
                !de.u.Exception.dwFirstChance 
                || 
                !(pThread = CThread::get(de.dwThreadId, &ThreadListHead, pThread))
                )
            {
                bQuit = TRUE;
                continue;
            }

            status = DBG_EXCEPTION_NOT_HANDLED;

            switch (de.u.Exception.ExceptionRecord.ExceptionCode)
            {
            case STATUS_BREAKPOINT:
            case STATUS_WX86_BREAKPOINT:
                if (bFirst)
                {
                    bFirst = FALSE;
                    status = DBG_CONTINUE;
                }
                break;

            case STATUS_SINGLE_STEP:
            case STATUS_WX86_SINGLE_STEP:
                {
                    ::CONTEXT ctx = {};
                    ctx.ContextFlags = CONTEXT_CONTROL;
                    if (GetThreadContext(pThread->_hThread, &ctx))
                    {
                        ctx.EFlags |= RESUME_FLAG;
                        SetThreadContext(pThread->_hThread, &ctx);
                    }
                }
                break;

            case STATUS_ACCESS_VIOLATION:
                if (de.u.Exception.ExceptionRecord.NumberParameters > 1)
                {
                    ULONG_PTR ptr = de.u.Exception.ExceptionRecord.ExceptionInformation[1];
                }

                break;                              
            }

            break;

        case CREATE_PROCESS_DEBUG_EVENT:
            CloseHandle(de.u.CreateProcessInfo.hFile);
            //CloseHandle(de.u.CreateProcessInfo.hProcess);// will be auto closed in ContinueDebugEvent
            de.u.CreateThread.hThread = de.u.CreateProcessInfo.hThread;

        case CREATE_THREAD_DEBUG_EVENT:
            if (pThread = new CThread(de.u.CreateThread.hThread, de.dwThreadId))
            {
                InsertHeadList(&ThreadListHead, pThread);
            }
            break;

        case EXIT_THREAD_DEBUG_EVENT:
            if (pThread = CThread::get(de.dwThreadId, &ThreadListHead, pThread))
            {
                RemoveEntryList(pThread);
                delete pThread;
                pThread = 0;
            }
            break;

        case LOAD_DLL_DEBUG_EVENT:
            CloseHandle(de.u.LoadDll.hFile);
            break;

        case EXIT_PROCESS_DEBUG_EVENT:
            bQuit = TRUE;
            break;

        case OUTPUT_DEBUG_STRING_EVENT:
        case UNLOAD_DLL_DEBUG_EVENT:
            __nop();
            break;
        default:
            __nop();
        }

        if (!ContinueDebugEvent(de.dwProcessId, de.dwThreadId, status))
        {
            break;
        }
    }

    CThread::DeleteAll(&ThreadListHead);
}
void Ep()
{
    // tag by * in begin of CommandLine
    PWSTR CommandLine = GetCommandLine();

    if (!CommandLine || *CommandLine != '*')
    {
        // debugger case

        WCHAR FileName[MAX_PATH];
        if (ULONG n = GetModuleFileName(0, FileName, RTL_NUMBER_OF(FileName)))
        {
            if (n < MAX_PATH)
            {
                PROCESS_INFORMATION pi;
                STARTUPINFO si = { sizeof(si) };
                PWSTR newCommandLine = (PWSTR)alloca((wcslen(CommandLine) + 2)*sizeof(WCHAR));
                *newCommandLine = '*';
                wcscpy(newCommandLine + 1, CommandLine);

                if (CreateProcessW(FileName, newCommandLine, 0, 0, 0, DEBUG_PROCESS, 0, 0, &si, &pi))
                {
                    CloseHandle(pi.hThread);
                    CloseHandle(pi.hProcess);

                    RunDebuggerLoop();
                }
            }
        }
        ExitProcess(0);
    }
    else
    {
        // main case

        wcscpy(CommandLine, CommandLine + 1);

        OutputDebugStringA("AAAAAA\n");

        if (MessageBoxW(0, L"xxx", CommandLine, MB_YESNO) == IDYES)
        {
            OutputDebugStringW(L"WWWWWWWW\n");
        }
        ExitProcess(0);
    }
}
#include "Header.h"
#include <iostream>

int main() {


hpChangeBreakpoint = 0x013FB279;

SetDebugPrivilege(TRUE);

DWORD dwProcessID = 0;
DWORD dwGame = 0;

printf("Looking for game process...\n");

while (dwProcessID == 0) {
    dwProcessID = GetProcessID(L"PathOfExile.exe");
    if (dwProcessID != 0)
        dwGame = 1;

    Sleep(100);
}

printf("dwProcessID = %p\n", dwProcessID);

HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, dwProcessID);

BOOL bDebugging = DebugActiveProcess(dwProcessID);
printf("bDebugging = %d\n", bDebugging);


DWORD dwThreadID = GetProcessThreadID(dwProcessID);

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

CONTEXT context;

context.ContextFlags = CONTEXT_DEBUG_REGISTERS;

if (GetThreadContext(hThread, &context))
{
    context.Dr0 = hpChangeBreakpoint;
    context.Dr7 = 0x00000001;

    std::cout << "GetThreadContext successful" << std::endl;

    SetThreadContext(hThread, &context);
}


DEBUG_EVENT DebugEvent;
BOOL bContinueDebugging = false;



for(;;)
{
    WaitForDebugEvent(&DebugEvent, INFINITE);

    switch (DebugEvent.dwDebugEventCode)
    {

    case EXCEPTION_DEBUG_EVENT:

        switch (DebugEvent.u.Exception.ExceptionRecord.ExceptionCode)
        {
        case EXCEPTION_SINGLE_STEP:
            if (DebugEvent.u.Exception.ExceptionRecord.ExceptionAddress == (void*)hpChangeBreakpoint)
            {
                #define RESUME_FLAG 0x10000
                CONTEXT Context;
                Context.ContextFlags = CONTEXT_CONTROL;
                Context.EFlags |= RESUME_FLAG;


                std::cout << "Breakpoint" << std::endl;

                bContinueDebugging = true;
            }
            if (bContinueDebugging)
            {
                // DBG_CONTINUE to tell the program we have handled the exception
                ContinueDebugEvent(DebugEvent.dwProcessId, DebugEvent.dwThreadId, DBG_CONTINUE);
                bContinueDebugging = false;
            }
            else // if the exception was not handled by our exception-handler, we want the program to handle it, so..
                ContinueDebugEvent(DebugEvent.dwProcessId, DebugEvent.dwThreadId, DBG_EXCEPTION_NOT_HANDLED);

            break;
        default:
            ContinueDebugEvent(DebugEvent.dwProcessId, DebugEvent.dwThreadId, DBG_EXCEPTION_NOT_HANDLED);
        }


        break;

    case LOAD_DLL_DEBUG_EVENT:
    {
        std::cout << "load dll debug event" << std::endl;
        CloseHandle(DebugEvent.u.LoadDll.hFile);
        break;
    }
    default:
        ContinueDebugEvent(DebugEvent.dwProcessId, DebugEvent.dwThreadId, DBG_EXCEPTION_NOT_HANDLED);
    }

}

system("pause>nul");
return 0;