-
-
[原创]利用数组越界绕过IE的alsr+dep
-
发表于:
2012-9-5 11:35
11556
-
漏洞描述
该漏洞是CVE-2011-1999的利用方式。之前Ivan Fratric's Security Blog中提到了该方法,我对该方法进行了总结,又加入了自己的一些观点。进入正题。
select元素结构中存在一个option cache结构,该结构是option元素的指针数组,该数组存在数组越界漏洞。将option元素添加到select元素过程中,如果添加的索引是负值,那么会覆盖数组前方的数据。浏览器的数组越界漏洞属于高风险漏洞,可以同时绕过ASLR和DEP,能够稳定执行。类似的漏洞还有:CVE-2011-1999,CVE-2010-1883,CVE-2008-3475。之所以说能够绕过ASLR和DEP,是因为它能准确的获得mshtml.dll的基地址,但是有时利用mshtml.dll不能构造出合适的rop链。我的思路是通过一些变换来获得ntdll.dll中的rop链。
漏洞利用简述
利用该数组越界漏洞,更改option cache前方的某个字符串的长度位,将长度位改为较大数值,这样该字符串就可以读取该字符串后面的所有数据,因为长度没有限制。通过获得该功能,先将该字符串所在虚拟空间的准确位置测算出。通过获得的准确位置和内存任意地址读取功能,获得刚才option数组的基地址。到此为止通过该漏洞已经具备了:从任意给定地址中读取数据和向任意给定地址中写入固定数据的功能。
通过获得的准确位置和内存任意地址读取功能,读取飞地中的ntdll.dll函数地址,进而获得ntdll.dll模块的基地址。为rop chain做铺垫。
通过获得的准确位置和内存任意地址读取功能,读取option对象的虚函数表的基地址,进而获得mshtml.dll模块的基地址。为rop chain做铺垫。(可选)
具备了读写功能后,伪造对象,来触发漏洞。具体为:使用optarray中的option的指针来替换option cache中的option元素中的CTreeNode指针,然后立即删除该option元素,导致原CTreeNode指针的位置指向的内存是释放内存,然后使用恶意数据填充到该内存处。
关键知识点
• 覆盖字符串长度位
• 利用该漏洞同时具备读写功能
• 内存构造对象数据结构
• 利用飞地地址
js中存在字符串,字符串在内存中的表示是前4个字节是长度位,后面是字符串内容。字符串内容的读取受到字符串长度位的限制,如果长度位足够大,那么字符串可以读取其后用户空间的所有内容。
这里和普通的漏洞触发不同,这里是手工构造出触发漏洞的条件。有一种use-after-free现在已经不可能存在了,那就是:同时有两个地方引用到某个对象,如果删除某个引用和对象,并在该对象位置放入其他恶意数据,那么另一个引用将能引用到该恶意数据。使用optarray中的option的指针来替换option cache中的option元素中的CTreeNode指针,然后立即删除该option元素,导致原CTreeNode指针的位置指向的内存是释放内存,然后使用恶意数据填充到该内存处。
用户空间的最后一块内存中存在“飞地地址”。飞地区域指的是SharedUserData内存区
早期系统调用
Ntdll中的存根函数调用SharedUserData内存区的SystemCallStub代码。ntdll.dll中的存根函数内的代码为call edx,其中edx存储着SystemCallStub的地址,执行call edx将使程序转移到“飞地区域”执行程序代码。
后来系统调用
后来SharedUserData内存区没有了可执行权限,也不存放执行代码,而是仅仅用来存放地址,存放的是一个指向ntdll.dll中的ntdll.KiFastSystemCall的地址。并且ntdll.dll中的存根函数内的代码不是call edx,而是call [edx],SharedUserData内存区内不是SystemCallStub的地址,而是放入了一个指向ntdll.dll中的ntdll.KiFastSystemCall的地址。ntdll.KiFastSystemCall在ntdll.dll中的位置固定,因此通过该地址可以得到ntdll.dll模块的首地址。
伪造对象(创造触发条件)
步骤1
将selarray[99]中的option cache 指针数组中的第61个option的指针赋值给corruptedoption, option cache 指针数组中的元素删除
函数
– corruptedoptionaddr = readmem(optarryaddr+60*4);
– corruptedoption = selarray[99].options[60];
– selarray[99].options.remove(60);
– corruptaddr = corruptedoptionaddr+0x14;
步骤2
另一个options对象畸形添加给selarray[99]中的option cache 指针数组中,覆盖了之前option对象中的CTreeNode指针
函数
– overwrite(corruptaddr);
步骤3
因为之前是畸形添加,导致selarray[99]遗忘了添加的option元素,空间最终被回收
函数
– selarray[99].options.remove(0);
步骤4
函数
– elms[i].className = fakeobj;
步骤5
parentNode即CTreeNode指针指向的对象已经被字符串替换,调用parentNode的click方法时,系统底层就会寻找该对象的虚函数表,并执行其中相关的函数
函数
– corruptedoption.parentNode.click();
注意
1.
selarray[99].options.remove(0)非常关键。CTreeNode指针即在corruptedoption对象中,也在option cache指针数组中。执行完后就是删除option cache指针数组中的option指针和option对象。其实并没有真正删除,仅仅是使其无效化。
2.
整个脚本的最前方缺少下面的一个语句。<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)