手把手教你如何構(gòu)造Office漏洞POC(以CVE-2012-0158為例)

下面小編為大家介紹office漏洞CVE-2012-0158就憑借其經(jīng)典、通用又穩(wěn)定的漏洞利用經(jīng)常出現(xiàn)在各種報告中,詳細的講解這個漏洞的原理,以及如何基于原理手動構(gòu)造出可利用的POC樣本。
漏洞原理關(guān)于本漏洞原理,網(wǎng)上有各種分析文章,一般都基于實例樣本來定位漏洞的二進制代碼并分析原理,這里不作詳細的分析過程,直接給出漏洞成因,后面也有少部分的調(diào)試演示。這個漏洞發(fā)生在office的一個組件MSCOMCTL.OCX,多個版本office的該模塊都存在這個漏洞,本文的測試環(huán)境均以WINXP+office2007為例。MSCOMCTL.OCX這個漏洞模塊是office解析activeX控件用到的一個動態(tài)庫,如果一個office文檔中包含activeX這類控件元素的話,比如按鈕、列表、樹形控件等,當文檔通過office打開時MSCOMCTL.OCX就會被自動載入office程序的進程空間被調(diào)用來解析和顯示控件。
本漏洞屬于經(jīng)典緩沖區(qū)溢出漏洞里的棧內(nèi)存拷貝溢出漏洞,當office解析到一個被構(gòu)造好的控件(以ListView列表控件為例),會發(fā)生棧內(nèi)存越界拷貝。以下?;厮菔疽鈭D可以代表本漏洞的發(fā)生過程:
可以看出,Excel在解析ListView控件的時候,讀取并加載了控件的數(shù)據(jù)流,加載數(shù)據(jù)流的過程中會調(diào)用到一個內(nèi)部函數(shù)ReadBytesFromStreamPadded,該函數(shù)的功能類似于memcpy內(nèi)存拷貝函數(shù),根據(jù)參數(shù)從指定內(nèi)存拷貝指定大小數(shù)據(jù)到目標內(nèi)存。但仔細往上跟蹤就會發(fā)現(xiàn),漏洞并不是出現(xiàn)在這個函數(shù)里,而是出現(xiàn)在CObj::load這個函數(shù),下面分析一下這個函數(shù)如何出現(xiàn)的漏洞,先貼上IDA關(guān)于這個函數(shù)的偽代碼:
int __stdcall CObj__Load( int a1, void *lpMem)
{
int result; // eax@1
void *v3; // ebx@1
int v4; // esi@4
int v5; // [sp+Ch] [bp-14h]@1
SIZE_T dwBytes; // [sp+14h] [bp-Ch]@3
int v7; // [sp+18h] [bp-8h]@4
int v8; // [sp+1Ch] [bp-4h]@8
v3 = lpMem;
result = ReadBytesFromStreamPadded(&v5, lpMem, 0xCu ); //第一次正??截?,讀取數(shù)據(jù)頭
if ( result >= 0 )
{
if ( v5 == 'jboC' && dwBytes >= 8 ) //漏洞觸發(fā)條件
{
v4 = ReadBytesFromStreamPadded(& v7, v3, dwBytes); //第二次拷貝,此處調(diào)用必然越界
if ( v4 >= 0 )
{
if ( ! v7 )
goto LABEL_8;
lpMem = 0;
v4 = ReadBstrFromStreamPadded(( UINT)&lpMem, (int )v3);
if ( v4 >= 0 )
{
CObj__SetKey((BSTR) lpMem);
SysFreeString((BSTR) lpMem);
LABEL_8:
if ( v8 )
v4 = ReadVariantFromStream(( struct tagVARIANT *)(a1 + 20) , (struct IStream *) v3);
return v4;
}
}
return v4;
}
result = 2147549183;
}
return result;
}
CObj::Load,顧名思義,是CObj對象加載的方法,需要從內(nèi)存里讀取對象數(shù)據(jù),所以一開始便從數(shù)據(jù)流里讀取了0x0c個字節(jié)到臨時變量v5中。接著判斷v5的前4個字節(jié)是否為”Cobj”來檢測是否為要加載的對象類型,并且dwBytes這個變量如果大于8才進行下一步的加載。注意到,dwBytes 這個變量是讀取那0x0c個字節(jié)的時候一起讀取進來的,因為從IDA的變量備注中可以看出dwBytes =[bp-0x0c]落在v5=[bp-0x14]和v5+0x0c=[bp-0x08]的內(nèi)存區(qū)間中,所以這里的一個關(guān)鍵是dwBytes的值可以通過修改數(shù)據(jù)流被控制。
再看下一步,同樣從原來的數(shù)據(jù)流讀取dwBytes個字節(jié)到臨時變量v7中,v7=[bp-0x08],而dwBytes此時卻大于8,所以這個讀取拷貝必然會覆蓋ebp,發(fā)生越界拷貝,形成棧溢出漏洞。根據(jù)此分析可以推測,正常情況從控件數(shù)據(jù)讀取出來dwBytes值不會大于8,因為如果大于8的話必然導(dǎo)致棧拷貝異常,那么這個漏洞早就被測試出來了。而且通過IDA里查看此函數(shù)的交叉引用會發(fā)現(xiàn),這個函數(shù)似乎作用并不大,都是在加載特定幾個控件的開頭被調(diào)用了一下。所以,我懷疑這個漏洞不是所謂的嚴重的失誤,把本來的小于8寫成了大于8,就是微軟故意留下來的后門漏洞。
構(gòu)造觸發(fā)漏洞的POC
經(jīng)過上面的原理分析,office在解析ListView控件時調(diào)用了漏洞函數(shù)CObj::Load,該函數(shù)在加載CObj對象時根據(jù)可被篡改的dwBytes讀取指定大小的內(nèi)存數(shù)據(jù)到8字節(jié)的臨時變量,且校驗大小時存在后門嫌疑,導(dǎo)致可被利用的緩沖區(qū)溢出漏洞。為了檢驗我們的分析是否正確,下面我們參考上面的?;厮穲D構(gòu)造可觸發(fā)此漏洞的Excel文檔。
首先Excel文檔里需要存在一個ListView控件,可以通過Excel軟件里面的開發(fā)者工具添加,添加完后相當于文檔里嵌入了一個空的ListView對象。
接著,還需要往這個對象里面添加ListItems以及ListItem子對象,這樣就能使Excel程序調(diào)用到CObj::Load函數(shù)。但是這里有個問題,ListItem對象無法直接通過Excel操作添加,Excel只能通過ListView控件的屬性添加列表標題,沒有直接辦法添加列表內(nèi)容。解決辦法是通過編寫Excel支持的VBA程序代碼,編譯生成一個ListItem對象。
但是這樣帶來另外一個問題,就是如果文檔里邊存在VBA這類宏代碼,Excel會默認禁止代碼執(zhí)行,這樣依舊解析不到ListView控件里的ListItem對象,一個簡單的解決辦法就是先寫好代碼編譯運行后生成了初始化好的ListView控件,再把所有的生成代碼刪除后保存即可,因為宏代碼會被阻止執(zhí)行而控件對象不會被阻止解析。
下一步,只要將保存好的文檔通過十六進制編輯器打開,定位到CObj對象的數(shù)據(jù),修改偏移量為8的dwBytes值為大于8的數(shù)值就能觸發(fā)漏洞。事實上只修改那一個值還無法看到漏洞觸發(fā)的效果,原因是拷貝函數(shù)ReadBytesFromStreamPadded還會接著校驗dwBytes的值,幸運的是該校驗只是從要拷貝的數(shù)據(jù)頭部讀取另一個dwBytes的值,檢驗兩個值是否相等,所以我們只需要把對象數(shù)據(jù)里的那個數(shù)值也修改成相應(yīng)的大小就可以通過校驗從而觸發(fā)漏洞。
觸發(fā)漏洞后,由于我們只是簡單的用一些隨機數(shù)據(jù)覆蓋ebp和相關(guān)函數(shù)返回地址,所以Excel最終優(yōu)雅的返回一個我們想要看到的程序錯誤提示框。
漏洞利用
現(xiàn)在,我們得到了一個可以觸發(fā)的棧緩沖區(qū)溢出漏洞,下面要怎么利用這個漏洞來做一些事情就各顯神通了,本文還是給大家彈個計算器來拋磚引玉。
通過上面構(gòu)造的POC,我們可以修改兩個dwBytes的值和后面的數(shù)據(jù)來控制運行棧的內(nèi)存布局。為了更好的編排數(shù)據(jù),最好通過調(diào)試樣本去動態(tài)修改數(shù)據(jù)以達到目的,最后只要將內(nèi)存里編排好的數(shù)據(jù)拷貝到文檔對應(yīng)的部分即可。而調(diào)試過程中,我們的第一目標自然是獲取程序控制器,控制eip,這里一般是通過覆蓋函數(shù)返回值或SEH鏈指針來實現(xiàn)。由于MSCOMCTRL.DLL沒有開啟GS保護,我們采取最簡單的覆蓋函數(shù)返回值即可控制eip。然而,為了使程序順利的走到返回值,我們還需要修改數(shù)據(jù),滿足一些返回條件,控制程序流程,使之不進入復(fù)雜的函數(shù)或指令操作集,避免因棧被破壞導(dǎo)致一些異常的發(fā)生。
一旦程序順利到達返回地址,我們便可以根據(jù)運行環(huán)境做各種事情,比如構(gòu)造一個rop鏈繞過dep保護,或者直接跳轉(zhuǎn)到??臻g執(zhí)行代碼,這些對于一個熟悉漏洞利用的人來說都是輕車熟路了。這里有個需求,就是棧內(nèi)存數(shù)據(jù)需要有足夠大小的空間來容納無論是rop鏈還是shellcode,所以需要增加一下ListView控件的數(shù)據(jù)規(guī)模,簡單的方法就是添加ListItem的時候把字符串寫的足夠長。
當所有的必要條件都具備的時候,我們的代碼就可以放進棧里執(zhí)行了,這里我簡單使用一個通用的跳轉(zhuǎn)地址直接跳轉(zhuǎn)至棧內(nèi)存代碼執(zhí)行,由于XP+office 2007默認不開啟dep保護,所以我的環(huán)境可以順利彈出計算器。
關(guān)于更多的需求比如如何編寫rop鏈繞過office2010以上默認開啟的dep保護,我將會在接下去其他的漏洞分享中陸續(xù)展開。另外,限于本文是文稿形式,更詳細的視頻演示也可以訪問本人的博客地址(搜索維一零小站)進行參考。
總結(jié)通過本文詳細的分析,我們了解到這個漏洞的原理和危害性,由于MSCOMCTL.OCX是基礎(chǔ)動態(tài)庫,影響的應(yīng)用軟件自然比較多,除了office全套裝外,sql和其他第三方應(yīng)用軟件,只要存在使用該漏洞庫的地方,都有可能被利用。而利用的方法和本文一樣,都離不開漏洞的原理,構(gòu)造的“畸形”數(shù)據(jù)必須要通過漏洞函數(shù)的檢驗流程,才能最終繞過程序本身的限制,奪取程序的控制權(quán)。
相關(guān)文章
- SSL(安全套接字層)逐漸被大家所重視,但是最不能忽視的也是SSL得漏洞,隨著SSL技術(shù)的發(fā)展,新的漏洞也就出現(xiàn)了,下面小編就為大家介紹簡單七步教你如何解決關(guān)鍵SSL安全問題2016-09-23
- 偶爾在網(wǎng)上看到這些,拿來和大家一塊看看,也好讓各個站長懂得保護自己的網(wǎng)站2012-10-16
- Ewebeditor編輯器目前分為asp,aspx,php,jsp四種程序,各類ewebeditor版本很多,功能強大頗收使用者喜愛,在國內(nèi)使用極為廣泛。2010-05-13
eWebEditor 6.2 目錄遍歷漏洞(asp/browse.asp)
最新eWebEditor 6.2版本存在目錄遍歷漏洞,漏洞頁面asp/browse.asp,可通過漏洞遍里特定目錄下的所有文件列表.2010-05-13- 以下是search.inc.php 文件漏洞利用代碼VBS版 [code] Dim strUrl,strSite,strPath,strUid showB() Set Args = Wscript.Arguments If Args.Count <> 3 Then Sho2009-04-18
- 最新dedecms 5.6的注入代碼: http://www.dedecms.com/plus/rss.php?tid=1&_Cs[][1]=1&_Cs[2%29%29%20AND%20%22%27%22%20AND%20updatexml%281,%28SELECT%22011-03-11
查找Centos Linux服務(wù)器上入侵者的WebShell后門
服務(wù)器被掛馬或被黑的朋友應(yīng)該知道,黑客入侵web服務(wù)器的第一目標是往服務(wù)器上上傳一個webshell,有了webshell黑客就可以干更多的事 情2012-07-10- 影響2.5.x和2.6.x,其他版本未測試 goods_script.php 44行: [code] if (empty($_GET['type'])) { ... } elseif ($_GET['type'] == 'collection') { ... } $sql2009-04-18
- 漏洞無處不在,它是在硬件、軟件、協(xié)議的具體實現(xiàn)或系統(tǒng)安全策略上存在的缺陷,從而可以使攻擊者能夠在未授權(quán)的情況下訪問或破壞系統(tǒng)2016-09-29