【MS17-010】永恒之蓝漏洞复现
漏洞重现
准备工作
工具:
攻击机:kali 192.168.107.128
靶机:windows server 2003 192.168.107.130
软件:nmap,msf
需要两边进行确认主机网络正常通信,可能有防火墙或者其他原因导致网络不通
开始攻击
nmap扫描
先使用namp进行主机存活测试,nmap一般使用流程:
主机->端口->端口对应服务类型及版本->操作系统
nmap -sP 192.168.107.0/24 #扫描网段存活主机
多出了两台,应该是虚拟机内部网卡啥的,感觉也不像,算了先把这个漏洞弄完
nmap 192.168.107.130 -p- #扫描靶机开放端口1-65535
该漏洞需要利用445端口远程连接,所以必须要保证打开
nmap -O 192.168.56.132 #扫描操作系统类型
系统为winodws2003_server_sp2
现在搜集了大多信息可以直接用脚本对靶机进行漏洞发现
nmap --script vuln 192.168.107.130 #三种检测方式,这是最常使用的发现常见漏洞
存在好几个漏洞发现有010漏洞存在
现在可以开始使用关于该漏洞脚本进行攻击了
msf攻击
官方解释:
Metasploit
(MSF)是一个免费的、可下载的框架,通过它可以很容易地获取、开发并对计算机软件漏洞实施攻击。它本身附带数百个已知软件漏洞,是一款专业级漏洞攻击工具
因为只要掌握MSF的使用方法,每个人都可以使用MSF来攻击那些未打过补丁或者刚刚打过补丁的漏洞。
即将漏洞利用脚本程序化,只需要更改其中参数即可
search ms17-010 #搜索攻击脚本是否存在
show options #展示参数配置选项
run
发现解释器变成了meterpreter,可以使用命令对靶机不现在应该是肉鸡了开始操控
漏洞分析
由上面可知漏洞与445端口和SMB文件共享协议有关,事实上是由SMB中函数强制转换引起的缓冲区溢出,除此之外还利用了两个小的漏洞控制缓冲区的分配
SMB 协议是应用程序级别的网络协议,主要用于共享打印机、文件访问、串行端口以及网络上的节点之间的其他通信。 SMB 主要由Windows 系统使用,是一种经过验证的进程间通信机制,可以在多种协议上运行。 在Oracle Solaris OS 中,SMB 协议主要用于共享打印机。 所有这些进程都在网络上执行。
从靶机目录C:\Windows\System32\drivers取出文件srv.sys,问题函数就是在这里面
srv.sys
前置知识:
1 | struct _FEA{ //用于文件扩展属性结构 |
理论上索引不能为变量,但事实上使用的时候是将结构体这么看做的
SrvOs2FeaListToNt的作用是将Os2 _Fea列表转化为NT Fea列表,漏洞触发点也恰好位于这个函数中
函数
SrvOs2FeaListToNt
的功能是:
- 接收一个 OS/2 格式的 FEA 列表并将其转换为 NT 格式。
- 计算转换后的 FEA 列表的大小。
- 如果转换后的大小不为零,则分配一个非分页池来存储转换后的列表。
- 根据需要处理每个 FEA 项目,并将它们转换为 NT 格式。
- 释放分配的内存。
静态分析
函数四个参数表示
- 指向Os2Fea列表
- 传换完成存放地址
- 指向需要为新结构分配的空间大小
- 发生错误时被赋值
1 | __int64 __fastcall SrvOs2FeaListToNt(_FEALIST *a1, __int64 *a2, unsigned int *a3, _WORD *a4) |
LOWORD(a1->cbList) = (_WORD)v10 - (_WORD)a1;
所以关键在这,给于了多余空间,即溢出
Trans2
相关函数:
SMB_COM_TRANSACTION2 子命令支持一组更丰富的服务器端文件系统语义。这些所谓的“Trans2 子命令”允许客户端设置和检索扩展属性键/值对、使用长文件名(比原始 8.3 格式的名称更长)以及执行目录搜索等任务。
SMB_COM_NT_TRANSACT 子命令扩展了SMB_COM_TRANSACTION2(第 2.2.4.46 节)提供的文件系统功能访问,并且还允许传输非常大的参数和数据块。SMB_COM_NT_TRANSACT 消息可能会超出单个 SMB 消息的最大大小(由MaxBufferSize会话参数的值决定 )。在这种情况下,客户端将使用一个或多个 SMB_COM_NT_TRANSACT_SECONDARY 消息来传输 初始消息中容纳不下的事务数据和参数字节。
访问流程
1 | // 初始事务请求 |
trans2允许传输word参数类型数据大小,transact允许dword参数类型数据大小,他们对应子命令也是如此,但数据传输时并没有做函数验证判断,默认以最后一个子命令类型判断调用函数为trans2还是transact,这样就可能出现
当
SMB_COM_NT_TRANSACT
(Dword
) 后跟SMB_COM_TRANSACTION2_SECONDARY
(Word
) 时,就会发生这种情况。这会导致错误地解析数据,就好像它最初来自SMB_COM_TRANSACTION2
类型的事务一样。
同时只有最后一个secondary子命令被发送才会执行后面代码
Non-paged Pool Allocation Bug
利用识别错误的请求数据结构读取错误的SMB_DATA->ByteCount偏移
通过SMB_COM_SESSION_SETUP_ANDX可以将本该由GetExtendSecurityParameters函数换成调用NtSecrityParameters函数,因而将原ntm2当做了ntm1解析,但两者数据大小并不一样,因而解析对应值发生了变化,而后会为NatiuveOS和NativeLanMan分配读取ByteCount空间
利用这个错误通过发送一个数据包,在非分页池中可以分配大缓冲区后又被释放,在该攻击中起占位作用,为后续NtFea分配到该释放位置
动态验证
VM打开设置闪退有点问题,之后修好再补上调试内容,win2003虚拟机坏了,换了一台win7 x64专业版
内核调试
通过串行端口管道连接win7
kali攻击
srv.sys
计算的两个字节结果会被存入rsi指向两个字节中,但取值却是四个字节
漏洞利用
前置概念
1
2
3
4
5
6
7 物理内存:RAM(随机存取存储器),拥有比硬盘更高速的读写速度
虚拟内存:搁硬盘扩展内存区域,即使用下面的内存分页机制,但速度慢些
内存分页机制:系统为了有效利用物理内存,会将不常用物理内存放入磁盘中页面文件,再次使用需要先从磁盘中加载出来
非分页内存池:常驻于物理内存中,数据可以立即被访问,多用于驱动与系统内核
SRVNET 驱动: Windows 操作系统中的一个网络驱动程序,专门用于处理服务器网络通信。srvnet.sys的一个实例和程序
内存对齐:内存对齐是指数据在内存中存储时的地址必须满足某些对齐要求,例如双字(4字节)数据必须存储在地址为4的倍数的位置上。这种对齐要求可以提高内存访问效率和系统性能。否则可能报错或者崩溃
srvnet标头:标头有两个重要的成员,其一`MDL` 结构体下有StartVa表示下一个srvnet客户端连接发送数据将被映射内存位置;另一个**`pSrvNetWskStruct`**下有一个HanderFunction函数指针,当srvnet连接被关闭时会自动执行该函数指针指向函数
制作缓冲区
直接溢出的区域是随机没有对齐的,需要通过多次分配释放,构建出对齐非分页堆,即内存池喷射
每次srvnet.sys连接被创建都会申请一个缓存区用来存放传输数据,且缓存区都含有srvnet标头,当连接被关闭,缓存区被释放,srv.sys创建时也是这样
- 首先创建srv连接,会申请Fea堆块
- 使用trans2填充Fea内容,但不发送最后一个secondary数据包,这样由srv中的错误计算就暂时不会被执行
- 创建多个srvnet连接,这样可以同时占用多个缓存区,增加溢出到srvnet标头机会(完全可以后面创建连接为什么要在这里提前建立)
- 利用Non-paged这个漏洞申请一块和第一个漏洞转化后的NtFea一样大的堆块,用于NtFea的占位
- 继续创建多个srvnet连接直到有缓存被分配到占位堆块前面紧挨着以方便溢出时覆盖
- 释放占位堆块
- 发送最后一个secondary数据包,会激发第二步NtFea的转化,此时会为他分配占位释放堆块存放
- NtFea会溢出覆盖srvnet中MDL和**
pSrvNetWskStruct
** - 创建含自定义数据的新srvnet连接,他会被映射入MDL记录地址
- 关闭srvnet连接,会自动执行pSrvNetWskStruct结构中的HanderFunction指向函数,而在覆盖时,这被改为了shellcode地址
pSrvNetWskStruct指向的结构被包含在新srvnet连接自定义数据中伪造的SrveNetWskStruck结构,shellcode紧跟着结构体后面
MDL指定地址应该为堆中具有可执行权限的内存,例如HAL’Heap
借用大神的图片,溢出代码被执行时需要接收到最后一个数据包,所以先发送SMB请求前面的数据报文不断申请修整缓冲块被分配位置,便于溢出时申请空间是对齐的,发送最后一个数据包,在这个数据包的内容将覆盖溢出区域,也是MDL的指定位置处,shellcode将会被写入这块区域
然后更改DisconnectHandleFunc
指针链
srvnet!SrvNetWskReceiveComplete执行时会自动调用该地址
流量分析
可恶,分析一半环境崩了,电脑直接宕机了
可以看到图中正在发送srv的transact请求但没有发送最后一个包
后面直接借用第三个链接的图吧
可以发现和上面说的一样,出现三个不同缓冲区,然后缓冲区一在最后一个secondary包发送后会映射到第三个缓存区位置,如果有第二个和第三个刚好挨着就会出现RCE
遗留问题
- 为什么创建连接会申请堆块
- trans2错误解析数据之后是怎么在攻击中起作用的,猜测应该也是依靠word数据被解析成dword造成数据的溢出
- 对trans2和Non bug没进行完动态验证
参考链接: