反调试器附加
一、反调试器附加
建立调试会话是调试过程的第一步,其建立方式包含两种情况。一种情况是在调试器中启动被调试程序,另一种情况是直接用调试器附加到一个已经运行的进程上。
为了反调试器附加,我们首先要详细的了解一下这两种方法的附加过程。
1 用调试器打开程序
我们先来看一下用调试器打开程序的流程图:
1.1 CreateProcess()
当调试器打开一个程序时,首先会执行 CreateProcess
函数来为可执行文件映像创建一个进程,在进程创建的早期(执行内核服务 NtCreateProcess/NtCreateProcessEx 之前)会调用 DbgUiConnectToDbg
函数来使得调用线程与调试子系统建立连接。
在 Windows XP 及以后的系统中, DbgUiConnectToDbg
函数内部会调用 ZwCreateDebugObject
来创建 DEBUG_OBJECT 内核对象,并将其句柄保存在当前线程(调试器的工作线程)环境块的 DbgSsReserved[1]
字段中。
注:在
CreateProcess
返回后,Windbg 会调用DbgSetThreadDebugObject
将DbgSsReserved[1]
字段设置为 0。
创建完调试对象后调试器才着手开始为被调试进程创建进程环境。调试器首先会调用 NtCrateProcess/NtCreateProcessEx
,并将 DbgSsReserved[1] 字段中记录的对象句柄以参数(第 7 个参数)形式传递给内核中的进程管理器。接下来内核中的进程创建函数(PspCreateProcess
)会检查这个调试对象句柄是否为空,如果不为空,会取得它的对象指针,然后设置到进程执行块(EPROCESS 结构)的 DebugPort 字段中。
随后,PspCreateProcess
会继续调用 MmCreatePeb
函数创建进程环境快(PEB),根据被调试进程的 EPROCESS 结构的 DebugPort 字段设置 PEB 中的 BeingDebug 字段。
1.2 KiThreadStartup()
CreateProcess
函数已经为进程创建好了运行前的环境准备,此时还没有初始线程,一个新创建进程的的初始线程是从内核中的 KiThreadStartup
开始执行的,这个函数很简短,在将线程的 IRQL 降低到 APC 级别后,便将执行权交给了 PspUserThreadStartup
函数。
PspUserThreadStartup
函数内部会调用 DbgkCreateThread
向调试子系统通知新线程的创建事件,此时调试子系统会向调试对象的调试事件队列中放入一个进程创建事件,并等待调试器来处理和回复。随后会安排用户模式的 APC 并触发,此时用户初始的 0 号线程会执行