Exemple #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)
Exemple #2
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 != '')