一、前言
相比于上一章,本章的内容就稍微有意思一点了,因为可以直接上手使用。
本文要介绍的时win32 api中提供的一系列用于调试的api,比如vs中为什么能打断点调试程序?x64dbg为什么能让程序运行的时候暂停下来?其很大程度上就依赖于这些api。
二、API概述
常用的调试API大概有以下几个:
-
DebugActiveProcess:将调试器捆版在一个正常运行的进程上
-
DebugActiveProcessStop:将调试器从一个正常运行的进程上卸载
-
DebugBreak:在当前进程中产生以恶搞断点异常,如果当前进程未处在调试状态,那么该异常将被系统例程接管。
-
DebugBreakProcress:在指定进程中产生一个断点异常。
-
FatalExit:使调用进程强制退出,并将控制权转移至调试器
-
FlushInstructionCatche:刷新指令高速缓存。
-
GetThreadContext:获取指定线程的执行环境。
-
GetThreadSelectorEntry:获取指定选择器和线程的描述符表入口地址
-
IsDebuggerPresent:判断本进程是否处于调试状态。
-
ContinueDebugEvent:恢复因调试被挂起的线程
-
OutputDebugString:将一个字符串传递给调试器显示
-
ReadProcessMemory:读取指定进程的某块内存区域数据
-
WriteProcessMemory:想指定进程某内存区域写入数据
-
SetThreadContext:设置指定线程的执行环境
-
WaitForDebugEvent:用于等待被调试进程发生调试事件。
如果有兴趣的可以自行点击前往官方文档研究研究如何使用,后续逆向实战我也会使用一下这些函数。
三、调试事件
调试器的作用就是监视目标进程的执行、并对其发出的每一个调试事件做出应有的反应。
一旦目标进程发生了一个调试事件,那么系统就会通知调试器来处理这个事件,调试器就可以通过WaitForDebugEvent
函数来获取目标进程的相关环境信息。
也就是这个函数第一个参数返回的值,更多内容可以查看官方文档:DEBUG_EVENT
主要就是下面这个结构体:
typedef struct _DEBUG_EVENT {
DWORD dwDebugEventCode;
DWORD dwProcessId;
DWORD dwThreadId;
union {
EXCEPTION_DEBUG_INFO Exception;
CREATE_THREAD_DEBUG_INFO CreateThread;
CREATE_PROCESS_DEBUG_INFO CreateProcessInfo;
EXIT_THREAD_DEBUG_INFO ExitThread;
EXIT_PROCESS_DEBUG_INFO ExitProcess;
LOAD_DLL_DEBUG_INFO LoadDll;
UNLOAD_DLL_DEBUG_INFO UnloadDll;
OUTPUT_DEBUG_STRING_INFO DebugString;
RIP_INFO RipInfo;
} u;
} DEBUG_EVENT, *LPDEBUG_EVENT;
其中dwDebugEventCode
属性就标识了当前发生的调试事件类型,而dwProcessId
是目标进程的id,dwThreadId
是目标线程的id。