HeapSpray堆喷射技术是用来辅助覆盖函数/虚函数指针的利用技术
HeapSpray简介
HeapSpray首次出现至少是在2001年,广泛使用应该在2005年,因为浏览器漏洞上这种利用比较有效造成了这种技术的爆发
HeapSpray是在shellcode前面加上大量滑板指令(slide code),组成一个注入代码段。然后向系统申请大量内存,并且反复用注入代码段来填充。这样就使得进程的地址空间被大量的注入代码所占据。然后结合其他的漏洞攻击技术控制程序流,使得程序执行到堆上,最终将导致shellcode的执行。(来自参考资料[1])
就像我想往水面上放一张纸,我可以想办法直接让纸停留在水面上,也可以把水填平了直接摆放纸,这种方法就类似后者的做法
所谓滑板指令,就是不会影响shellcode执行的指令,一般是0x90 NOP
指令,还有类NOP的指令0x0C0C or al 0x0c
,0x0C0D or al,0x0d
等
HeapSpray原理
HeapSpray的作用
对于传统的堆栈溢出攻击技术,利用难度很高了已经,有各种防范机制在:(来自参考资料[1])
目的 | 保护措施 |
---|---|
覆盖返回地址 | GS机制保护 |
覆盖SEH链表 | 通过SafeSEH,SEHOP机制保护 |
覆盖本地变量 | 可能被编译器经过重新整理和优化 |
覆盖空闲堆双向链表 | 通过Safe Unlinking保护 |
覆盖堆块投 | XP下使用HeaderCookie保护,Vista之后通过XOR HeaderData保护 |
覆盖Lookaside Linked list | Vista之后被移除 |
除此之外,还可以覆盖函数指针,对象指针,覆盖指针之后的利用就需要通过HeapSpray来辅助了
HeapSpray的内存填充
因为堆的起始分配地址很大,所以当申请大量内存的时候,堆很可能覆盖到的地址:0x0a0a0a0a,0x0c0c0c0c,0x0d0d0d0d等,为了稳定覆盖到0x0c0c0c0c地址,所以一般申请内存大小为200M
正常情况下的堆布局:
堆喷射后的堆布局:
要想shellcode执行成功,需要能准确命中shellcode的第一条语句,为了加强成功率,就在shellcode前面加上大量滑板指令,这样一来,只要能命中滑板指令也能命中shellcode,填充滑板指令可以大大提高shellcode的命中率
HeapSpray攻击技术
构造slide+shellcode,然后申请大量空间,覆盖到0x0c0c0c0c
滑板指令为啥不选择0x90,因为当覆盖函数指针之后,使用0x90909090去覆盖,程序就会跑到内核空间去执行,这就执行不了了,所以选择0x0c0c0c0c就可以了
调用该函数的时候就会跳转到0x0c0c0c0c去执行,然后通过滑板指令一路滑到shellcode上执行
不管是函数指针还是虚函数指针,都可以用这种方法进行攻击
HeapSpray防范
-
HeapSpray技术的一个特点就是会突然申请大量内存,内存中有大量的滑板指令,可以检测应用程序内存是否突然大量增加,然后检查堆上的数据是否是滑板指令,来判断是否发生了HeapSpray攻击
-
注入模块到进程中检测敏感地址(0x0c0c0c0c)的覆盖行为