演示Heap Spray(堆喷射)的原理
来源:互联网 发布:汽车驾驶模拟软件 编辑:程序博客网 时间:2024/04/30 12:21
Heap Spray原理浅析 这篇文章应该是网上阐释堆喷原理最为详尽和易懂的一篇。唯一让我感到遗憾的是:文章结尾处给出的例子是基于javascript的,这对于我这种门外汉来说并不是一个很好的练功房。结合自己对文章的理解,在这给出c++版本的堆喷射演示代码。
#include <windows.h>#include <stdio.h>class base{char m_buf[8];public:virtual int baseInit1(){printf("%s\n","baseInit1");return 0;}virtual int baseInit2(){printf("%s\n","baseInit2");return 0;}};int main(){unsigned int bufLen = 200*1024*1024;base* baseObj = new base;char buff[8] = {0};char* spray = new char[bufLen];memset(spray,0x0c,sizeof(char)*bufLen);memset(spray+bufLen-0x10,0xcc,0x10);strcpy(buff,"12345678\x0c\x0c\x0c\x0c");baseObj->baseInit1();return 0;}
演示用的代码就长这样,堆喷射的过程容我缓缓道来。
初始时baseObj分配得到的对象地址为:
0:000> dd baseObj L10012ff6c 004300A012ff6c是指针变量baseObj在栈上的地址,其值指向0x4300A0----这是分配在堆上的base对象。从这开始的4B是base对象的虚函数表指针,其值:0:000> dd 4300a0 L1004300A0 0042202c虚函数表指针当然就指向虚函数表,表中每项都是函数指针,当程序调用虚函数时就会依次通过检索虚函数表指针->虚函数表->虚函数来定位要执行的代码。基于上面这种程序定位虚函数的方法,要利用虚函数的核心就变成伪造虚函数表。常见方法有:溢出栈变量,因为baseObj指针保存在栈上,溢出后baseObj指向的不再是堆上的base对象,而是指向某个被伪造的数值。这样,baseObj就认为这个伪造的数值就是从new base;返回的对象。接着只要在这个伪造的数值上继续构造虚函数表以及虚函数指针,就能达到利用的目的。
当程序调用new分配大约200M的虚拟空间后,应该会把分配得到的空间存放到crt堆的VirtualAllocdBlocks队列中:
0:000> dt _PEB 7ffdf000 ;查看进程堆分布ntdll!_PEB+0x088 NumberOfHeaps : 4+0x090 ProcessHeaps : 0x773a8500 -> 0x001c0000 Void;进程有4个堆 堆句柄记录在0x773a8500开始的数组中0:000> dd 0x773a8500 L8773a8500 001c0000 00010000 00020000 003c0000;crt堆一般是程序堆数组元素中最后一个 所以调用new char[bufLen];后挂入从0x3c0000开始处的堆虚拟分配的HEAP!VirtualAllocdBlocks队列0:000> dt _HEAP 003c0000ntdll!_HEAP+0x0a0 VirtualAllocdBlocks : _LIST_ENTRY [ 0x630000 - 0x630000 ] 0:000> dd 0x530000 00630000 003c00a0 003c00a0 ;<----00630000处的8B是_LIST_ENTRY结构,指向HEAP!VirtualAllocdBlocks队列头00630030 0c800000 ;<----00530030处的16进制0c800000正好是请求分配的内存00630040 cdcdcdcd cdcdcdcd cdcdcdcd cdcdcdcd ;
从上面的结果来看,刚才调用new申请了从0x630000开始的大约200MB的内存,spray分配到的起始地址是0x630040,从此处开始到0x0CE30040结束,覆盖了共200MB的0x0C---所谓的slidecode,这当然包含了Heap Spray的目标地址0x0c0c0c0c:
0:000> dd 0x0c0c0c0c0c0c0c0c 0c0c0c0c 0c0c0c0c 0c0c0c0c 0c0c0c0c0c0c0c1c 0c0c0c0c 0c0c0c0c 0c0c0c0c 0c0c0c0c之后通过语句:strcpy(buff,"12345678\x0c\x0c\x0c\x0c");溢出并覆盖对象baseObj的虚表,使得虚表指针指向0x0c0c0c0c;这个地址又是个自指向的,从0x0c0c0c0c取到虚函数表。之后再从0x0c0c0c0c取出函数指针执行。当然,这又从0x0c0c0c0c继续执行下去,直到遇到最后的shellcode部分0:000> dd buff L10012ff64 00000000 ;buff位于栈地址0x12ff640:000> dd baseObj L10012ff6c 004300a0 ;baseObj位于栈地址0x12ff6c,覆盖后baseObj的虚函数表vftable指针值被设置为0x0c0c0c0c之后baseObj去虚函数表0x0c0c0c0c中取虚函数,由于0x0c0c0c0c附近的内存块取到的值都是0x0c0c0c0c,而这个值被进程当做函数指针,因此最后会发生类似call 0x0c0c0c0c,引导Eip去堆空间0x0c0c0c0c处取指令运行。eip将执行不痛不痒的指令,最终将执行到堆空间的最后部分----那是我们的Shellcode部分。总结起来:堆喷射是比较简单的一种利用方式;不同以往将shellcode存放在栈中,堆喷射将shellcode放在堆中,通过多种溢出方式组合使Eip执行到0x0c0c0c0c之类的堆空间
0 0
- 演示Heap Spray(堆喷射)的原理
- Heap Spray原理浅析
- Heap Spray原理浅析
- Heap Spray原理浅析
- Heap Spray原理浅析
- Heap Spray原理浅析
- Heap Spray原理浅析
- 堆喷射原理
- 传统的Heap Spray(转)
- Heap Spray
- Heap Spray:高危漏洞的垫脚石
- Heap Spray相关
- Heap Spray 技术
- 堆喷射学习笔记~
- Advanced Heap Spray Technique -- Heap Spray in Java
- 【HTML】菊花文、边框文和喷射尾巴的原理
- 堆的实现 Heap
- 堆(heap)的实现
- C++中cin、cin.get()、cin.getline()、getline()、gets()等函数的用法
- PAT(basic level) 1030 完美数列(25)
- weblogic 第一次进入控制台特别的慢处理方法
- java的Collection类详解
- 制作自定义背景Button按钮、自定义形状Button的全攻略
- 演示Heap Spray(堆喷射)的原理
- JSP—实现文件保存
- Android学习_使用Adapter创建ListView
- 正则表达式
- Codeforces 729A Interview with Oleg 简单暴力
- ubuntu update-alternatives命令
- struts2配置文件详解
- 【ARM-Linux开发】Gstreamer+QT+摄像头 编程总结
- LearnOpenGL 1.1 创建窗口