CVE-2017-11882及利用樣本分析
1.本文由複眼小組ERFZE師傅原創
2.本文略微偏向基礎,首先介紹了該漏洞的成因,並且分析了該漏洞在蔓靈花,摩訶草,響尾蛇APT組織用於實際攻擊活動中的詳細除錯過程
3.本文全文字數共2234字,圖片95張 預計閱讀時間14分鐘
0x01 漏洞描述
成因:Windows的公式編輯器EQNEDT32.EXE
讀入包含MathType的OLE資料,在拷貝公式字型名稱時沒有對名稱長度進行校驗,使得攻擊者可以通過刻意構造的資料內容覆蓋棧上的函式返回地址,從而劫持程式流程。
影響版本:Microsoft Office 2007 Service Pack 3, Microsoft Office 2010 Service Pack 2, Microsoft Office 2013 Service Pack 1, Microsoft Office 2016
POC:https://github.com/Ridter/CVE-2017-11882
0x02 漏洞分析
筆者復現及分析環境:Windows 7 Service Pack 1、Microsoft Office 2010、x32dbg、IDA 7.0
EQUATION.exe
存在:

設定登錄檔項HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\EQNEDT32.EXE
:

Debugger
鍵值為x32dbg路徑。
生成POC:

開啟該文件,於WinExec()
函式處設斷:

成功斷下後,檢視棧中返回地址:

繼續向上檢視棧,發現呼叫WinExec()
的函式:

通過IDA分析sub_4115A7
功能:

跟進sub_41160F
檢視:

未校驗長度,直接使用strcpy()
函式,此處應該就是漏洞觸發位置。進一步確定具體位置:

於0x411658
處設斷,重新執行。第二次成功斷下後,檢視ESI暫存器指向記憶體內容:

此時ECX暫存器值為0xC,即複製48個位元組到EDI暫存器指向記憶體,而var_28
實際大小隻有36個位元組:

到達函式結束處:

leave
指令執行完畢後,棧頂0x18F1D0
處值為0x430C12
,即呼叫WinExec()
。而傳遞引數正是0x18F350
指向記憶體中的cmd指令:

成功彈出計算器:

下面對使用到的POC進行簡要分析。各變數含義由命名可知,RTF文件格式並非本文重點,如讀者此前對RTF文件格式沒有了解,建議先閱讀文末參考連結中有關RTF文件格式的文章後再看POC原始碼。

首先判斷命令長度是否小於43,而43這個數字是因為:

上圖選中部分是插入命令處,具體偏移由POC中COMMAND_OFFSET(0x949*2)
變數給出。
將命令插入到構造資料中之後,函式返回拼接好的OLE。下面將OLE嵌入到RTF文件中:

0x03 摩訶草(APT-C-09)組織某樣本分析
MD5:0D38ADC0B048BAB3BD91861D42CD39DF
於0x411658
處設斷,在第二次斷下時,各暫存器值如下:

繼續執行到函式結束處leave
指令:

0x18F230
地址處值0x430C47
即覆蓋後的函式返回地址:

而該地址處指令是ret
,有些出乎意料。繼續向下執行,來到0x18F3B0
處,正是0x18F234
地址處值:

這方才是構造者意欲執行的指令。經過藍色方框中的一系列運算後,EBX指向是真正的Shellcode:

上述內容均可在OLE中檢視(路徑\xl\embeddings
):


將OLE0x1000
—0x1520
中資料複製到一bin檔案後,通過IDA檢視。sub_247
功能如下:

該函式接受的第二個引數即上文提到的EBX指向地址,於OLE中位置是0x1040
,而0x1040
+0x558
處內容如下:

故該函式第一個功能是修正PE檔案頭。第二個功能流程如下:




將0x1040
+0x558
後的PE檔案資料寫入到%APPDATA%\MSBuild.exe
中。第三個功能流程如下:



將%APPDATA%\MSBuild.exe
寫入登錄檔run項鍵值lollipop
中。
0x04 響尾蛇(SideWinder)組織某樣本分析
將文件拖進WinHex檢視:

可以看出該文件實質是一RTF格式文件。
用rtfobj.py
分析如下:

Package後文會提到,先來看其CVE-2017-11882利用部分。
同樣是第二次斷下時:

其後的執行流程與上一樣本相似:


經過綠色方框中的一系列運算後,呼叫GlobalLock()
函式,傳遞引數如下:

接下來跳轉到GlobalLock()
函式返回記憶體區域中:

經過兩次call
呼叫:


修正記憶體中的字串:

接下來定址kernel32.dll
:

其所呼叫的函式功能如下:

兩次call
呼叫之後:


其功能為返回某函式呼叫地址,此次是LoadLibrayW()
:


接下來,返回GetProcAddress()
呼叫地址:


繼續call
呼叫:

其後流程如圖所示:



下面將字串解密,並覆蓋原CommandLine內容:


執行完結果如下:

最後實際執行部分:
javascript:eval("sa=ActiveXObject;ab=new sa(\"Scripting.FileSystemObject\");
eval(ab.OpenTextFile(ab.GetSpecialFolder(2)+\"\\\\1.a\",1).ReadAll());windowclose()")
其後呼叫RunHTMLApplication()
:





1.a就是之前提到RTF文件中的Package,其實質是一JS檔案:


最後,其執行結果大體如下圖所示:

0x05 蔓靈花(Bitter)組織某樣本分析
通過遠端模板注入的方式下載一RTF格式文件:

拖進WinHex檢視,可以確認其格式為RTF文件格式:

新增副檔名後,開啟該文件。同樣是于于0x411658
處第二次斷下時:



跳轉之後經過綠色方框中一系列計算,接著跳轉:

fldpi
將π的值載入到FPU堆疊:

執行完後fpu_instruction_pointer
指向fldpi
指令,其後的fnstenv
指令將FpuSaveState
結構體儲存到esp-0xC
處:

如此一來,pop ebp
後EBP暫存器的值是fpu_instruction_pointer
——fldpi
指令位置:

由EBP計算出需要解密的資料起始位置,EDX中儲存的是資料長度(0x315):

接著執行解密後的指令:


跳轉後,執行相應指令,接下來call
呼叫:

sub_562B2F
功能是獲取指定的系統函式呼叫地址,此次是kernel32.VirtualAlloc()
:


之後呼叫VirtualAlloc()
申請記憶體空間:

向申請的記憶體空間中寫入資料:

呼叫sub_562B2F
獲取kernel32.Wow64DisableWow64FsRedirection()
呼叫地址:

LoadLibrary(shell32)
:

傳遞引數給sub_562B2F
,獲取shell32.ShellExcute()
呼叫地址:


LoadLibrary(urlmon)
:

獲取urlmon.URLDownloadToFile()
呼叫地址:


呼叫URLDownloadToFile()
,其傳遞引數如圖:


讀取檔案:


由於沒有獲取到檔案,計算出的EBX值錯誤:

故至此結束。
0x06 參考連結
Office惡意檔案解析與混淆研究 -https://zhuanlan.zhihu.com/p/31345299
https://github.com/Ridter/CVE-2017-11882
Office檔案格式基礎知識 -https://www.anquanke.com/post/id/175548