手把手教你如何構造Office漏洞POC(以CVE-2012-0158為例)
下面小編為大家介紹office漏洞CVE-2012-0158就憑借其經典、通用又穩(wěn)定的漏洞利用經常出現在各種報告中,詳細的講解這個漏洞的原理,以及如何基于原理手動構造出可利用的POC樣本。
漏洞原理關于本漏洞原理,網上有各種分析文章,一般都基于實例樣本來定位漏洞的二進制代碼并分析原理,這里不作詳細的分析過程,直接給出漏洞成因,后面也有少部分的調試演示。這個漏洞發(fā)生在office的一個組件MSCOMCTL.OCX,多個版本office的該模塊都存在這個漏洞,本文的測試環(huán)境均以WINXP+office2007為例。MSCOMCTL.OCX這個漏洞模塊是office解析activeX控件用到的一個動態(tài)庫,如果一個office文檔中包含activeX這類控件元素的話,比如按鈕、列表、樹形控件等,當文檔通過office打開時MSCOMCTL.OCX就會被自動載入office程序的進程空間被調用來解析和顯示控件。
本漏洞屬于經典緩沖區(qū)溢出漏洞里的棧內存拷貝溢出漏洞,當office解析到一個被構造好的控件(以ListView列表控件為例),會發(fā)生棧內存越界拷貝。以下棧回溯示意圖可以代表本漏洞的發(fā)生過程:
可以看出,Excel在解析ListView控件的時候,讀取并加載了控件的數據流,加載數據流的過程中會調用到一個內部函數ReadBytesFromStreamPadded,該函數的功能類似于memcpy內存拷貝函數,根據參數從指定內存拷貝指定大小數據到目標內存。但仔細往上跟蹤就會發(fā)現,漏洞并不是出現在這個函數里,而是出現在CObj::load這個函數,下面分析一下這個函數如何出現的漏洞,先貼上IDA關于這個函數的偽代碼:
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 ); //第一次正??截?,讀取數據頭
if ( result >= 0 )
{
if ( v5 == 'jboC' && dwBytes >= 8 ) //漏洞觸發(fā)條件
{
v4 = ReadBytesFromStreamPadded(& v7, v3, dwBytes); //第二次拷貝,此處調用必然越界
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對象加載的方法,需要從內存里讀取對象數據,所以一開始便從數據流里讀取了0x0c個字節(jié)到臨時變量v5中。接著判斷v5的前4個字節(jié)是否為”Cobj”來檢測是否為要加載的對象類型,并且dwBytes這個變量如果大于8才進行下一步的加載。注意到,dwBytes 這個變量是讀取那0x0c個字節(jié)的時候一起讀取進來的,因為從IDA的變量備注中可以看出dwBytes =[bp-0x0c]落在v5=[bp-0x14]和v5+0x0c=[bp-0x08]的內存區(qū)間中,所以這里的一個關鍵是dwBytes的值可以通過修改數據流被控制。
再看下一步,同樣從原來的數據流讀取dwBytes個字節(jié)到臨時變量v7中,v7=[bp-0x08],而dwBytes此時卻大于8,所以這個讀取拷貝必然會覆蓋ebp,發(fā)生越界拷貝,形成棧溢出漏洞。根據此分析可以推測,正常情況從控件數據讀取出來dwBytes值不會大于8,因為如果大于8的話必然導致??截惍惓?,那么這個漏洞早就被測試出來了。而且通過IDA里查看此函數的交叉引用會發(fā)現,這個函數似乎作用并不大,都是在加載特定幾個控件的開頭被調用了一下。所以,我懷疑這個漏洞不是所謂的嚴重的失誤,把本來的小于8寫成了大于8,就是微軟故意留下來的后門漏洞。
構造觸發(fā)漏洞的POC
經過上面的原理分析,office在解析ListView控件時調用了漏洞函數CObj::Load,該函數在加載CObj對象時根據可被篡改的dwBytes讀取指定大小的內存數據到8字節(jié)的臨時變量,且校驗大小時存在后門嫌疑,導致可被利用的緩沖區(qū)溢出漏洞。為了檢驗我們的分析是否正確,下面我們參考上面的棧回朔圖構造可觸發(fā)此漏洞的Excel文檔。
首先Excel文檔里需要存在一個ListView控件,可以通過Excel軟件里面的開發(fā)者工具添加,添加完后相當于文檔里嵌入了一個空的ListView對象。
接著,還需要往這個對象里面添加ListItems以及ListItem子對象,這樣就能使Excel程序調用到CObj::Load函數。但是這里有個問題,ListItem對象無法直接通過Excel操作添加,Excel只能通過ListView控件的屬性添加列表標題,沒有直接辦法添加列表內容。解決辦法是通過編寫Excel支持的VBA程序代碼,編譯生成一個ListItem對象。
但是這樣帶來另外一個問題,就是如果文檔里邊存在VBA這類宏代碼,Excel會默認禁止代碼執(zhí)行,這樣依舊解析不到ListView控件里的ListItem對象,一個簡單的解決辦法就是先寫好代碼編譯運行后生成了初始化好的ListView控件,再把所有的生成代碼刪除后保存即可,因為宏代碼會被阻止執(zhí)行而控件對象不會被阻止解析。
下一步,只要將保存好的文檔通過十六進制編輯器打開,定位到CObj對象的數據,修改偏移量為8的dwBytes值為大于8的數值就能觸發(fā)漏洞。事實上只修改那一個值還無法看到漏洞觸發(fā)的效果,原因是拷貝函數ReadBytesFromStreamPadded還會接著校驗dwBytes的值,幸運的是該校驗只是從要拷貝的數據頭部讀取另一個dwBytes的值,檢驗兩個值是否相等,所以我們只需要把對象數據里的那個數值也修改成相應的大小就可以通過校驗從而觸發(fā)漏洞。
觸發(fā)漏洞后,由于我們只是簡單的用一些隨機數據覆蓋ebp和相關函數返回地址,所以Excel最終優(yōu)雅的返回一個我們想要看到的程序錯誤提示框。
漏洞利用
現在,我們得到了一個可以觸發(fā)的棧緩沖區(qū)溢出漏洞,下面要怎么利用這個漏洞來做一些事情就各顯神通了,本文還是給大家彈個計算器來拋磚引玉。
通過上面構造的POC,我們可以修改兩個dwBytes的值和后面的數據來控制運行棧的內存布局。為了更好的編排數據,最好通過調試樣本去動態(tài)修改數據以達到目的,最后只要將內存里編排好的數據拷貝到文檔對應的部分即可。而調試過程中,我們的第一目標自然是獲取程序控制器,控制eip,這里一般是通過覆蓋函數返回值或SEH鏈指針來實現。由于MSCOMCTRL.DLL沒有開啟GS保護,我們采取最簡單的覆蓋函數返回值即可控制eip。然而,為了使程序順利的走到返回值,我們還需要修改數據,滿足一些返回條件,控制程序流程,使之不進入復雜的函數或指令操作集,避免因棧被破壞導致一些異常的發(fā)生。
一旦程序順利到達返回地址,我們便可以根據運行環(huán)境做各種事情,比如構造一個rop鏈繞過dep保護,或者直接跳轉到??臻g執(zhí)行代碼,這些對于一個熟悉漏洞利用的人來說都是輕車熟路了。這里有個需求,就是棧內存數據需要有足夠大小的空間來容納無論是rop鏈還是shellcode,所以需要增加一下ListView控件的數據規(guī)模,簡單的方法就是添加ListItem的時候把字符串寫的足夠長。
當所有的必要條件都具備的時候,我們的代碼就可以放進棧里執(zhí)行了,這里我簡單使用一個通用的跳轉地址直接跳轉至棧內存代碼執(zhí)行,由于XP+office 2007默認不開啟dep保護,所以我的環(huán)境可以順利彈出計算器。
關于更多的需求比如如何編寫rop鏈繞過office2010以上默認開啟的dep保護,我將會在接下去其他的漏洞分享中陸續(xù)展開。另外,限于本文是文稿形式,更詳細的視頻演示也可以訪問本人的博客地址(搜索維一零小站)進行參考。
總結通過本文詳細的分析,我們了解到這個漏洞的原理和危害性,由于MSCOMCTL.OCX是基礎動態(tài)庫,影響的應用軟件自然比較多,除了office全套裝外,sql和其他第三方應用軟件,只要存在使用該漏洞庫的地方,都有可能被利用。而利用的方法和本文一樣,都離不開漏洞的原理,構造的“畸形”數據必須要通過漏洞函數的檢驗流程,才能最終繞過程序本身的限制,奪取程序的控制權。
版權聲明:本站文章來源標注為YINGSOO的內容版權均為本站所有,歡迎引用、轉載,請保持原文完整并注明來源及原文鏈接。禁止復制或仿造本網站,禁止在非maisonbaluchon.cn所屬的服務器上建立鏡像,否則將依法追究法律責任。本站部分內容來源于網友推薦、互聯網收集整理而來,僅供學習參考,不代表本站立場,如有內容涉嫌侵權,請聯系alex-e#qq.com處理。
關注官方微信