三、调试事件的处理
回顾一下,前面讲了,可以通过WaitForDebugEvent()函数填充DEBUG_EVENT结构获取DEBUG事件,下面介绍对于事件的处理。
处理无非分为两种:作出适当处理后继续运行被调试者或者终止被调试者运行。
Windows Debug API中通过ContinueDebugEvent()处理调试事件。
BOOL WINAPI ContinueDebugEvent(
_In_ DWORD dwProcessId,
_In_ DWORD dwThreadId,
_In_ DWORD dwContinueStatus
);
前面两个参数在DEBUG_EVENT结构中包含,最后一个参考:XXXXXXXXXXXXXXXXXXXXXXXXX/en-us/library/windows/desktop/ms679285(v=vs.85).aspx。
一般选择DBG_CONTINUE使被调试者继续运行。
四、DEBUG循环
通过建立一个DEBUG循环,可以实现对DEBUG事件的动态处理。通过一个循环+switch...case结构,可以很好地完成。
STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi;
CreateProcess("C://1.exe",NULL,NULL,NULL,false,DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS|CREATE_NEW_CONSOLE,NULL,NULL,&si,&pi);
cout<<"[s:9]roccess Creat"<<endl;
DEBUG_EVENT dbe;
while(true){
WaitForDebugEvent(&dbe,INFINITE);
switch(dbe.dwDebugEventCode){
case CREATE_PROCESS_DEBUG_EVENT:
//Do what you want.
ContinueDebugEvent(dbe.dwProcessId,dbe.dwThreadId,DBG_CONTINUE);
case LOAD_DLL_DEBUG_EVENT:
//Do what you want.
ContinueDebugEvent(dbe.dwProcessId,dbe.dwThreadId,DBG_CONTINUE);
case EXCEPTION_DEBUG_EVENT:
cout<<"EXCEPTION!"<<endl;
ContinueDebugEvent(dbe.dwProcessId,dbe.dwThreadId,DBG_CONTINUE);
case EXIT_PROCESS_DEBUG_EVENT:
cout<<"[s:9]orocess Exit!"<<endl;
ContinueDebugEvent(dbe.dwProcessId,dbe.dwThreadId,DBG_CONTINUE);
break;
default:
ContinueDebugEvent(dbe.dwProcessId,dbe.dwThreadId,DBG_CONTINUE);
}
}
TerminateProcess(pi.hProcess,-1);
循环开始的时候完成对事件的获取,接下来在switch...case结构中进行判断和处理。
五、更多
我们的调试器还能实现更多功能,除了利用进程句柄管理其内存外,还可以通过GetThreadContext()填充CONTEXT结构获取某线程的寄存器内容,甚至还可以通过SetThreadContext()来修改。
BOOL WINAPI GetThreadContext(
_In_ HANDLE hThread,
_Inout_ LPCONTEXT lpContext
);
BOOL WINAPI SetThreadContext(
_In_ HANDLE hThread,
_In_ const CONTEXT *lpContext
);
typedef struct _CONTEXT
{
DWORD ContextFlags;
DWORD Dr0;
DWORD Dr1;
DWORD Dr2;
DWORD Dr3;
DWORD Dr6;
DWORD Dr7;
FLOATING_SAVE_AREA FloatSave;
DWORD SegGs;
DWORD SegFs;
DWORD SegEs;
DWORD SegDs;
DWORD Edi;
DWORD Esi;
DWORD Ebx;
DWORD Edx;
DWORD Ecx;
DWORD Eax;
DWORD Ebp;
DWORD Eip;
DWORD SegCs;
DWORD EFlags;
DWORD Esp;
DWORD SegSs;
}CONTEXT;
Eip也可以修改,可以通过它在直接控制被调试程序的运行,当然修改EFlags也可以。
回顾一下,前面讲了,可以通过WaitForDebugEvent()函数填充DEBUG_EVENT结构获取DEBUG事件,下面介绍对于事件的处理。
处理无非分为两种:作出适当处理后继续运行被调试者或者终止被调试者运行。
Windows Debug API中通过ContinueDebugEvent()处理调试事件。
BOOL WINAPI ContinueDebugEvent(
_In_ DWORD dwProcessId,
_In_ DWORD dwThreadId,
_In_ DWORD dwContinueStatus
);
前面两个参数在DEBUG_EVENT结构中包含,最后一个参考:XXXXXXXXXXXXXXXXXXXXXXXXX/en-us/library/windows/desktop/ms679285(v=vs.85).aspx。
一般选择DBG_CONTINUE使被调试者继续运行。
四、DEBUG循环
通过建立一个DEBUG循环,可以实现对DEBUG事件的动态处理。通过一个循环+switch...case结构,可以很好地完成。
STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi;
CreateProcess("C://1.exe",NULL,NULL,NULL,false,DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS|CREATE_NEW_CONSOLE,NULL,NULL,&si,&pi);
cout<<"[s:9]roccess Creat"<<endl;
DEBUG_EVENT dbe;
while(true){
WaitForDebugEvent(&dbe,INFINITE);
switch(dbe.dwDebugEventCode){
case CREATE_PROCESS_DEBUG_EVENT:
//Do what you want.
ContinueDebugEvent(dbe.dwProcessId,dbe.dwThreadId,DBG_CONTINUE);
case LOAD_DLL_DEBUG_EVENT:
//Do what you want.
ContinueDebugEvent(dbe.dwProcessId,dbe.dwThreadId,DBG_CONTINUE);
case EXCEPTION_DEBUG_EVENT:
cout<<"EXCEPTION!"<<endl;
ContinueDebugEvent(dbe.dwProcessId,dbe.dwThreadId,DBG_CONTINUE);
case EXIT_PROCESS_DEBUG_EVENT:
cout<<"[s:9]orocess Exit!"<<endl;
ContinueDebugEvent(dbe.dwProcessId,dbe.dwThreadId,DBG_CONTINUE);
break;
default:
ContinueDebugEvent(dbe.dwProcessId,dbe.dwThreadId,DBG_CONTINUE);
}
}
TerminateProcess(pi.hProcess,-1);
循环开始的时候完成对事件的获取,接下来在switch...case结构中进行判断和处理。
五、更多
我们的调试器还能实现更多功能,除了利用进程句柄管理其内存外,还可以通过GetThreadContext()填充CONTEXT结构获取某线程的寄存器内容,甚至还可以通过SetThreadContext()来修改。
BOOL WINAPI GetThreadContext(
_In_ HANDLE hThread,
_Inout_ LPCONTEXT lpContext
);
BOOL WINAPI SetThreadContext(
_In_ HANDLE hThread,
_In_ const CONTEXT *lpContext
);
typedef struct _CONTEXT
{
DWORD ContextFlags;
DWORD Dr0;
DWORD Dr1;
DWORD Dr2;
DWORD Dr3;
DWORD Dr6;
DWORD Dr7;
FLOATING_SAVE_AREA FloatSave;
DWORD SegGs;
DWORD SegFs;
DWORD SegEs;
DWORD SegDs;
DWORD Edi;
DWORD Esi;
DWORD Ebx;
DWORD Edx;
DWORD Ecx;
DWORD Eax;
DWORD Ebp;
DWORD Eip;
DWORD SegCs;
DWORD EFlags;
DWORD Esp;
DWORD SegSs;
}CONTEXT;
Eip也可以修改,可以通过它在直接控制被调试程序的运行,当然修改EFlags也可以。
200字以内,仅用于支线交流,主线讨论请采用回复功能。