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