简单分析IFrame漏洞
文/图 Mameluke
Bugtraq公布了一个IE的溢出漏洞,并给出了相关的利用EXP。这个漏洞目前还没有官方的补丁,所以危害挺大,更为严重的是这个漏洞的影响系统很广,在几乎所有的Windows语言和版本下面都可以利用。可以想象,隔不了多久也许就有相应的蠕虫或者是木马出来。 这个漏洞的描述和利用出来以后,有人专门写了分析的文章,为了照顾没有看过这个文章的朋友,这里还是简要的描述一下:
IE在处理IFrame的时候,调用Wcscpy拷贝IFrame的Name,这一步没有做长度的检查,结果导致覆盖到后面一个结构。这不是一个典型的栈溢出,所以并没有覆盖到Ret地址或者是Seh,所以利用基本上集中在利用原来程序本身代码的基础上。Ollydbg跟踪一个出错的HTML页面可以看到,异常触发时EIP一般会停在这一步上:
7108E242 8B40 34 MOV EAX,DWORD PTR DS:[EAX+34]
回溯到函数的开头,我们可以看到反汇编后出错的函数是这样的:
7108E229 55 PUSH EBP
7108E22A 8BEC MOV EBP,ESP
7108E22C 8B45 14 MOV EAX,DWORD PTR SS:[EBP+14]
7108E22F 8320 00 AND DWORD PTR DS:[EAX],0
7108E232 53 PUSH EBX
7108E233 8B5D 08 MOV EBX,DWORD PTR SS:[EBP+8]
7108E236 8B83 FC130000 MOV EAX,DWORD PTR DS:[EBX+13FC]
7108E23C 85C0 TEST EAX,EAX
7108E23E 56 PUSH ESI
7108E23F 57 PUSH EDI
7108E240 74 28 JE SHORT SHDOCVW.7108E26A
7108E242 8B40 34 MOV EAX,DWORD PTR DS:[EAX+34]
7108E245 85C0 TEST EAX,EAX
7108E247 74 21 JE SHORT SHDOCVW.7108E26A
7108E249 8B75 0C MOV ESI,DWORD PTR SS:[EBP+C]
7108E24C 6A 04 PUSH 4
7108E24E 59 POP ECX
7108E24F BF E8E30871 MOV EDI,SHDOCVW.7108E3E8
7108E254 33D2 XOR EDX,EDX
7108E256 F3:A7 REPE CMPS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
7108E258 75 10 JNZ SHORT SHDOCVW.7108E26A
7108E25A FF75 14 PUSH DWORD PTR SS:[EBP+14]
7108E25D 8B08 MOV ECX,DWORD PTR DS:[EAX]
7108E25F FF75 10 PUSH DWORD PTR SS:[EBP+10]
7108E262 50 PUSH EAX
7108E263 FF11 CALL DWORD PTR DS:[ECX]
我们可以控制的值最终在7108E236处传递给了Eax,然后我们精简一下上面的代码,更为直观的看看,是这样的:
7108E242 8B40 34 MOV EAX,DWORD PTR DS:[EAX+34]
7108E25D 8B08 MOV ECX,DWORD PTR DS:[EAX]
7108E263 FF11 CALL DWORD PTR DS:[ECX]
我们仅能控制EAX,接着IE会把EAX+13处的内容赋给EAX,再把EAX处的内容赋给ECX,最后ECX作为一个函数的指针被调用。这个过程还是很麻烦的,虽然我们能够控制其中的一个寄存器,并且可以间接的影响到程序的流程,但是这个“间接”的层数实在太多,三次对地址的访问使得我们很难找到一个比较好的地址,还有更糟糕的是就算找到了,也没有寄存器可以定位,栈内的数据似乎也没有直接指向我们能够控制的地方。
外面给出来的利用是使用的强行定位的方法。这种方法比较野蛮,去年某个Office漏洞时似乎见到有人用过,就是通过其它的路子预先申请大量的内存,强迫某个地址出现某些代码,然后让这个地址的内容和这个地址的值一致。这样不管你间接多少次,最后得到的还是这个地址,再Call的时候,就跳转过来了。
对于这个漏洞,直观的解释是比如我通过大量申请内存,最后控制了0x11111111及其附近的内容全部为0x11111111,那我就设定会间接影响到程序流程的那个EAX为0x111111111,通过两次取地址的内容操作后,Ecx的值还是0x11111111,最后一个Call自然就会跳转到0x11111111。
可以看到,这个地址除了要与其内容相同以外,还要求地址本身要是一个可执行且不会再次导致异常的指令。外面POC的是用的0x0D0D0D0D这个地址,填充的也是大量的0x0D0D0D0D,因为连续五个0x0D刚好可以构成一个XOR EAX, 0D0D0D0Dh,这是一个肯定不会再次导致异常的指令,按照这个POC所设想的,经过大量(而且个数通常不确定)的XOR EAX,0D0D0D0Dh后,最后肯定会执行到ShellCode,也就是JavaScript里面定义的那个ShellCode包含的数据。
这里还有一个小细节,那就是ShellCode前面四个字节为什么都是0x43呢?其实很简单,因为你不能确定前面这么多的0D,是不是刚好都构成了XOR EAX, 0D0D0D0Dh,最坏的情况是在ShellCode之前有一个0x0D,那肯定是要和ShellCode的前四个字节形成一条语句的,这四个0x43就是为了保证ShellCode能够完整地从开头开始运行,而本身0x43就是一个单字节的Inc edx,即使单独成为一条语句也没有什么大碍。
因为这个溢出不是堆溢出,而且对字符似乎也没有什么特别的约束,所以可以按照自己的需求替换掉ShellCode,无论是反向连接或者是下载并执行的都可以。最简单的办法就是在原来的基础上直接Copy&Paste一个过去,倘若要自己生成文件,那就要稍微麻烦一点,因为你要控制Eax的值,而它本身读过来的是一个Widechar,所以得要求你生成的文件也要是Unicode的。
一开始的时候,我也是直接就写,写到一半发现不太对劲,文件大小似乎不对(是我估计大小的两倍),结果用二进制编辑器打开一看才知道,原来这是一个Unicode格式的东西,文件的开头是0xFFFE,于是只好推翻重来。
我其实并没有弄清楚为什么作者选用了0x0D0D0D0D这样一个数字,也许和堆的管理有关。有几次我用04来代替所有的0d是成功的,不过大部分情况下0x0c0c0c0c处的数据不是我们所能控制的,如果堆的虚拟分配确实是从低地址到高地址,那至多200M的数据就能控制到0x0d0d0d0d的地方,JavaScript中循环分配的次数,也许还可以减上一减。不过不清楚堆的分配情况,这些也就是瞎猜的。
另外,还有没有可能有其它比较好的利用方法呢?Leven在XFocus上提到有,不过不知道具体是什么,希望Leven高人能够共享一下……前段时间看Shok的文章时知道Lookaside表,当小堆(1000字节)释放的时候会注册一个对应的项,而这个项是可以计算出来的,如果我们可以在内存中找到我们计算出来的这个数字,似乎也是条路子。麻烦的是已经释放的堆头部会有一个指针,这个指针是不是可以执行的,这是一个问题,看来这种方法成功率还要看当时的人品是否有问题……
这个漏洞目前虽然没有官方的补丁,但是“民间补丁”已经有了,大家最好赶快补上,因为这个漏洞还是比较有攻击性的。
本篇文章来源于 黑客基地-全球最大的中文黑客站 原文链接:http://www.hackbase.com/tech/2009-02-16/51234.html
简单学习 IFrame 漏洞
最新推荐文章于 2023-12-26 10:09:09 发布