コード例 #1
0
def test_arm_postprocess_ret():

    for i in xrange(3):
        # e91ba8f0
        # ldmdb  R11, {R4,R11,SP,PC}
        irsb = pyvex.IRSB(data=b'\xe9\x1b\xa8\xf0',
                          mem_addr=0xed4028,
                          arch=archinfo.ArchARMEL(endness=archinfo.Endness.BE),
                          num_inst=1,
                          opt_level=i)
        nose.tools.assert_equal(irsb.jumpkind, 'Ijk_Ret')

        # e91badf0
        # ldmdb  R11, {R4-R8,R10,R11,SP,PC}
        irsb = pyvex.IRSB(data=b'\xe9\x1b\xa8\xf0',
                          mem_addr=0x4d4028,
                          arch=archinfo.ArchARMEL(endness=archinfo.Endness.BE),
                          num_inst=1,
                          opt_level=i)
        nose.tools.assert_equal(irsb.jumpkind, 'Ijk_Ret')

        # 00a89de8
        # ldmfd SP, {R11,SP,PC}
        # Fixed by Fish in the VEX fork, commit 43c78f608490f9a5c71c7fca87c04759c1b93741
        irsb = pyvex.IRSB(data=b'\x00\xa8\x9d\xe8',
                          mem_addr=0xc800b57c,
                          arch=archinfo.ArchARMEL(endness=archinfo.Endness.LE),
                          num_inst=1,
                          opt_level=1)
        nose.tools.assert_equal(irsb.jumpkind, 'Ijk_Ret')
コード例 #2
0
def test_arm_postprocess_ret():
    for i in range(3):
        # e91ba8f0
        # ldmdb  R11, {R4,R11,SP,PC}
        irsb = pyvex.IRSB(
            data=b"\xe9\x1b\xa8\xf0",
            mem_addr=0xED4028,
            arch=archinfo.ArchARMEL(endness=archinfo.Endness.BE),
            num_inst=1,
            opt_level=i,
        )
        assert irsb.jumpkind == "Ijk_Ret"

        # e91badf0
        # ldmdb  R11, {R4-R8,R10,R11,SP,PC}
        irsb = pyvex.IRSB(
            data=b"\xe9\x1b\xa8\xf0",
            mem_addr=0x4D4028,
            arch=archinfo.ArchARMEL(endness=archinfo.Endness.BE),
            num_inst=1,
            opt_level=i,
        )
        assert irsb.jumpkind == "Ijk_Ret"

        # 00a89de8
        # ldmfd SP, {R11,SP,PC}
        # Fixed by Fish in the VEX fork, commit 43c78f608490f9a5c71c7fca87c04759c1b93741
        irsb = pyvex.IRSB(
            data=b"\x00\xa8\x9d\xe8",
            mem_addr=0xC800B57C,
            arch=archinfo.ArchARMEL(endness=archinfo.Endness.LE),
            num_inst=1,
            opt_level=1,
        )
        assert irsb.jumpkind == "Ijk_Ret"
コード例 #3
0
ファイル: elf.py プロジェクト: mephi42/cle
    def extract_arch(reader):
        arch_str = reader['e_machine']
        if arch_str == 'ARM':
            if reader.header.e_flags & 0x200:
                return archinfo.ArchARMEL('Iend_LE' if reader.little_endian else 'Iend_BE')
            elif reader.header.e_flags & 0x400:
                return archinfo.ArchARMHF('Iend_LE' if reader.little_endian else 'Iend_BE')

        return archinfo.arch_from_id(arch_str, 'le' if reader.little_endian else 'be', reader.elfclass)
コード例 #4
0
ファイル: elf.py プロジェクト: zhuyue1314/cle
    def __init__(self, binary, **kwargs):
        super(ELF, self).__init__(binary, **kwargs)
        self.reader = elffile.ELFFile(open(self.binary, 'rb'))

        # Get an appropriate archinfo.Arch for this binary, unless the user specified one
        if self.arch is None:
            if self.reader.header.e_machine == 'EM_ARM' and \
                    self.reader.header.e_flags & 0x200:
                self.set_arch(archinfo.ArchARMEL('Iend_LE' if 'LSB' in self.reader.header.e_ident.EI_DATA else 'Iend_BE'))
            elif self.reader.header.e_machine == 'EM_ARM' and \
                    self.reader.header.e_flags & 0x400:
                self.set_arch(archinfo.ArchARMHF('Iend_LE' if 'LSB' in self.reader.header.e_ident.EI_DATA else 'Iend_BE'))
            else:
                self.set_arch(archinfo.arch_from_id(self.reader.header.e_machine,
                                                self.reader.header.e_ident.EI_DATA,
                                                self.reader.header.e_ident.EI_CLASS))

        self.strtab = None
        self.dynsym = None
        self.hashtable = None

        self._dynamic = {}
        self.deps = []
        self.rela_type = None

        self._inits_extracted = False
        self._preinit_arr = []
        self._init_func = None
        self._init_arr = []
        self._fini_func = None
        self._fini_arr = []

        self._symbol_cache = {}
        self.symbols_by_addr = {}
        self.imports = {}
        self.resolved_imports = []

        self.relocs = []
        self.jmprel = {}

        self._entry = self.reader.header.e_entry
        self.pic = self.reader.header.e_type == 'ET_DYN'

        self.tls_used = False
        self.tls_module_id = None
        self.tls_block_offset = None
        self.tls_block_size = None
        self.tls_tdata_start = None
        self.tls_tdata_size = None

        self.__register_segments()
        self.__register_sections()

        # call the methods defined by MetaELF
        self._ppc64_abiv1_entry_fix()
        self._load_plt()
コード例 #5
0
def test_arm_postprocess_ret():

    for i in xrange(3):
        # e91ba8f0
        # ldmdb  R11, {R4,R11,SP,PC}
        irsb = pyvex.IRSB(data='\xe9\x1b\xa8\xf0',
                          mem_addr=0xed4028,
                          arch=archinfo.ArchARMEL(endness=archinfo.Endness.BE),
                          num_inst=1,
                          opt_level=i)
        nose.tools.assert_equal(irsb.jumpkind, 'Ijk_Ret')

        # e91badf0
        # ldmdb  R11, {R4-R8,R10,R11,SP,PC}
        irsb = pyvex.IRSB(data='\xe9\x1b\xa8\xf0',
                          mem_addr=0x4d4028,
                          arch=archinfo.ArchARMEL(endness=archinfo.Endness.BE),
                          num_inst=1,
                          opt_level=i)
        nose.tools.assert_equal(irsb.jumpkind, 'Ijk_Ret')
コード例 #6
0
    def extract_arch(reader):
        arch_str = reader['e_machine']
        if 'ARM' in arch_str:
            # Check the ARM attributes, if they exist
            arm_attrs = ELF._extract_arm_attrs(reader)
            if arm_attrs and 'TAG_CPU_NAME' in arm_attrs:
                if arm_attrs['TAG_CPU_NAME'].endswith("-M") \
                    or 'Cortex-M' in arm_attrs['TAG_CPU_NAME']:
                    return archinfo.ArchARMCortexM('Iend_LE')
            if reader.header.e_flags & 0x200:
                return archinfo.ArchARMEL(
                    'Iend_LE' if reader.little_endian else 'Iend_BE')
            elif reader.header.e_flags & 0x400:
                return archinfo.ArchARMHF(
                    'Iend_LE' if reader.little_endian else 'Iend_BE')

        return archinfo.arch_from_id(arch_str,
                                     'le' if reader.little_endian else 'be',
                                     reader.elfclass)
コード例 #7
0
def detect_arm_ivt(stream):
    """

    :param stream:
    :type stream: file
    :return:
    """
    min_arm_sp = 0x20000000
    max_arm_sp = 0x20100000

    # TODO: We're just looking at the front for now
    try:
        maybe_sp = stream.read(4)
        maybe_le_sp = struct.unpack('<I', maybe_sp)[0]
        maybe_be_sp = struct.unpack(">I", maybe_sp)[0]
        if min_arm_sp < maybe_le_sp < max_arm_sp:
            maybe_arch = archinfo.ArchARMEL(endness=archinfo.Endness.LE)
            l.debug(
                "Found possible Little-Endian ARM IVT with initial SP %#08x" %
                maybe_le_sp)
            maybe_entry = struct.unpack('<I', stream.read(4))[0]
            l.debug("Reset vector at %#08x" % maybe_entry)
            maybe_base = maybe_entry & 0xffff0000  # A complete guess
            l.debug("Guessing base address at %#08x" % maybe_base)
            return maybe_arch, maybe_base, maybe_entry
        elif min_arm_sp < maybe_be_sp < max_arm_sp:
            maybe_arch = archinfo.ArchARM(endness=archinfo.Endness.BE)
            l.debug("Found possible Big-Endian ARM IVT with initial SP %#08x" %
                    maybe_be_sp)
            maybe_entry = struct.unpack('>I', stream.read(4))[0]
            l.debug("Reset vector at %#08x" % maybe_entry)
            maybe_base = maybe_entry & 0xffff0000  # A complete guess
            l.debug("Guessing base address at %#08x" % maybe_base)
            return maybe_arch, maybe_base, maybe_entry
        else:
            # Nope
            return (None, None, None)
    except:
        l.exception("Something died")
        return (None, None, None)
    finally:
        stream.seek(0)
コード例 #8
0
ファイル: test_arm_postprocess.py プロジェクト: schieb/pyvex
def test_arm_postprocess():
    for i in xrange(3):
        # Thumb

        # push  {r7}
        # add   r7, sp, #0
        # mov.w r1, #6
        # mov   r0, pc
        # add.w lr, r0, r1
        # b.w   10408
        irsb = pyvex.IRSB(data=('\x80\xb4'
                                '\x00\xaf'
                                '\x4f\xf0\x06\x01'
                                '\x78\x46'
                                '\x00\xeb\x01\x0e'
                                '\xff\xf7\xec\xbf'),
                          mem_addr=0x1041f,
                          arch=archinfo.ArchARMEL(),
                          num_inst=6,
                          bytes_offset=1,
                          opt_level=i)
        nose.tools.assert_equals(irsb.jumpkind, 'Ijk_Call')

        # mov   lr, pc
        # b.w   10408
        irsb = pyvex.IRSB(data=('\xfe\x46'
                                '\xe9\xe7'),
                          mem_addr=0x10431,
                          arch=archinfo.ArchARMEL(),
                          num_inst=2,
                          bytes_offset=1,
                          opt_level=i)
        nose.tools.assert_equals(irsb.jumpkind, 'Ijk_Call')

        # add   r2, pc, #0
        # add.w lr, r2, #4
        # ldr.w pc, [pc, #52]
        irsb = pyvex.IRSB(data=('\x00\xa2'
                                '\x02\xf1\x06\x0e'
                                '\xdf\xf8\x34\xf0'),
                          mem_addr=0x10435,
                          arch=archinfo.ArchARMEL(),
                          num_inst=3,
                          bytes_offset=1,
                          opt_level=i)
        nose.tools.assert_equals(irsb.jumpkind, 'Ijk_Call')

        # ldr   r0, [pc, #48]
        # mov   r1, pc
        # add.w r2, r1, #4
        # add.w r3, r2, #4
        # add.w r4, r3, #4
        # add.w lr, r4, #4
        # mov   pc, r0
        irsb = pyvex.IRSB(data=('\x0c\x48'
                                '\x79\x46'
                                '\x01\xf1\x04\x02'
                                '\x02\xf1\x04\x03'
                                '\x03\xf1\x04\x04'
                                '\x04\xf1\x04\x0e'
                                '\x87\x46'),
                          mem_addr=0x1043f,
                          arch=archinfo.ArchARMEL(),
                          num_inst=7,
                          bytes_offset=1,
                          opt_level=i)
        nose.tools.assert_equals(irsb.jumpkind, 'Ijk_Call')

        # eor.w r0, r0, r0
        # mov   lr, pc
        # b.n   10460
        irsb = pyvex.IRSB(data=('\x80\xea\x00\x00'
                                '\x86\x46'
                                '\x01\xe0'),
                          mem_addr=0x10455,
                          arch=archinfo.ArchARMEL(),
                          num_inst=3,
                          bytes_offset=1,
                          opt_level=i)
        nose.tools.assert_equals(irsb.jumpkind, 'Ijk_Boring')

        # Thumb compiled with optimizations (gcc -O2)

        # mov.w r1, #6
        # mov   r0, pc
        # add.w lr, r0, r1
        # b.w   104bc
        irsb = pyvex.IRSB(data=('\x4f\xf0\x06\x01'
                                '\x78\x46'
                                '\x00\xeb\x01\x0e'
                                '\x00\xf0\xc5\xb8'),
                          mem_addr=0x10325,
                          arch=archinfo.ArchARMEL(),
                          num_inst=4,
                          bytes_offset=1,
                          opt_level=i)
        nose.tools.assert_equals(irsb.jumpkind, 'Ijk_Call')

        # ldr   r0, [pc, #56]
        # mov   r1, pc
        # add.w r2, r1, #4
        # add.w r3, r2, #4
        # add.w r4, r3, #4
        # add.w lr, r4, #4
        # mov   pc, r0
        irsb = pyvex.IRSB(data=('\x0e\x48'
                                '\x79\x46'
                                '\x01\xf1\x04\x02'
                                '\x02\xf1\x04\x03'
                                '\x03\xf1\x04\x04'
                                '\x04\xf1\x04\x0e'
                                '\x87\x46'),
                          mem_addr=0x10333,
                          arch=archinfo.ArchARMEL(),
                          num_inst=7,
                          bytes_offset=1,
                          opt_level=i)
        nose.tools.assert_equals(irsb.jumpkind, 'Ijk_Call')

        # add   r2, pc, #0
        # add.w lr, r2, #6
        # ldr.w pc, [pc, #28]
        irsb = pyvex.IRSB(data=('\x00\xa2'
                                '\x02\xf1\x06\x0e'
                                '\xdf\xf8\x1c\xf0'),
                          mem_addr=0x10349,
                          arch=archinfo.ArchARMEL(),
                          num_inst=3,
                          bytes_offset=1,
                          opt_level=i)
        nose.tools.assert_equals(irsb.jumpkind, 'Ijk_Call')

        # mov   lr, pc
        # b.w   104bc
        irsb = pyvex.IRSB(data=('\xfe\x46'
                                '\xb2\xe0'),
                          mem_addr=0x10353,
                          arch=archinfo.ArchARMEL(),
                          num_inst=2,
                          bytes_offset=1,
                          opt_level=i)
        nose.tools.assert_equals(irsb.jumpkind, 'Ijk_Call')

        # eor.w r0, r0, r0
        # mov   lr, pc
        # b.n   10362
        irsb = pyvex.IRSB(data=('\x80\xea\x00\x00'
                                '\x86\x46'
                                '\x01\xe0'),
                          mem_addr=0x10357,
                          arch=archinfo.ArchARMEL(),
                          num_inst=3,
                          bytes_offset=1,
                          opt_level=i)
        nose.tools.assert_equals(irsb.jumpkind, 'Ijk_Boring')

        # ARM compiled with optimizations (gcc -O2)

        # mov   r1, #4
        # mov   r0, pc
        # add   lr, r0, r1
        # ldr   pc, [pc, #56]
        irsb = pyvex.IRSB(data=('\x04\x10\xa0\xe3'
                                '\x0f\x00\xa0\xe1'
                                '\x01\xe0\x80\xe0'
                                '\x38\xf0\x9f\xe5'),
                          mem_addr=0x10298,
                          arch=archinfo.ArchARMEL(),
                          num_inst=4,
                          opt_level=i)
        nose.tools.assert_equals(irsb.jumpkind, 'Ijk_Call')

        # add   r1, pc, #0
        # add   r2, r1, #4
        # add   r3, r2, #4
        # add   r4, r3, #4
        # add   lr, r4, #4
        # b     10414
        irsb = pyvex.IRSB(data=('\x00\x10\x8f\xe2'
                                '\x04\x20\x81\xe2'
                                '\x04\x30\x82\xe2'
                                '\x04\x40\x83\xe2'
                                '\x04\xe0\x84\xe2'
                                '\x54\x00\x00\xea'),
                          mem_addr=0x102a8,
                          arch=archinfo.ArchARMEL(),
                          num_inst=6,
                          opt_level=i)
        nose.tools.assert_equals(irsb.jumpkind, 'Ijk_Call')

        # mov   lr, pc
        # b     10414
        irsb = pyvex.IRSB(data=('\x0f\xe0\xa0\xe1'
                                '\x52\x00\x00\xea'),
                          mem_addr=0x102c0,
                          arch=archinfo.ArchARMEL(),
                          num_inst=2,
                          opt_level=i)
        nose.tools.assert_equals(irsb.jumpkind, 'Ijk_Call')

        # eor   r0, r0, r0
        # mov   lr, r0
        # b     102d8
        irsb = pyvex.IRSB(data=('\x00\x00\x20\xe0'
                                '\x00\xe0\xa0\xe1'
                                '\x00\x00\x00\xea'),
                          mem_addr=0x102c8,
                          arch=archinfo.ArchARMEL(),
                          num_inst=3,
                          opt_level=i)
        nose.tools.assert_equals(irsb.jumpkind, 'Ijk_Boring')

        # ARM

        # push  {fp}
        # add   fp, sp, #0
        # mov   r1, #4
        # mov   r0, pc
        # add   lr, r0, r1
        # ldr   pc, [pc, #68]
        irsb = pyvex.IRSB(data=('\x04\xb0\x2d\xe5'
                                '\x00\xb0\x8d\xe2'
                                '\x04\x10\xa0\xe3'
                                '\x0f\x00\xa0\xe1'
                                '\x01\xe0\x80\xe0'
                                '\x44\xf0\x9f\xe5'),
                          mem_addr=0x103e8,
                          arch=archinfo.ArchARMEL(),
                          num_inst=6,
                          opt_level=i)
        nose.tools.assert_equals(irsb.jumpkind, 'Ijk_Call')

        # add   r1, pc, #0
        # add   r2, r1, #4
        # add   r3, r2, #4
        # add   r4, r3, #4
        # add   lr, r4, #4
        # b     103c4
        irsb = pyvex.IRSB(data=('\x00\x10\x8f\xe2'
                                '\x04\x20\x81\xe2'
                                '\x04\x30\x82\xe2'
                                '\x04\x40\x83\xe2'
                                '\x04\xe0\x84\xe2'
                                '\x54\xff\xff\xea'),
                          mem_addr=0x10400,
                          arch=archinfo.ArchARMEL(),
                          num_inst=6,
                          opt_level=i)
        nose.tools.assert_equals(irsb.jumpkind, 'Ijk_Call')

        # mov   lr, pc
        # b     103c4
        irsb = pyvex.IRSB(data=('\x0f\xe0\xa0\xe1'
                                '\xe8\xff\xff\xea'),
                          mem_addr=0x10418,
                          arch=archinfo.ArchARMEL(),
                          num_inst=2,
                          opt_level=i)
        nose.tools.assert_equals(irsb.jumpkind, 'Ijk_Call')

        # eor   r0, r0, r0
        # mov   lr, r0
        # b     10430
        irsb = pyvex.IRSB(data=('\x00\x00\x20\xe0'
                                '\x00\xe0\xa0\xe1'
                                '\x00\x00\x00\xea'),
                          mem_addr=0x10420,
                          arch=archinfo.ArchARMEL(),
                          num_inst=3,
                          opt_level=i)
        nose.tools.assert_equals(irsb.jumpkind, 'Ijk_Boring')
コード例 #9
0
def test_arm_postprocess_call():
    for i in range(3):
        # Thumb

        # push  {r7}
        # add   r7, sp, #0
        # mov.w r1, #6
        # mov   r0, pc
        # add.w lr, r0, r1
        # b.w   10408
        irsb = pyvex.IRSB(
            data=(
                b"\x80\xb4"
                b"\x00\xaf"
                b"\x4f\xf0\x06\x01"
                b"\x78\x46"
                b"\x00\xeb\x01\x0e"
                b"\xff\xf7\xec\xbf"
            ),
            mem_addr=0x1041F,
            arch=archinfo.ArchARMEL(),
            num_inst=6,
            bytes_offset=1,
            opt_level=i,
        )
        assert irsb.jumpkind == "Ijk_Call"

        # mov   lr, pc
        # b.w   10408
        irsb = pyvex.IRSB(
            data=(b"\xfe\x46" b"\xe9\xe7"),
            mem_addr=0x10431,
            arch=archinfo.ArchARMEL(),
            num_inst=2,
            bytes_offset=1,
            opt_level=i,
        )
        assert irsb.jumpkind == "Ijk_Call"

        # add   r2, pc, #0
        # add.w lr, r2, #4
        # ldr.w pc, [pc, #52]
        irsb = pyvex.IRSB(
            data=(b"\x00\xa2" b"\x02\xf1\x06\x0e" b"\xdf\xf8\x34\xf0"),
            mem_addr=0x10435,
            arch=archinfo.ArchARMEL(),
            num_inst=3,
            bytes_offset=1,
            opt_level=i,
        )
        assert irsb.jumpkind == "Ijk_Call"

        # ldr   r0, [pc, #48]
        # mov   r1, pc
        # add.w r2, r1, #4
        # add.w r3, r2, #4
        # add.w r4, r3, #4
        # add.w lr, r4, #4
        # mov   pc, r0
        irsb = pyvex.IRSB(
            data=(
                b"\x0c\x48"
                b"\x79\x46"
                b"\x01\xf1\x04\x02"
                b"\x02\xf1\x04\x03"
                b"\x03\xf1\x04\x04"
                b"\x04\xf1\x04\x0e"
                b"\x87\x46"
            ),
            mem_addr=0x1043F,
            arch=archinfo.ArchARMEL(),
            num_inst=7,
            bytes_offset=1,
            opt_level=i,
        )
        assert irsb.jumpkind == "Ijk_Call"

        # eor.w r0, r0, r0
        # mov   lr, pc
        # b.n   10460
        irsb = pyvex.IRSB(
            data=(b"\x80\xea\x00\x00" b"\x86\x46" b"\x01\xe0"),
            mem_addr=0x10455,
            arch=archinfo.ArchARMEL(),
            num_inst=3,
            bytes_offset=1,
            opt_level=i,
        )
        assert irsb.jumpkind == "Ijk_Boring"

        # Thumb compiled with optimizations (gcc -O2)

        # mov.w r1, #6
        # mov   r0, pc
        # add.w lr, r0, r1
        # b.w   104bc
        irsb = pyvex.IRSB(
            data=(
                b"\x4f\xf0\x06\x01" b"\x78\x46" b"\x00\xeb\x01\x0e" b"\x00\xf0\xc5\xb8"
            ),
            mem_addr=0x10325,
            arch=archinfo.ArchARMEL(),
            num_inst=4,
            bytes_offset=1,
            opt_level=i,
        )
        assert irsb.jumpkind == "Ijk_Call"

        # ldr   r0, [pc, #56]
        # mov   r1, pc
        # add.w r2, r1, #4
        # add.w r3, r2, #4
        # add.w r4, r3, #4
        # add.w lr, r4, #4
        # mov   pc, r0
        irsb = pyvex.IRSB(
            data=(
                b"\x0e\x48"
                b"\x79\x46"
                b"\x01\xf1\x04\x02"
                b"\x02\xf1\x04\x03"
                b"\x03\xf1\x04\x04"
                b"\x04\xf1\x04\x0e"
                b"\x87\x46"
            ),
            mem_addr=0x10333,
            arch=archinfo.ArchARMEL(),
            num_inst=7,
            bytes_offset=1,
            opt_level=i,
        )
        assert irsb.jumpkind == "Ijk_Call"

        # add   r2, pc, #0
        # add.w lr, r2, #6
        # ldr.w pc, [pc, #28]
        irsb = pyvex.IRSB(
            data=(b"\x00\xa2" b"\x02\xf1\x06\x0e" b"\xdf\xf8\x1c\xf0"),
            mem_addr=0x10349,
            arch=archinfo.ArchARMEL(),
            num_inst=3,
            bytes_offset=1,
            opt_level=i,
        )
        assert irsb.jumpkind == "Ijk_Call"

        # mov   lr, pc
        # b.w   104bc
        irsb = pyvex.IRSB(
            data=(b"\xfe\x46" b"\xb2\xe0"),
            mem_addr=0x10353,
            arch=archinfo.ArchARMEL(),
            num_inst=2,
            bytes_offset=1,
            opt_level=i,
        )
        assert irsb.jumpkind == "Ijk_Call"

        # eor.w r0, r0, r0
        # mov   lr, pc
        # b.n   10362
        irsb = pyvex.IRSB(
            data=(b"\x80\xea\x00\x00" b"\x86\x46" b"\x01\xe0"),
            mem_addr=0x10357,
            arch=archinfo.ArchARMEL(),
            num_inst=3,
            bytes_offset=1,
            opt_level=i,
        )
        assert irsb.jumpkind == "Ijk_Boring"

        # ARM compiled with optimizations (gcc -O2)

        # mov   r1, #4
        # mov   r0, pc
        # add   lr, r0, r1
        # ldr   pc, [pc, #56]
        irsb = pyvex.IRSB(
            data=(
                b"\x04\x10\xa0\xe3"
                b"\x0f\x00\xa0\xe1"
                b"\x01\xe0\x80\xe0"
                b"\x38\xf0\x9f\xe5"
            ),
            mem_addr=0x10298,
            arch=archinfo.ArchARMEL(),
            num_inst=4,
            opt_level=i,
        )
        assert irsb.jumpkind == "Ijk_Call"

        # add   r1, pc, #0
        # add   r2, r1, #4
        # add   r3, r2, #4
        # add   r4, r3, #4
        # add   lr, r4, #4
        # b     10414
        irsb = pyvex.IRSB(
            data=(
                b"\x00\x10\x8f\xe2"
                b"\x04\x20\x81\xe2"
                b"\x04\x30\x82\xe2"
                b"\x04\x40\x83\xe2"
                b"\x04\xe0\x84\xe2"
                b"\x54\x00\x00\xea"
            ),
            mem_addr=0x102A8,
            arch=archinfo.ArchARMEL(),
            num_inst=6,
            opt_level=i,
        )
        assert irsb.jumpkind == "Ijk_Call"

        # mov   lr, pc
        # b     10414
        irsb = pyvex.IRSB(
            data=(b"\x0f\xe0\xa0\xe1" b"\x52\x00\x00\xea"),
            mem_addr=0x102C0,
            arch=archinfo.ArchARMEL(),
            num_inst=2,
            opt_level=i,
        )
        assert irsb.jumpkind == "Ijk_Call"

        # eor   r0, r0, r0
        # mov   lr, r0
        # b     102d8
        irsb = pyvex.IRSB(
            data=(b"\x00\x00\x20\xe0" b"\x00\xe0\xa0\xe1" b"\x00\x00\x00\xea"),
            mem_addr=0x102C8,
            arch=archinfo.ArchARMEL(),
            num_inst=3,
            opt_level=i,
        )
        assert irsb.jumpkind == "Ijk_Boring"

        # ARM

        # push  {fp}
        # add   fp, sp, #0
        # mov   r1, #4
        # mov   r0, pc
        # add   lr, r0, r1
        # ldr   pc, [pc, #68]
        irsb = pyvex.IRSB(
            data=(
                b"\x04\xb0\x2d\xe5"
                b"\x00\xb0\x8d\xe2"
                b"\x04\x10\xa0\xe3"
                b"\x0f\x00\xa0\xe1"
                b"\x01\xe0\x80\xe0"
                b"\x44\xf0\x9f\xe5"
            ),
            mem_addr=0x103E8,
            arch=archinfo.ArchARMEL(),
            num_inst=6,
            opt_level=i,
        )
        assert irsb.jumpkind == "Ijk_Call"

        # add   r1, pc, #0
        # add   r2, r1, #4
        # add   r3, r2, #4
        # add   r4, r3, #4
        # add   lr, r4, #4
        # b     103c4
        irsb = pyvex.IRSB(
            data=(
                b"\x00\x10\x8f\xe2"
                b"\x04\x20\x81\xe2"
                b"\x04\x30\x82\xe2"
                b"\x04\x40\x83\xe2"
                b"\x04\xe0\x84\xe2"
                b"\x54\xff\xff\xea"
            ),
            mem_addr=0x10400,
            arch=archinfo.ArchARMEL(),
            num_inst=6,
            opt_level=i,
        )
        assert irsb.jumpkind == "Ijk_Call"

        # mov   lr, pc
        # b     103c4
        irsb = pyvex.IRSB(
            data=(b"\x0f\xe0\xa0\xe1" b"\xe8\xff\xff\xea"),
            mem_addr=0x10418,
            arch=archinfo.ArchARMEL(),
            num_inst=2,
            opt_level=i,
        )
        assert irsb.jumpkind == "Ijk_Call"

        # eor   r0, r0, r0
        # mov   lr, r0
        # b     10430
        irsb = pyvex.IRSB(
            data=(b"\x00\x00\x20\xe0" b"\x00\xe0\xa0\xe1" b"\x00\x00\x00\xea"),
            mem_addr=0x10420,
            arch=archinfo.ArchARMEL(),
            num_inst=3,
            opt_level=i,
        )
        assert irsb.jumpkind == "Ijk_Boring"

        # From a "real thing" compiled with armc
        # ARM:
        #
        irsb = pyvex.IRSB(
            data=(
                b"H\x10\x9b\xe5"
                b"\x0b\x00\xa0\xe1"
                b"\x04 \x91\xe5"
                b"\x04\xe0\x8f\xe2"
                b"\x01\x10\x82\xe0"
                b"\x01\xf0\xa0\xe1"
            ),
            mem_addr=0x264B4C,
            arch=archinfo.ArchARMEL(),
            num_inst=6,
            opt_level=i,
        )
        assert irsb.jumpkind == "Ijk_Call"
コード例 #10
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()
コード例 #11
0
    def __init__(self, binary, **kwargs):
        super(ELF, self).__init__(binary, **kwargs)
        try:
            self.reader = elffile.ELFFile(self.binary_stream)
        except ELFError:
            raise CLECompatibilityError

        # Get an appropriate archinfo.Arch for this binary, unless the user specified one
        if self.arch is None:
            arch_str = self.reader['e_machine']
            if arch_str == 'ARM':
                if self.reader.header.e_flags & 0x200:
                    self.set_arch(
                        archinfo.ArchARMEL('Iend_LE' if self.reader.
                                           little_endian else 'Iend_BE'))
                elif self.reader.header.e_flags & 0x400:
                    self.set_arch(
                        archinfo.ArchARMHF('Iend_LE' if self.reader.
                                           little_endian else 'Iend_BE'))
            else:
                self.set_arch(
                    archinfo.arch_from_id(
                        arch_str, 'le' if self.reader.little_endian else 'be',
                        self.reader.elfclass))

        self.strtab = None
        self.dynsym = None
        self.hashtable = None

        self._dynamic = {}
        self.deps = []
        self.rela_type = None

        self._inits_extracted = False
        self._preinit_arr = []
        self._init_func = None
        self._init_arr = []
        self._fini_func = None
        self._fini_arr = []
        self._nullsymbol = Symbol(self, '', 0, 0, None, 'STT_NOTYPE', 0)

        self._symbol_cache = {}
        self.symbols_by_addr = {}
        self.demangled_names = {}
        self.imports = {}
        self.resolved_imports = []

        self.relocs = []
        self.jmprel = {}

        self._entry = self.reader.header.e_entry
        self.pic = self.reader.header.e_type == 'ET_DYN'

        self.tls_used = False
        self.tls_module_id = None
        self.tls_block_offset = None
        self.tls_block_size = None
        self.tls_tdata_start = None
        self.tls_tdata_size = None

        self.__parsed_reloc_tables = set()

        self.__register_segments()
        self.__register_sections()

        # call the methods defined by MetaELF
        self._ppc64_abiv1_entry_fix()
        self._load_plt()

        self._populate_demangled_names()
コード例 #12
0
ファイル: elf.py プロジェクト: ocean1/cle
    def __init__(self, binary, **kwargs):
        super(ELF, self).__init__(binary, **kwargs)

        patch_undo = None
        try:
            self.reader = elffile.ELFFile(self.binary_stream)
        except ELFError:
            self.binary_stream.seek(5)
            ty = self.binary_stream.read(1)
            if ty not in ('\1', '\2'):
                raise CLECompatibilityError

            patch_data = (0x20, '\0\0\0\0') if ty == '\1' else (0x28, '\0\0\0\0\0\0\0\0')
            self.binary_stream.seek(patch_data[0])
            patch_undo = (patch_data[0], self.binary_stream.read(len(patch_data[1])))
            self.binary_stream = PatchedStream(self.binary_stream, [patch_data])
            l.error("PyReadELF couldn't load this file. Trying again without section headers...")

            try:
                self.reader = elffile.ELFFile(self.binary_stream)
            except ELFError:
                raise CLECompatibilityError

        # Get an appropriate archinfo.Arch for this binary, unless the user specified one
        if self.arch is None:
            arch_str = self.reader['e_machine']
            if arch_str == 'ARM':
                if self.reader.header.e_flags & 0x200:
                    self.set_arch(archinfo.ArchARMEL('Iend_LE' if self.reader.little_endian else 'Iend_BE'))
                elif self.reader.header.e_flags & 0x400:
                    self.set_arch(archinfo.ArchARMHF('Iend_LE' if self.reader.little_endian else 'Iend_BE'))
            else:
                self.set_arch(archinfo.arch_from_id(arch_str,
                                                'le' if self.reader.little_endian else 'be',
                                                self.reader.elfclass))

        self.strtab = None
        self.dynsym = None
        self.hashtable = None

        self._dynamic = {}
        self.deps = []
        self.rela_type = None

        self._inits_extracted = False
        self._preinit_arr = []
        self._init_func = None
        self._init_arr = []
        self._fini_func = None
        self._fini_arr = []
        self._nullsymbol = Symbol(self, '', 0, 0, None, 'STT_NOTYPE', 0)

        self._symbol_cache = {}
        self.symbols_by_addr = {}
        self.demangled_names = {}
        self.imports = {}
        self.resolved_imports = []

        self.relocs = []
        self.jmprel = {}

        self._entry = self.reader.header.e_entry
        self.pic = self.reader.header.e_type == 'ET_DYN'

        self.tls_used = False
        self.tls_module_id = None
        self.tls_block_offset = None
        self.tls_block_size = None
        self.tls_tdata_start = None
        self.tls_tdata_size = None

        self.__parsed_reloc_tables = set()

        self.__register_segments()
        self.__register_sections()

        # call the methods defined by MetaELF
        self._ppc64_abiv1_entry_fix()
        self._load_plt()

        self._populate_demangled_names()

        if patch_undo is not None:
            self.memory.write_bytes(self.get_min_addr() + patch_undo[0], patch_undo[1])