作者百度安全實驗室

一、概述

近期,百度安全實驗室反高級威脅團隊截獲多封利用Microsoft Office Word漏洞進行攻擊的惡意郵件。

通過對郵件附件樣本進一步分析發現,其利用的漏洞為澳洲國防部計算機應急響應中心提交的CVE-2016-7193。該漏洞為RTF文件解析漏洞,成功利用該漏洞可以遠程執行任意代碼。我們攔截的樣本雙擊打開后會在本地釋放后門程序,從而完全控制目標主機。

微軟已經于2016年10月11日發布了該漏洞的相關補丁(參見微軟安全公告 MS16-121)。公告顯示,該漏洞影響的Office版本非常廣泛,幾乎全版本Word都會受到該漏洞影響,包括最新的Word 2016。可以預見的將來,本漏洞將和CVE-2012-0158、CVE-2015-1641等經典Word內存破壞型漏洞一起,作為黑客進行APT滲透的標準工具包核心成員。雖然微軟已經針對該漏洞發布了補丁,但由于多數用戶安全意識薄弱,不傾向于打Office補丁,導致此類漏洞會長期威脅這批用戶。通過進一步樣本篩選以及情報確認,黑色產業地下市場已經有很成熟的利用該漏洞生成Exploit的工具在售(見附錄參考鏈接)。

從2017年3月份開始,該漏洞利用樣本首次在VirusTotal上出現。如下圖所示,多家安全廠商雖然可以識別該樣本,但命名均不準確,顯然并未深入了解該漏洞的本質,可能誤導用戶對于漏洞針對性地防范。通過百度安全實驗室數據監測顯示,利用該漏洞進行的遠程攻擊事件數量正在不斷增長,廣大網民和安全從業者要提高警惕,做好相應的防范措施。

受影響的 Word 版本:

Microsoft Word 2007 Service Pack 3
Microsoft Word 2010 Service Pack 2
Microsoft Word 2013 Service Pack 1
Microsoft Word 2013 RT Service Pack 1
Microsoft Word 2016
Microsoft Word for Mac 2011
Microsoft Word 2016 for Mac
Microsoft Office 兼容包 Pack Service Pack 3
Microsoft Word Viewer
Microsoft SharePoint Server 2010 Service  Pack 2 上的 Word Automation Services
Microsoft SharePoint Server 2013 Service  Pack 1 上的 Word Automation Services
Microsoft Office Web Apps 2010 Service  Pack 2
Microsoft Office Web Apps Server 2013  Service Pack 1

二、漏洞成因分析

  1. 分析環境
    文件信息:wwlibversion:12.0.4518.1014
  2. 分析過程
    經測試發現,該樣本在一些特定的操作步驟下打開會利用失敗,我們在這種情形下得到了如下的崩潰現場:

可見崩潰點位于 wwlib.dll 中,而負責 RTF 解析的邏輯正是位于該模塊。通過進一步回溯,edi 的值來源于 [obj_xx+0x761c],相關的調用點如下:

關于這里用到的ROP鏈及shellcode本文最后將單獨說明。這里繼續查找地址edi+0x761c中0x09c00c0c的來源。我們定位到了如下關鍵代碼:

很顯然,關鍵代碼位于一個大的switch結構中。應該是解析某種“bytecode”對應的handler部分。從這段代碼來看,eax+0x75f8開始是一個字節數組(不是數組指針),而位于eax+0x7618處是當前數組元素個數。每解析對應的“bytecode”時,該數組附加一個字節。數組最大長度被限制為0x40字節。按代碼邏輯來看,數組起始于eax+0x75f8,終止于eax+0x7638。而表示數組當前元素個數的變量位于該數組范圍內,即eax+0x7618。

這似乎很不科學!

在wwlib的反匯編中搜索所有對75f8的引用代碼,也就是對該數組的引用。結果有些意外,只有一處有效的。關鍵代碼如圖:

可以看出這個代碼是復制該數組數據的邏輯,從拷貝大小參數來看該數組實際分配的大小為0x20字節。而在為該數組附加字節的邏輯中限制寫成了0x40字節,發生數組越界寫入,進而導致數組之后的類成員變量被改寫。

重新加載樣本,仔細觀察該數組的數據賦值過程:

0:000> bp 315EB380 "db @edi+75f8;"
*** ERROR: Symbol  file could not be found.  Defaulted to  export symbols for C:\Program Files\Microsoft Office\Office12\wwlib.dll -
0:000> g
//第1次附加字節
(1e0.610):  Unknown exception - code e0000002 (first chance)
03bb75f8  09 00 00 00  00 00 00 00-00 00 00 00 00 00 00 00   ................
03bb7608  00 00 00 00 00 00 00 00-00 00 00 00 00 00  00 00  ................
03bb7618  01 00 00 00 60 59 57 01-00 00 00 00 00 00 00 00   ....`YW.........
03bb7628  00 00 00 00 00 00 00 00-00 00 00 00 00 00  00 00  ................
03bb7638  00 00 00 00 00 00 00 00-00 00 00 00 00 00  00 00  ................
03bb7648  00 00 00 00 60 59 57 01-00 00 00 00 00 00  00 00  ....`YW.........
03bb7658  01 00 00 00 00 00 00 00-00 00 00 00 00 00  00 00  ................
03bb7668  ff ff ff ff ff ff ff ff-00 00 00 00 00 00  00 00  ................
eax=03bb0000  ebx=00000009  ecx=00000000  edx=02000000  esi=03bb0948  edi=03bb0000
eip=315eb380   esp=00127b9c  ebp=00128124  iopl=0  nv up ei pl nz na po cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000  efl=00000203
wwlib!wdGetApplicationObject+0x2977a:
315eb380  e968c8a500  jmp  wwlib!DllCanUnloadNow+0x5598ab  (32047bed)
0:000> g
//第2次附加字節
03bb75f8  09 c0 00 00  00 00 00 00-00 00 00 00 00 00 00 00   ................
03bb7608  00 00 00 00 00 00 00 00-00 00 00 00 00 00  00 00  ................
03bb7618  02 00 00 00 60 59 57 01-00 00 00 00 00 00 00 00   ....`YW.........
03bb7628  00 00 00 00 00 00 00 00-00 00 00 00 00 00  00 00  ................
03bb7638  00 00 00 00 00 00 00 00-00 00 00 00 00 00  00 00  ................
03bb7648  00 00 00 00 60 59 57 01-00 00 00 00 00 00  00 00  ....`YW.........
03bb7658  01 00 00 00 00 00 00 00-00 00 00 00 00 00  00 00  ................
03bb7668  ff ff ff ff ff ff ff ff-00 00 00 00 00 00  00 00  ................
eax=03bb0000  ebx=000000c0 ecx=00000001 edx=02000000 esi=03bb0948 edi=03bb0000
eip=315eb380  esp=00127b9c ebp=00128124 iopl=0   nv up ei pl nz na po cy
cs=001b  ss=0023   ds=0023  es=0023  fs=003b   gs=0000    efl=00000203
wwlib!wdGetApplicationObject+0x2977a:
315eb380  e968c8a500  jmp  wwlib!DllCanUnloadNow+0x5598ab  (32047bed)
0:000> g
……略
0:000> g
//第0x20次附加字節
03bb75f8  09 c0 0c 0c 0c c0  09 0c-0c c0 09 0c 0d c0 09 0c   ................
03bb7608  0c 09 c0 0b 18 20  17 15-0c 0c c0 09 c0 09 0c 20   ..... .........
03bb7618  20 00 00 00  60 59 57 01-00 00 00 00 00 00 00 00    ...`YW.........
03bb7628  00 00 00 00 00 00 00 00-00 00 00 00 00 00  00 00  ................
03bb7638  00 00 00 00 00 00 00 00-00 00 00 00 00 00  00 00  ................
03bb7648  00 00 00 00 60 59 57 01-00 00 00 00 00 00  00 00  ....`YW.........
03bb7658  01 00 00 00 00 00 00 00-00 00 00 00 00 00  00 00  ................
03bb7668  ff ff ff ff ff ff ff ff-00 00 00 00 00 00  00 00  ................
eax=03bb0000  ebx=00000020 ecx=0000001f  edx=02000000  esi=03bb0948 edi=03bb0000
eip=315eb380  esp=00127b9c  ebp=00128124  iopl=0  nv up ei pl nz ac po cy
cs=001b  ss=0023   ds=0023  es=0023  fs=003b  gs=0000  efl=00000213
wwlib!wdGetApplicationObject+0x2977a:
315eb380  e968c8a500  jmp  wwlib!DllCanUnloadNow+0x5598ab  (32047bed)

0:000> g
//第0x21次附加字節,注意,該次要正確覆蓋偏移為7618處的變量(計數器變量,表示當前字節數組的字符個數),不然之后會無法覆蓋到目標指針,惡意代碼作者提供的數據為0x23,計數器加1后恰好為0x24,這個可以保證后續正確覆蓋對象指針!

03bb75f8  09 c0 0c 0c 0c c0  09 0c-0c c0 09 0c 0d c0 09 0c   ................
03bb7608  0c 09 c0 0b 18 20  17 15-0c 0c c0 09 c0 09 0c 20   ..... .........
03bb7618  24 00 00 00 60 59 57 01-00  00 00 00 00 00 00 00  $...`YW.........
03bb7628  00 00 00 00 00 00 00 00-00 00 00 00 00 00  00 00  ................
03bb7638  00 00 00 00 00 00 00 00-00 00 00 00 00 00  00 00  ................
03bb7648  00 00 00 00 60 59 57 01-00 00 00 00 00 00  00 00  ....`YW.........
03bb7658  01 00 00 00 00 00 00 00-00 00 00 00 00 00  00 00  ................
03bb7668  ff ff ff ff ff ff ff ff-00 00 00 00 00 00  00 00  ................
eax=03bb0000  ebx=00000023ecx=00000020 edx=02000000  esi=03bb0948 edi=03bb0000
eip=315eb380  esp=00127b9c ebp=00128124 iopl=0  nv up ei pl nz na pe cy
cs=001b  ss=0023   ds=0023  es=0023  fs=003b   gs=0000   efl=00000207
wwlib!wdGetApplicationObject+0x2977a:
315eb380  e968c8a500  jmp  wwlib!DllCanUnloadNow+0x5598ab  (32047bed)
0:000> dps  1575960

之后將覆蓋我們關心的偏移為0x761c處的值0x01575960,而該值為mso模塊創建的一個對象指針,覆蓋完成后該值被替換成了0x09c00c0c。

最終“0x40”字節的數組內容如下:

這些附加的字節又從哪里來呢?由于有針對RTF格式混淆技術的運用,現有工具無法滿足提取ole對象的目的,我們人工仔細分析了該RTF文檔發現,該RTF文檔包括如下幾個部分:

1)文件頭(被混淆過,會影響一些工具或者殺毒引擎的解析)
2)一個ocx控件(用于加載OTKLOADR、msvcr71等)
3)一個內嵌的word文檔(用于進行堆噴射)。0x09c00c0c就指向堆噴射的數據區域
4)關鍵控制字區域。(用于數組越界寫,劫持控制流)
5)overlay數據。(編碼payload和偽word文檔)

通過分析第4部分的關鍵控制字區域,我們看到了如下的敏感數據:

很明顯,數據源于控制字\dfrxst。查閱RTF格式文檔,相關說明如下:

該控制字用于構造RevsionMark相關的字符串,參數為字節。即構造unicode字符串也是以單字節的形式進行的。然而文檔中對控制字 \dfrxst 對應的內部字節數組是多長并未明確指出。詳細查看該部分其它的控制字,我們發現了一個類似的控制字有這樣的描述:

根據此處的描述我們推斷對于\dfrxst,內部分配的字節數組長度為0x20字節。然而在解析該控制字的代碼中,控制數組字節數的常量被認為是0x20(32)個Unicode字符,寫成了 0x20* sizeof(wchar_t),結果為0x40,大于內存分配的長度0x20,結果導致數組越界寫入。 之后進一步的分析我們發現,被0x09c00c0c替換掉的偏移0x761c處的對象與\shp控制字相關。因而該控制字在樣本中是必要的。還有兩個控制字\shpbxignore和\shpbyignore用于操作\shp對應的對象過程中執行流的調整(位于wwlib.31fd6d99處的函數調用中),以避免相關的邏輯執行導致對象數據構造復雜化。當然,這里樣本中這么做取決于作者開發漏洞利用的方法。我們調試發現,控制了\shp對象數據后,還有其它劫持控制流的路徑,本文不再詳述。

3. 原理及利用流程總結

Word(wwlib.dll)在解析RTF文檔的控制字 “\dfrxst”時發生內存越界寫,導致緊鄰的對象指針被覆蓋。通過堆噴射技術,精心構造被覆蓋的對象,可以達到劫持控制流,從而執行任意代碼的目的。CVE-2016-7193漏洞原理的偽碼表示如下:

#define MAX_CHARS 0x20
class CParserObj {
public:
    BYTE m_ByteArray[MAX_CHARS]; //offs 75f8h DWORD m_NrOfChars;//offs 7618h
    CXXObj *m_pShpObj; //offs 761ch
    ......
    RESULT ParseControlWord(BYTE ByteCode,PVOID Params); 
}
RESULT CParserObj:: ParseControlWord(BYTE ByteCode,PVOID Params) 
{
    ......;
    switch(ByteCode)
    {
    case BYTE_CODE_ dfrxst:
        if(m_NrOfChars < MAX_CHARS * sizeof(WCHAR) //0x40 {
            m_ByteArray[m_NrOfChars++] = (BYTE)Params; 
            }
        break; 
    case ......:
        break; 
    default:
        break; 
    }
return RESULT_ERROR_CODE; 
}

三、ROP 鏈、shellcode 和 payload 簡要分析

首先,樣本在劫持控制流后,首先運行ROP鏈(基于msvcr71構造)將shellcode所在內存區修改為可執行屬性,對應的代碼和ROP鏈的信息如下:

內存屬性修改成功后,接著跳入shellcode

然后執行解碼器解碼shellcode。該解碼器很簡單僅僅是xor解碼。

最后執行解碼后的shellcode,其功能包括:

1)暴力遍歷句柄,尋找當前進程中對應RTF文檔的句柄。
2)創建RTF文檔的內存映射。
3)通過 egg hunt 技術定位位于RTF文檔Overlay部分的大型shellcode,并跳入執行,加載執行payload。

本文分析的Payload中包含一個正常doc文件用于覆蓋當前文檔迷惑用戶和一個要釋放的商業遠控木馬用于控制目標主機。當然,這里的payload可以很方便地替換成其它的惡意程序,滿足黑客個性化的需求。

四、結語

如今越來越多的APT攻擊使用Office套件中的Nday甚至0day漏洞進行攻擊,雖然微軟提供了該漏洞相應的修復補丁,但大部分用戶對于此類應用補丁的不重視造成了漏洞威脅依然存在。百度安全實驗室建議用戶提高安全意識,及時更新如Office、Flash、瀏覽器等常被漏洞利用的應用程序,對于安全性未知的程序應謹慎執行。

參考鏈接:

1、微軟 MS16-121 安全公告 https://technet.microsoft.com/library/security/ms16-121

2、exploit生成器的相關信息 http://www.tuicool.com/articles/BNnqArU https://www.youtube.com/watch?v=D3hwTBD0xE4

3、RTF官方文檔 https://www.microsoft.com/en-us/download/details.aspx?id=10725


Paper 本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/288/