今天是我在15pb最后一天的课程,明天火车就要离开北京南下到广东去求职了。在这里祝愿20、21期的伙伴有一个好的前程,也祝愿15pb各位老师身体健康,事业红火。
本文不会讲异常分发流程,因为异常分发流程我想分为两篇文章来写,链接如下:
1.
从异常分发流程的实现看反用户调试器 2.
从异常分发流程的实现看反双机调试【有码】 由于本人水平有限,错误之处难免,请大神们不吝指正哈!目录
从调试器代码框架上去看整个调试流程(之前我写的3环调试器扣出来的):... 1
以调试方式启动调试器:... 1
以附加的方式启动调试器:... 1
调试器等待调试事件的到来:... 1
调试器事件的分发:... 1
总结:...1
从关键数据结构角度来看调试流程:... 1
调试内核对象的结构体:...1
常见的调试事件:...1
调试器获取调试事件的答题流程图:...1
总结:... 1
对调试框架中关键函数进行源代码分析:... 1
CreateProcess以创建进程方式调试... 1
DebugActiveProcess以附加方式调试:... 1
WaitForDebugEvent调试器中等待调试事件的到来... 1
从整个流程总结出的反调试方法:... 1
从调试器代码框架上去看整个调试流程(之前我写的3环调试器扣出来的):
以调试方式启动:
以附加的方式启动调试器:
调试器等待调试事件的到来:
异常分发流程:
总结:
1. 以调试方式或者附加的方式启动程序,对应的API分别是:CreateProcess和DebugActiveProcess
2. WaitForDebugEvent以等待调试事件的到来
3. DispatchEvent,分发调试事件,这里面有各种handle
从关键数据结构角度来看调试流程:
调试内核对象的结构体:
常见调试事件:
调试器获取调试事件的大体流程图:
对调试框架中关键函数进行源代码分析:
CreateProcess以创建进程方式调试:
以调试方式启动进程在(3环):
具体分析DbgUiConnectToDbg:
总结下:
1. 创建一个一个调试内核对象,通过ZwCreateDebugObject
2. 放到主动调试进程的teb中,这个偏移是f24
具体分析下创建调试对象(0环):
把上面创建的调试对象,填充到被调试进程的EPROCESS的DebugPort字段(0环):
DebugActiveProcess以附加方式调试 :
直接贴出以调试方式打开进程:
因为DbgUiConnectToDbg已经在上面分析过直接分析DbgUiDebugActiveProcess:
总结:
1. NtDebugActiveProcess,根据Teb中F24中中存放的句柄,找到调试对象,然后发送假的进程创建消息(因为这里是attach的进程,进程之前已经创建 了,所以这里发送的是假的)
2.DbgUiIssueRemoteBreakin,在被调试进程中创建一个线程,然后在线程中触发int3断点,这个也是附加调试调试器能段下程序的原因
NtDebugActiveProcess的函数简单分析:
总结:
1. DbgkpPostFakeProcessCreateMessages,主要发送进程创建、线程创建、模块加载的伪造消息
2. DbgkpSetProcessDebugObject,主要任务设置事件,以便调试线程从阻塞中返回获取调试信息
DbgUiIssueRemoteBreakin的函数的详细分析:
总结:
1. 在被调试线程中创建一个远程线程,这个远程线程函数DbgUiRiRemoteBreakin
2. 这个函数主要设置一个int3断点,以便产生int3断点
WaitForDebugEvent调试器中等待调试事件的到来:
调用了DbgUIWaitStateChange等待调试对象被设置:
直接跳到内核去看,可以看到是直接等待DebugObject->EventsPresent 这个内核事件被触发
获取具体的调试信息DbgUiConvertStateChangeStructure这个结构体为PDEBUG_EVENT:
一大堆的switchcase匹配,各种调试事件,主要的任务就是填充WaitForDebugEvent中的第二个参数(LPDEBUG_EVENT)
从整个流程总结出来反调试的方法,其实远远不止我下面写的:
1. 被调试进程的Debugport一定不为0,所以可以对debugport清零破坏掉调试流程
2. 遍历所有的线程的teb的偏移f24字段,这个是调试对象Debugport的句柄,如果不为0直接清零,达到反调试的手段
3. 在内核中挂钩ObCreateObject,其中第第三个参数为DbgkDebugObjectType,这个参数是全局变量,挂钩后禁止创建
4. 对NtCreateDebugObject挂钩,可以禁止调试对象的创建
5. 可以对NtWaitForDebugEvent挂钩,破坏WaitForDebugEvent让它没法正常接收调试事件
6. 在线程启动回调中拦截线程函数为DbgUiRemoteBreakin的创建,让附加的调试器没法断下来(其实也可以在3环中做这个东西,让调试器没法附加,写到壳里面)
7. 可以对DbgkpQueueMessage函数挂钩,这样就算被调试程序出现异常,调试事件也没法添加到DEBUG_OBJECT的EVENT_LIST中,这些都是调试系列函数不会影响操作系统
8. 在整个调试流程中调试器需要用到被调试进程的句柄,所以可以遍历句柄表并且关闭,会影响到调试器的ReadProcessMemory和WriteProcessMemory,中断调试流程
9. 挂钩自己进程的DbgBreakPoint(),没错没什么正常的程序会使用这个api的,一旦在自己进程发现DbgBreakPoint了就可能自己被调试了
10. PEB的BeingDebugged检测
最后,谢谢大家观看!
[课程]Linux pwn 探索篇!
最后于 2018-4-7 12:07
被又出bug了编辑
,原因: