调试debug,就是两个进程之间建立起调试与被调试的关系,主要过程包括:
1、打开调试进程,就是CreateProcess等函数,设置标志位DEBUG_PROCESS或者DEUBG_ONLY_THIS_PROCESS,建立一个调试者与被调试者的关系。CreateProcess最终调用到NTDLL!DbgUiConnectToDbg,最终创建DEBUG_OBJECT调试端口对象和等待端口数据的信号量(Semaphore),把他们存到调试者当前线程TEB中的DbgSsReserved[0]和DbgSsReserved[1]中。并将端口对象句柄作为参数传入到内核进程管理器,内核中的进程创建函数会根据这个参数来设置EPROCESS中的DebugPort字段。当这个参数不为空时,找到这个句柄所对应的内核对象,并把他填入到EPROCESS结构中的DebugPort字段,如果为空,那么DebugPort字段也为NULL。PspCreateProcess函数在创建进程时会简历MmCreatePeb,进程PEB中的BeingDebugged字段的设置也就可以根据DebugPort来确定了。
这样调试进程和被调试进程就建立了调试关系了,并且可以通过调试端口对象进行通信。2、Attach工作的机理与调试打开类似,通过调用DebugActiveProcess函数来简历调试关系。
1)首先也是调用DbgUiConnectToDbg函数,对调试者当前线程的TEB设置DbgSsReserved数组
2)API传入参数是进程ID,所以内部会调用ProcessIdToHandle,这个函数会调用OpenProcess函数,来获取进程的句柄。所以我们要Attach的进程权限要小于等于调试者。
3)NTDLL!DebugUiDebugActiveProcess将调试进程的句柄和调试对象的句柄传递给NtDebugActiveProcess,这个函数会通过进程句柄获取被调试者的EPROCESS结构,然后向调试对象发送虚假的调试事件,调用DebugkpSetProcessDebugObject函数将调试对象设置到的EPROCESS结构的DebugPort字段,并调用DbgkpMarkProcessPeb设置BeingDebugged字段。

3、调试过程就是在调试者(od)中,调用WaitForDebugEvent(OUT LPDEBUG_EVENT lpDebugEvent, IN DWORD dwMilliseconds);光从这个函数看,调试者和被调试者的关系无法显现?因为我们已经设置了DEBUG_OBJECT。
4、单步调试,就是通过x86架构下的EFLAGE寄存器的TF标志位,当这个标志为被置位TF=1,则被调试进程执行一条指令之后中断,并将TF=0重新置位。在中断处理中,重新设置TF=1,下一次执行一条指令之后,有继续中断......
调试debug涉及调试者与被调试者间的关系建立,通过CreateProcess函数开启调试,利用DEBUG_PROCESS标志。调试过程中,创建DEBUG_OBJECT和Semaphore,存储在TEB中,并设置EPROCESS的DebugPort字段。WaitForDebugEvent用于捕获调试事件,而单步调试依赖x86架构的EFLAGS寄存器TF标志,控制执行与中断。
3473

被折叠的 条评论
为什么被折叠?



