Eternal Synergy Exploit Analysis

最近我们宣布了一系列博客文章,分析了ShadowBrokers于2017年4月发布的漏洞;特别是一些较少探索的漏洞。本周我们将看一下永久协同,这是一个SMBv1认证漏洞。这一个特别有趣,因为许多开发步骤纯粹是基于分组的,而不是本地的shellcode执行。像其他SMB漏洞一样,MS17-010也被解决了CVE-2017-0143。漏洞利用工作可以适用于Windows 8,但不能像任何较新的平台一样写入。

这篇文章有四个主要部分。我们将深入探讨该漏洞,随后讨论如何将该漏洞武器化以创建在整个漏洞利用中用作构建块的读/写/电子原始图元。接下来,我们将继续执行EternalSynergy,看看这些原语如何被用来提供一个完整的漏洞。最后,我们将简要讨论近期缓解对所提出的漏洞利用技术的影响。

此漏洞的根本原因在于确定消息是否是事务的一部分时,不考虑SMB消息的命令类型。换句话说,只要SMB头UIDPIDTIDOtherInfo字段与相应的事务字段匹配,则该消息将被认为是该事务的一部分。

通常, OtherInfo字段存储一个MID。但是,在SMB_COM_WRITE_ANDX消息的情况下,它会存储FID。这将产生一个潜在的消息类型混淆:给定一个现有的SMB_COM_WRITE_ANDX事务,MID等于事务FID的传入SMB消息将被包含在事务中。

PTRANSACTION
SrvFindTransaction(
    IN PCONNECTION连接,
    IN PSMB_HEADER标题,
    使用Fid可选
    )
{
    ...

    //
    //如果这是一个多体事务SMB,那么所有的MID都是MID
    // 必须匹配。如果它是一个多体式WriteAndX协议的碎片
    //使用FID。
    //
 
    if(Header-> Command == SMB_COM_WRITE_ANDX){
        targetOtherInfo = Fid;
    } else {
        targetOtherInfo = SmbGetAlignedUshort(&Header-> Mid);
    }

    ...

    //
    //走交易列表,寻找一个相同的
    //身份作为新的交易。
    //
 
    for(listEntry = Connection-> PagedConnection-> TransactionList.Flink;
          listEntry!=&Connection-> PagedConnection-> TransactionList;
          listEntry = listEntry-> Flink){
 
        thisTransaction = CONTAINING_RECORD(
                            一个ListEntry,
                            交易,
                            ConnectionListEntry
                            );
 
        if((thisTransaction-> Tid == SmbGetAlignedUshort(&Header-> Tid))&&
             (thisTransaction-> Pid == SmbGetAlignedUshort(&Header-> Pid))&&
             (thisTransaction-> Uid == SmbGetAlignedUshort(&Header-> Uid))&&
             (thisTransaction-> OtherInfo == targetOtherInfo)){
 
            ...
 
            //找到具有相同身份的事务
 
            ...
        }
...
}

当SMB消息到达时,相应的处理程序将其内容复制到相应的事务缓冲区,即InDataSMB_COM_TRANSACTION_SECONDARY处理程序假定InData地址指向缓冲区的开头。

if(dataCount!= 0){
    RtlMoveMemory(
        事务 - > InData + dataDisplacement,
        (PCHAR)header + dataOffset,
        DATACOUNT
        );      
}

但是,在SMB_COM_WRITE_ANDX事务的情况下,每当接收到该事务的SMB时,将更新InData地址以InData现有数据的结尾。

 RtlCopyMemory(transaction-> InData,writeAddress,writeLength);
 
//
//将事务数据指针更新到下一个位置
// WriteAndX数据缓冲区会去。
//
 
transaction-> InData + = writeLength; 

利用数据包混淆,攻击者可以将SMB_COM_TRANSACTION_SECONDARY消息插入到SMB_COM_WRITE_ANDX事务中。在这种情况下, InData将指向缓冲区的开头,因此在复制传入的消息数据期间, SMB_COM_TRANSACTION_SECONDARY处理程序可以溢出缓冲区。

接管交易

在利用中使用的RWX原语的构建块通过利用上一节中描述的消息混淆来接管事务结构。首先,通过SMB_COM_TRANSACTION客户端消息分配“控制”事务。

图1 - 触发了包类型混淆之前的内存布局。条纹表示攻击者控制的输入。

kd> dt srv!TRANSACTION 0xfffff8a00167f010
   ...
   + 0x080 InData:0xfffff8a0`0167f110
   + 0x088 OutData:(null)
   ...
   + 0x0a4 DataCount:0x0
   + 0x0a8 TotalDataCount:0x5100
   ...
   + 0x0ba Tid:0x800
   + 0x0bc Pid:0xab9e
   + 0x0be Uid:0x800
   + 0x0c0 OtherInfo:0x4000  

然后,发送一个SMB_COM_WRITE_ANDX消息,用于利用数据包混淆。因此,控制事务的InData指针被破坏以指向缓冲区的开始。在这种情况下,它是关闭0x200 。字节。

kd> dt srv!TRANSACTION 0xfffff8a00167f010
   ...
   + 0x080 InData:0xfffff8a0`0167f310
   + 0x088 OutData:(null)
   ...
   + 0x0a4 DataCount:0x200
   + 0x0a8 TotalDataCount:0x5100
   ...
   + 0x0ba Tid:0x800
   + 0x0bc Pid:0xab9e
   + 0x0be Uid:0x800
   + 0x0c0 OtherInfo:0x4000 

接下来, SMB_COM_TRANSACTION_SECONDARY消息被发送到相同的事务,并且通过利用损坏的InData指针来修改相邻的“受害者”事务。我们再次访问如何计算目标写入地址。

if(dataCount!= 0){
    RtlMoveMemory(
        事务 - > InData + dataDisplacement,
        (PCHAR)header + dataOffset,
        DATACOUNT
        );
}

传入的消息dataDisplacement足够大以到达相邻的事务。

kd> dv dataDisplacement
dataDisplacement = 0x5020

图2 - 分组类型混淆后的内存布局导致覆盖受害者事务。条纹表示攻击者控制的输入。

具体来说,它将使用攻击者控制的值(在这种情况下为0)来覆盖事务的OtherInfo字段,以便使用MID=0发送的所有将来的消息都将被指向受害者事务。下面我们看到在覆盖发生之前的受害者事务。

 kd> dt srv!TRANSACTION 0xfffff8a00167f310 + 0x5020-0xc0
   ...
   + 0x080 InData:0xfffff8a0`0168436c
   + 0x088 OutData:0xfffff8a0`01684ffc
   ...
   + 0x0ba Tid:0x800
   + 0x0bc Pid:0xab9f
   + 0x0be Uid:0x800
   + 0x0c0 OtherInfo:0x8ccb

在接管受害者交易之后,漏洞利用可以预测地在相同或其他事务中继续腐败的领域,并通过向事务发送消息来可靠地触发它们。请注意,为了使这种技术有效,攻击者必须能够可预测地分配一对邻近的事务。

远程任意写入原语

任意写入原语允许攻击者修改受害者系统上的内存内容,并作为此漏洞中使用的其余技术的基础。为了破坏内存,它利用上一节中描述的技术。具体来说,写入原语分为两个步骤:

图3 - 破坏构建任意写入原语的方法是破坏受害者事务。条纹表示攻击者控制的输入。

步骤1中 ,受害者事务InData缓冲区地址被覆盖,使其指向目标写入地址。

图4 - 用于对目标地址0xfffff802846f4000执行步骤1的SMB消息示例。

接下来在步骤2中 ,攻击者可以通过发送到受害者事务来覆盖任意内核内存。收到该消息后,其内容将被复制到InData缓冲区;然而,在我们的情况下,缓冲区地址被破坏,所以内容被复制到攻击者控制的地址。下面是一个示例数据包,其中包含在“额外字节参数”中的shellcode将被复制到受害计算机。

图5 - 用于将有效负载复制到受害机器的SMB消息示例,

远程任意读取原语

任意读取原语允许攻击者从目标系统远程读取任何内存地址的内容。要使用这个原语,攻击者必须成功:

  • 采取连接,并建立了写入原语,如上所述。
  • 泄漏一个有效的TRANSACTION结构

如图6所示 ,我们有一个控制事务与受害者#1事务相邻,用于写入原语和受害人#2事务。 消息#1使用写入原语来破坏受害者#1 InData缓冲区地址,以便它指向受害者#2基地址。这意味着针对受害人#1交易的任何消息将导致在消息的“数据移位”字段指定的偏移量下破坏受害者#2事务。受害者#2是泄露的TRANSACTION结构,其基址可以通过其内容推断。

图6 - 构建任意读取原语,漏洞覆盖受害者#2事务OutData指针。条纹表示攻击者控制的输入。

其余消息包含Transaction Secondary命令(0x26),并使用相同的TID,PID和UID。 消息#2-5定位受害者#1交易(MID = 0),并执行受害人#2交易的特定字段的覆盖。下表总结了每条消息的修改:

消息# 抵消 交易领域 覆盖值
0×001 BlockHeader.State 0X2
3 量0x054 时间到 0x40000023
2 0x088 OutData 攻击者指定的地址(例如0xfffff88004b78150)
2 0x090 SetupCount 为0x4
2 0x094 MaxSetupCount 为0x0
2 0x098 ParameterCount 为0x0
2 0x09c TotalParameterCount 为0x0
2 0x0a0 MaxParameterCount 为0x10
2 0x0a4 DATACOUNT 为0x0
2 0x0a8 TotalDataCount 为0x0
2 0x0ac MaxDataCount 地址0x20000
4 0x0e3 执行为0x0

图7 - 在任意读取操作期间损坏的受害者#2事务字段的列表

作为示例,下面是发送以执行远程读取操作的消息。有效负载在“额外字节参数”中指定,“数据位移”中的目标地址和“数据计数”字段中的大小。

图8 - 覆盖受害者#2事务的SMB消息示例。

消息#5是一个虚拟数据包,具有一个非零MID对象,受害者#2事务,发送到触发服务器响应。在该响应消息期间,将损坏的DataOut指针的内存地址的内容复制出去并发送回SMB客户端。此类消息的示例如下所示:

图9 - 示例SMB消息,演示触发任意读取操作的最后一步。

代码执行

前面章节讨论的技术在记忆中运行;漏洞利用仍然需要一种方式来改变控制流并以可重复的方式调用执行。漏洞利用破坏SMB消息处理程序的指针来实现此目的。

首先,它使用写入原语来覆盖srv!SrvTransaction2DispatchTable条目0xe与执行目标的地址。这是一个dispatch表,其中包含SMB消息处理程序的指针。定位TRANS2_SESSION_SETUP子命令处理程序的特定条目是非常方便的,因为它未被实现,因此不期望由“正常”SMB流量使用。有关如何将这个全局指针发现并泄漏回攻击者的详细信息将在下一节中介绍。

接下来,将类型为SMB_COM_TRANSACTION2和设置为TRANS2_SESSION_SETUP子命令的消息发送到受害者,从而触发损坏的函数指针的执行。此消息的目标事务并不重要。下面看到一个示例数据包。

图10 - 发送的示例SMB消息,以触发受害者机器上的有效负载执行。

在本节中,我们将详细介绍这些漏洞,并了解上述构建块如何组合以实现远程内核代码执行。

图11 - 试图泄露TRANSACTION结构的EternalSynergy

图12 - TRANSACTION泄漏阶段期间的网络流量。

在此阶段, TRANSACTION结构从受害机器泄漏。这种结构以两种方式使用。首先,它包含用作发现其他有用地址的基础的指针(例如EndpointSpinLock )。第二,它被用作受害者#2交易,因为为了构建一个Read原语,攻击者需要一个有效的TRANSACTION结构的细节。用于泄漏指针的方法类似于永恒冠军漏洞中描述的方法。

以下是包含泄漏池内存的SMB_COM_TRANSACTION消息的内容。泄漏的TRANSACTION结构从偏移0xb0开始。我们可以看到它包含事务TIDPIDUIDOtherInfo等等。而且,诸如InData (偏移量0x130 )的指针允许攻击者确定事务的基本内存地址。

0000 ff 53 4d 42 a0 00 00 00 00 98 03 c0 00 00 00 00 .SMB ............
0010 00 00 00 00 00 00 00 00 00 08 37 ca 00 08 56 15 .......... 7 ... V。
0020 12 00 00 00 04 00 00 00 c0 10 00 00 00 00 00 00 ...............
0030 48 00 00 00 04 00 00 00 58 01 00 00 48 00 00 00 H ....... X ... H ...
0040 b8 10 00 00 00 59 01 00 fc 84 36 3a 10 77 98 5a ..... Y .... 6:.wZ
0050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ...............
0060 00 01 02 03 46 72 61 67 00 00 00 00 00 00 00 00 .... Frag ........
0070 20 51 00 00 00 00 00 00 00 00 00 00 00 00 00 00 Q ..............
0080 02 01 01 00 46 72 65 65 00 00 00 00 00 00 00 00 ....免费........
0090 01 01 eb 03 4c 53 74 72 30 a1 07 00 83 fa ff ff .... LStr0 .......
00a0 8c 0e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ...............
00b0 0c 02 8c 0e 00 00 00 00 d0 2d e6 00 83 fa ff f ..... .........
00c0 90 bb e5 00 83 fa ff ff d0 2d 46 02 a0 f8 ff ff .........- F .....
00d0 d0 8d 41 02 a0 f8 ff ff 48 00 56 02 a0 f8 ff f .. .. ..... ..... .....
00e0 48 c0 55 02 a0 f8 ff f 00 00 00 00 00 00 00 00 HU ............
00f0 00 00 02 00 00 00 00 00 68 b2 57 02 a0 f8 ff ff ........ hW ....
0100 6d 39 00 00 ff ff ff 00 00 00 00 00 00 00 00 m9 ..............
0110 6c b2 57 02 a0 f8 ff f 00 00 00 00 00 00 00 00 lW ............
0120 6c b2 57 02 a0 f8 ff ff fc b2 57 02 a0 f8 ff ff lW ...... W .....
0130 6c b2 57 02 a0 f8 ff ff fc bf 57 02 a0 f8 ff ff lW ...... W .....
0140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ...............
0150 00 0d 00 00 00 00 00 00 90 00 00 00 00 00 00 00 ...............
0160 00 00 00 00 01 01 00 00 00 00 00 0837 ca00 08 ............ 7 ...
0170 5a 15 00 00 00 00 00 00 00 00 00 00 00 00 00 00 Z ...............
0180 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ...............
0190 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 00 ...............

图13 - 漏洞试图分配相邻的控制 - 受害者事务。

图14 - 控制 - 受害者事务分配期间的网络数据包。

发送一系列SMB_COM_TRANSACTION消息以便分配一对邻近的控制 - 受害者事务。具体来说,“新郎”数据包包含SMB消息,用于创建数据包混淆,或换句话说,有资格成为控制事务。“新娘”数据包创建作为腐败候选者的交易,即受害者交易。

图15 - 漏洞利用触发消息类型混淆。

图16 - 显示利用消息类型混淆的SMB_COM_WRITE_ANDX消息的网络数据包。

漏洞利用了对R / W原语使用的邻居受害者事务的控制。

图17 - exploit定位并泄漏srv!SrvTransaction2DispatchTable内存地址。

读取的原语是多次执行,以便发现srv!SrvTransaction2DispatchTable全局指针的位置,使用触发器shellcode执行。

图18 - 漏洞利用位置查找和泄漏页面。

图19 - 3次远程读取操作期间的网络流量。

读取的原语再次被多次运行以发现ntoskrnl.exe的基础。上面发现的RWX内存被用作一个暂存页面,其中shellcode被写入和执行,返回值被存储。该页面由于ntoskrnl.exe的RWX部分而存在。值得一提的是,Windows 8.1及更高版本的ntoskrnl.exe没有RWX部分。

kd> ?? 0xfffff802846f4000-0xfffff80284483000
unsigned int64 0x271000
 
kd>!dh nt -s
第3节
  RWEXEC名称
    1000虚拟大小
  271000虚拟地址
       0原始数据大小
       0文件指针到原始数据
       0文件指针到重定位表
       0个文件指针到行号
       0搬迁数量
       0行号码
E80000A0标志
         码
         未初始化的数据
         不分页
         (未指定对齐)
         执行读写

图20 - 复制和执行有效负载的漏洞的最后阶段

图21 - 在执行写入和读取原语的最后阶段中的SMB数据包。

这是在受害者机器上复制和执行shellcode时。首先,使用写入原语,将exploit shellcode复制到scratch页面。这个shellcode只是使用nt!ExAllocatePoolWithTag在池中分配内存的存根功能。然后,发送一个SMB_COM_TRANSACTION2消息来执行shellcode。返回值以临时页面上的固定偏移量保存,并使用读取原语泄漏回攻击者。我们可以看到stub功能如下:

;
;检索_KPRCB结构
;
fffff802`846f400 65488b042520000000 mov rax,qword ptr gs:[20h]

;
;访问PPNxPagedLookasideList.AllocateEx成员
;
fffff802`846f4009 4805b0080000加rax,8B0h                                                           
fffff802`846f400f 31c9 xor ecx,ecx

;
;为Size参数设置NumberOfBytes(0xe4b)
;
fffff802`846f4011 8b151e000000 mov edx,dword ptr [fffff802`846f4035]
fffff802`846f4017 4883ec20 sub rsp,20h

;
;调用nt!ExAllocatePoolWithTag
;
fffff802`846f401b ff10 call qword ptr [rax]                                  
fffff802`846f401d 4883c420加rsp,20h

;
;检查错误
;
fffff802`846f4021 85c0测试eax,eax
fffff802`846f4023 7407 je fffff802`846f402c

;
;保存分配的内存地址
;
fffff802`846f4025 48890501000000 mov qword ptr [fffff802`846f402d],rax
fffff802`846f402c c3 ret

最后,临时页面被清除,攻击者提供的shellcode被写入池分配的页面,并且发送消息以触发执行。

由于几个内核安全性的改进,用于此漏洞的技术不能直接适用于较新的平台。尤其是:

  1. 虚拟机管理程序强制的代码完整性(HVCI)可防止未签名的内核页面被执行,并防止攻击者复制和执行代码,即使存在RWX内存。
  2. 控制流程保护(CFG)可防止无效的间接函数调用,例如调用损坏的函数指针,此漏洞利用的技术可触发代码执行。

在CVE-2017-0143:Swamy Shivaganga Nagaraju,Nicolas Joly(MSRC Vulnerabilities&Mitigations Team)和Viktor Brange(Windows Offensive Security Research Team)的初步调查期间,我要感谢以下人员的工作。

Georgios Baltas
MSRC漏洞和缓解小组


为您推荐了相关的技术文章:

  1. 条件竞争导致的安全问题--抵现券一券多用问题原理分析和总结 - ThreatHunter
  2. org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread
  3. 微软对 ShadowBrokers 公开的 Eternal Synergy SMBv1 Exploit 的分析(CVE-2017-0143)
  4. 通过DNS响应欺骗来绕过域控制验证
  5. 从 Things 开始(四):你的收件箱

原文链接: blogs.technet.microsoft.com