实验目的
掌握堆漏洞中fastbinattack
的原理和重复释放漏洞的利用方法.
实验条件
- 操作系统:Linux
- 语言环境:python
- 调试器:gdb、IDA Pro
实验要求
- 对被攻击程序的漏洞利用过程进行详细分析;
- 详细列出重复释放漏洞利用过程中 ,
fastbin
在4次malloc
过程中的变化情况,以及system()
函数地址被写入和system(/bin/sh)
调用被调用的过程;
四、程序分析
通过IDA对程序进行反编译,发现程序提供了四种操作new
、write
、delete
、exit
,对它们分别进行分析;
new
用于malloc
分配堆块,但限制最多只能分配九个堆块,并且限制了分配的大小小于96大于0,并且将malloc(v2)
后的指针赋值给ptr,由于ptr数组是未被初始化的,因此ptr位于bss段;
write
用于在ptr[i]
指向的位置直接进行read写操作,如果可以控制prt[i]
的内容,就可以完成任意写;
delete
函数中使用free
释放空间后,ptr
指针没有清零,造成DouobleFree漏洞;
system
程序存在system函数,位于0x4006E0
处,可以通过system函数实现/bin/sh
;
实验步骤
程序限制了malloc的大小,使得new只能申请到fastbin,所以利用fastbin attack来构造特定的chunk单链表链。
程序可以申请的大小为96字节(0x60
,再加上size
与prev_size
各8字节,一共是0x70
, 在fastbin中会位于0x70
的位置。
分析四次malloc过程中,fastbin的变化情况:
第一次malloc
首先进行第一次double free ,查看fastbin中的指针变化,步骤为
按照顺序申请chunk0、chunk1;
按照顺序释放chunk0、chunk1、chunk0;
1
2
3
4
5New(p, 0x60) # 0
New(p, 0x60) # 1
Delete(p, 0)
Delete(p, 1)
Delete(p, 0)在申请chunk之前,fastbin如下:
申请两个chunk之后,将chunk分配到fastbin中,其中堆顶的位置为
0xb2c0e0
;当free
chunk0
之后,chunk0
被放进fastbin里面,地址为0xb2c000
;free
chunk1
之后,chunk1
被放进fastbin中,chunk1
指向chunk0
,fd
表示了 下一个未被使用的chunk
的地址,这时后free的chunk1
成为了fastbin中的首个chunk
;再次执行free
chunk0
时,由于fastbin在执行free的时候仅验证了链表指针头部的块,对于链表后面的块,并没有进行验证。所以再次freechunk0
的时候,实际上是把chunk0
又加到了链的开头;
第二次malloc
在double free
之后,我们使得链表的形式为0xb2c000—▸0xb2c070◂—0xb2c000
,再次malloc
时,会从链表末尾取下一个块,直接分配给用户,所以malloc到的2号实际上是0xb2c000
,对该块进行编辑时,编辑起始的位置是0xb2c0e0
1 | New(p, 0x60) # 2 |
在执行过write 2 之后,地址0xb2c070
位置被改变了,变成了0x60208d
。由于0xb2c000
仍然被记录在链表中,所以fastbins中链表的最后一项也发生了改变;
修改了的fastbin链表,导致的是0x60208d这块被当做了fastbin的一个块,在分配的时候,申请的0x60大小实际上会分配0x70大小,而0x7f,也就是图中的0x60802d开始的第二个字节,恰好满足分配的条件,如果再往左或往右偏移,会出现不满足条件的情况;
接下来进行了三次malloc
操作,每一次malloc
操作都会从fastbin链表头取一个块进行分配;
1 | New(p, 0x60) # 3 |
取第一个块进行分配,分配
0xb2c070
;取第二个块进行分配,分配
0xb2c000
;第三次分配,把
0xb2c070
写入ptr[5]
中,fastbin只剩下了之前0x60208d这个地址里面的内容;查看
ptr
所在的地方,可以看到ptr[0]=ptr[2]=ptr[4]
、ptr[1]=ptr[3]
,而ptr[5]
是bss
段上的一个地址;
第三次malloc
接下来需要进行任意写,更改got
表里某一函数的地址为system,并写入参数/bin/sh
;
1 | Write(p, 4, '/bin/sh\x00') |
在向5写入payload之后,也就是向bss
段上的ptr
写入payload,把0、1、2这三个的ptr
都改为了free的got所在的地址0x602018
;
ptr
地址
执行write 2之后,free函数got
表的位置,理论上被写成system
函数的地址,但是由于掌握不熟练,一直没有调试到地址位置0x4006E0
;
get shell
此时程序已经get shell
完毕,可以执行命令如下;