日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Hacking Team Flash 0day漏洞学习笔记

發(fā)布時間:2024/4/15 编程问答 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Hacking Team Flash 0day漏洞学习笔记 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

? ? ??周日的夜晚,與囧桑下載下來Hacking Team之前爆出的flash 0day漏洞,懷著緊張激動的心情,在自己的機子上做了實驗,經(jīng)測試,在我的虛擬機(一個sp3的XP,貌似沒裝Flash)上根本跑不出Flash漏洞,在我的Win10宿主機上跑,貌似剛升級的Flash,洞被補上了,也不能用。最后在囧桑的Win7機子上實驗,點擊了網(wǎng)頁上的按鈕,出現(xiàn)了測試用的程序--計算器。那一瞬間老激動了。

言歸正傳,下面開始Hacking Team的Flash 0day漏洞學(xué)習(xí)。感謝Hacking Team 公司的挖洞專家們這么敬業(yè),給了一個有注釋有README的項目,讓我這初學(xué)者表示可以慢慢啃了。 漏洞原理分析 漏洞成因在于Flash對ByteArray內(nèi)部的buffer使用不當(dāng),而造成了Use After Free漏洞,被釋放后的內(nèi)存區(qū)域可以立即被新創(chuàng)建的Vector對象重用,從而出現(xiàn)UaF漏洞。 漏洞利用代碼分析 MyClass類 核心類,用于觸發(fā)UaF漏洞。 MyClass1類 是ByteArray的子類,其中包含4個對象。 MyClass2類 是MyClass1類的子類,也是ByteArray的子類,有四個對象,且用重復(fù)且大量的屬性來擴充MyClass2類的大小。 本人新手,將對整個代碼進行分析,以免自己以后忘記。 首先是繪制整個flash區(qū)域的代碼。紅框框里將點擊事件與函數(shù)btnClickHandler進行綁定。 隨后看看這個btnClickHandler函數(shù)。 關(guān)鍵就是這個TryExpl函數(shù),它實際上就是觸發(fā)整個漏洞的關(guān)鍵,相當(dāng)于整個Flash利用程序的入口點。這個函數(shù)的主要目的是為了破壞Vector.<uint>的長度值,再接著查找破壞后的內(nèi)存區(qū)域,尋找受破壞的Vector對象,然后根據(jù)操作系統(tǒng)的位數(shù),以及操作系統(tǒng)的特征決定到底執(zhí)行哪個PayLoad代碼。 首先定義一個長為90的數(shù)組a,數(shù)組以3個元素為一組,元素1為一個MyClass2的實例,元素2為一個ByteArray即字符數(shù)組,當(dāng)new一個ByteArray時,AVM將會為數(shù)組分配0x1000大小的內(nèi)存(相當(dāng)于操作系統(tǒng)的內(nèi)存申請機制,每次申請大小為0x1000,為一個內(nèi)存區(qū)塊),隨后這個數(shù)組的長度設(shè)置為0xfa0。而a這個數(shù)組里將會有30個ByteArray數(shù)組。 ? ?? 然后數(shù)組a的末尾開始修改倒數(shù)第二個ByteArray,行為是將一個MyClass的對象賦給那個ByteArray的第四個元素,這個元素類型為Byte而MyClass是個對象,所以AVM會試圖將其轉(zhuǎn)化為Byte類型,從而調(diào)用MyClass類中的valueOf方法。 valueOf函數(shù)中new一個5個元素的數(shù)組_va,隨后修改靜態(tài)變量ByteArray數(shù)組_ba的長度為0x1100,這是關(guān)鍵,由于這個操作會觸發(fā)ByteArray的緩沖區(qū)buffer的重新分配(原來這個buffer長度為0xfa0,占地0x1000,現(xiàn)在長度要求為0x1100了,所以要重新分配內(nèi)存),舊的buffer區(qū)域被釋放。緊接著分配5個Vector.<uint>對象,每個對象長度為0x3f0,占地0x1000字節(jié),且Vector對象的長度值存儲于Vector緩沖區(qū)的前四位區(qū)域。這時分配的區(qū)域?qū)噲D使用之前已經(jīng)釋放的ByteArray _ba的內(nèi)存區(qū)域。而_va[x]指向的就是之前_ba的地址,且該地址仍然在這個函數(shù)的調(diào)用方的棧中存儲,即esi這個寄存器中存儲著_ba[3]的地址,而這個地址現(xiàn)在實質(zhì)上已經(jīng)指向了_va[?]這個Vector的第四位,返回的0x40就被寫到了這個內(nèi)存中了。隨后的_va[x]前四位如下所示。(具體哪個被分配到了_ba釋放的內(nèi)存不得而知,但是只有出現(xiàn)UaF的_va[x]才會出現(xiàn)異常的長度,從而被檢測。) _va[x]: ? ? f0 ? ? 03 ? ? 00 ? ? 00 ? ? => ? ? va[0]: ? ? f0 ? ? 03 ? ? 00 ? ? 40 那么以后再去讀取這個Vector的長度就會錯誤的返回一個超巨大的長度0x400003f0。? ? ? ?繼續(xù)對TryExpl進行分析,因為_ba[3]已經(jīng)指向在MyClass.valueOf里重新分配的區(qū)域,所以不出意外這里返回_ba[3]的值是0不會變化。接著對_va中的每個Vector.<uint>對象進行檢測,找到那個被我們剛才改了長度值的Vector的首地址。再接著令k等于1094,相當(dāng)于一個足夠遠離首地址的位置,檢查v[k]中的內(nèi)容是否為0x11223344,即該指針是否還處于MyClass2的范圍內(nèi),并逐漸接近Vector的首地址。當(dāng)找到非0x11223344的地址時,該區(qū)域就是MyClass2的a0這個變量的位置,這個位置為MyClass2的id。之后令這個位置為MyCLass2實例mc,改變mc的長度為0x123. ? ? ?隨后就是根據(jù)k走過的距離是不是大于30來確定是不是在64位系統(tǒng)上運行的程序,再確定系統(tǒng)類型,是win還是Mac來,32位還是64位。 ? ? ? PayLoad代碼分析
  • ? ? ?ShellWin64類 是MyClass的子類,是Win64上的PayLoad代碼,為的就是打開計算器程序。
  • ? ? ?ShellMac64類 是MyClass的子類,是Mac上的PayLoad代碼,為的也是打開計算器程序。
  • ? ? ?ShellWin32類 是MyClass的子類,是Win32上的PayLoad代碼,為的也是打開計算器程序。
ShellWin32 首先觀察ShellWin32的初始化操作,v是中間被我們修改的Vector向量,而v[k]則是MyClass2中的變量a0,那么v[k-4]則是MyClass2中的o1,即該MyClass2對象的實際地址,與0xfffff000相與可以獲得其前5位即該MyClass2對象所在的0x1000塊的首地址,這時減去0x1000就獲得了中間Vector的首地址,再加上8則是跳過了Vector頭部的8位到達了Vector中存儲值的首地址,即v[0]的實際地址,接著將該實際地址存入vAddr中。 這個vAddr作為實際地址相當(dāng)有用。 通過v[(address-vAddr)>>>2]就可以訪問任意地址內(nèi)存了,這個在ShellWin32中被封裝成了Get。 通過mc.o1=obj ;返回v[k-4]-1就可以返回任意對象的絕對地址了。即先將obj放入到MyClass2的o1中,再去讀取o1這個位置中的值,該值減一就是該對象的絕對地址。這個也在ShellWin32中被封裝成了GetAddr。 首先初始化,將一些參數(shù)存入ShellWin32的內(nèi)部變量中,隨后通過驗證v[vAddr-8]位置存儲的值和v中的長度是否一致,確保傳入的v和vAddr是否匹配。 隨后進入執(zhí)行函數(shù)。 第一部分是獲取shellcode這個Vector.<uint>對象的首地址,隨后獲取shellcode中的數(shù)據(jù)區(qū)地址。其中的_isDbg在MyClass中定義。 其中Vector實際存儲的緩沖區(qū)指針,即真正的shellcode位置在Release和Debug版分別放置于0x18和0x1c的位置。為了顧全所有版本,還注意到Flash11.4版本之前是不存在這個便宜區(qū)別的,11.4之后的Debug版才在緩沖區(qū)指針前加入了一個0x00000001字段。下圖中是Vector的內(nèi)存分布,左側(cè)是11.4之前的Release和Debug,右側(cè)是11.4以后的Release和Debug。不得不說HackTeam寫代碼為了保證向后兼容以及針對Release和Debug版本,也是做了很多工作的。 開啟ShellCode執(zhí)行權(quán)限 隨后進入獲得kernel32.VirtualProtect()地址的流程。 進入FindVP函數(shù)。 b是dll或者exe文件中的虛函數(shù)表指針。將b指針對齊0x10000,再減去0x400000,隨后減去_vAddr得到PE文件頭部,看看DOS_HEADER,(真的嗎,我也不清楚這里為何如此,有人知道的話請給我留言,么么噠~),隨后一路推導(dǎo)到達NT_HEADER,獲得了IMPORT_DIRECTORY導(dǎo)入目錄,在導(dǎo)入目錄中尋到了kernel32.dll。 隨后再在kernel32.dll中找到了VirtualProtect API的地址。 接著調(diào)用VirtualProtect開啟shellcode這段區(qū)域的執(zhí)行權(quán)限。 首先生成一個FunctionObject類的對象Payload,然后獲得該對象的地址。隨后的一段比較難以理解。剛開始以為要把AS3里的許多結(jié)構(gòu)體都擼明白才能算出偏移,其實沒這么蛋疼,看看Flash中的FunctionObject::AS3_call就全明白了。 1 int AS3_call(void *this, int thisArg, int *argv, int argc) 2 push ebx 3 push esi 4 mov esi, ecx 5 mov ecx, [esp+8+thisArg] 6 mov eax, [esi] 7 mov edx, [eax+8Ch] 8 push edi 9 push ecx 10 mov ecx, esi 11 call edx 12 mov ebx, eax 13 mov eax, [esi+8] 14 mov ecx, [eax+14h] 15 mov edx, [ecx+4] 16 mov eax, [esi] 17 mov edi, [edx+0B0h] 18 mov edx, [eax+90h] 19 lea ecx, [esp+0Ch+thisArg] 20 push ecx 21 mov ecx, esi 22 call edx 23 mov ecx, [esp+0Ch+argv] 24 mov eax, [eax] 25 mov edx, [edi] 26 mov edx, [edx+1Ch] 27 push ecx 28 mov ecx, [esp+10h+argc] 29 push ecx 30 push ebx 31 push eax 32 mov ecx, edi 33 call edx 34 pop edi 35 pop esi 36 pop ebx 37 retn 0Ch

?



Payload是個FunctionObject類型,最終對其調(diào)用call的時候最終到達FunctionObject::AS3_call,其內(nèi)部調(diào)用core()->exec->call跳轉(zhuǎn)到Payload對象JIT(Just In Time,即時編譯)出來的代碼。由于是FunctionObject和ExecMgr的繼承關(guān)系,可以通過自身結(jié)構(gòu)定位到ExeMgr的虛函數(shù)表。 在剛進入AS3_call時,ecx也就是隨后的esi指向了Payload對象,也就是esi=p(GetAddress(Payload))。參考上述匯編代碼中紅色字體部分,可知ExecMgr對象的虛函數(shù)表位于[[[[esi+8]+0x14]+4]+0xB0],偏移0處就是PayLoad的虛函數(shù)表,就是CallVP中的ptbl所指。后三行的三個Get指令表明,虛函數(shù)表的首地址ptbl的值存入p1中,需要執(zhí)行VirtualProtect的首地址存放于payload實際地址+0x1c位置,取出放于p2中,地址區(qū)域長度為xLen,存放于payload實際地址+0x20位置,取出存放于p3中。core->exec->call會牽涉一些其他虛函數(shù)的調(diào)用,所以以上CallVP對虛函數(shù)表上下共0x400字節(jié)全部備份。然后在被備份的那段內(nèi)存區(qū)域改寫0x1C處為VirtualProtect的地址,0x20處填寫需要改寫執(zhí)行權(quán)限的內(nèi)存區(qū)域地址長度。而args設(shè)置為一個存放了0x41個元素的數(shù)組(為什么是0x41,不該是0x40么,多個1不就是NO_access么)。 現(xiàn)在調(diào)用Payload.call就會跳轉(zhuǎn)到VirtualProtect執(zhí)行了。觀察上述的匯編代碼,core->exec->call(env,thisArg,argc,argv)和VirtualProtect(lpAddress,dwSize,flNewProtect,lpflOldProtect)一樣都是四個參數(shù)。其中argc和argv好理解,就是CallVP中調(diào)用Payload.call傳入的參數(shù)個數(shù)和參數(shù)所在數(shù)組,只要讓參數(shù)個數(shù)為0x40,flNewProtect就變成RWX,而argv本來只想存儲參數(shù)的可寫堆內(nèi)存,就不用管了(這里還是不清楚為什么上面的args的長度為0x41,這樣argc不就等于0x41了么,就不是執(zhí)行權(quán)限了啊),前兩個參數(shù)實際上是位于Payload對象的0x1c和0x20位置的,如下圖所示,其中左側(cè)為Payload對象的內(nèi)存,右側(cè)是core->exec->call()的棧。 如此一來,直接改寫Payload的內(nèi)存就可以控制VirtualProtect的參數(shù)了。代碼中的apply(null,args)就是call(null*0x41)。之所以是0x41個null而非0x40個null,是因為第一個null是調(diào)用者而不是參數(shù)。call(object,param1,param2...)等價于call.apply(object,new Array(param1,param2,...))。args按說完全是參數(shù)數(shù)組了,長度還要設(shè)置為0×41是因為apply的調(diào)用者為call,而object指針不會從apply向call傳遞。在call看來傳過來參數(shù)包含了object指針和參數(shù),所以數(shù)組的第一個參數(shù)就作為了object指針,也就是這種傳遞過程會吃掉一個參數(shù)。 調(diào)用VirtualProtect后再恢復(fù)修改過的虛函數(shù)表和Payload內(nèi)存就可以執(zhí)行shellcode了。 執(zhí)行Shellcode 上述執(zhí)行VirtualProtect的方法用于執(zhí)行shellcode也是可行的。但是人家偏不復(fù)用,非要換個方法,就是直接替換掉Payload的MethodEnv->Methodinfo里存儲的JIT后的代碼地址,這個與Core Security提出的繞過CFG方法相當(dāng)類似(見參考鏈接2)。 Payload對象中0x1C偏移的位置存儲了MethodEnv指針,而MethodEnv中的0x8偏移的位置指向了MethodInfo,而MethodInfo的0x4偏移的位置就是_implGPR,存儲了JIT后的代碼地址,所以調(diào)用Shellcode的代碼就變成了如下圖所示。 隨后替換了Payload函數(shù)對象中JIT后的代碼地址為shellcode的地址。 隨后對利用Payload.call進行shellcode的觸發(fā),但是上次是替換了ExecMgr的虛函數(shù)call,這次是直接替換了JIT后的代碼地址。JIT代碼的調(diào)用不在CFG監(jiān)測的范圍之內(nèi),而ExecMgr的虛函數(shù)表由于頻繁使用考慮性能也沒有CFG守護。(CFG:control flow guard控制流保護,見參考鏈接3)。 其實使用JIT的方法調(diào)用shellcode好處還在于,shellcode可以返回需要的結(jié)果,并讓ActionScript獲取指導(dǎo)下一步操作,比如EAX存儲了CreateProcessA的執(zhí)行結(jié)果,若返回前構(gòu)造一個這樣的代碼,就可以讓EAX轉(zhuǎn)化為atom。 1 04DDE32D  SHL  EAX,3 2 04DDE330  ADD  EAX,6 3 04DDE333  LEAVE 4 04DDE334  RETN

?

   當(dāng)執(zhí)行完call之后,AS3可以根據(jù)進程創(chuàng)建情況判斷沙箱的限制,來決定是否進一步部署內(nèi)核漏洞利用代碼進行提權(quán)。 結(jié)語 ? ??HackTeam的Flash Exploit在超長Vector獲取前的堆分布,獲得后的代碼執(zhí)行階段加入了不少獨辟蹊徑的技巧,對不同版本和操作系統(tǒng)的考量也讓利用代碼異常穩(wěn)定。只是如今隨著Adobe在18.0.0.209時引入了Vector內(nèi)存隔離和類似對抗JIT-Spray的長度異或校驗(見參考鏈接[4]),這套利用模板已經(jīng)不能走得更遠了。一整年的喧囂后,Flash大概也想清靜一下了。? 參考:
  • http://www.freebuf.com/vuls/73074.html
  • https://blog.coresecurity.com/2015/03/25/exploiting-cve-2015-0311-part-ii-bypassing-control-flow-guard-on-windows-8-1-update-3/
  • http://drops.wooyun.org/tips/4839
  • http://googleprojectzero.blogspot.com/2015/07/significant-flash-exploit-mitigations_16.html
  • 轉(zhuǎn)載于:https://www.cnblogs.com/crazyDogge/p/4718047.html

    總結(jié)

    以上是生活随笔為你收集整理的Hacking Team Flash 0day漏洞学习笔记的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。