首页
社区
课程
招聘
[原创]WannaCry勒索软件中“永恒之蓝”漏洞利用分析
发表于: 2017-5-19 15:23 17528

[原创]WannaCry勒索软件中“永恒之蓝”漏洞利用分析

2017-5-19 15:23
17528

WannaCry勒索软件中,利用了NSA泄露工具中的“永恒之蓝”漏洞,关于这个漏洞,之前已经有一些分析,在我看的文章中,http://blogs.360.cn/360safe/2017/04/17/nsa-eternalblue-smb/说得最详细,该文章中针对win7 32位的系统的漏洞触发过程进行了分析。

但是在整个网络上,我没有看到关于64位系统的分析,因此我在该文章的基础上,对win7 64位的触发,以及触发后的shellcode的行为进行了分析整理成此文。

其中若有疏漏,还请大家指教。最后感谢武汉科锐,感谢钱老师的悉心教学,钱老师严谨的治学作风和渊博的知识深深的影响着我,使我受益终身。

 

搭建测试环境

因为样本的原有行为,是随机产生IP地址,并对目标进行发包。这非常不方便我们测试。因此,需要先在特定的位置断下,IP地址改为我们的测试目标,并拍快照记录。

具体步骤如下:

1. 0x00407982处下断,该处为拼接IP字符串,在此处将该字符串修改为自己的测试目标值。

2. 单步(如果不单步可能会因为多线程的原因造成测试不成功,因此推荐单步)至下方的线程创建函数,并在该线程回调处下断点。

 

3. 在上一步的线程回调函数中,有两处关键点,一处为该样本的第一波发包攻击,攻击结果为:在远程电脑上安装一个后门;第二处为第二波发包攻击,攻击结果为:利用第一波攻击安装的后门,在远程电脑上的系统进程中注入一个dll。他们的调用位置如下图所示:

    

漏洞的原理

Srv.sys中的SrvOs2FeaListToNt函数中,会有以下调用关系:

SrvOs2FeaListToNt

   call SrvOs2FeaListSizeToNt

   call SrvOs2FeaToNt

其中在SrvOs2FeaListSizeToNt中因为有一个DWORD*WORD*并赋值的bug,造成在SrvOs2FeaListToNt的一个循环中,SrvOs2FeaToNt被调用的次数会多于预期,而造成SrvOs2FeaToNt中的一个memmove拷贝越界。

   

可以看到,运行到下图时,对大小为0x11000

 

      

通过!pool指令查看:

 

      

而实际运行时:

    

不过,越界覆盖后,最终pool中的地址+0xa8处的数据,会作为一个指针被当作数据接受缓冲区,这是为什么,这其中的原理我没有完全搞明白,还请熟悉的朋友指教。

    

定位第一轮发包的shellcode触发点

尝试定位shellcode,要知道一个前提,这在其它报告中也已经提到,那就是

该样本的第一次发包,会安装一个后门,该后门的实现方式是在srv模块中,挂钩SrvTransaction2DispatchTable表中的一个表项,可以通过命令.

我之后就是利用这一点,来检验自己的测试机是否已经被触发漏洞,并一步步定位到触发点的(见下文分析).

kd> dps srv!SrvTransaction2DispatchTable查看:

挂钩前:

fffff880`0301e760  fffff880`03088780 srv!SrvSmbOpen2

fffff880`0301e768  fffff880`0304fb20 srv!SrvSmbFindFirst2

fffff880`0301e770  fffff880`03085f40 srv!SrvSmbFindNext2

fffff880`0301e778  fffff880`03051650 srv!SrvSmbQueryFsInformation

fffff880`0301e780  fffff880`0307ad20 srv!SrvSmbSetFsInformation

fffff880`0301e788  fffff880`0304f670 srv!SrvSmbQueryPathInformation

fffff880`0301e790  fffff880`03088cb0 srv!SrvSmbSetPathInformation

fffff880`0301e798  fffff880`0304d420 srv!SrvSmbQueryFileInformation

fffff880`0301e7a0  fffff880`0304e080 srv!SrvSmbSetFileInformation

fffff880`0301e7a8  fffff880`0306f660 srv!SrvSmbFsctl

fffff880`0301e7b0  fffff880`03088ae0 srv!SrvSmbIoctl2

fffff880`0301e7b8  fffff880`0306f660 srv!SrvSmbFsctl

fffff880`0301e7c0  fffff880`0306f660 srv!SrvSmbFsctl

fffff880`0301e7c8  fffff880`0307b4f0 srv!SrvSmbCreateDirectory2

fffff880`0301e7d0  fffff880`0306f460 srv!SrvTransactionNotImplemented

fffff880`0301e7d8  fffff880`0306f460 srv!SrvTransactionNotImplemented

 

挂钩后:

fffff880`0301e760  fffff880`03088780 srv!SrvSmbOpen2

fffff880`0301e768  fffff880`0304fb20 srv!SrvSmbFindFirst2

fffff880`0301e770  fffff880`03085f40 srv!SrvSmbFindNext2

fffff880`0301e778  fffff880`03051650 srv!SrvSmbQueryFsInformation

fffff880`0301e780  fffff880`0307ad20 srv!SrvSmbSetFsInformation

fffff880`0301e788  fffff880`0304f670 srv!SrvSmbQueryPathInformation

fffff880`0301e790  fffff880`03088cb0 srv!SrvSmbSetPathInformation

fffff880`0301e798  fffff880`0304d420 srv!SrvSmbQueryFileInformation

fffff880`0301e7a0  fffff880`0304e080 srv!SrvSmbSetFileInformation

fffff880`0301e7a8  fffff880`0306f660 srv!SrvSmbFsctl

fffff880`0301e7b0  fffff880`03088ae0 srv!SrvSmbIoctl2

fffff880`0301e7b8  fffff880`0306f660 srv!SrvSmbFsctl

fffff880`0301e7c0  fffff880`0306f660 srv!SrvSmbFsctl

fffff880`0301e7c8  fffff880`0307b4f0 srv!SrvSmbCreateDirectory2

fffff880`0301e7d0  fffff880`053e2060

fffff880`0301e7d8  fffff880`0306f460 srv!SrvTransactionNotImplemented

可以发现第0xe项会被hook。这个表项的hook是由一段shellcode代码所完成的,具体如何定位到shellcode的入口,见以下分析。

 

因为已知漏洞会在srvnet! SrvNetWskReceiveComplete中完成触发,只是不确认win 7 64位的shellcode写入点是否与前辈win 7 32位地址一样(通常不一样),因此一开始通过下断点并打印内存情况摸索规律:

kd> u

srvnet!SrvNetWskReceiveComplete+0x15:

fffff880`02d3cdc5 488bca          mov     rcx,rdx

fffff880`02d3cdc8 498bf8          mov     rdi,r8

kd> ba e1 srvnet!SrvNetWskReceiveComplete+0x15 "dq r8 r8+0x48;gc"

得到以下结果:

fffffa80`049236b0  00000000`00000003 fffffa80`042fd800

fffffa80`049236c0  fffffa80`042fd800 000059b4`918947fc

fffffa80`049236d0  fffffa80`049237f0 00000000`00000810

fffffa80`049236e0  fffffa80`04923710 fffffa80`00000000

fffffa80`049236f0  00000000`00000438 fffffa80`0568d730

……

fffffa80`04a9b010  00000000`0000ffff 00000000`0000ffff

fffffa80`04a9b020  00000000`00000000 00000000`00000000

fffffa80`04a9b030  00000000`ffdff100 ffdff020`00000000

fffffa80`04a9b040  ffffffff`ffdff100 00000000`10040060

fffffa80`04a9b050  00000000`ffdfef80 ffffffff`ffd00010

 

经过比对,发现以上标红内容特殊,是x86报告所记录的溢出时机断点。因此重启环境,下条件断点:

kd> ba e1 srvnet!SrvNetWskReceiveComplete+0x15 ".if(poi(@r8+0x48) == 0xffffffffffd00010){}.else{gc}"

结合以上所知的,SrvTransaction2DispatchTable会被shellcode挂钩,因此在该表项处下断点:

kd> ba w8 srv!SrvTransaction2DispatchTable+0x8*0xe

经过验证,在以上第一个断点触发后,继续运行,会触发第二个断点:


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 1
支持
分享
打赏 + 1.00雪花
打赏次数 1 雪花 + 1.00
 
赞赏  CCkicker   +1.00 2017/05/22
最新回复 (9)
雪    币: 14
活跃值: (10)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
2
精彩!原来是这样触发漏洞的。
2017-5-19 17:28
0
雪    币: 346
活跃值: (25)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
3
感谢分享!
2017-5-19 17:47
0
雪    币: 1
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
感谢分析!
2017-5-19 19:03
0
雪    币: 346
活跃值: (45)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
5
2017-5-19 20:52
0
雪    币: 4762
活跃值: (4351)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
好帖
2017-5-20 21:42
0
雪    币: 1
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
学习
2017-5-21 22:38
0
雪    币: 96
活跃值: (45)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
smb传播是在服务部分的,可以指出下怎么启动调试这个服务吗
2017-5-23 15:30
0
雪    币: 46
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
您好,谢谢您的分析。试着在0x00407982处下断,将IP修改为自己的测试目标值,但是单步调试发现004074CA  处socket初始化总是返回-1,请问是什么原因?另外,smb传播是在服务部分的,可以指导下怎么启动调试这个服务?

2017-7-4 16:57
0
游客
登录 | 注册 方可回帖
返回
//