最后这行代码cls.array(2)=cls会调用NameTbl::InvokeEx
逆向结果显示,NameTbl::InvokeEx接着会调用AccessArray和AssignVar,其中stackFor_ecx为导致栈分配接着写入的传递值=ecx也就是AssignVar的edx的寄存器,如图1
关于UAF写入位置我的理解是array()默认的长度是1,也就是是占用0x10位置空间, 通过NameTbl::InvokeEx->AccessArray->AssignVar,因为默认长度是1,所以AccessArray的stackFor_ecx分配0x10之后后面的空间都是???,实际上仅仅是分配了0x10后面没有更多的空间后续分配,在SafeArrayRedim又将array的pvData长度变为array(2)的大小也就是3个元素*0x10=0x30,从地址空间的布局可以看出这个0x30空间最后0x10空间正好是0ceaeff0也就是array()默认的长度1个元素所占用的空间,由于RedimPreserveArray把这个空间给释放了,导致实际上释放后可重用的空间还是最初AccessArray申请的array()默认的长度1个元素所占用的空间,最后cls.array(2)=cls调用AssignVar也是往这个地址空间写入数据,因为申请的栈的位置还是AccessArray这里申请的stackFor_ecx->edi,导致崩溃,所以在8373后面的代码
这个3值首先往申请的栈写入
这里只是array的pvData赋值成array2,仅仅是引用,array2的pvData在它直接pvData指针指向的地址所以为实际写入array的pvData
MyClass的p属性需要往栈写入值,通过AssignVar,所以导致array()默认的0x10空间在也就是RedimPreserveArray最后的0x10空间数据为3 和0fffffff
vbscrpt.dll文件比较结果
在打了补丁的机器上会出现这个错误
主要原因是在调用vbscript!RedimPreservearray内部会先调用SafeArrayLock检查数组长度,然后抛出错误码2147418113也就是[该数组为定长的或临时被锁定]
和之前crash的调试方法一样下断点bp vbscript!RedimPreservearray "dc ecx"
由于array的默认长度是1,所以同理uaf区域大小也为0x10,首次在RedimPreservearray断下
由于array(2)的空间大小为0x30和tagSAFEARRAY大小相同,导致rgsabound[1]位置内存被覆盖成3和 和0fffffff
看到index_vul的值为0也就是第0个元素,也是uaf默认元素的位置,详细原理在crash分析,
再次查看内存中数据
由于uaf堆结构,和tagSAFEARRAY结果头部数据的存在导致错位8个字节
在2和3间隔的区域 将array(index_vul)(index_a, 0)设置为“AAAA”,导致下一段array2 的 Data 域就变成了 8,因为string的VarType类型为8
这样就得到了一组可以混肴的 array(index_vul)(index_a+n, 0)和array(index_b)(0, n),通过将array(index_vul)(index_a, 0)处的 variant 转化为长整型,令
array(index_vul)(index_a, 0)处的 variant 转化为数组,从而得到了一段泄露的内存util_mem,可以读写的内存指定区域的通用方法
分析下rw_primit前
分析下rw_primit后
看到这个地址的值和fake_array的数据相同
我把shellcode改了一下把原来运行cmd的shellcode改成8174的弹出计算器模式,欢迎有兴趣的读者一起研究,exp在附件里,在运行shellcode之前看到提示的地址是
下断点bp vbscript!VAR::Clear "dc esi"在若干次触发后正确断下
逆向结果显示当varTypeNext为77时
EIP和ESP是在CONTEXT精心布局好的
查看结构体指定偏移量的数据,也就是EIP和ESP
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2019-7-30 19:04
被王cb编辑
,原因: