首页
论坛
课程
招聘
[调试逆向] [系统底层] [原创]断其粮道——内核级拒绝服务攻击
2020-7-24 12:08 1937

[调试逆向] [系统底层] [原创]断其粮道——内核级拒绝服务攻击

2020-7-24 12:08
1937

1、何为断其粮道?

古时的军队大体分为两部分,一是前线作战的士兵,二是后方运粮的人员,两者共同组成一个系统,双方配合才能完成作战任务。两者之间保持互相通信,前者就可以派人向后者催粮,后者就可以派人向前者运粮,而这个运粮(通信)的关键就在于粮道,如果被敌军切断,那么前线士兵就无法向后勤人员征求粮食(请求服务),后勤人员也就无法为前线士兵运送粮食(提供服务),此可谓之拒绝服务攻击。

 

以图示之,前线5万大军因吃不上饭而开始出现军心不稳的情况了。。。

2、应用程序的粮道在哪里?

那么程序有类似的“粮道”吗,有的话在哪里呢?答案就要从3环进0环说起了。
Windows系统下有几个重要的DLL:Kernel32.dll、User32.dll、Gdi32.dll、Ntdll.dll。运行在3环的应用程序不可避免的会使用这些Dll提供的API,而这些API大部分会通过Ntdll.dll进入0环,参考《加密与解密》的第7章的图7.6。

 

举一个例子来说明这个过程吧!用Windbg和win7 x86双机调试。
Kernel32.dll中的ReadProcessMemory,其代码如下:

 

其中只有一条jmp指令,跳到一个导入函数里去执行,我们看看该函数是什么:

 

原来是kernelbase.dll中的同名函数,继续反汇编,在+12附近的位置又调用了一个导入函数:

 

继续看该导入函数是什么,原来是ntdll.dll中的NtReadVirtualMemory函数:

 

此时就到了关键的地方了。ntdll.dll中的NtReadVirtualMemory函数非常简单,就4句,非常简单,它的作用是什么呢?
在ntdll.dll中,大部分API也是这样的格式:

mov eax, API索引号
mov edx, 一个地址      ;该地址里的值是一个函数地址
call [edx]            ;调用这个函数,实现进入0环
retn 14h

API索引号就是在3环调用了一个API,这个API在内核也就是0环,会有对应的内核函数,这个内核函数的地址在SSDT表中位于某个位置,这个位置就是索引号。进0环后,得找到对应的内核函数进行调用吧,就是根据这个索引号找到的。

 

一个地址,里面存的值是一个函数地址,反汇编看一下就知道了:

 

原来这个函数名为KiFastSystemCall,如果CPU支持快速调用的话,那么call [edx]就是call KiFastSystemCall,如果是通过中断门进入0环的话,那么call [edx]就是call KiIntSystemCall。

 

KiFastSystemCall里的sysenter指令实现进入0环。操作系统在执行这条指令前会把进0环后需要的东西(CS/SS/ESP/EIP)提前准备好,存入一个叫做MSR的寄存器中,等到sysenter指令执行时,就会从MSR寄存器中取出这些值赋给相应的寄存器,其中eip寄存器就得到一个值,这个值就是nt!KiFastCallEntry函数的地址。

 

那其实就明白了,通过快速调用进0环后的第一个要执行的函数就是KiFastCallEntry。这个函数的作用就是拿着前面传下来的API索引号,获取相应的内核函数,调用之,从而实现应用层想要的功能。整个过程整理如下:

 

把其他API的调用过程也画上去,看看整体的流程:

 

其中的“粮道”我把它选为了Ntdll.dll中的KiFastSystemCall,即上图蓝色的线,因为这个函数实现进入0环,3环的API就得通过这个必经之路进入0环。如果把这个必经之路给断了,那岂不是3环API进不了0环,从而0环无法为3环提供服务,这就达到了内核级拒绝服务攻击。还有一个地方也可以选为“粮道”,那就是MSR寄存器,进0环后要执行的函数地址是来源于MSR寄存器中的eip值,所以修改MSR寄存器也可以达到截断“粮道”的目的。

3、截断应用程序的粮道

根据第2节可知,3环进0环的关键函数是Ntdll.dll中的KiFastSystemCall,而且是以下面的形式来对它进行调用的:

mov edx, 7ffe0300
call [edx]                ; call KiFastSystemCall

7ffe0300地址里保存了KiFastSystemCall的地址。
其实这里涉及一个名为_KUSER_SHARED_DATA的数据结构,在3环和0环分别定义了一个该结构,其中在3环,这个结构地址固定为7ffe0000;在0环,这个结构地址固定为ffdf0000。这两个结构的内容完全相同,它们偏移+300处的成员名为SystemCall,保存的正好就是KiFastSystemCall函数的地址,所以上面的7ffe0300就是这么来的。看图。

 

好,既然3环API进0环,要访问7ffe0000+300处的成员,来实现进0环,那么我们把这个成员给改了(改之前拍个快照):

ed 7ffe0000+300 12345678

把7ffe0000+300处的成员,随便改成12345678,那么3环进0环时,就会去12345678地址里去执行,而这个地址肯定是无意义的,看看会发生什么情况,根据我的实验得到:
Windbg首先有动静,问我中断还是忽略

选b的话,Windbg会再次询问我相同的问题,再次选b,就会中断了

此时的栈回溯信息如下:

 

如果选i的话,步骤和结果如下:

 

系统跑起来了,问题是,鼠标移到记事本里,会改变形状为插入型,移动到桌面会显示正常的光标,移动到开始菜单处会显示漏洞状,但是均无法点击。向虚拟机发送Ctrl+Alt+Delete键,也是没有反应的。
整个系统就保持这种状态,既不会蓝屏,Windbg也不会继续捕获到异常。

(注:图片是gif格式的,不知道能不能播放,而且录制的时候没有录制出光标的变化效果,大家有兴趣的自己做实验就可以看出变化的)

 

修改ffdf0000+300处的成员也会使系统出现这种现象。以下是修改ffdf0000+300中断后的栈回溯信息。

4、实验结果说明

根据以上的的实验可知,修改进0环的关键位置,使得整个系统发生了无响应而不蓝屏的现象,大概可以解释成:是3环进0环的地方出了问题,而这个进0环的函数又是属于3环的,所以问题发生在3环而不是0环,故系统内核没有崩溃。

 

7ffe0000+300、ffdf0000+300这两个地方用来耍流氓是挺合适的,发现你对我的程序有分析行为,那我就阻断你进0环的路,你的程序得不到内核的服务,于是什么分析行为都无法进行下去了,这个就是断其粮道的含义。其实对一些函数设置钩子,使其他调用者得不到正确的结果,也可以叫做拒绝服务攻击。

 

那么怎么对付这个流氓行为呢?从前面的两个栈回溯信息就可以看出端倪。

 

如果反过来呢?我们在分析的时候,触发了检测代码,从而发生了这种系统无响应而不蓝屏的现象,于是就没有蓝屏文件为我们提供信息,而如果又不知道3环进0环的原理,那么即便是看Windbg的栈回溯信息,也没法对付,所以很可能就想不到是程序的“粮道”出了问题。

 

代码就不写了,有兴趣的同学可以自己写个驱动,随便检测一个进程,然后修改这两个7ffe0000+300、ffdf0000+300试试,看看有什么效果。

 

一点思考:系统无响应而不蓝屏,说明用户层废了,而内核还活着,此时我们提前写个驱动打算一直循环干活,那么在系统无响应期间,驱动是否也在工作呢?如果在工作的话,那其他规范化的程序是不是就不能收集我们的种种行为呢?(应用层软件显然无法收集我们的行为了,内核层的驱动一般要和应用层通信,此时无法通信了,功能肯定大打折扣。)

5、参考资料

《加密与解密》
《软件调试》


挖华为终端产品漏洞赢巨额奖金! 注明看雪会员还有额外奖励!!

最后于 2020-7-25 00:23 被minorory编辑 ,原因: 增加一点思考
上传的附件:
收藏
点赞4
打赏
分享
最新回复 (14)
雪    币: 998
活跃值: 活跃值 (86)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Rookietp 活跃值 2020-7-24 12:38
2
0
这图画的属实佩服。
雪    币: 963
活跃值: 活跃值 (2870)
能力值: (RANK:260 )
在线值:
发帖
回帖
粉丝
0x2l 活跃值 3 2020-7-24 13:03
3
0
师傅,你画的图太牛了,我实名制建议给这篇帖子一个精华
雪    币: 9214
活跃值: 活跃值 (351)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
minorory 活跃值 2020-7-24 13:15
4
0
Rookietp 这图画的属实佩服。
发帖前还专门去学了一点美术
雪    币: 9214
活跃值: 活跃值 (351)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
minorory 活跃值 2020-7-24 13:16
5
0
0x2l 师傅,你画的图太牛了,我实名制建议给这篇帖子一个精华
我也想要精华,哈哈
雪    币: 15153
活跃值: 活跃值 (764)
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
wsc 活跃值 2020-7-24 14:10
6
0
这画风深得名师真传,很赞
雪    币: 216
活跃值: 活跃值 (115)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
惊电 活跃值 2020-7-24 15:15
7
0
SystemCall成员在32位系统下保存的是KiFastSystemCall的地址,但在64位系统下已为0...
雪    币: 9214
活跃值: 活跃值 (351)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
minorory 活跃值 2020-7-24 19:21
8
0
wsc 这画风深得名师真传,很赞
那我转行学画画了
雪    币: 9214
活跃值: 活跃值 (351)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
minorory 活跃值 2020-7-24 19:21
9
0
minorory 那我转行学画画了
那就得另外分析咯
雪    币: 686
活跃值: 活跃值 (126)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
flarejune 活跃值 2020-7-25 10:14
10
0

从历史上,从中国语文文学上,从计算机技术术语上,
你这篇就是**************文.
1.古代行军打仗,讲求的是粮草先行,何来催粮的说法,计划指定日期的食粮,粮草先行,打到指定日期攻不下,就撤退.
2."拒绝服务",字义解释是:当事人不愿意给别人提供服务,不是当事人无法给人提供服务.
3."DDOS"攻击,也就是翻译为中文的"拒绝服务攻击",大概意思是服务供应者由于负荷不起需求者请求,而暂停(拒绝)为新的需求者提供服务.

你所说的一切,其实就是一个BUG...一个无聊到极致的BUG.根本不是什么攻击.也不是什么手法.

最后于 2020-7-27 18:20 被kanxue编辑 ,原因:
雪    币: 9214
活跃值: 活跃值 (351)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
minorory 活跃值 2020-7-25 10:24
11
0
flarejune 从历史上,从中国语文文学上,从计算机技术术语上, 你这篇*************. 1.古代行军打仗,讲求的是粮草先行,何来催粮的说法,计划指定日期的食粮,粮草先行,打到指定日期攻不下,就撤退. ...

1、屯粮的地方和前线部队在同一个地方?你怕是没听过长平之战?古来切断敌军粮道的的做法比比皆是。
2、什么愿不愿意,机器有不愿意的说法么?
你德何其薄也~

最后于 2020-7-25 15:24 被kanxue编辑 ,原因:
雪    币: 384
活跃值: 活跃值 (28)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
edgeflow 活跃值 2020-7-25 11:43
12
0

文章写得很生动,但其中一处向下箭头的调用关系误导我了,让我陷入了思考。

于是上机看了下。

原来在KERNELBASE处就有其他调用分支(图中的那条调用关系可能更重要,存在即合理)

,这才像应用层多姿多彩的现象。

内核实现固然重要,但应用层的分模块分层级的合理调用同样重要。

雪    币: 9214
活跃值: 活跃值 (351)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
minorory 活跃值 2020-7-25 12:44
13
0
edgeflow 文章写得很生动,但其中一处向下箭头的调用关系误导我了,让我陷入了思考。于是上机看了下。原来在KERNELBASE处就有其他调用分支(图中的那条调用关系可能更重要,存在即合理),这才像应用层多姿多彩的现 ...

嗯嗯,系统不同,实验的现象也不同。

在Win7 x86里就直奔0环,在其他系统上可能就有更多的调用来丰富功能

游客
登录 | 注册 方可回帖
返回