导语:Eternal Synergy是一个SMBv1认证漏洞,它特别有趣,许多开发步骤纯粹是基于分组的,而不是本地shellcode执行。像其他SMB漏洞一样,MS17-010也解决了CVE-2017-0143这一问题。该漏洞利用可以在Windows 8上进行,但不能像任何较新的平台一样

最近我们发布了一系列博客文章,来分析ShadowBrokers于2017年4月发布的漏洞,特别是其中一些较少被研究的漏洞。本周我们来看一下Eternal Synergy,这是一个SMBv1认证漏洞。其实它特别有趣,因为许多开发步骤纯粹是基于分组的,而不是本地的shellcode执行。像其他SMB漏洞一样,MS17-010也解决了CVE-2017-0143这一问题。该漏洞利用可以在Windows 8上进行,但不能像任何较新的平台一样进行写入。

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

漏洞:CVE-2017-0143

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

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

PTRANSACTION
SrvFindTransaction (
    IN PCONNECTION Connection,
    IN PSMB_HEADER Header,
    IN USHORT Fid OPTIONAL
    )
{
    ...

    //
    // If this is a multipiece transaction SMB, the MIDs of all the pieces
    // must match.  If it is a multipiece WriteAndX protocol the pieces
    // using the FID.
    //
 
    if (Header->Command == SMB_COM_WRITE_ANDX) {targetOtherInfo = Fid;} else {targetOtherInfo = SmbGetAlignedUshort( &Header->Mid );}

    ...

    //
    // Walk the transaction list, looking for one with the same
    // identity as the new transaction.
    //
 
    for ( listEntry = Connection->PagedConnection->TransactionList.Flink;
          listEntry != &Connection->PagedConnection->TransactionList;
          listEntry = listEntry->Flink ) {
 
        thisTransaction = CONTAINING_RECORD(
                            listEntry,
                            TRANSACTION,
                            ConnectionListEntry
                            );
 
        if ( (thisTransaction->Tid == SmbGetAlignedUshort( &Header->Tid) ) &&
             (thisTransaction->Pid == SmbGetAlignedUshort( &Header->Pid) ) &&
             (thisTransaction->Uid == SmbGetAlignedUshort( &Header->Uid) ) &&
             (thisTransaction->OtherInfo == targetOtherInfo) ) {
 
            ...
 
            // A transaction with the same identity has been found
 
            ...
        }
...
}

开发

当SMB消息到达时,相应的处理程序将其内容复制到相应的事务(Transaction)缓冲区中,即InData。该SMB_COM_TRANSACTION_SECONDARY处理器假定InData地址指向缓冲区的开始。

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

然而,在SMB_COM_WRITE_ANDX的事务(Transaction)情况下,每当接收到该事务的SMB时,该InData地址被更新以指向现有数据的结束。

RtlCopyMemory(transaction->InData, writeAddress, writeLength );
 
//
// Update the transaction data pointer to where the next
// WriteAndX data buffer will go.
//transaction->InData += writeLength;

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

接手事务(Transaction)

为利用过程中中使用的RWX基元构建块然后通过利用上一节中描述的消息混淆来接手事务结构。首先,通过SMB_COM_TRANSACTION客户端消息分配“控制”事务。

1.png

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(
        transaction->InData + dataDisplacement,
        (PCHAR)header + dataOffset,
        dataCount
        );
}

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

kd> dv dataDisplacement
dataDisplacement = 0x5020

2.png

具体来说,它将OtherInfo使用攻击者控制的值(在这种情况下为0)来覆盖事务的字段,以便将使用的所有将来的消息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.png

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

 4.png

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

 5.png

远程任意读取原语

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

1、采取连接,并建立了写入原语,如上所述。

2、泄漏一个有效的TRANSACTION结构

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

 6.png

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

 7.png

作为示例,下面是发送以执行远程读取操作的消息。payload在“Extra byte parameters”中指定“Data Displacement”中的目标地址和“Data Count”字段中的大小。

 8.png

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

 9.png

代码执行

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

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

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

 10.png

把所有的都放在一起

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

 

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

以下是SMB_COM_TRANSACTION包含泄露池内存的消息的内容。泄漏的TRANSACTION结构从偏移开始0xb0。我们可以看到,除其他事项外, 该事务包含 TID,PID,UID和OtherInfo。此外,诸如InData(offset 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:.w.Z
0050   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  ....Free........
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 ff  .........-......
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 ff  ..A.....H.V.....
00e0   48 c0 55 02 a0 f8 ff ff 00 00 00 00 00 00 00 00  H.U.............
00f0   00 00 02 00 00 00 00 00 68 b2 57 02 a0 f8 ff ff  ........h.W.....
0100   6d 39 00 00 ff ff ff ff 00 00 00 00 00 00 00 00  m9..............
0110   6c b2 57 02 a0 f8 ff ff 00 00 00 00 00 00 00 00  l.W.............
0120   6c b2 57 02 a0 f8 ff ff fc b2 57 02 a0 f8 ff ff  l.W.......W.....
01306c b2 57 02 a0 f8 ff fffc bf 57 02 a0 f8 ff ff  l.W.......W.....
0140   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 0000 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  ................
0190   01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 00  ................

SMB_COM_TRANSACTION发送一系列消息以分配一对相邻的控制 – 受害者事务。具体来说,“groom”数据包包含SMB消息,用于创建数据包混淆,或换句话说,有资格成为控制事务。“Bride”数据包创建了一个作为破坏候选者的事务,即受害者事务。

 

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

 17.png

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

 18.png

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

kd> ?? 0xfffff802846f4000-0xfffff80284483000
unsigned int640x271000kd> !dh nt -s
SECTION HEADER #3
  RWEXEC name
    1000 virtual size271000virtual address
       0 size of raw data
       0 file pointer to raw data
       0 file pointer to relocation table
       0 file pointer to line numbers
       0 number of relocations
       0 number of line numbers
E80000A0 flags
         Code
         Uninitialized Data
         Not Paged
         (no align specified)Execute Read Write

19.png

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

;
; Retrieve the _KPRCB structure
;
fffff802`846f400 65488b042520000000 mov   rax,qword ptr gs:[20h]
;
; Access the PPNxPagedLookasideList.AllocateEx member
;
fffff802`846f4009 4805b0080000       add     rax,8B0h                                                           
fffff802`846f400f 31c9               xor     ecx,ecx
;
; Set NumberOfBytes (0xe4b) for size argument
;
fffff802`846f4011 8b151e000000       mov     edx,dword ptr [fffff802`846f4035]
fffff802`846f4017 4883ec20           sub     rsp,20h
;
; Call nt!ExAllocatePoolWithTag
;
fffff802`846f401b ff10               call    qword ptr [rax]                                  
fffff802`846f401d 4883c420           add     rsp,20h
;
; Check for errors
;
fffff802`846f4021 85c0               test    eax,eax
fffff802`846f4023 7407               je      fffff802`846f402c
;
; Save the allocated memory address
;
fffff802`846f4025 48890501000000     mov     qword ptr [fffff802`846f402d],rax
fffff802`846f402c c3                 ret

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

缓解措施对利用的影响

由于几个内核安全性的改进,利用此漏洞的技术已经不能直接适用于较新的平台了。特别是:

1、虚拟机管理程序强制的代码完整性(HVCI)可防止未签名的内核页面被执行,并防止攻击者复制和执行代码,即使存在RWX内存。

2、控制流程保护(CFG)可防止无效的间接函数调用,例如调用损坏的函数指针,此漏洞利用的技术可触发代码执行。

源链接

Hacking more

...