コード例 #1
0
    def hook_symbol(self, symbol_name, obj, kwargs=None):
        """
        Resolve a dependency in a binary. Uses the "externs object" (project.loader.extern_object) to
        allocate an address for a new symbol in the binary, and then tells the loader to re-perform
        the relocation process, taking into account the new symbol.

        :param symbol_name: The name of the dependency to resolve.
        :param obj:         The thing with which to satisfy the dependency.
        :param kwargs:      If you provide a SimProcedure for the hook, these are the keyword
                            arguments that will be passed to the procedure's `run` method
                            eventually.
        :returns:           The address of the new symbol.
        :rtype:             int
        """
        if type(obj) in (int, long):
            # this is pretty intensely sketchy
            l.info("Instructing the loader to re-point symbol %s at address %#x", symbol_name, obj)
            self.loader.provide_symbol(self.loader.extern_object, symbol_name, AT.from_mva(obj, self.loader.extern_object).to_rva())
            return obj

        sym = self.loader.find_symbol(symbol_name)
        if sym is None:
            l.error("Could not find symbol %s", symbol_name)
            return None

        hook_addr, _ = self._simos.prepare_function_symbol(symbol_name, basic_addr=sym.rebased_addr)

        if self.is_hooked(hook_addr):
            l.warning("Re-hooking symbol %s", symbol_name)
            self.unhook(hook_addr)

        self.hook(hook_addr, obj, kwargs=kwargs)
        return hook_addr
コード例 #2
0
    def prepare_function_symbol(self, symbol_name, basic_addr=None):
        """
        Prepare the address space with the data necessary to perform relocations pointing to the given symbol.

        Returns a 2-tuple. The first item is the address of the function code, the second is the address of the
        relocation target.
        """
        if self.arch.name == 'PPC64':
            if basic_addr is not None:
                pointer = self.project.loader.memory.read_addr_at(basic_addr)
                return pointer, basic_addr

            pseudo_hookaddr = self.project._extern_obj.get_pseudo_addr(
                symbol_name)
            pseudo_toc = self.project._extern_obj.get_pseudo_addr(symbol_name +
                                                                  '#func',
                                                                  size=0x18)
            self.project._extern_obj.memory.write_addr_at(
                AT.from_mva(pseudo_toc, self.project._extern_obj).to_rva(),
                pseudo_hookaddr)
            return pseudo_hookaddr, pseudo_toc
        else:
            if basic_addr is None:
                basic_addr = self.project._extern_obj.get_pseudo_addr(
                    symbol_name)
            return basic_addr, basic_addr
コード例 #3
0
ファイル: loader.py プロジェクト: mikalv/cle
    def find_symbol(self, name):
        """
        Search for the symbol with the given name or address.

        :param name:        Either the name or address of a symbol to look up

        :returns:           A :class:`cle.backends.Symbol` object if found, None otherwise.
        """
        if type(name) in (int, long):
            so = self.find_object_containing(name)
            if so is not None:
                addr = AT.from_mva(name, so).to_rva()
                if addr in so._symbols_by_addr:
                    return so._symbols_by_addr[addr]
        else:
            for so in self.all_objects:
                if so is self._extern_object:
                    continue
                sym = so.get_symbol(name)
                if sym is None:
                    continue

                if sym.is_import:
                    if sym.resolvedby is not None:
                        return sym.resolvedby
                else:
                    return sym

            if self._extern_object is not None:
                sym = self.extern_object.get_symbol(name)
                if sym is not None:
                    return sym

        return None
コード例 #4
0
ファイル: project.py プロジェクト: moonsea/angr
    def hook_symbol(self, symbol_name, obj, kwargs=None, replace=None):
        """
        Resolve a dependency in a binary. Looks up the address of the given symbol, and then hooks that
        address. If the symbol was not available in the loaded libraries, this address may be provided
        by the CLE externs object.

        :param symbol_name: The name of the dependency to resolve.
        :param obj:         The thing with which to satisfy the dependency.
        :param kwargs:      If you provide a SimProcedure for the hook, these are the keyword
                            arguments that will be passed to the procedure's `run` method
                            eventually.
        :param replace:     Control the behavior on finding that the address is already hooked. If
                            true, silently replace the hook. If false, warn and do not replace the
                            hook. If none (default), warn and replace the hook.
        :returns:           The address of the new symbol.
        :rtype:             int
        """
        if type(obj) in (int, long):
            # this is pretty intensely sketchy
            l.info("Instructing the loader to re-point symbol %s at address %#x", symbol_name, obj)
            self.loader.provide_symbol(self.loader.extern_object, symbol_name, AT.from_mva(obj, self.loader.extern_object).to_rva())
            return obj

        sym = self.loader.find_symbol(symbol_name)
        if sym is None:
            l.error("Could not find symbol %s", symbol_name)
            return None

        hook_addr, _ = self._simos.prepare_function_symbol(symbol_name, basic_addr=sym.rebased_addr)

        self.hook(hook_addr, obj, kwargs=kwargs, replace=replace)
        return hook_addr
コード例 #5
0
ファイル: linux.py プロジェクト: AkshaySG14/582proj-angr
    def prepare_function_symbol(self, symbol_name, basic_addr=None):
        """
        Prepare the address space with the data necessary to perform relocations pointing to the given symbol.

        Returns a 2-tuple. The first item is the address of the function code, the second is the address of the
        relocation target.
        """
        if self.project.loader.main_object.is_ppc64_abiv1:
            if basic_addr is not None:
                pointer = self.project.loader.memory.unpack_word(basic_addr)
                return pointer, basic_addr

            pseudo_hookaddr = self.project.loader.extern_object.get_pseudo_addr(
                symbol_name)
            pseudo_toc = self.project.loader.extern_object.allocate(size=0x18)
            self.project.loader.extern_object.memory.pack_word(
                AT.from_mva(pseudo_toc,
                            self.project.loader.extern_object).to_rva(),
                pseudo_hookaddr)
            return pseudo_hookaddr, pseudo_toc
        else:
            if basic_addr is None:
                basic_addr = self.project.loader.extern_object.get_pseudo_addr(
                    symbol_name)
            return basic_addr, basic_addr
コード例 #6
0
    def hook_symbol_batch(self, hooks):
        """
        Hook many symbols at once.

        :param dict hooks:     A mapping from symbol name to hook
        """

        provisions = {}

        for name, obj in hooks.iteritems():
            sym = self.loader.find_symbol(name)
            if sym is None:
                hook_addr, link_addr = self._simos.prepare_function_symbol(
                    name)
                l.info("Providing extern symbol for unresolved %s at #%x",
                       name, hook_addr)
                self.hook(hook_addr, obj)
                provisions[name] = (AT.from_mva(link_addr,
                                                self._extern_obj).to_lva(), 0,
                                    None)
            else:
                hook_addr, _ = self._simos.prepare_function_symbol(
                    name, basic_addr=sym.rebased_addr)
                if self.is_hooked(hook_addr):
                    l.warning("Re-hooking symbol %s", name)
                    self.unhook(hook_addr)
                self.hook(hook_addr, obj)

        if provisions:
            self.loader.provide_symbol_batch(self._extern_obj, provisions)
コード例 #7
0
def run_sections(arch, filename, sections):

    binary_path = os.path.join(TESTS_BASE, arch, filename)

    ld = cle.Loader(binary_path, auto_load_libs=False)

    nose.tools.assert_equal(len(ld.main_object.sections), len(sections))
    for i, section in enumerate(ld.main_object.sections):
        nose.tools.assert_equal(section.name, sections[i].name)
        nose.tools.assert_equal(section.offset, sections[i].offset)
        nose.tools.assert_equal(
            AT.from_mva(section.vaddr, ld.main_object).to_lva(),
            sections[i].vaddr)
        nose.tools.assert_equal(section.memsize, sections[i].memsize)

    # address lookups
    nose.tools.assert_is_none(
        ld.main_object.sections.find_region_containing(-1))

    # skip all sections that are not mapped into memory
    mapped_sections = [section for section in sections if section.vaddr != 0]

    for section in mapped_sections:
        nose.tools.assert_equal(
            ld.main_object.find_section_containing(section.vaddr).name,
            section.name)
        nose.tools.assert_equal(
            ld.main_object.sections.find_region_containing(section.vaddr).name,
            section.name)
        if section.memsize > 0:
            nose.tools.assert_equal(
                ld.main_object.find_section_containing(section.vaddr + 1).name,
                section.name)
            nose.tools.assert_equal(
                ld.main_object.sections.find_region_containing(section.vaddr +
                                                               1).name,
                section.name)
            nose.tools.assert_equal(
                ld.main_object.find_section_containing(section.vaddr +
                                                       section.memsize -
                                                       1).name, section.name)
            nose.tools.assert_equal(
                ld.main_object.sections.find_region_containing(
                    section.vaddr + section.memsize - 1).name, section.name)

    for i in range(len(mapped_sections) - 1):
        sec_a, sec_b = mapped_sections[i], mapped_sections[i + 1]
        if sec_a.vaddr + sec_a.memsize < sec_b.vaddr:
            # there is a gap between sec_a and sec_b
            for j in range(min(sec_b.vaddr - (sec_a.vaddr + sec_a.memsize),
                               20)):
                a = sec_a.vaddr + sec_a.memsize + j
                nose.tools.assert_is_none(
                    ld.main_object.find_section_containing(a))
                nose.tools.assert_is_none(
                    ld.main_object.sections.find_region_containing(a))

    nose.tools.assert_is_none(
        ld.main_object.find_section_containing(0xffffffff), None)
コード例 #8
0
ファイル: __init__.py プロジェクト: angr/cle
    def make_extern(self, name, size=0, alignment=None, thumb=False, sym_type=Symbol.TYPE_FUNCTION, libname=None):
        try:
            return self._symbol_cache[name]
        except KeyError:
            pass

        l.info("Creating extern symbol for %s", name)

        if alignment is None:
            alignment = self.arch.bytes

        SymbolCls = Symbol
        simdata = lookup(name, libname)
        tls = sym_type == Symbol.TYPE_TLS_OBJECT
        if simdata is not None:
            SymbolCls = simdata
            size = simdata.static_size(self)
            if sym_type != simdata.type:
                l.warning("Symbol type mismatch between export request and response for %s. What's going on?", name)

        addr = self.allocate(max(size, 1), alignment=alignment, thumb=thumb, tls=tls)

        if hasattr(self.loader.main_object, 'is_ppc64_abiv1') and self.loader.main_object.is_ppc64_abiv1 and sym_type == Symbol.TYPE_FUNCTION:
            func_symbol = SymbolCls(self, name + '#func', AT.from_mva(addr, self).to_rva(), size, sym_type)
            func_symbol.is_export = True
            func_symbol.is_extern = True
            self._symbol_cache[name + '#func'] = func_symbol
            self.symbols.add(func_symbol)
            self._init_symbol(func_symbol)

            toc = self.allocate(0x18, alignment=8)
            size = 0x18
            self.memory.pack_word(AT.from_mva(toc, self).to_rva(), addr)
            addr = toc
            sym_type = Symbol.TYPE_OBJECT
            SymbolCls = Symbol

        new_symbol = SymbolCls(self, name, addr if tls else AT.from_mva(addr, self).to_rva(), size, sym_type)
        new_symbol.is_export = True
        new_symbol.is_extern = True

        self._symbol_cache[name] = new_symbol
        self.symbols.add(new_symbol)
        self._init_symbol(new_symbol)
        return new_symbol
コード例 #9
0
ファイル: project.py プロジェクト: chen93/angr
    def hook_symbol(self, symbol_name, obj, kwargs=None, replace=None):
        """
        Resolve a dependency in a binary. Looks up the address of the given symbol, and then hooks that
        address. If the symbol was not available in the loaded libraries, this address may be provided
        by the CLE externs object.

        Additionally, if instead of a symbol name you provide an address, some secret functionality will
        kick in and you will probably just hook that address, UNLESS you're on powerpc64 ABIv1 or some
        yet-unknown scary ABI that has its function pointers point to something other than the actual
        functions, in which case it'll do the right thing.

        :param symbol_name: The name of the dependency to resolve.
        :param obj:         The thing with which to satisfy the dependency.
        :param kwargs:      If you provide a SimProcedure for the hook, these are the keyword
                            arguments that will be passed to the procedure's `run` method
                            eventually.
        :param replace:     Control the behavior on finding that the address is already hooked. If
                            true, silently replace the hook. If false, warn and do not replace the
                            hook. If none (default), warn and replace the hook.
        :returns:           The address of the new symbol.
        :rtype:             int
        """
        if type(obj) in (int, long):
            # this is pretty intensely sketchy
            l.info("Instructing the loader to re-point symbol %s at address %#x", symbol_name, obj)
            self.loader.provide_symbol(self.loader.extern_object, symbol_name, AT.from_mva(obj, self.loader.extern_object).to_rva())
            return obj

        if type(symbol_name) not in (int, long):
            sym = self.loader.find_symbol(symbol_name)
            if sym is None:
                # it could be a previously unresolved weak symbol..?
                new_sym = None
                for reloc in self.loader.find_relevant_relocations(symbol_name):
                    if not reloc.symbol.is_weak:
                        raise Exception("Symbol is strong but we couldn't find its resolution? Report to @rhelmot.")
                    if new_sym is None:
                        new_sym = self.loader.extern_object.make_extern(symbol_name)
                    reloc.resolve(new_sym)
                    reloc.relocate([])

                if new_sym is None:
                    l.error("Could not find symbol %s", symbol_name)
                    return None
                sym = new_sym

            basic_addr = sym.rebased_addr
        else:
            basic_addr = symbol_name
            symbol_name = None

        hook_addr, _ = self.simos.prepare_function_symbol(symbol_name, basic_addr=basic_addr)

        self.hook(hook_addr, obj, kwargs=kwargs, replace=replace)
        return hook_addr
コード例 #10
0
ファイル: project.py プロジェクト: lewpeng/angr
    def hook_symbol(self, symbol_name, obj, kwargs=None, replace=None):
        """
        Resolve a dependency in a binary. Looks up the address of the given symbol, and then hooks that
        address. If the symbol was not available in the loaded libraries, this address may be provided
        by the CLE externs object.

        Additionally, if instead of a symbol name you provide an address, some secret functionality will
        kick in and you will probably just hook that address, UNLESS you're on powerpc64 ABIv1 or some
        yet-unknown scary ABI that has its function pointers point to something other than the actual
        functions, in which case it'll do the right thing.

        :param symbol_name: The name of the dependency to resolve.
        :param obj:         The thing with which to satisfy the dependency.
        :param kwargs:      If you provide a SimProcedure for the hook, these are the keyword
                            arguments that will be passed to the procedure's `run` method
                            eventually.
        :param replace:     Control the behavior on finding that the address is already hooked. If
                            true, silently replace the hook. If false, warn and do not replace the
                            hook. If none (default), warn and replace the hook.
        :returns:           The address of the new symbol.
        :rtype:             int
        """
        if type(obj) in (int, long):
            # this is pretty intensely sketchy
            l.info(
                "Instructing the loader to re-point symbol %s at address %#x",
                symbol_name, obj)
            self.loader.provide_symbol(
                self.loader.extern_object, symbol_name,
                AT.from_mva(obj, self.loader.extern_object).to_rva())
            return obj

        if type(symbol_name) not in (int, long):
            sym = self.loader.find_symbol(symbol_name)
            if sym is None:
                l.error("Could not find symbol %s", symbol_name)
                return None
            basic_addr = sym.rebased_addr
        else:
            basic_addr = symbol_name
            symbol_name = None

        hook_addr, _ = self.simos.prepare_function_symbol(
            symbol_name, basic_addr=basic_addr)

        self.hook(hook_addr, obj, kwargs=kwargs, replace=replace)
        return hook_addr
コード例 #11
0
ファイル: simos.py プロジェクト: axt/angr
    def prepare_function_symbol(self, symbol_name, basic_addr=None):
        """
        Prepare the address space with the data necessary to perform relocations pointing to the given symbol.

        Returns a 2-tuple. The first item is the address of the function code, the second is the address of the
        relocation target.
        """
        if self.project.loader.main_object.is_ppc64_abiv1:
            if basic_addr is not None:
                pointer = self.project.loader.memory.read_addr_at(basic_addr)
                return pointer, basic_addr

            pseudo_hookaddr = self.project.loader.extern_object.get_pseudo_addr(symbol_name)
            pseudo_toc = self.project.loader.extern_object.allocate(size=0x18)
            self.project.loader.extern_object.memory.write_addr_at(AT.from_mva(pseudo_toc, self.project.loader.extern_object).to_rva(), pseudo_hookaddr)
            return pseudo_hookaddr, pseudo_toc
        else:
            if basic_addr is None:
                basic_addr = self.project.loader.extern_object.get_pseudo_addr(symbol_name)
            return basic_addr, basic_addr
コード例 #12
0
ファイル: test_regions.py プロジェクト: angr/cle
def run_sections(arch, filename, sections):

    binary_path = os.path.join(TESTS_BASE, arch, filename)

    ld = cle.Loader(binary_path, auto_load_libs=False)

    nose.tools.assert_equal(len(ld.main_object.sections), len(sections))
    for i, section in enumerate(ld.main_object.sections):
        nose.tools.assert_equal(section.name, sections[i].name)
        nose.tools.assert_equal(section.offset, sections[i].offset)
        nose.tools.assert_equal(AT.from_mva(section.vaddr, ld.main_object).to_lva(), sections[i].vaddr)
        nose.tools.assert_equal(section.memsize, sections[i].memsize)

    # address lookups
    nose.tools.assert_is_none(ld.main_object.sections.find_region_containing(-1))

    # skip all sections that are not mapped into memory
    mapped_sections = [ section for section in sections if section.vaddr != 0 ]

    for section in mapped_sections:
        nose.tools.assert_equal(ld.main_object.find_section_containing(section.vaddr).name, section.name)
        nose.tools.assert_equal(ld.main_object.sections.find_region_containing(section.vaddr).name, section.name)
        if section.memsize > 0:
            nose.tools.assert_equal(ld.main_object.find_section_containing(section.vaddr + 1).name, section.name)
            nose.tools.assert_equal(ld.main_object.sections.find_region_containing(section.vaddr + 1).name, section.name)
            nose.tools.assert_equal(ld.main_object.find_section_containing(section.vaddr + section.memsize - 1).name,
                                    section.name)
            nose.tools.assert_equal(
                ld.main_object.sections.find_region_containing(section.vaddr + section.memsize - 1).name, section.name)

    for i in range(len(mapped_sections) - 1):
        sec_a, sec_b = mapped_sections[i], mapped_sections[i + 1]
        if sec_a.vaddr + sec_a.memsize < sec_b.vaddr:
            # there is a gap between sec_a and sec_b
            for j in range(min(sec_b.vaddr - (sec_a.vaddr + sec_a.memsize), 20)):
                a = sec_a.vaddr + sec_a.memsize + j
                nose.tools.assert_is_none(ld.main_object.find_section_containing(a))
                nose.tools.assert_is_none(ld.main_object.sections.find_region_containing(a))

    nose.tools.assert_is_none(ld.main_object.find_section_containing(0xffffffff), None)
コード例 #13
0
ファイル: __init__.py プロジェクト: yuzeming/cle
 def add_name(self, name, addr):
     self._symbol_cache[name] = Symbol(self, name, AT.from_mva(addr, self).to_rva(), 1, SymbolType.TYPE_FUNCTION)
コード例 #14
0
def test_lva_mva_translation():
    nose.tools.assert_equal(AT.from_lva(0x8048000, owner).to_mva(), 0xa000000)
    nose.tools.assert_equal(AT.from_mva(0xa1b9a1b, owner).to_lva(), 0x8201a1b)
コード例 #15
0
    def make_extern(self,
                    name,
                    size=0,
                    alignment=None,
                    thumb=False,
                    sym_type=SymbolType.TYPE_FUNCTION,
                    libname=None):
        try:
            return self._symbol_cache[name]
        except KeyError:
            pass

        l.info("Creating extern symbol for %s", name)

        if alignment is None:
            alignment = self.arch.bytes

        SymbolCls = Symbol
        simdata = lookup(name, libname)
        tls = sym_type == SymbolType.TYPE_TLS_OBJECT
        if simdata is not None:
            SymbolCls = simdata
            size = simdata.static_size(self)
            if sym_type != simdata.type:
                l.warning(
                    "Symbol type mismatch between export request and response for %s. What's going on?",
                    name)

        addr = self.allocate(max(size, 1),
                             alignment=alignment,
                             thumb=thumb,
                             tls=tls)

        if hasattr(
                self.loader.main_object, 'is_ppc64_abiv1'
        ) and self.loader.main_object.is_ppc64_abiv1 and sym_type == SymbolType.TYPE_FUNCTION:
            func_symbol = SymbolCls(self, name + '#func',
                                    AT.from_mva(addr, self).to_rva(), size,
                                    sym_type)
            func_symbol.is_export = True
            func_symbol.is_extern = True
            self._symbol_cache[name + '#func'] = func_symbol
            self.symbols.add(func_symbol)
            self._init_symbol(func_symbol)

            toc = self.allocate(0x18, alignment=8)
            size = 0x18
            self.memory.pack_word(AT.from_mva(toc, self).to_rva(), addr)
            addr = toc
            sym_type = SymbolType.TYPE_OBJECT
            SymbolCls = Symbol

        new_symbol = SymbolCls(
            self, name, addr if tls else AT.from_mva(addr, self).to_rva(),
            size, sym_type)
        new_symbol.is_export = True
        new_symbol.is_extern = True

        self._symbol_cache[name] = new_symbol
        self.symbols.add(new_symbol)
        self._init_symbol(new_symbol)
        return new_symbol
コード例 #16
0
ファイル: test_address_translator.py プロジェクト: angr/cle
def test_lva_mva_translation():
    nose.tools.assert_equal(AT.from_lva(0x8048000, owner).to_mva(), 0xa000000)
    nose.tools.assert_equal(AT.from_mva(0xa1b9a1b, owner).to_lva(), 0x8201a1b)
コード例 #17
0
ファイル: __init__.py プロジェクト: angr/cle
 def add_name(self, name, addr):
     self._symbol_cache[name] = Symbol(self, name, AT.from_mva(addr, self).to_rva(), 1, Symbol.TYPE_FUNCTION)