成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

基于Chakra JIT的CFG繞過(guò)技術(shù)

安全 黑客攻防 應(yīng)用安全
在本文中,我們將向讀者介紹在攻擊Internet Explorer和Edge瀏覽器時(shí)可用于繞過(guò)Microsoft的控制流防護(hù)(CFG)的方法。

[[180043]]

引言

在本文中,我們將向讀者介紹在攻擊Internet Explorer和Edge瀏覽器時(shí)可用于繞過(guò)Microsoft的控制流防護(hù)(CFG)的方法。我們以前的概念驗(yàn)證性質(zhì)的漏洞利用代碼是通過(guò)覆蓋對(duì)象的函數(shù)指針來(lái)實(shí)現(xiàn)的。但是,當(dāng)遇到CFG時(shí),這種方法就不太好使了。我們假設(shè)攻擊者已經(jīng)獲得了讀寫(xiě)內(nèi)存權(quán)限。

背景知識(shí)

CFG是微軟近來(lái)為Windows系統(tǒng)添加一種安全防護(hù)機(jī)制。該機(jī)制通過(guò)間接調(diào)用/跳轉(zhuǎn)指令的目標(biāo)地址的高效檢查來(lái)提供保護(hù)。如果您希望進(jìn)一步了解CFG的更多詳情,可以參閱參考文獻(xiàn)[1][2][3],所以我們不做深入細(xì)致的講解。

雖然該緩解機(jī)制增加了控制流劫持型攻擊的難度,但是CFG本身并不完美。該技術(shù)的設(shè)計(jì)目標(biāo)是保護(hù)間接調(diào)用和跳轉(zhuǎn),所以,沒(méi)有為堆棧(即ROP仍是可能的)提供保護(hù)。此外,值得注意的是,這是一個(gè)編譯時(shí)插樁技術(shù),需要重新編譯源代碼。盡管微軟現(xiàn)在的許多二進(jìn)制文件可以受益于CFG,但還有很多其他程序不是利用CFG保護(hù)機(jī)制編譯的。

Chakra JIT

Chakra JIT負(fù)責(zé)為多次調(diào)用的函數(shù)和循環(huán)生成優(yōu)化的JIT代碼。這個(gè)過(guò)程分為多個(gè)階段完成,其中Full JIT Compiler和Garbage Collection階段是在后臺(tái)線(xiàn)程中進(jìn)行的。如果您有興趣的話(huà),可以從MSDN上找到相關(guān)的工作流程和各種圖釋。

JIT工作流程

我們關(guān)注的重點(diǎn)是Full JIT Compiler階段,它負(fù)責(zé)獲取字節(jié)碼和輸出本地代碼。針對(duì)單個(gè)函數(shù)或循環(huán)的高級(jí)處理是在Func::Codegen()中進(jìn)行的。首先,它會(huì)生成字節(jié)碼的中間表示(IR)。然后,這些IR將被轉(zhuǎn)換若干次:優(yōu)化、寄存器分配、prolog和epilog等。一旦IR準(zhǔn)備就緒,就會(huì)被Encoder::Encode()編碼為本地代碼。

  1. // https://github.com/Microsoft/ChakraCore/blob/master/lib/Backend/Encoder.cpp#L15 
  2. void 
  3. Encoder::Encode() 
  4.     NoRecoverMemoryArenaAllocator localAlloc(_u("BE-Encoder"), m_func->m_alloc->GetPageAllocator(), Js::Throw::OutOfMemory); 
  5.     m_tempAlloc = &localAlloc; 
  6. ... 
  7.     m_encodeBuffer = AnewArray(m_tempAlloc, BYTE, m_encodeBufferSize); 
  8. ... 

實(shí)際上,真正生成實(shí)際本地代碼的任務(wù)是由Encoder完成的。首先,它會(huì)分配m_encodeBuffer來(lái)臨時(shí)存放本地代碼。當(dāng)所有本地指令被發(fā)送到m_encodeBuffer之后,Encoder將對(duì)該緩沖區(qū)進(jìn)行重新定位,將其復(fù)制到read-only-execute內(nèi)存,并按照CFG的要求處理調(diào)用目標(biāo)。此時(shí),該臨時(shí)緩沖區(qū)就不再使用,所以可以釋放了。

  1. // https://github.com/Microsoft/ChakraCore/blob/master/lib/Backend/Encoder.cpp#L294 
  2. ... 
  3.     m_encoderMD.ApplyRelocs((size_t) workItem->GetCodeAddress()); 
  4.     workItem->RecordNativeCode(m_func, m_encodeBuffer); 
  5.     m_func->GetScriptContext()->GetThreadContext()->SetValidCallTargetForCFG((PVOID) workItem->GetCodeAddress()); 
  6. ... 

注意,一旦代碼被復(fù)制到可執(zhí)行內(nèi)存后,就很難修改了。但是,當(dāng)Encoder在這個(gè)臨時(shí)緩沖器中生成本地代碼時(shí),是無(wú)法防止攻擊者利用寫(xiě)入內(nèi)存權(quán)限來(lái)更改臨時(shí)緩沖器中的代碼的。由于JIT進(jìn)程位于后臺(tái)線(xiàn)程中,所以JavaScript線(xiàn)程仍然可以正常運(yùn)行。攻擊者的難點(diǎn)是找到該臨時(shí)緩沖區(qū),并在Encoder運(yùn)行的極短時(shí)間內(nèi)完成相應(yīng)的修改任務(wù)。

繞過(guò)CFG防護(hù)

既然已經(jīng)知道了修改JIT代碼的基本方法,下面就讓我們付諸行動(dòng),以便設(shè)法繞過(guò)CFG。

我們的過(guò)程分為三步:

觸發(fā)JIT。

查找臨時(shí)的本地代碼緩沖區(qū)。

修改緩沖區(qū)的內(nèi)容。

當(dāng)然,這里隱含的最后一步是執(zhí)行JIT處理過(guò)的代碼。

觸發(fā)JIT

第一步,也是最簡(jiǎn)單的一步,就是觸發(fā)JIT,讓它開(kāi)始對(duì)一個(gè)函數(shù)進(jìn)行編碼。為了使第二步變得更容易一些,我們希望函數(shù)的代碼多一些,以便我們有足夠的時(shí)間在內(nèi)存中尋找該臨時(shí)緩沖區(qū)。當(dāng)然,函數(shù)中的具體指令是無(wú)關(guān)緊要的。

  1. var code = "var i = 10; var j = 1; "
  2. for (var i = 0; i < 6000; i++) 
  3.     code += "i *= i + j.toString();"
  4. code += "return i.toString();" 
  5. f = Function(code); 
  6. for (var i = 0; i < 1000; i++) 
  7.     // trigger jit 
  8.     f.call(); 

查找本機(jī)代碼緩沖區(qū)

一旦后臺(tái)線(xiàn)程進(jìn)入Encoder::Encode(),我們需要快速找到臨時(shí)本地代碼緩沖區(qū)。發(fā)現(xiàn)緩沖區(qū)的一種方法是,找到給該緩沖區(qū)分配內(nèi)存的頁(yè)分配器,然后逐個(gè)查看它分配的內(nèi)存段。我們注意到,可以先找到ThreadContext,然后找到該后臺(tái)線(xiàn)程的BackgroundJobProcessor,這樣就可以找到該頁(yè)面分配器的引用了。

  1. // find the ThreadContext using ThreadContext::globalListLast 
  2. var tctx = readN(jscript9Base + 0x00349034, 4); 
  3. // BackgroundJobProcessor 
  4. var bgjob = readN(tctx + 0x3b0, 4); 
  5. // PageAllocator 
  6. var pgalloc = bgjob + 0x1c; 

PageAllocator具有若干已分配段的列表。由于經(jīng)JIT處理過(guò)的函數(shù)會(huì)變大,所以該臨時(shí)本地代碼緩沖器也將很大。所以,通過(guò)檢查largeSegments列表,我們就可以輕松找到該內(nèi)存段了。我們可以使用一個(gè)while循環(huán),這樣一直等到這個(gè)largeSegments列表變?yōu)榉强眨缓筮M(jìn)入最后一步。

  1. while (true) { 
  2.     // read largeSegments list 
  3.     var largeseg = readN(pgalloc + 0x24, 4); 
  4.     // check if the list was empty 
  5.     if (largeseg == pgalloc + 0x24) continue
  6.     // get the address of the actual data 
  7.     var page = readN(largeseg + 8 + 8, 4); 
  8.     if (page == 0) continue
  9.     break; 

修改并運(yùn)行

現(xiàn)在,既然已經(jīng)知道了臨時(shí)本地代碼緩沖區(qū)的位置,那么接下來(lái)就可以修改其內(nèi)容來(lái)注入shellcode了。當(dāng)然,按理說(shuō)只要使用我們的shellcode覆蓋緩沖區(qū)的內(nèi)容就行了,但是實(shí)際上要比這個(gè)過(guò)程要復(fù)雜的多,因?yàn)槲覀儽仨毐苊飧采w未來(lái)在重定位步驟中將要修改的任何內(nèi)容。因?yàn)橛糜谟|發(fā)JIT的函數(shù)需要多次調(diào)用toString(),同時(shí)還要避免重定位的影響,所以,實(shí)際上可用于shellcode的空間并不充裕。

雖然最佳之選是修改要進(jìn)行JIT處理的函數(shù),但這里選擇使用first-stage shellcode,它只是簡(jiǎn)單調(diào)用VirtualProtect,然后跳轉(zhuǎn)到我們的second-stage shellcode。這個(gè)first-stage shellcode通常是非常小(只有20個(gè)字節(jié))的。所以 ,我們可以把first-stage shellcode放到距這個(gè)緩沖區(qū)比較近的地方,然后在這個(gè)緩沖區(qū)的起始位置放上一個(gè)近轉(zhuǎn)移指令,從而跳轉(zhuǎn)至該代碼。

這樣的話(huà),我們的second-stage shellcode可以是任何長(zhǎng)度,所以在我們的漏洞利用代碼中,使用了一個(gè)metasploit生成shellcode來(lái)執(zhí)行notepad.exe。實(shí)際上,這個(gè)second-stage shellcode還可以繞過(guò)保護(hù)模式(沙箱)。

在修改好臨時(shí)緩沖區(qū)之后,我們將進(jìn)入最后一步,就是進(jìn)行等待,直到JIT處理完成并執(zhí)行修改后的JIT代碼。為此,你可以不斷調(diào)用目標(biāo)函數(shù),直到你的shellcode得到執(zhí)行為止。

  1. for (var i = 0; i < 1000; i++) 
  2.     // call overwritten jit block 
  3.     f.call(); 

漏洞利用

為了演示這種繞過(guò)技術(shù),我們借鑒了此前用于Windows 10上的Internet Explorer 11的利用代碼,并進(jìn)行了相應(yīng)的修改。其中,獲取讀寫(xiě)內(nèi)存權(quán)限的代碼沒(méi)有改變,但是在執(zhí)行我們的shellcode的時(shí)候,使用的是JIT代碼覆蓋技術(shù),而不是去覆蓋觸發(fā)CFG的函數(shù)指針。

你可以在https://github.com/theori-io/jscript9-typedarray-cfg頁(yè)面中找到最終的概念驗(yàn)證漏洞利用代碼。

安全影響

由于該CFG繞過(guò)漏洞的影響僅限于攻擊者已經(jīng)獲得了讀寫(xiě)內(nèi)存權(quán)限的情況,因此其實(shí)用性在現(xiàn)實(shí)中可能會(huì)受到一些限制。需要引起警覺(jué)的是,這個(gè)繞過(guò)方法具有內(nèi)置到Chakra JIT架構(gòu)內(nèi)部的優(yōu)勢(shì),這意味著它可能很難修補(bǔ),并且不會(huì)受到像英特爾的CET這樣的未來(lái)緩解措施的影響。

補(bǔ)救措施

微軟已經(jīng)承諾對(duì)ChakraCore進(jìn)行相應(yīng)的修改,以緩解我們發(fā)現(xiàn)的CFG繞過(guò)(以及其他CVE補(bǔ)丁)漏洞所造成的威脅。他們的基本思想是,在編碼器編碼指令時(shí)計(jì)算校驗(yàn)和,然后在將整個(gè)緩沖區(qū)復(fù)制到最終的RX(read/execute-only)緩沖區(qū)之后對(duì)校驗(yàn)和進(jìn)行驗(yàn)證。并且,只有通過(guò)驗(yàn)證后,JIT處理后的代碼的入口點(diǎn)才能作為有效的CFG目標(biāo)。這里的選擇的校驗(yàn)和算法是CRC32。

責(zé)任編輯:武曉燕 來(lái)源: theori.io
相關(guān)推薦

2017-01-20 14:49:46

2015-09-28 14:12:36

2009-02-20 11:36:38

Chakra Alpha 2發(fā)布

2010-07-20 15:28:09

ChakraIE9瀏覽器

2010-09-27 14:20:00

JITJVM

2010-09-27 10:11:54

JVMLinux

2010-09-27 15:26:17

JVM for Lin

2013-01-11 16:23:29

2021-12-29 14:41:12

Chakra Linu倉(cāng)庫(kù)源代碼

2019-01-17 04:41:38

2023-02-28 09:47:42

2023-08-31 07:55:21

Android系統(tǒng)壓縮處理

2010-04-22 16:02:36

2013-12-18 09:39:37

XSSWAF繞過(guò)

2017-02-20 09:46:59

2024-01-17 07:00:56

JIT 技術(shù)數(shù)據(jù)庫(kù)表達(dá)式求值

2009-07-02 16:56:51

JSP技術(shù)

2012-10-31 17:21:57

2017-01-03 15:51:43

2009-09-03 14:26:17

Jit編譯
點(diǎn)贊
收藏

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

主站蜘蛛池模板: 黄色片a级 | 99精品久久久 | 国产ts人妖系列高潮 | 一级黄色毛片免费 | 激情毛片 | 亚洲欧美日韩国产综合 | 中文字幕在线精品 | 国产97在线 | 日韩 | 日本精品一区二区三区在线观看视频 | 免费观看av| 日韩在线精品 | 亚洲电影免费 | 人人九九精 | 亚洲精品视频在线观看视频 | 亚洲欧美日韩成人在线 | 小视频你懂得 | 精品真实国产乱文在线 | www.三级 | 国产91 在线播放 | 蜜桃视频在线观看免费视频网站www | 成人欧美一区二区 | 99精品国产一区二区青青牛奶 | 在线视频日韩 | 在线观看视频一区二区三区 | 黄色大片视频 | 中文字幕一区二区三区乱码在线 | 日韩欧美一级片 | 久久看精品 | 岛国一区 | 波多野结衣一区二区三区在线观看 | 久久久国产一区二区三区 | 日日操夜夜操天天操 | 日韩欧美三区 | 成人片免费看 | 欧美日日 | 国产精品成人av | 好姑娘影视在线观看高清 | 日韩在线一区二区 | 国产免费一区二区 | 美女中文字幕视频 | 久草新在线 |