滴水逆向软件调试

一、调试对象

滴水逆向软件调试_第1张图片
滴水逆向软件调试_第2张图片
分为两种:创建进程和附加进程
创建进程为将未运行的程序创建进程
附加进程为将运行中的进程附加
滴水逆向软件调试_第3张图片
对调试器做的事
DebugActiveProcess调用了DbgUiConnectToDbg,然后调用了ntdll.dll模块中的DbgUiConnectToDbg
在这里插入图片描述
DbgUiConnectToDbg调用ZwCreateDebugObject,进入0环,创建_DEBUG_OBJECT
滴水逆向软件调试_第4张图片
滴水逆向软件调试_第5张图片
_ZwCreateDebugObject第一个参数为输出,由于是在3环,所以是一个句柄,存在当前线程TEB(0XF24)中
滴水逆向软件调试_第6张图片

对被调试进程做的事
DebugActiveProcess函数,成功创建调试对象后和调试器进程创建连接后。调用ProcessIdToHandle,将进程ID转换成进程句柄。然后将进程句柄做为参数调用DbgUiDebugActiveProcess
滴水逆向软件调试_第7张图片
DbgUiDebugActiveProcess调用ntdll.dll模块中的DbgUiDebugActiveProcess函数
在这里插入图片描述
DbgUiDebugActiveProcess中调用_NtDebugActiveProcess,参数一为上面传下来的被调试进程的句柄,参数二为TEB+0XF24,当前线程的调试对象
滴水逆向软件调试_第8张图片
_ntDebugActiveProcess进入0环
滴水逆向软件调试_第9张图片
NtDebugActiveProcess中两个传下来的参数,因为是3环传下来的,所以是句柄。ObReferenceObjectByHandle函数为根据句柄获得对象,参数一为进程句柄,获得EPROCESS地址放到参数5,参数5被占用,函数调用完后参数5为EPROCESS地址
滴水逆向软件调试_第10张图片
获取当前线程所处进程,如果是当前进程或者是PsInitialSystemProcess,结束
滴水逆向软件调试_第11张图片
再次调用ObReferenceObjectByHandle,这次获取调试对象的地址
滴水逆向软件调试_第12张图片
然后调用DbgKpSetProcessDebugObject函数将调试对象和被调试进程关联起来,参数一为被调试进程的EPROCESS,参数二为调试对象的地址
在这里插入图片描述
判断EPROCESS+0BCh,也就是DebugPort是不是为0
滴水逆向软件调试_第13张图片
如果DebugPort是0,将DEBUG_OBJECT存储到被调试进程EPROCESS的DebugPort中
滴水逆向软件调试_第14张图片
_DEBUG_OBJECT的本质:桥
滴水逆向软件调试_第15张图片

二、调试事件的采集

只有几个关键的调试事件种类才会记录到调试事件
滴水逆向软件调试_第16张图片
谁替被调试进程生成调试事件,装入调试事件链表中。在函数调用的必经之路中有一组Dbgk开头的函数,先判断DebugPort是否为0,不为0才调用Dbgk函数
滴水逆向软件调试_第17张图片
每一种事件要求描述的信息不同,需要封装不同的结构体,所以需要不同的调试事件采集函数
滴水逆向软件调试_第18张图片
滴水逆向软件调试_第19张图片
在这里插入图片描述

三、调试事件的处理

调试器进程循环判断DEBUG_OBJECT链表中是否有数据
WaitForDebugEvent函数为判断DEBUG_OBJECT中是否有调试事件,如果有就把调试事件取出,放到DEBUG_EVENT中
滴水逆向软件调试_第20张图片
ContinueDebugEvent告诉被调试进程继续执行
滴水逆向软件调试_第21张图片
滴水逆向软件调试_第22张图片

四、异常的处理流程

滴水逆向软件调试_第23张图片
滴水逆向软件调试_第24张图片
第二次异常分发由UnhandledExceptionFilter分发
滴水逆向软件调试_第25张图片

五、软件断点

调试的本质是异常的处理
在调试器中按下一个F2时会生成一个断点,将这个地方的代码改成int 3,硬编码为CC
反调试中CRC可以用来检测软件断点
滴水逆向软件调试_第26张图片

六、内存断点

内存读或写断点 ,Memory,on access 或Memory,on write
设置内存断点要修改内存的页的属性,如果要设置访问断点将内存页属性设置为不可访问。如果要设置内存写断点要将内存页属性设置为可读可执行不可写
反调试可以写一个程序使当前代码内存页属于永远可以访问
滴水逆向软件调试_第27张图片
滴水逆向软件调试_第28张图片

七、硬件断点

硬件断点最多只有四个,调试寄存器只有四个,Dr0-Dr3
Dr0-Dr3存储线性地址,每个线程都有上下文context,当目标线程的值被装入寄存器时才起作用
当想要调试寄存器Dr0到Dr3有作用,Dr7中的对应的Lx~Gx必须有一个为1
硬件断点类型可以分为访问,写入和执行
反调试可以写一个线程可以将调试寄存器不停清0,反反调试可以找到清0的线程处理掉
滴水逆向软件调试_第29张图片
CPU检测到调试寄存器中的值和当前正在读的值是相同的,触发单步异常,IDT表01号中断处理函数
滴水逆向软件调试_第30张图片
CPU的eflag中的TF位置1也是触发单步异常
滴水逆向软件调试_第31张图片
查看Dr6中的B0-B3是否有值,如果没有为eflag中的TF位为1导致

九、单步步过

滴水逆向软件调试_第32张图片
判断当前指令是否为CALL指令,如果为call,在下一行设置硬件断点,将当前指令给反汇编引擎,计算当前指令长度,下一行指令开始位置

你可能感兴趣的:(软件调试)