再利用Chakra引擎繞過CFG

xlab · 2015/12/24 15:00

Author:[email?protected]

0x00 前言


本文源自一次與TK閑聊,期間得知成功繞過CFG的經過與細節(參考:[利用Chakra JIT繞過DEP和CFG])。隨即出于對技術的興趣,也抽出一些時間看了相關的東西,結果發現了另一處繞過CFG的位置。所以這篇文章中提到的思路與技術歸根結底是來自TK提示的,在此特別感謝。

關于CFG的分析文章已經有很多了,想要了解的話可以參考我之前在HitCon 2015上的演講(spartan 0day & exploit)。要說明的是,本文的內容即為我演講中馬賽克的部分,至此通過一次內存寫實現edge的任意代碼執行方法就全部公開了。

0x01 Chakra調用函數的邏輯


chakra引擎在函數調用時,會根據所調用函數狀態的不同進行不同的處理。比如第一次調用的函數、多次調用的函數、DOM接口函數及經過jit編譯后的函數。不同的函數類型會有不同的處理流程,而這些不同的處理都會通過Js::InterpreterStackFrame::OP_CallCommon<Js::OpLayoutDynamicProfile<Js::OpLayoutT_CallI<Js::LayoutSizePolicy<0> > > >函數調用Js::JavascriptFunction::CallFunction<1>函數來實現。

1.函數的首次調用與多次調用

當調用如下腳本時,Js::JavascriptFunction::CallFunction<1>函數會被Js::InterpreterStackFrame::OP_CallCommon<Js::OpLayoutDynamicProfile<Js::OpLayoutT_CallI<Js::LayoutSizePolicy<0> > > >函數調用。

#!js
function test(){}test();
復制代碼

如果函數是第一次被調用,則執行流程如下。

#!bash
chakra!Js::InterpreterStackFrame::OP_CallCommon<Js::OpLayoutDynamicProfile<Js::OpLayoutT_CallI<Js::LayoutSizePolicy<0> > > >|-chakra!Js::JavascriptFunction::CallFunction<1>|-chakra!Js::JavascriptFunction::DeferredParsingThunk|-chakra!Js::JavascriptFunction::DeferredParse|-chakra!NativeCodeGenerator::CheckCodeGenThunk|-chakra!Js::InterpreterStackFrame::DelayDynamicInterpreterThunk|-jmp_code|-chakra!Js::InterpreterStackFrame::InterpreterThunk
復制代碼

如果再次調用這個函數的話,調用流程如下。

#!bash
chakra!Js::InterpreterStackFrame::OP_CallCommon<Js::OpLayoutDynamicProfile<Js::OpLayoutT_CallI<Js::LayoutSizePolicy<0> > > >|-chakra!Js::JavascriptFunction::CallFunction<1>|-chakra!NativeCodeGenerator::CheckCodeGenThunk|-chakra!Js::InterpreterStackFrame::DelayDynamicInterpreterThunk|-jmp_code|-chakra!Js::InterpreterStackFrame::InterpreterThunk
復制代碼

兩次的調用流程大致是相同的,其中主要不同是因為,函數在第一次調用時候需要通過DeferredParsingThunk函數對其進行解析。其實函數只有在第一次調用時才進行進一步的初始化解析操作,這樣設計主要是為了效率。而后續調用再直接解釋執行。

分析發現,Js::JavascriptFunction::CallFunction<1>函數調用的子函數是通過Js::ScriptFunction對象中的數據獲得的。后續調用的函數Js::JavascriptFunction::DeferredParsingThunkNativeCodeGenerator::CheckCodeGenThunk都存在于Js::ScriptFunction對象中。兩次調用中Js::ScriptFunction對象的變化。

第一次調用時的Js::ScriptFunction對象。

#!bash
0:010> u poi(06eaf050 )
chakra!Js::ScriptFunction::`vftable':0:010> dd 06eaf050 
06eaf050  5f695580 06eaf080 00000000 000000000:010> dd poi(06eaf050+4) 
06eaf080  00000012 00000000 06e26c00 06e1fea0
06eaf090  5f8db3f0 00000000 5fb0b454 000001010:010> u poi(poi(06eaf050+4)+0x10)
chakra!Js::JavascriptFunction::DeferredParsingThunk:
復制代碼

第二次調用時的Js::ScriptFunction對象。

#!bash
0:010> u poi(06eaf050 )
chakra!Js::ScriptFunction::`vftable':0:010> dd 06eaf050 
06eaf050  5f695580 1ce1a0c0 00000000 000000000:010> dd poi(06eaf050+4)
1ce1a0c0  00000012 00000000 06e26c00 06e1fea0
1ce1a0d0  5f8db9e0 00000000 5fb0b454 000001010:010> u poi(poi(06eaf050+4)+0x10)
chakra!NativeCodeGenerator::CheckCodeGenThunk:
復制代碼

所以函數在第一次調用與后續調用的不同,是通過修改Js::ScriptFunction對象中的函數指針來實現的。

2.函數的jit

接下來我們看一下函數的jit。測試腳本代碼如下,多次調用test1函數觸發其jit。

#!js
function test1(num)
{return num + 1 + 2 + 3;
}//觸發jittest1(1);
復制代碼

經過jit的Js::ScriptFunction對象。

#!bash
//新的調試,對象內存地址會不同0:010> u poi(07103050 )
chakra!Js::ScriptFunction::`vftable':0:010> dd 07103050 
07103050  5f695580 1d7280c0 00000000 000000000:010> dd poi(07103050+4)
1d7280c0  00000012 00000000 07076c00 071080a0
1d7280d0  0a510600 00000000 5fb0b454 000001010:010> u poi(poi(07103050+4)+0x10)              //jit code
0a510600 55              push    ebp
0a510601 8bec            mov     ebp,esp
0a510603 81fc5cc9d005    cmp     esp,5D0C95Ch
0a510609 7f21            jg      0a51062c
0a51060b 6a00            push    0
0a51060d 6a00            push    0
0a51060f 68d0121b04      push    41B12D0h
0a510614 685c090000      push    95Ch
0a510619 e802955b55      call    chakra!ThreadContext::ProbeCurrentStack2 (5fac9b20)
0a51061e 0f1f4000        nop     dword ptr [eax]
0a510622 0f1f4000        nop     dword ptr [eax]
0a510626 0f1f4000        nop     dword ptr [eax]
0a51062a 6690            xchg    ax,ax
0a51062c 6a00            push    0
0a51062e 8d6424ec        lea     esp,[esp-14h]
0a510632 56              push    esi
0a510633 53              push    ebx
0a510634 b8488e0607      mov     eax,7068E48h
0a510639 8038ff          cmp     byte ptr [eax],0FFh
0a51063c 7402            je      0a510640
0a51063e fe00            inc     byte ptr [eax]
0a510640 8b450c          mov     eax,dword ptr [ebp+0Ch]
0a510643 25ffffff08      and     eax,8FFFFFFh
0a510648 0fbaf01b        btr     eax,1Bh
0a51064c 83d802          sbb     eax,2
0a51064f 7c2f            jl      0a510680
0a510651 8b5d14          mov     ebx,dword ptr [ebp+14h] //ebx = num
0a510654 8bc3            mov     eax,ebx        //eax = num (num << 1 & 1)
0a510656 d1f8            sar     eax,1          //eax = num >> 1
0a510658 732f            jae     0a510689
0a51065a 8bf0            mov     esi,eax
0a51065c 8bc6            mov     eax,esi
0a51065e 40              inc     eax            //num + 1
0a51065f 7040            jo      0a5106a1
0a510661 8bc8            mov     ecx,eax
0a510663 83c102          add     ecx,2          //num + 2
0a510666 7045            jo      0a5106ad
0a510668 8bc1            mov     eax,ecx
0a51066a 83c003          add     eax,3          //num + 3
0a51066d 704a            jo      0a5106b9
0a51066f 8bc8            mov     ecx,eax
0a510671 d1e1            shl     ecx,1          //ecx = num << 1
0a510673 7050            jo      0a5106c5
0a510675 41              inc     ecx            //ecx = num += 1
0a510676 8bd9            mov     ebx,ecx
0a510678 8bc3            mov     eax,ebx
0a51067a 5b              pop     ebx
0a51067b 5e              pop     esi
0a51067c 8be5            mov     esp,ebp
0a51067e 5d              pop     ebp
0a51067f c3              ret
復制代碼

Js::ScriptFunction對象中原本指向NativeCodeGenerator::CheckCodeGenThunk函數的指針,在jit之后變為指向jit code的指針。實現了直接調用函數jit code。

這里簡單說明一下,在調用函數傳遞參數時,是先將參數左移一位,然后將最低位置1之后的值進行傳遞的(parameter = (num << 1) & 1)。所以其在獲取參數之后的第一件事是將其右移1位,獲取參數原始的值。至于為什么要這樣,我想應該是因為腳本引擎垃圾回收機制導致的,引擎通過最低位來區分對象與數據。

#!bash
chakra!Js::InterpreterStackFrame::OP_CallCommon<Js::OpLayoutDynamicProfile<Js::OpLayoutT_CallI<Js::LayoutSizePolicy<0> > > >|-chakra!Js::JavascriptFunction::CallFunction<1>|-jit code
復制代碼

調用jit函數時的調用棧如上所示,這就是chakra引擎調用jit函數的方法。

3.DOM接口函數

最后為了完整性,還有一類函數需要簡單介紹一下,就是DOM接口函數,由其它引擎如渲染引擎提供的函數(理論上可以為任何其它引擎)。

#!js
document.createElement("button");
復制代碼

執行上面腳本則會通過下面的函數調用流程,最后調用到提供接口函數的引擎中。

#!bash
chakra!Js::InterpreterStackFrame::OP_CallCommon<Js::OpLayoutDynamicProfile<Js::OpLayoutT_CallI<Js::LayoutSizePolicy<0> > > >|-chakra!Js::JavascriptFunction::CallFunction<1>|-chakra!Js::JavascriptExternalFunction::ExternalFunctionThunk //調用dom接口函數|-dom_interface_function    //EDGEHTML!CFastDOM::CDocument::Trampoline_createElement
復制代碼

當調用dom接口函數時,Js::InterpreterStackFrame::OP_CallCommon<Js::OpLayoutDynamicProfile<Js::OpLayoutT_CallI<Js::LayoutSizePolicy<0> > > >函數及后續的處理流程中所使用的Function對象與前面不同,使用的是Js::JavascriptExternalFunction對象。然后與前面的函數調用類似,也是通過解析對象內的函數指針,并對其進行調用,最終進入到想要調用的DOM接口函數中。

#!bash
0:010> u poi(06f2cea0)
chakra!Js::JavascriptExternalFunction::`vftable':0:010> dd 06f2cea0 
06f2cea0  5f696c4c 06e6f7a0 00000000 000000000:010> dd poi(06f2cea0+4)
06e6f7a0  00000012 00000000 06e76c00 06f040a0
06e6f7b0  5f8c6130 00000000 5fb0b454 000001010:010> u poi(poi(06f2cea0+4)+0x10)
chakra!Js::JavascriptExternalFunction::ExternalFunctionThunk:
復制代碼

這就是chakra引擎對不同類型函數的不同調用的方式。

0x02 漏洞與利用


經過前面對chakra引擎各種調用函數方法的介紹,我們再來看一下本文的重點繞過cfg的漏洞。前面提到的在第一次調用腳本創建的函數時與后續調用此函數會有不同的流程。這里我們再看一下此處的邏輯,調用棧如下。

#!bash
//第一次調用
chakra!Js::InterpreterStackFrame::OP_CallCommon<Js::OpLayoutDynamicProfile<Js::OpLayoutT_CallI<Js::LayoutSizePolicy<0> > > >|-chakra!Js::JavascriptFunction::CallFunction<1>|-chakra!Js::JavascriptFunction::DeferredParsingThunk|-chakra!Js::JavascriptFunction::DeferredParse    //獲取NativeCodeGenerator::CheckCodeGenThunk函數|-chakra!NativeCodeGenerator::CheckCodeGenThunk|-chakra!Js::InterpreterStackFrame::DelayDynamicInterpreterThunk|-jmp_code  |-chakra!Js::InterpreterStackFrame::InterpreterThunk
復制代碼

在前面沒有提到的是,上面調用流程中的Js::JavascriptFunction::DeferredParse函數。此函數內部會進行函數解析相關的工作,并且返回NativeCodeGenerator::CheckCodeGenThunk函數的指針,然后在返回Js::JavascriptFunction::DeferredParsingThunk函數后對其進行調用。NativeCodeGenerator::CheckCodeGenThunk函數的指針也是通過解析Js::JavascriptFunction對象獲得的。代碼如下。

#!js
int __cdecl Js::JavascriptFunction::DeferredParsingThunk(struct Js::ScriptFunction *p_script_function)
{NativeCodeGenerator_CheckCodeGenThunk = Js::JavascriptFunction::DeferredParse(&p_script_function);return NativeCodeGenerator_CheckCodeGenThunk();
}.text:002AB3F0 push    ebp
.text:002AB3F1 mov     ebp, esp
.text:002AB3F3 lea     eax, [esp+p_script_function]
.text:002AB3F7 push    eax             ; struct Js::ScriptFunction **
.text:002AB3F8 call    Js::JavascriptFunction::DeferredParse
.text:002AB3FD pop     ebp
.text:002AB3FE jmp     eax
復制代碼

在這個跳轉位置上并沒有對eax中的函數指針進行CFG檢查。所以可以利用其進行eip劫持。不過還首先還要知道Js::JavascriptFunction::DeferredParse函數返回的NativeCodeGenerator::CheckCodeGenThunk函數指針是如何通過Js::ScriptFunction對象何解析出來的。解析過程如下。

#!bash
0:010> u poi(070af050)
chakra!Js::ScriptFunction::`vftable':0:010> dd 070af050 + 14
070af064  076690e0 5fb11ef4 00000000 000000000:010> dd 076690e0 + 10
076690f0  076690e0 04186628 07065f90 000000000:010> dd 076690e0 + 28
07669108  07010dc0 000001a8 00000035 000000000:010> dd 07010dc0 
07010dc0  5f696000 05a452b8 00000000 5f8db9e00:010> u 5f8db9e0
chakra!NativeCodeGenerator::CheckCodeGenThunk:
復制代碼

如上所述,Js::JavascriptFunction::DeferredParse通過解析Js::ScriptFunction對象獲取NativeCodeGenerator::CheckCodeGenThunk函數指針,解析方法簡寫為[[[Js::ScriptFunction+14]+10]+28]+0c。所以只要偽造此處內存中的數據,即可通過調用函數來間接觸發Js::JavascriptFunction::DeferredParse函數的調用,進而劫持eip,具體如下。

#!bash
0:010> g
Breakpoint 0 hit
eax=603ba064 ebx=063fba10 ecx=063fba40 edx=063fba40 esi=00000001 edi=058fc6b0
eip=603ba064 esp=058fc414 ebp=058fc454 iopl=0         nv up ei ng nz na po cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000283
chakra!`dynamic initializer for 'DOMFastPathInfo::getterTable''+0x734:
603ba064 94              xchg    eax,esp
603ba065 c3              ret
復制代碼

這樣就繞過了cfg,成功劫持了eip。這種方法簡單穩定,在獲得了內存讀寫能力時使用是很方便的。此漏洞已于2015年7月25日報告微軟。

0x03 修補方案


本文所述的漏洞微軟已經修補,修補方案也比較簡單就是對此處跳轉增加cfg檢查。

#!bash
.text:002AB460 push    ebp
.text:002AB461 mov     ebp, esp
.text:002AB463 lea     eax, [esp+arg_0]
.text:002AB467 push    eax
.text:002AB468 call    Js::JavascriptFunction::DeferredParse
.text:002AB46D mov     ecx, eax        ; this
.text:002AB46F call    ds:___guard_check_icall_fptr  //增加cfg檢查
.text:002AB475 mov     eax, ecx
.text:002AB477 pop     ebp
.text:002AB478 jmp     eax
.text:00
復制代碼

0x04 參考


  • 利用Chakra JIT繞過DEP和CFG
  • spartan 0day & exploit

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/391082.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/391082.shtml
英文地址,請注明出處:http://en.pswp.cn/news/391082.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

論文搜索源

中國科學院文獻情報中心 見下圖 中國計算機學會推薦國際學術會議和期刊目錄 EI學術會議中心,        engieer village 轉載于:https://www.cnblogs.com/cxy-941228/p/7693097.html

重學TCP協議(10)SYN flood 攻擊

1.SYN flood 攻擊 SYN Flood&#xff08;半開放攻擊&#xff09;是一種拒絕服務&#xff08;DDoS&#xff09;攻擊&#xff0c;其目的是通過消耗所有可用的服務器資源使服務器不可用于合法流量。通過重復發送初始連接請求&#xff08;SYN&#xff09;數據包&#xff0c;攻擊者能…

大數據入門課程_我根據數千個數據點對互聯網上的每門數據科學入門課程進行了排名...

大數據入門課程by David Venturi大衛文圖里(David Venturi) A year ago, I dropped out of one of the best computer science programs in Canada. I started creating my own data science master’s program using online resources. I realized that I could learn everyt…

python 數據框缺失值_Python:處理數據框中的缺失值

python 數據框缺失值介紹 (Introduction) In the last article we went through on how to find the missing values. This link has the details on the how to find missing values in the data frame. https://medium.com/kallepalliravi/python-finding-missing-values-in-…

Spring Cloud 5分鐘搭建教程(附上一個分布式日志系統項目作為參考) - 推薦

http://blog.csdn.net/lc0817/article/details/53266212/ https://github.com/leoChaoGlut/log-sys 上面是我基于Spring Cloud ,Spring Boot 和 Docker 搭建的一個分布式日志系統. 目前已在我司使用. 想要學習Spring Cloud, Spring Boot以及Spring 全家桶的童鞋,可以參考學習,如…

51nod1832(二叉樹/高精度模板+dfs)

題目鏈接: http://www.51nod.com/onlineJudge/questionCode.html#!problemId1832 題意: 中文題誒~ 思路: 若二叉樹中有 k 個節點只有一個子樹, 則答案為 1 << k. 詳情參見:http://blog.csdn.net/gyhguoge01234/article/details/77836484 代碼: 1 #include <iostream&g…

重學TCP協議(11)TFO(Tcp Fast Open)

1. TFO 為了改善web應用相應時延&#xff0c;google發布了通過修改TCP協議利用三次握手時進行數據交換的TFO(TCP fast open&#xff0c;RFC 7413)。 TFO允許在TCP握手期間發送和接收初始SYN分組中的數據。如果客戶端和服務器都支持TFO功能&#xff0c;則可以減少建立到同一服…

[網絡安全] 遠程登錄

遠程登錄方式: 1.圖像化遠程登錄 做法: 運行"窗口"輸入 "mstsc " 輸入ip地址 注意: 被遠程計算機&#xff0c;必須打開遠程登錄服務: 信息面板–系統–允許遠程訪問。被遠程計算機&#xff0c;必須存在擁有遠程桌面權限的用戶。 2.命令行遠程登錄 teln…

外星人圖像和外星人太空船_衛星圖像:來自太空的見解

外星人圖像和外星人太空船By Christophe Restif & Avi Hoffman, Senior Software Engineers, Crisis Response危機應對高級軟件工程師Christophe Restif和Avi Hoffman Editor’s note: In 2019, we piloted a new feature in Search SOS Alerts for major California wild…

chrome恐龍游戲_如何玩沒有互聯網的Google Chrome恐龍游戲-在線和離線

chrome恐龍游戲Several years ago, Google added a fun little Easter egg to Chrome: if your internet went down and you tried to visit a web page, youd see the message "Unable to connect to the Internet" or "No internet" with a little pixi…

Hotpatch潛在的安全風險

屎蛋 2016/06/22 10:11author:[email protected]0x00 “Hotpatch”簡介IOS App的開發者們經常會出現這類問題&#xff1a;當一個新版本上線后發現存在一個嚴重的bug&#xff0c;有可能因為一個邏輯問題導致支付接口存在被薅羊毛的風險&#xff0c;這個時候能做的只能是趕快修復…

spring中@Inject和@Autowired的區別?分別在什么條件下使用呢?

問題&#xff1a;spring中Inject和Autowired的區別&#xff1f;分別在什么條件下使用呢&#xff1f; 我在瀏覽SpringSource上的一些博客&#xff0c;在其他一個博客中&#xff0c;那個作者用了Inject&#xff0c;但是我覺得他用Autowired也行 下面是一部分代碼&#xff1a; …

Objective-C語言的動態性

Objective-C具有相當多的動態特性&#xff0c;基本的&#xff0c;也是經常被提到和用到的有動態類型&#xff08;Dynamic typing&#xff09;&#xff0c;動態綁定&#xff08;Dynamic binding&#xff09;和動態加載&#xff08;Dynamic loading&#xff09; 一、編譯時和運行…

內存泄漏和內存溢出的區別

原文地址https://www.zhihu.com/question/40560123 簡單來說&#xff0c;操作系統就像資源分配人員&#xff0c;你要使用內存的時候分給你&#xff0c;你用完了還給它。如果你使用了沒有分配給你的內存就是內存溢出&#xff0c;如果你用完了沒有還就是內存泄漏。會引起的問題&a…

怎么注銷筆記本icloud_如何在筆記本電腦或臺式機的Web瀏覽器中在線查看Apple iCloud照片

怎么注銷筆記本icloudPicture this: you just returned from a beautiful vacation and want to show all those gorgeous photos to your family. But your phone just died. And since youre at a family dinner your laptop is nowhere to be found.想象一下&#xff1a;您剛…

棒棒糖 宏_棒棒糖圖表

棒棒糖 宏AKA: lollipop plot又名&#xff1a;棒棒糖情節 WHY: a lollipop chart (LC) is a handy variation of a bar chart where the bar is replaced with a line and a dot at the end. Just like bar graphs, lollipop plots are used to make comparisons between diff…

ubuntu上如何安裝tomcat

1. 在官網下載linux里面的tomcat 2. 放到DownLoads下面--把tomcat的壓縮包放到DownLoads3. sudo mkdir /usr/local/tomcat/ -在usr/local/路徑下新建一個tomcat的文件夾4 sudo tar zxvf tomcat。。。。tar.gz -C /usr/local/tomcat/---把解壓后的tomcat放到usr/local/下的tomca…

leetcode 1734. 解碼異或后的排列(位運算)

給你一個整數數組 perm &#xff0c;它是前 n 個正整數的排列&#xff0c;且 n 是個 奇數 。 它被加密成另一個長度為 n - 1 的整數數組 encoded &#xff0c;滿足 encoded[i] perm[i] XOR perm[i 1] 。比方說&#xff0c;如果 perm [1,3,2] &#xff0c;那么 encoded [2,…

ZooKeeper3.4.5-最基本API開發

2019獨角獸企業重金招聘Python工程師標準>>> package cn.itcast.bigdata.zk;import java.io.IOException; import java.util.List;import org.apache.zookeeper.CreateMode; import org.apache.zookeeper.KeeperException; import org.apache.zookeeper.WatchedEven…

字符串轉換整數python_將Python字符串轉換為Int:如何在Python中將字符串轉換為整數

字符串轉換整數pythonUnlike many other programming languages out there, Python does not implicitly typecast integers (or floats) to strings when you concatenate them to strings.與現有的許多其他編程語言不同&#xff0c;Python在將整數連接到字符串時不會隱式地將…