def display_symbol_tables(self): """ Display the symbol tables contained in the file """ for section in self.elffile.iter_sections(): if not isinstance(section, SymbolTableSection): continue if section['sh_entsize'] == 0: self._emitline("\nSymbol table '%s' has a sh_entsize of zero!" % ( bytes2str(section.name))) continue self._emitline("\nSymbol table '%s' contains %s entries:" % ( bytes2str(section.name), section.num_symbols())) if self.elffile.elfclass == 32: self._emitline(' Num: Value Size Type Bind Vis Ndx Name') else: # 64 self._emitline(' Num: Value Size Type Bind Vis Ndx Name') for nsym, symbol in enumerate(section.iter_symbols()): # symbol names are truncated to 25 chars, similarly to readelf self._emitline('%6d: %s %5d %-7s %-6s %-7s %4s %.25s' % ( nsym, self._format_hex(symbol['st_value'], fullhex=True, lead0x=False), symbol['st_size'], describe_symbol_type(symbol['st_info']['type']), describe_symbol_bind(symbol['st_info']['bind']), describe_symbol_visibility(symbol['st_other']['visibility']), describe_symbol_shndx(symbol['st_shndx']), bytes2str(symbol.name)))
def load_symbols_elf(filename): """ Load the symbol tables contained in the file """ f = open(filename, 'rb') elffile = ELFFile(f) symbols = [] for section in elffile.iter_sections(): if not isinstance(section, SymbolTableSection): continue if section['sh_entsize'] == 0: logger.warn("Symbol table {} has a sh_entsize of zero.".format(section.name)) continue logger.info("Symbol table {} contains {} entries.".format(section.name, section.num_symbols())) for _, symbol in enumerate(section.iter_symbols()): if describe_symbol_shndx(symbol['st_shndx']) != "UND" and \ describe_symbol_type(symbol['st_info']['type']) == "FUNC": symbols.append((symbol['st_value'], symbol['st_size'], symbol.name)) f.close() symbols_by_addr = { addr: (name, size, True) for addr, size, name in symbols } return symbols_by_addr
def display_symbol_tables(self): self._init_versioninfo() symbol_tables = [ s for s in self.elffile.iter_sections() if isinstance(s, SymbolTableSection) ] imports = set() exports = set() for section in symbol_tables: if not isinstance(section, SymbolTableSection): continue if section['sh_entsize'] == 0: # print("\nSymbol table '%s' has a sh_entsize of zero!" % (section.name)) continue for nsym, symbol in enumerate(section.iter_symbols()): sym_type = describe_symbol_type(symbol['st_info']['type']) if sym_type == "FUNC": desc = describe_symbol_shndx(symbol['st_shndx']) if desc == "UND": imports.add(str(symbol.name)) try: exports.add(str(symbol.name)) except ValueError: pass self.data["imports"] = list(imports) self.data["exports"] = list(exports)
def _dump_elf(cls, buf): """ Dump the symbol table of an ELF file. Needs pyelftools (https://github.com/eliben/pyelftools) """ from elftools.elf.elffile import ELFFile from elftools.elf import descriptions from io import BytesIO f = ELFFile(BytesIO(buf)) print("ELF file:") for sec in f.iter_sections(): if sec['sh_type'] == 'SHT_SYMTAB': symbols = sorted(sec.iter_symbols(), key=lambda sym: sym.name) print(" symbols:") for sym in symbols: if not sym.name: continue print(" - %r: size=%d, value=0x%x, type=%s, bind=%s" % (sym.name.decode(), sym['st_size'], sym['st_value'], descriptions.describe_symbol_type(sym['st_info']['type']), descriptions.describe_symbol_bind(sym['st_info']['bind']), )) print()
def _dump_elf(cls, buf): """ Dump the symbol table of an ELF file. Needs pyelftools (https://github.com/eliben/pyelftools) """ from elftools.elf.elffile import ELFFile from elftools.elf import descriptions from io import BytesIO f = ELFFile(BytesIO(buf)) print("ELF file:") for sec in f.iter_sections(): if sec['sh_type'] == 'SHT_SYMTAB': symbols = sorted(sec.iter_symbols(), key=lambda sym: sym.name) print(" symbols:") for sym in symbols: if not sym.name: continue print(" - %r: size=%d, value=0x%x, type=%s, bind=%s" % ( sym.name.decode(), sym['st_size'], sym['st_value'], descriptions.describe_symbol_type( sym['st_info']['type']), descriptions.describe_symbol_bind( sym['st_info']['bind']), )) print()
def elf_symbol_tables(self): symbol_tables_list = [] def add_info(dic): symbol_tables_list.append(dic) self._init_versioninfo() symbol_tables = [ s for s in self.elffile.iter_sections() if isinstance(s, SymbolTableSection) ] if not symbol_tables and self.elffile.num_sections() == 0: return None for section in symbol_tables: if not isinstance(section, SymbolTableSection): continue if section['sh_entsize'] == 0: continue for nsym, symbol in enumerate(section.iter_symbols()): version_info = '' if (section['sh_type'] == 'SHT_DYNSYM' and self._versioninfo['type'] == 'GNU'): version = self._symbol_version(nsym) if (version['name'] != symbol.name and version['index'] not in ('VER_NDX_LOCAL', 'VER_NDX_GLOBAL')): if version['filename']: # external symbol version_info = '@%(name)s (%(index)i)' % version else: # internal symbol if version['hidden']: version_info = '@%(name)s' % version else: version_info = '@@%(name)s' % version symbol_info = {} symbol_info['index'] = nsym symbol_info['Value'] = self._format_hex(symbol['st_value'], fullhex=True, lead0x=False) symbol_info['Size'] = symbol['st_size'] symbol_info['Type'] = describe_symbol_type( symbol['st_info']['type']) symbol_info['Bind'] = describe_symbol_bind( symbol['st_info']['bind']) symbol_info['Vis'] = describe_symbol_visibility( symbol['st_other']['visibility']) symbol_info['Ndx'] = describe_symbol_shndx(symbol['st_shndx']) symbol_info['Name'] = symbol.name symbol_info['version_info'] = version_info add_info(symbol_info) return symbol_tables_list
def display_symbol_tables(self): """ Display the symbol tables contained in the file """ self._init_versioninfo() for section in self.elffile.iter_sections(): if not isinstance(section, SymbolTableSection): continue if section['sh_entsize'] == 0: self._emitline("\nSymbol table '%s' has a sh_entsize of zero!" % ( bytes2str(section.name))) continue self._emitline("\nSymbol table '%s' contains %s entries:" % ( bytes2str(section.name), section.num_symbols())) if self.elffile.elfclass == 32: self._emitline(' Num: Value Size Type Bind Vis Ndx Name') else: # 64 self._emitline(' Num: Value Size Type Bind Vis Ndx Name') for nsym, symbol in enumerate(section.iter_symbols()): version_info = '' # readelf doesn't display version info for Solaris versioning if (section['sh_type'] == 'SHT_DYNSYM' and self._versioninfo['type'] == 'GNU'): version = self._symbol_version(nsym) if (version['name'] != bytes2str(symbol.name) and version['index'] not in ('VER_NDX_LOCAL', 'VER_NDX_GLOBAL')): if version['filename']: # external symbol version_info = '@%(name)s (%(index)i)' % version else: # internal symbol if version['hidden']: version_info = '@%(name)s' % version else: version_info = '@@%(name)s' % version # symbol names are truncated to 25 chars, similarly to readelf self._emitline('%6d: %s %5d %-7s %-6s %-7s %4s %.25s%s' % ( nsym, self._format_hex( symbol['st_value'], fullhex=True, lead0x=False), symbol['st_size'], describe_symbol_type(symbol['st_info']['type']), describe_symbol_bind(symbol['st_info']['bind']), describe_symbol_visibility(symbol['st_other']['visibility']), describe_symbol_shndx(symbol['st_shndx']), bytes2str(symbol.name), version_info))
def _get_symbol_tables(self): symbol_tables = [] for section in self.elf.iter_sections(): if not isinstance(section, SymbolTableSection): continue for nsym, symbol in enumerate(section.iter_symbols()): symbol_tables.append({ "value": self._print_addr(symbol["st_value"]), "type": describe_symbol_type(symbol["st_info"]["type"]), "bind": describe_symbol_bind(symbol["st_info"]["bind"]), "ndx_name": symbol.name, }) return symbol_tables
def get_symbols(self,elf) -> list: ''' get symbols and types ''' _list = [] for section in elf.iter_sections(): if not isinstance(section, SymbolTableSection): continue for symbol in section.iter_symbols(): if len(symbol.name) > 0: _list.append({ "Type":describe_symbol_type(symbol['st_info']['type']), "Symbol":symbol.name, "Description":""}) return _list
def _get_symbol_tables(self) -> List[Dict[str, str]]: symbol_tables = [] for section in self.elf.iter_sections(): if not isinstance(section, SymbolTableSection): continue symbol_tables.extend( { "value": self._print_addr(symbol["st_value"]), "type": describe_symbol_type(symbol["st_info"]["type"]), "bind": describe_symbol_bind(symbol["st_info"]["bind"]), "ndx_name": symbol.name, } for symbol in section.iter_symbols() ) return symbol_tables
def symbols(self): if not self.__check_session(): return rows = [] for section in self.elf.iter_sections(): if not isinstance(section, SymbolTableSection): continue for cnt, symbol in enumerate(section.iter_symbols()): rows.append([ cnt, hex(symbol['st_value']), hex(symbol['st_size']), describe_symbol_type(symbol['st_info']['type']), symbol.name ]) print_info("ELF Symbols:") print(table(header=['Num', 'Value', 'Size', 'Type', 'Name'], rows=rows))
def symbols(self): if not self.__check_session(): return rows = [] for section in self.elf.iter_sections(): if not isinstance(section, SymbolTableSection): continue for cnt, symbol in enumerate(section.iter_symbols()): rows.append([ cnt, hex(symbol['st_value']), hex(symbol['st_size']), describe_symbol_type(symbol['st_info']['type']), symbol.name ]) self.log('info', "ELF Symbols:") self.log('table', dict(header=['Num', 'Value', 'Size', 'Type', 'Name'], rows=rows))
def parse_symbol_table(self): """ build symbol table data structure :return: list of symbols """ if self.symbol_table is None: self.symbol_table = SymbolTable() symbol_tables = [ section for section in self._elf.iter_sections() if isinstance(section, SymbolTableSection) ] for section in symbol_tables: for symbol in section.iter_symbols(): if ((int(symbol["st_size"]) > 0) and ("OBJECT" == describe_symbol_type( symbol["st_info"]["type"]))): symbol_entry = Symbol(symbol.name, symbol["st_value"], symbol["st_size"]) self.symbol_table.add_symbol(symbol_entry) return self.symbol_table
def symbols(self): if not self.__check_session(): return rows = [] for section in self.elf.iter_sections(): if not isinstance(section, SymbolTableSection): continue for cnt, symbol in enumerate(section.iter_symbols()): rows.append( [ cnt, hex(symbol["st_value"]), hex(symbol["st_size"]), describe_symbol_type(symbol["st_info"]["type"]), symbol.name, ] ) print_info("ELF Symbols:") print(table(header=["Num", "Value", "Size", "Type", "Name"], rows=rows))
def get_symbols(self): """Return a set of symbols from the dwarf symbol tables""" symbols = {} # We want .symtab and .dynsym tables = [ (idx, s) for idx, s in enumerate(self.elffile.iter_sections()) if isinstance(s, SymbolTableSection) ] for idx, section in tables: # Symbol table has no entries if this is zero # section.num_symbols() shows count, section.name is name if section["sh_entsize"] == 0: continue # We need the index of the symbol to look up versions for sym_idx, symbol in enumerate(section.iter_symbols()): # Version info is from the versym / verneed / verdef sections. version_info = self._get_symbol_version(section, sym_idx, symbol) # We aren't considering st_value, which could be many things # https://docs.oracle.com/cd/E19683-01/816-1386/6m7qcoblj/index.html#chapter6-35166 symbols[symbol.name] = { "version_info": version_info, "type": describe_symbol_type(symbol["st_info"]["type"]), "binding": describe_symbol_bind(symbol["st_info"]["bind"]), "visibility": describe_symbol_visibility( symbol["st_other"]["visibility"] ), "defined": describe_symbol_shndx( self._get_symbol_shndx(symbol, sym_idx, idx) ).strip(), } return symbols
def display_symbol_tables(self): """ Display the symbol tables contained in the file """ for section in self.elffile.iter_sections(): if not isinstance(section, SymbolTableSection): continue if section['sh_entsize'] == 0: self._emitline( "\nSymbol table '%s' has a sh_entsize of zero!" % (bytes2str(section.name))) continue self._emitline("\nSymbol table '%s' contains %s entries:" % (bytes2str(section.name), section.num_symbols())) if self.elffile.elfclass == 32: self._emitline( ' Num: Value Size Type Bind Vis Ndx Name') else: # 64 self._emitline( ' Num: Value Size Type Bind Vis Ndx Name' ) for nsym, symbol in enumerate(section.iter_symbols()): # symbol names are truncated to 25 chars, similarly to readelf self._emitline( '%6d: %s %5d %-7s %-6s %-7s %4s %.25s' % (nsym, self._format_hex(symbol['st_value'], fullhex=True, lead0x=False), symbol['st_size'], describe_symbol_type(symbol['st_info']['type']), describe_symbol_bind(symbol['st_info']['bind']), describe_symbol_visibility( symbol['st_other']['visibility']), describe_symbol_shndx( symbol['st_shndx']), bytes2str(symbol.name)))
def scan(self, data, file, options, expire_at): with io.BytesIO(data) as elf_io: try: elf = elffile.ELFFile(elf_io) self.event.setdefault('header', {}) for (key, value) in elf.header.items(): if key == 'e_flags': self.event['header']['flags'] = value elif key == 'e_shnum': self.event['header']['section_headers'] = value elif key == 'e_phnum': self.event['header']['program_headers'] = value elif key == 'e_version': self.event['header'][ 'file_version'] = descriptions.describe_e_version_numeric( value) elif key == 'e_machine': self.event['header'][ 'machine'] = descriptions.describe_e_machine(value) elif key == 'e_type': self.event['header'][ 'file_type'] = descriptions.describe_e_type(value) elif key == 'e_ident': for x, y in value.items(): if x == 'EI_DATA': self.event['header'][ 'data'] = descriptions.describe_ei_data(y) elif x == 'EI_OSABI': self.event['header'][ 'os_abi'] = descriptions.describe_ei_osabi( y) elif x == 'EI_VERSION': self.event['header'][ 'header_version'] = descriptions.describe_ei_version( y) elif x == 'EI_CLASS': self.event['header'][ 'class'] = descriptions.describe_ei_class( y) elif x == 'EI_ABIVERSION': self.event['header']['abi_version'] = y try: self.event.setdefault('shared_libraries', []) self.event.setdefault('imports', []) self.event.setdefault('exports', []) for section in elf.iter_sections(): if not section.is_null(): if isinstance(section, dynamic.DynamicSection): for tag in section.iter_tags(): if tag.entry.d_tag == 'DT_NEEDED': if tag.needed not in self.event[ 'shared_libraries']: self.event[ 'shared_libraries'].append( tag.needed) # Attempt to organize symbols into imports and exports # This is the most comprehensive explanation I've seen for organizing these symbols: http://www.m4b.io/elf/export/binary/analysis/2015/05/25/what-is-an-elf-export.html if isinstance(section, sections.SymbolTableSection): for symbol in section.iter_symbols(): if descriptions.describe_symbol_type( symbol['st_info']['type']) in [ 'FUNC', 'OBJECT' ]: if descriptions.describe_symbol_bind( symbol['st_info']['bind']) in [ 'GLOBAL', 'WEAK' ]: if descriptions.describe_symbol_shndx( symbol['st_shndx'] ) == 'UND': if symbol.name not in self.event[ 'imports']: self.event[ 'imports'].append( symbol.name) else: if symbol.name not in self.event[ 'exports']: self.event[ 'exports'].append( symbol.name) except OverflowError: self.flags.append('overflow_error') self.event.setdefault('segments', []) segment_cache = {} for segment in elf.iter_segments(): for section in elf.iter_sections(): if not section.is_null( ) and segment.section_in_segment(section): key = segment.header['p_type'] if key not in self.event['segments']: self.event['segments'].append(key) segment_cache.setdefault(key, []) segment_cache[key].append(section.name) self.event.setdefault('segment_sections', []) for (key, value) in segment_cache.items(): section_dict = {'segment': key, 'sections': value} if section_dict not in self.event['segment_sections']: self.event['segment_sections'].append(section_dict) except exceptions.ELFParseError: self.flags.append('elf_parse_error')
def get_sections(self): sections = [] for nsec, section in enumerate(self._elf.iter_sections()): result = {} result['nsec'] = nsec result['name'] = section.name result['sh_type'] = describe_sh_type(section['sh_type']) if self._elf.elfclass == 32: result['sh_addr'] = section['sh_addr'] result['shoffset'] = section['sh_offset'] result['sh_size'] = section['sh_size'] result['sh_entsize'] = section['sh_entsize'] result['sh_flags'] = describe_sh_flags(section['sh_flags']) result['sh_link'] = section['sh_link'] result['sh_info'] = section['sh_info'] result['sh_addralign'] = section['sh_addralign'] else: # 64 result['sh_addr'] = section['sh_addr'] result['sh_offset'] = section['sh_offset'] result['sh_size'] = section['sh_size'] result['sh_entsize'] = section['sh_entsize'] result['sh_flags'] = describe_sh_flags(section['sh_flags']) result['sh_link'] = section['sh_link'], section['sh_info'] result['sh_addralign'] = section['sh_addralign'] # Dynamic Section if isinstance(section, DynamicSection): result['special_type'] = 'dynamic' result['dynamic'] = [] has_dynamic_sections = True for tag in section.iter_tags(): dynamic = {} if tag.entry.d_tag == 'DT_NEEDED': parsed = 'Shared library: [%s]' % tag.needed elif tag.entry.d_tag == 'DT_RPATH': parsed = 'Library rpath: [%s]' % tag.rpath elif tag.entry.d_tag == 'DT_RUNPATH': parsed = 'Library runpath: [%s]' % tag.runpath elif tag.entry.d_tag == 'DT_SONAME': parsed = 'Library soname: [%s]' % tag.soname elif tag.entry.d_tag.endswith(('SZ', 'ENT')): parsed = '%i (bytes)' % tag['d_val'] elif tag.entry.d_tag.endswith(('NUM', 'COUNT')): parsed = '%i' % tag['d_val'] elif tag.entry.d_tag == 'DT_PLTREL': s = describe_dyn_tag(tag.entry.d_val) if s.startswith('DT_'): s = s[3:] parsed = '%s' % s else: parsed = '%#x' % tag['d_val'] dynamic['tag'] = ENUM_D_TAG.get( tag.entry.d_tag, tag.entry.d_tag) dynamic['tag_type'] = tag.entry.d_tag[3:] dynamic['tag_value'] = parsed result['dynamic'].append(dynamic) #Relocation Section if isinstance(section, RelocationSection): result['special_type'] = 'relocation' result['relocation'] = [] has_relocation_sections = True # The symbol table section pointed to in sh_link symtable = self._elf.get_section(section['sh_link']) for rel in section.iter_relocations(): relocation = {} relocation['r_offset'] = rel['r_offset'] relocation['r_info'] = rel['r_info'] relocation['r_info_type'] = describe_reloc_type( rel['r_info_type'], self._elf) if rel['r_info_sym'] == 0: continue symbol = symtable.get_symbol(rel['r_info_sym']) # Some symbols have zero 'st_name', so instead what's used is # the name of the section they point at if symbol['st_name'] == 0: symsec = self._elf.get_section(symbol['st_shndx']) relocation['symbol_name'] = symbol_name = symsec.name else: symbol_name = symbol.name relocation['st_value'] = symbol['st_value'] relocation['symbol_name'] = symbol_name if section.is_RELA(): relocation['r_addend'] = rel['r_addend'] result['relocation'].append(relocation) #Symbol Section if isinstance(section, SymbolTableSection): self._init_versioninfo() if section['sh_entsize'] == 0: continue result['special_type'] = 'symbol' result['symbol'] = [] for nsym, symbol in enumerate(section.iter_symbols()): sym_dic = {} version_info = '' # readelf doesn't display version info for Solaris versioning if (section['sh_type'] == 'SHT_DYNSYM' and self._versioninfo['type'] == 'GNU'): version = self._symbol_version(nsym) if (version['name'] != symbol.name and version['index'] not in ('VER_NDX_LOCAL', 'VER_NDX_GLOBAL')): if version['filename']: # external symbol version_info = '@%(name)s (%(index)i)' % version else: # internal symbol if version['hidden']: version_info = '@%(name)s' % version else: version_info = '@@%(name)s' % version # symbol names are truncated to 25 chars, similarly to readelf sym_dic['nsym'] = nsym sym_dic['st_value'] = symbol['st_value'] sym_dic['st_size'] = symbol['st_size'] sym_dic['st_type'] = describe_symbol_type( symbol['st_info']['type']) sym_dic['bind'] = describe_symbol_bind( symbol['st_info']['bind']) sym_dic['vis'] = describe_symbol_visibility( symbol['st_other']['visibility']) sym_dic['ndx'] = describe_symbol_shndx( symbol['st_shndx']) sym_dic['name'] = symbol.name sym_dic['version'] = version_info result['symbol'].append(sym_dic) sections.append(result) return sections
def display_symbol_tables(self): """ Display the symbol tables contained in the file """ self._init_versioninfo() listSyms = [] setClasses = set() for section in self.elffile.iter_sections(): if not isinstance(section, SymbolTableSection): continue if section['sh_entsize'] == 0: continue for nsym, symbolobj in enumerate(section.iter_symbols()): version_info = '' # readelf doesn't display version info for Solaris versioning if (section['sh_type'] == 'SHT_DYNSYM' and self._versioninfo['type'] == 'GNU'): version = self._symbol_version(nsym) if (version['name'] != symbolobj.name and version['index'] not in ('VER_NDX_LOCAL', 'VER_NDX_GLOBAL')): if version['filename']: # external symbol version_info = '@%(name)s (%(index)i)' % version else: # internal symbol if version['hidden']: version_info = '@%(name)s' % version else: version_info = '@@%(name)s' % version demang = demangler.demangle(symbolobj.name) nnn = indexStartsWith(demang, "vtable for ") if nnn: setClasses.add(nnn) continue nnn = indexStartsWith(demang, "typeinfo name for ") if nnn: setClasses.add(nnn) continue nnn = indexStartsWith(demang, "typeinfo for ") if nnn: setClasses.add(nnn) continue nnn = indexStartsWith(demang, "non-virtual thunk to ") if nnn: # No need to duplicate the symbol. # demang = nnn continue # Related to virtual inheritance. # http://stackoverflow.com/questions/6258559/what-is-the-vtt-for-a-class nnn = indexStartsWith(demang, "VTT for ") # TODO: Use it to build class hierarchy ??? if nnn: continue sym = ElfSym( demang, symbolobj.name, describe_symbol_type(symbolobj['st_info']['type']), describe_symbol_bind(symbolobj['st_info']['bind']), describe_symbol_visibility( symbolobj['st_other']['visibility']), describe_symbol_shndx(symbolobj['st_shndx']), version_info) listSyms.append(sym) return (listSyms, setClasses)