示例#1
0
 def __setstate__(self, data):
     self.__dict__.update(data)
     self.binary_stream = open(self.binary, 'rb')
     self.reader = elffile.ELFFile(self.binary_stream)
     if self._dynamic and 'DT_STRTAB' in self._dynamic:
         fakestrtabheader = {'sh_offset': self._dynamic['DT_STRTAB']}
         self.strtab = elffile.StringTableSection(fakestrtabheader,
                                                  'strtab_cle', self.memory)
         if 'DT_SYMTAB' in self._dynamic and 'DT_SYMENT' in self._dynamic:
             fakesymtabheader = {
                 'sh_offset': self._dynamic['DT_SYMTAB'],
                 'sh_entsize': self._dynamic['DT_SYMENT'],
                 'sh_size': 0
             }  # bogus size: no iteration allowed
             self.dynsym = elffile.SymbolTableSection(
                 fakesymtabheader, 'symtab_cle', self.memory, self.reader,
                 self.strtab)
             if 'DT_GNU_HASH' in self._dynamic:
                 self.hashtable = GNUHashTable(self.dynsym, self.memory,
                                               self._dynamic['DT_GNU_HASH'],
                                               self.arch)
             elif 'DT_HASH' in self._dynamic:
                 self.hashtable = ELFHashTable(self.dynsym, self.memory,
                                               self._dynamic['DT_HASH'],
                                               self.arch)
示例#2
0
文件: elf.py 项目: mephi42/cle
    def __setstate__(self, data):
        self.__dict__.update(data)

        if self.binary_stream is None:
            self.binary_stream = open(self.binary, 'rb')
        else:
            self.binary_stream.stream = open(self.binary, 'rb')

        self.reader = elffile.ELFFile(self.binary_stream)
        if self._dynamic and 'DT_STRTAB' in self._dynamic:
            self.strtab = next(x for x in self.reader.iter_segments() if x.header.p_type == 'PT_DYNAMIC')._get_stringtable()
            if 'DT_SYMTAB' in self._dynamic and 'DT_SYMENT' in self._dynamic:
                fakesymtabheader = {
                    'sh_offset': AT.from_lva(self._dynamic['DT_SYMTAB'], self).to_rva(),
                    'sh_entsize': self._dynamic['DT_SYMENT'],
                    'sh_size': 0, # bogus size: no iteration allowed
                    'sh_flags': 0,
                    'sh_addralign': 0,
                }
                self.dynsym = elffile.SymbolTableSection(fakesymtabheader, 'symtab_cle', self.reader, self.strtab)
                self.dynsym.stream = self.memory

                if 'DT_GNU_HASH' in self._dynamic:
                    self.hashtable = GNUHashTable(
                            self.dynsym,
                            self.memory,
                            AT.from_lva(self._dynamic['DT_GNU_HASH'], self).to_rva(),
                            self.arch)
                elif 'DT_HASH' in self._dynamic:
                    self.hashtable = ELFHashTable(
                            self.dynsym,
                            self.memory,
                            AT.from_lva(self._dynamic['DT_HASH'], self).to_rva(),
                            self.arch)
示例#3
0
    def __register_dyn(self, seg_readelf):
        """
        Parse the dynamic section for dynamically linked objects.
        """
        runpath, rpath = "", ""
        for tag in seg_readelf.iter_tags():
            # Create a dictionary, self._dynamic, mapping DT_* strings to their values
            tagstr = self.arch.translate_dynamic_tag(tag.entry.d_tag)
            self._dynamic[tagstr] = tag.entry.d_val
            # For tags that may appear more than once, handle them here
            if tagstr == 'DT_NEEDED':
                self.deps.append(maybedecode(tag.needed))
            elif tagstr == 'DT_SONAME':
                self.provides = maybedecode(tag.soname)
            elif tagstr == 'DT_RUNPATH':
                runpath = maybedecode(tag.runpath)
            elif tagstr == 'DT_RPATH':
                rpath = maybedecode(tag.rpath)

        self.extra_load_path = self.__parse_rpath(runpath, rpath)

        self.strtab = seg_readelf._get_stringtable()

        # To extract symbols from binaries without section headers, we need to hack into pyelftools.
        # None of the following things make sense without a string table or a symbol table
        if 'DT_STRTAB' in self._dynamic and 'DT_SYMTAB' in self._dynamic and 'DT_SYMENT' in self._dynamic:
            # Construct our own symbol table to hack around pyreadelf assuming section headers are around
            fakesymtabheader = {
                'sh_offset': AT.from_lva(self._dynamic['DT_SYMTAB'],
                                         self).to_rva(),
                'sh_entsize': self._dynamic['DT_SYMENT'],
                'sh_size': 0,  # bogus size: no iteration allowed
                'sh_flags': 0,
                'sh_addralign': 0,
            }
            self.dynsym = elffile.SymbolTableSection(fakesymtabheader,
                                                     'symtab_cle', self.reader,
                                                     self.strtab)
            self.dynsym.stream = self.memory

            # set up the hash table, prefering the gnu hash section to the old hash section
            # the hash table lets you get any symbol given its name
            if 'DT_GNU_HASH' in self._dynamic:
                self.hashtable = GNUHashTable(
                    self.dynsym, self.memory,
                    AT.from_lva(self._dynamic['DT_GNU_HASH'], self).to_rva(),
                    self.arch)
            elif 'DT_HASH' in self._dynamic:
                self.hashtable = ELFHashTable(
                    self.dynsym, self.memory,
                    AT.from_lva(self._dynamic['DT_HASH'], self).to_rva(),
                    self.arch)
            else:
                l.warning("No hash table available in %s", self.binary)

            # mips' relocations are absolutely screwed up, handle some of them here.
            self.__relocate_mips()

            # perform a lot of checks to figure out what kind of relocation tables are around
            self.rela_type = None
            if 'DT_PLTREL' in self._dynamic:
                if self._dynamic['DT_PLTREL'] == 7:
                    self.rela_type = 'RELA'
                    relentsz = self.reader.structs.Elf_Rela.sizeof()
                elif self._dynamic['DT_PLTREL'] == 17:
                    self.rela_type = 'REL'
                    relentsz = self.reader.structs.Elf_Rel.sizeof()
                else:
                    raise CLEInvalidBinaryError(
                        'DT_PLTREL is not REL or RELA?')
            else:
                if 'DT_RELA' in self._dynamic:
                    self.rela_type = 'RELA'
                    relentsz = self.reader.structs.Elf_Rela.sizeof()
                elif 'DT_REL' in self._dynamic:
                    self.rela_type = 'REL'
                    relentsz = self.reader.structs.Elf_Rel.sizeof()
                else:
                    return

            # try to parse relocations out of a table of type DT_REL{,A}
            rela_tag = 'DT_' + self.rela_type
            relsz_tag = rela_tag + 'SZ'
            if rela_tag in self._dynamic:
                reloffset = AT.from_lva(self._dynamic[rela_tag], self).to_rva()
                if relsz_tag not in self._dynamic:
                    raise CLEInvalidBinaryError(
                        'Dynamic section contains %s but not %s' %
                        (rela_tag, relsz_tag))
                relsz = self._dynamic[relsz_tag]
                fakerelheader = {
                    'sh_offset': reloffset,
                    'sh_type': 'SHT_' + self.rela_type,
                    'sh_entsize': relentsz,
                    'sh_size': relsz,
                    'sh_flags': 0,
                    'sh_addralign': 0,
                }
                readelf_relocsec = elffile.RelocationSection(
                    fakerelheader, 'reloc_cle', self.reader)
                readelf_relocsec.stream = self.memory
                self.__register_relocs(readelf_relocsec)

            # try to parse relocations out of a table of type DT_JMPREL
            if 'DT_JMPREL' in self._dynamic:
                jmpreloffset = AT.from_lva(self._dynamic['DT_JMPREL'],
                                           self).to_rva()
                if 'DT_PLTRELSZ' not in self._dynamic:
                    raise CLEInvalidBinaryError(
                        'Dynamic section contains DT_JMPREL but not DT_PLTRELSZ'
                    )
                jmprelsz = self._dynamic['DT_PLTRELSZ']
                fakejmprelheader = {
                    'sh_offset': jmpreloffset,
                    'sh_type': 'SHT_' + self.rela_type,
                    'sh_entsize': relentsz,
                    'sh_size': jmprelsz,
                    'sh_flags': 0,
                    'sh_addralign': 0,
                }
                readelf_jmprelsec = elffile.RelocationSection(
                    fakejmprelheader, 'jmprel_cle', self.reader)
                readelf_jmprelsec.stream = self.memory
                self.__register_relocs(readelf_jmprelsec, force_jmprel=True)
示例#4
0
    def __register_dyn(self, seg_readelf):
        """
        Parse the dynamic section for dynamically linked objects.
        """
        for tag in seg_readelf.iter_tags():
            # Create a dictionary, self._dynamic, mapping DT_* strings to their values
            tagstr = self.arch.translate_dynamic_tag(tag.entry.d_tag)
            self._dynamic[tagstr] = tag.entry.d_val
            # For tags that may appear more than once, handle them here
            if tagstr == 'DT_NEEDED':
                self.deps.append(tag.entry.d_val)

        # None of the following things make sense without a string table
        if 'DT_STRTAB' in self._dynamic:
            # To handle binaries without section headers, we need to hack around pyreadelf's assumptions
            # make our own string table
            fakestrtabheader = {
                'sh_offset': AT.from_lva(self._dynamic['DT_STRTAB'],
                                         self).to_rva()
            }
            self.strtab = elffile.StringTableSection(fakestrtabheader,
                                                     'strtab_cle', self.memory)

            # get the list of strings that are the required shared libraries
            self.deps = map(self.strtab.get_string, self.deps)

            # get the string for the "shared object name" that this binary provides
            if 'DT_SONAME' in self._dynamic:
                self.provides = self.strtab.get_string(
                    self._dynamic['DT_SONAME'])

            # None of the following structures can be used without a symbol table
            if 'DT_SYMTAB' in self._dynamic and 'DT_SYMENT' in self._dynamic:
                # Construct our own symbol table to hack around pyreadelf assuming section headers are around
                fakesymtabheader = {
                    'sh_offset':
                    AT.from_lva(self._dynamic['DT_SYMTAB'], self).to_rva(),
                    'sh_entsize':
                    self._dynamic['DT_SYMENT'],
                    'sh_size':
                    0
                }  # bogus size: no iteration allowed
                self.dynsym = elffile.SymbolTableSection(
                    fakesymtabheader, 'symtab_cle', self.memory, self.reader,
                    self.strtab)

                # set up the hash table, prefering the gnu hash section to the old hash section
                # the hash table lets you get any symbol given its name
                if 'DT_GNU_HASH' in self._dynamic:
                    self.hashtable = GNUHashTable(
                        self.dynsym, self.memory,
                        AT.from_lva(self._dynamic['DT_GNU_HASH'],
                                    self).to_rva(), self.arch)
                elif 'DT_HASH' in self._dynamic:
                    self.hashtable = ELFHashTable(
                        self.dynsym, self.memory,
                        AT.from_lva(self._dynamic['DT_HASH'], self).to_rva(),
                        self.arch)
                else:
                    l.warning("No hash table available in %s", self.binary)

                # mips' relocations are absolutely screwed up, handle some of them here.
                self.__relocate_mips()

                # perform a lot of checks to figure out what kind of relocation tables are around
                self.rela_type = None
                if 'DT_PLTREL' in self._dynamic:
                    if self._dynamic['DT_PLTREL'] == 7:
                        self.rela_type = 'RELA'
                        relentsz = self.reader.structs.Elf_Rela.sizeof()
                    elif self._dynamic['DT_PLTREL'] == 17:
                        self.rela_type = 'REL'
                        relentsz = self.reader.structs.Elf_Rel.sizeof()
                    else:
                        raise CLEInvalidBinaryError(
                            'DT_PLTREL is not REL or RELA?')
                else:
                    if 'DT_RELA' in self._dynamic:
                        self.rela_type = 'RELA'
                        relentsz = self.reader.structs.Elf_Rela.sizeof()
                    elif 'DT_REL' in self._dynamic:
                        self.rela_type = 'REL'
                        relentsz = self.reader.structs.Elf_Rel.sizeof()
                    else:
                        return

                # try to parse relocations out of a table of type DT_REL{,A}
                if 'DT_' + self.rela_type in self._dynamic:
                    reloffset = self._dynamic['DT_' + self.rela_type] and \
                                AT.from_lva(self._dynamic['DT_' + self.rela_type], self).to_rva()
                    if 'DT_' + self.rela_type + 'SZ' not in self._dynamic:
                        raise CLEInvalidBinaryError(
                            'Dynamic section contains DT_' + self.rela_type +
                            ', but DT_' + self.rela_type + 'SZ is not present')
                    relsz = self._dynamic['DT_' + self.rela_type + 'SZ']
                    fakerelheader = {
                        'sh_offset': reloffset,
                        'sh_type': 'SHT_' + self.rela_type,
                        'sh_entsize': relentsz,
                        'sh_size': relsz
                    }
                    readelf_relocsec = elffile.RelocationSection(
                        fakerelheader, 'reloc_cle', self.memory, self.reader)
                    self.__register_relocs(readelf_relocsec)

                # try to parse relocations out of a table of type DT_JMPREL
                if 'DT_JMPREL' in self._dynamic:
                    jmpreloffset = self._dynamic['DT_JMPREL'] and AT.from_lva(
                        self._dynamic['DT_JMPREL'], self).to_rva()
                    if 'DT_PLTRELSZ' not in self._dynamic:
                        raise CLEInvalidBinaryError(
                            'Dynamic section contains DT_JMPREL, but DT_PLTRELSZ is not present'
                        )
                    jmprelsz = self._dynamic['DT_PLTRELSZ']
                    fakejmprelheader = {
                        'sh_offset': jmpreloffset,
                        'sh_type': 'SHT_' + self.rela_type,
                        'sh_entsize': relentsz,
                        'sh_size': jmprelsz
                    }
                    readelf_jmprelsec = elffile.RelocationSection(
                        fakejmprelheader, 'jmprel_cle', self.memory,
                        self.reader)
                    self.jmprel = OrderedDict(
                        (reloc.symbol.name, reloc)
                        for reloc in self.__register_relocs(readelf_jmprelsec)
                        if reloc.symbol.name != '')