环境搭建
- 到msdn I tell you下载完镜像安装完,ping 2008ping不通,但它ping外面却可以,后来发现是默认开启了防火墙,把防火墙关闭了就好
- 之后是漏洞利用不成功,原来还要安装域控
实验环境及工具如下:
2008 sp1 datacenter (装了域控)
windbg
VirtualKD-3.0
wireshark
尝试分析
一开始简单了解了一下smb协议,尝试抓取攻击包,看了一下,也看不出什么
于是就修改里面配置文件的返回地址什么的东西为0x41414141,马上发第一个包就崩溃了
(一开始直接下断还断不下来,可能是因为那里初始的时候还不是代码)
1 | kd> !analyze -v |
后来就在这个崩溃的函数下断点
1 | kd> bp srv2!SrvConsumeDataAndComplete |
发现这参数正是客户端发送的smb数据,而异常是获取smb数据+0x3c的数值作为地址+0x18后无法读取的异常
这里的41414129应该是我们设置的值减了0x18后发送过来的
1 | PAGE:0003097B ; int __stdcall SrvConsumeDataAndComplete(PVOID DestinationBuffer) |
那我们把值改回原来的值0xffdf0908再调试
判断目标系统版本信息
协商后,发送SMB Command: Session Setup AndX (0x73)包
然后服务器就怪怪返回了信息了(SMB Command: Session Setup AndX (0x73))
两个的command都是0x73,怎么判断哪个是request,那个是response呢?原来在flags里(request是0,response是1)
后面两个包用意不知如何
- Tree Connect AndX Request (0x75) Path: \192.168.52.145\IPC$
- NT Create AndX Request (0xa2) File Name: browser
判断漏洞是否存在(存疑)
下面仅为猜测,调试的时候是下面路径,但是调试的时候的NewIrql指向的并不是SMB的数据
最后下面这个条件也不满足就直接退出了
后来跟导师沟通,知道是处理Process ID High的时候导致一个错误的返回值从而进入错误流程
下面为Smb2ValidateProviderCallback函数尾部截图
最终不等于0xC0000016,进入了错误流程
利用对任意地址+1的操作写入gadgets
利用的指令如下
通过发一个包对目标地址+1,写入如下gadgets
下面以一个包为例子说明写入经过的流程
首先包传进来给srv2!SrvProcessPacket处理,其中NewIrql指向SMB数据,也即下面截图中的esi
下面这个就是else,调用SrvConsumeDataAndComplete
SrvConsumeDataAndComplete又调用了调用SrvConsumeDataAndComplete2,其实就是将一些偏移置0
接下来开始是顺序执行
我们看看LABEL_56是什么,原来是刚刚调过的那个if里面最后的一小段
那我们继续跟看看,原来调用了这里
其实在这里面还可以跟
我们看看 LABEL_13
继续,就到下面的+1操作了
这里可能看得有点问题,看汇编好看一点
就这样完成了对任意地址+1的操作,过程真是漫长
最终写如效果如下
总结一下,就是通过控制某些偏移,控制if。整个过程如下:
SrvProcessPacket—>SrvProcCompleteRequest—>SrvConsumeDataAndComplete—>SrvConsumeDataAndComplete2—>SrvProcCompleteRequest—>SrvProcPartialCompleteCompoundedRequest
最后一个包利用漏洞分析
可以从下面看到调用轨迹跟上面一样
1 | kd> ba e1 0xffdf0908 |
下面给出最后一次调用srv2!SrvProcCompleteRequest的流程
shellcode分析
最后就到达真正的shellcode处了
下面一步步跟一下shellcode
就跳到下面来
之后又跳转了,很多干扰
之后又是一个call,又跳回来
1 | 8c69a605 e8b2fcffff call 8c69a2bc |
之后有一段寻找内存值为905A4Dh的,一开是不知道是什么
仔细一看,原来是PE文件头,后来发下你个地址每次的装载地址都不变,lm看了一下是ntkrpamp.exe这个模块的空间,这个应该是很重要的东西,
跟着通过上面ntkrpamp.exe这个找到很多内核的api地址
后来看到nt!_imp__VidBitBlt
正好指向上面的pe文件头,这个好像没啥用。。。
再后来就精彩了,既然找到api函数地址了,就开始调用了
首先nt!ExAllocatePool申请内存, (复制将要执行的汇编代码到这个申请的内存)
之后调用nt!PsGetCurrentProcess
接下来是一个循环查找svchost.exe,attach上去再detach,不断循环
找到后进行如下操作:
1 | nt!KeStackAttachProcess(attach上去) |
最后回到nt!KeRemoveQueue,就启动了svchost尝试连接攻击者,怎么启动连接的还没搞清楚
与msf的简单对比
发送的数据如下(AAAA后面的是返回地址,再之后就是加密的payload,payload部分没有全部展示出来)
1 | 8c69f530 ff 53 4d 42 72 00 00 00 00 18 53 c8 17 02 00 e9 .SMBr.....S..... |
之后利用下面的代码对smb数据的第一个dword+1操作(之后漏洞利用的时候有用)
结果如下(0xff+1=0x00 进位,所以后面也要加1, 0x53+1=0x54)
利用的位置有点不一样,但大同小异(v36也是1,这是必须保证的)
之后就直到漏洞利用处,流程相对简单
对于开始的前两字节的写入,说明如下:
利用漏洞将返回地址处
1 | 97dc8b91 ffd0 call eax {ffd00d09} |
那里是一个pop esi ret //kernels HAL memory region …no ASLR
1 | kd> g |
从上可以看到跳到了smb数据开始处,正是开始的修改起了作用,利用得非常秒
最后就是真正地执行shellcode了,比NSA简单多了
总结
在NSA的工具中利用了两个漏洞,一个是对任意地址+1的操作,另一个是逻辑漏洞,没有对数据进行校验,就直接call了
当时傻傻地跟,由于对 lock xadd 指令不熟悉,所以对其印象深刻,后来看看NSA工具的输出,为什么发那么多包,回想一下应该这个指令+1操作了,后来对地址下写入断点确认了
猜想:搞那么长调用路径,目标应该是使SrvProcCompleteRequest的第3个参数为1,从而执行call eax
NSA整个漏洞利用的过程:
- 先探测目标系统的版本信息
- 判断该目标是否存在
- 利用对任意地址+1的操作写入gadgets,最后利用逻辑漏洞跳到gadgets处利用漏洞
shellcode很多坑,很能抗静态分析,相对复杂,基本只能动态跟
一些小问题:
- 一开始直接下断还断不下来,应该是因为那里初始的时候还不是代码,ba e1比较好
- 搭建环境挺浪费时间的