def display_elf_fh(elf, out): header = elf.header e_ident = header['e_ident'] if (out == "None"): print("\n----------ELF_HEADER----------") print("Magic: {}".format(' '.join('%2.2x' % byte2int(b) for b in elf.e_ident_raw))) print("Class: {}".format(describe_ei_class(e_ident['EI_CLASS']))) print("Data: {}".format(describe_ei_data(e_ident['EI_DATA']))) print("Version: {}".format(describe_ei_version(e_ident['EI_VERSION']))) print("OS | ABI: {}".format(describe_ei_osabi(e_ident['EI_OSABI']))) print("ABI version: {}".format(e_ident['EI_ABIVERSION'])) print("Type: {}".format(describe_e_type(header['e_type']))) print("Machine: {}".format(describe_e_machine(header['e_machine']))) print("Version: {}".format(describe_e_version_numeric(header['e_version']))) print("Entry Point: {}".format(_format_hex(header['e_entry'], elf))) print("Program Header Start: {} (bytes in)".format(header['e_phoff'])) print("Section Header Start: {} (bytes in)".format(header['e_shoff'])) print("Flags: {}{}".format(_format_hex(header['e_flags'], elf), decode_flags(header['e_flags'], elf))) print("Header Size: {}".format(header['e_ehsize'])) print("Program Headers Size: {}".format(header['e_phentsize'])) print("Program Header Count: {}".format(header['e_phnum'])) print("Section Headers Size: {}".format(header['e_shentsize'])) print("Section Header Count: {}".format(header['e_shnum'])) print("Section Header String Table Index: {}".format(header['e_shstrndx'])) else: try: with open(str(out, "utf-8"), "w") as outfile: outfile.write("----------ELF_HEADER----------\n") outfile.write("Magic: {}\n".format(' '.join('%2.2x' % byte2int(b) for b in elf.e_ident_raw))) outfile.write("Class: {}\n".format(describe_ei_class(e_ident['EI_CLASS']))) outfile.write("Data: {}\n".format(describe_ei_data(e_ident['EI_DATA']))) outfile.write("Version: {}\n".format(describe_ei_version(e_ident['EI_VERSION']))) outfile.write("OS | ABI: {}\n".format(describe_ei_osabi(e_ident['EI_OSABI']))) outfile.write("ABI version: {}\n".format(e_ident['EI_ABIVERSION'])) outfile.write("Type: {}\n".format(describe_e_type(header['e_type']))) outfile.write("Machine: {}\n".format(describe_e_machine(header['e_machine']))) outfile.write("Version: {}\n".format(describe_e_version_numeric(header['e_version']))) outfile.write("Entry Point: {}\n".format(_format_hex(header['e_entry'], elf))) outfile.write("Program Header Start: {} (bytes in)\n".format(header['e_phoff'])) outfile.write("Section Header Start: {} (bytes in)\n".format(header['e_shoff'])) outfile.write("Flags: {}{}\n".format(_format_hex(header['e_flags'], elf), decode_flags(header['e_flags'], elf))) outfile.write("Header Size: {}\n".format(header['e_ehsize'])) outfile.write("Program Headers Size: {}\n".format(header['e_phentsize'])) outfile.write("Program Header Count: {}\n".format(header['e_phnum'])) outfile.write("Section Headers Size: {}\n".format(header['e_shentsize'])) outfile.write("Section Header Count: {}\n".format(header['e_shnum'])) outfile.write("Section Header String Table Index: {}\n".format(header['e_shstrndx'])) outfile.close() except PermissionError as pErr: print("[Disassimpl][MAIN] - Permission denied on file") return False except Exception as e: print("[Disassimpl][MAIN] - Error {}".format(e)) return False
def elf_file_header(self): elf_header = {} def add_info(key, value): elf_header[key] = value header = self.elffile.header e_ident = header['e_ident'] add_info( 'Magic', ' '.join('%2.2x' % byte2int(b) for b in self.elffile.e_ident_raw)) add_info('Class', describe_ei_class(e_ident['EI_CLASS'])) add_info('Data', describe_ei_data(e_ident['EI_DATA'])) add_info('Version', e_ident['EI_VERSION']) add_info('OS/ABI', describe_ei_osabi(e_ident['EI_OSABI'])) add_info('ABI Version', e_ident['EI_ABIVERSION']) add_info('Type', describe_e_type(header['e_type'])) add_info('Machine', describe_e_machine(header['e_machine'])) add_info('Version_e', describe_e_version_numeric(header['e_version'])) add_info('Entry point address', self._format_hex(header['e_entry'])) add_info('Start of program headers', header['e_phoff']) add_info('Start of section headers', header['e_shoff']) add_info('Flags', [ self._format_hex(header['e_flags']), self.decode_flags(header['e_flags']) ]) add_info('Size of this header', header['e_ehsize']) add_info('Size of program headers', header['e_phentsize']) add_info('Number of program headers', header['e_phnum']) add_info('Size of section headers', header['e_shentsize']) add_info('Number of section headers', header['e_shnum']) add_info('Section header string table index', header['e_shstrndx']) return elf_header
def __init__(self, path): self.path = path self.parser = ELFFile(open(path, 'rb')) self.type = 'ELF' self.sections = [] self.stringAddrs = [] self.strings = self.strings() self.imageBase = 0 self.entryPoint = 0 for section in self.parser.iter_sections(): if '.text' in section.name: self.entryPoint = section.header.sh_addr if describe_e_type(self.parser.header.e_type).split()[0] != 'DYN': for seg in self.iter_segments_by_type('PT_LOAD'): addr = seg.header.p_vaddr if addr != 0: if addr < self.imageBase or self.imageBase == 0: self.imageBase = addr for section in self.parser.iter_sections(): if section.name: s = Section(section.name, section.header.sh_addr, section.header.sh_size) self.sections.append(s) self.symbols = {} self.imports = [] self.exports = [] self.populateSymbols() self.populateIEFunctions() self.findStrings()
def _get_file_header(self): return { "magic": convert_to_printable(self.elf.e_ident_raw[:4]), "class": describe_ei_class(self.elf.header.e_ident["EI_CLASS"]), "data": describe_ei_data(self.elf.header.e_ident["EI_DATA"]), "ei_version": describe_ei_version(self.elf.header.e_ident["EI_VERSION"]), "os_abi": describe_ei_osabi(self.elf.header.e_ident["EI_OSABI"]), "abi_version": self.elf.header.e_ident["EI_ABIVERSION"], "type": describe_e_type(self.elf.header["e_type"]), "machine": describe_e_machine(self.elf.header["e_machine"]), "version": describe_e_version_numeric(self.elf.header["e_version"]), "entry_point_address": self._print_addr(self.elf.header["e_entry"]), "start_of_program_headers": self.elf.header["e_phoff"], "start_of_section_headers": self.elf.header["e_shoff"], "flags": "{}{}".format( self._print_addr(self.elf.header["e_flags"]), self._decode_flags(self.elf.header["e_flags"]) ), "size_of_this_header": self.elf.header["e_ehsize"], "size_of_program_headers": self.elf.header["e_phentsize"], "number_of_program_headers": self.elf.header["e_phnum"], "size_of_section_headers": self.elf.header["e_shentsize"], "number_of_section_headers": self.elf.header["e_shnum"], "section_header_string_table_index": self.elf.header["e_shstrndx"], }
def print_basic_info(filename: str) -> None: with open(filename, "rb") as f: elffile = ELFFile(f) # ELF object # variables sections = "" debug = RED + "No" + RESET fileMD5 = file_MD5sum(filename) filesha1 = file_sha1sum(filename) filesha256 = file_sha256sum(filename) fileSSDEEP = file_ssdeepsum(filename) vtlink = tinyurl("https://www.virustotal.com/gui/file/" + filesha256) # logic if not vtlink: vtlink = "https://www.virustotal.com/gui/file/" + filesha256 for x in range(elffile.num_sections()): if len(elffile.get_section(x).name) > 0: sections += "{}{} {}({}) ".format( GREEN, elffile.get_section(x).name, RESET, hex(elffile.get_section(x).data_size)) if x % 4 == 0 and x > 0: sections += "\n" if not sections: sections = RED + "No sections found" + RESET # has debug info? if elffile.has_dwarf_info(): debug = GREEN + "Yes" + RESET info_table = [ ["Filename:", filename], ["Filesize:", file_size(filename)], [ "Filetype:", GREEN + "ELF " + str(elffile.get_machine_arch()) + RESET ], [ "Subsystem:", GREEN + describe_e_type(elffile.header['e_type']) + RESET ], ["MD5: ", fileMD5], ["SHA1: ", filesha1], ["SHA256: ", filesha256], ["SSDEEP:", fileSSDEEP], ["VT link:", vtlink], ["Symbols:", debug], ["Entropy:", str(file_entropy(filename))], ["Sections:\n(with size)", sections], ["Entrypoint:", "{}".format(hex(elffile.header["e_entry"]))] ] print("") print( AsciiTable( title="Basic Information", table_data=info_table, ).table) print("")
async def is_binary_pie(rpm: RPMFile, filename: str) -> Dict[str, Any]: with rpm.extractfile(filename) as handle: sig = handle.read(4) if len(sig) != 4 or sig != b"\x7fELF": return handle.seek(0) return { "is_pie": bool( describe_e_type(ELFFile(handle).header.e_type).split()[0] == "DYN") }
def display_file_header(self): """ Display the ELF file header """ self._emitline('ELF Header:') self._emit(' Magic: ') self._emitline(' '.join('%2.2x' % byte2int(b) for b in self.elffile.e_ident_raw)) header = self.elffile.header e_ident = header['e_ident'] self._emitline(' Class: %s' % describe_ei_class(e_ident['EI_CLASS'])) self._emitline(' Data: %s' % describe_ei_data(e_ident['EI_DATA'])) self._emitline(' Version: %s' % describe_ei_version(e_ident['EI_VERSION'])) self._emitline(' OS/ABI: %s' % describe_ei_osabi(e_ident['EI_OSABI'])) self._emitline(' ABI Version: %d' % e_ident['EI_ABIVERSION']) self._emitline(' Type: %s' % describe_e_type(header['e_type'])) self._emitline(' Machine: %s' % describe_e_machine(header['e_machine'])) self._emitline(' Version: %s' % describe_e_version_numeric(header['e_version'])) self._emitline(' Entry point address: %s' % self._format_hex(header['e_entry'])) self._emit(' Start of program headers: %s' % header['e_phoff']) self._emitline(' (bytes into file)') self._emit(' Start of section headers: %s' % header['e_shoff']) self._emitline(' (bytes into file)') self._emitline(' Flags: %s%s' % (self._format_hex(header['e_flags']), self.decode_flags(header['e_flags']))) self._emitline(' Size of this header: %s (bytes)' % header['e_ehsize']) self._emitline(' Size of program headers: %s (bytes)' % header['e_phentsize']) self._emitline(' Number of program headers: %s' % header['e_phnum']) self._emitline(' Size of section headers: %s (bytes)' % header['e_shentsize']) self._emitline(' Number of section headers: %s' % header['e_shnum']) self._emitline(' Section header string table index: %s' % header['e_shstrndx'])
def display_file_header(self): """ Display the ELF file header """ self._emitline('ELF Header:') self._emit(' Magic: ') self._emitline(' '.join('%2.2x' % byte2int(b) for b in self.elffile.e_ident_raw)) header = self.elffile.header e_ident = header['e_ident'] self._emitline(' Class: %s' % describe_ei_class(e_ident['EI_CLASS'])) self._emitline(' Data: %s' % describe_ei_data(e_ident['EI_DATA'])) self._emitline(' Version: %s' % describe_ei_version(e_ident['EI_VERSION'])) self._emitline(' OS/ABI: %s' % describe_ei_osabi(e_ident['EI_OSABI'])) self._emitline(' ABI Version: %d' % e_ident['EI_ABIVERSION']) self._emitline(' Type: %s' % describe_e_type(header['e_type'])) self._emitline(' Machine: %s' % describe_e_machine(header['e_machine'])) self._emitline(' Version: %s' % describe_e_version_numeric(header['e_version'])) self._emitline(' Entry point address: %s' % self._format_hex(header['e_entry'])) self._emit(' Start of program headers: %s' % header['e_phoff']) self._emitline(' (bytes into file)') self._emit(' Start of section headers: %s' % header['e_shoff']) self._emitline(' (bytes into file)') self._emitline(' Flags: %s' % self._format_hex(header['e_flags'])) self._emitline(' Size of this header: %s (bytes)' % header['e_ehsize']) self._emitline(' Size of program headers: %s (bytes)' % header['e_phentsize']) self._emitline(' Number of program headers: %s' % header['e_phnum']) self._emitline(' Size of section headers: %s (bytes)' % header['e_shentsize']) self._emitline(' Number of section headers: %s' % header['e_shnum']) self._emitline(' Section header string table index: %s' % header['e_shstrndx'])
def get_elf_header(self): result = {} header = self._elf.header if (hasattr(header, 'e_ident')): e_ident = header['e_ident'] EI_MAG = '' for MAG in e_ident['EI_MAG']: EI_MAG += str(hex(MAG)).replace("0x", '') result['EI_MAG'] = EI_MAG result['EI_CLASS'] = describe_ei_class(e_ident['EI_CLASS']) result['EI_DATA'] = describe_ei_data(e_ident['EI_DATA']) result['EI_VERSION'] = describe_ei_version(e_ident['EI_VERSION']) result['EI_OSABI'] = describe_ei_osabi(e_ident['EI_OSABI']) if (hasattr(header, 'e_type')): result['e_type'] = describe_e_type(header['e_type']) if (hasattr(header, 'e_machine')): result['e_machine'] = describe_e_machine(header['e_machine']) if (hasattr(header, 'e_version')): result['e_version'] = header['e_version'] if (hasattr(header, 'e_entry')): result['e_entry'] = header['e_entry'] if (hasattr(header, 'e_phoff')): result['e_phoff'] = header['e_phoff'] if (hasattr(header, 'e_shoff')): result['e_shoff'] = header['e_shoff'] if (hasattr(header, 'e_flags')): result['e_flags'] = header['e_flags'] if (hasattr(header, 'e_ehsize')): result['e_ehsize'] = header['e_ehsize'] if (hasattr(header, 'e_phentsize')): result['e_phentsize'] = header['e_phentsize'] if (hasattr(header, 'e_phnum')): result['e_phnum'] = header['e_phnum'] if (hasattr(header, 'e_shentsize')): result['e_shentsize'] = header['e_shentsize'] if (hasattr(header, 'e_shnum')): result['e_shnum'] = header['e_shnum'] if (hasattr(header, 'e_shstrndx')): result['e_shstrndx'] = header['e_shstrndx'] return result
def elftype(self): """ELF type (EXEC, DYN, etc)""" return describe_e_type(self.header.e_type).split()[0]
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 elftype(self): """:class:`str`: ELF type (``EXEC``, ``DYN``, etc)""" return describe_e_type(self.header.e_type).split()[0]
def display_program_headers(self, show_heading=True): """ Display the ELF program headers. If show_heading is True, displays the heading for this information (Elf file type is...) """ self._emitline() if self.elffile.num_segments() == 0: self._emitline('There are no program headers in this file.') return elfheader = self.elffile.header if show_heading: self._emitline('Elf file type is %s' % describe_e_type(elfheader['e_type'])) self._emitline('Entry point is %s' % self._format_hex(elfheader['e_entry'])) # readelf weirness - why isn't e_phoff printed as hex? (for section # headers, it is...) self._emitline( 'There are %s program headers, starting at offset %s' % (elfheader['e_phnum'], elfheader['e_phoff'])) self._emitline() self._emitline('Program Headers:') # Now comes the table of program headers with their attributes. Note # that due to different formatting constraints of 32-bit and 64-bit # addresses, there are some conditions on elfclass here. # # First comes the table heading # if self.elffile.elfclass == 32: self._emitline( ' Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align' ) else: self._emitline( ' Type Offset VirtAddr PhysAddr' ) self._emitline( ' FileSiz MemSiz Flags Align' ) # Now the entries # for segment in self.elffile.iter_segments(): self._emit(' %-14s ' % describe_p_type(segment['p_type'])) if self.elffile.elfclass == 32: self._emitline( '%s %s %s %s %s %-3s %s' % (self._format_hex(segment['p_offset'], fieldsize=6), self._format_hex(segment['p_vaddr'], fullhex=True), self._format_hex(segment['p_paddr'], fullhex=True), self._format_hex(segment['p_filesz'], fieldsize=5), self._format_hex(segment['p_memsz'], fieldsize=5), describe_p_flags(segment['p_flags']), self._format_hex(segment['p_align']))) else: # 64 self._emitline( '%s %s %s' % (self._format_hex(segment['p_offset'], fullhex=True), self._format_hex(segment['p_vaddr'], fullhex=True), self._format_hex(segment['p_paddr'], fullhex=True))) self._emitline(' %s %s %-3s %s' % ( self._format_hex(segment['p_filesz'], fullhex=True), self._format_hex(segment['p_memsz'], fullhex=True), describe_p_flags(segment['p_flags']), # lead0x set to False for p_align, to mimic readelf. # No idea why the difference from 32-bit mode :-| self._format_hex(segment['p_align'], lead0x=False))) if isinstance(segment, InterpSegment): self._emitline(' [Requesting program interpreter: %s]' % bytes2str(segment.get_interp_name())) # Sections to segments mapping # if self.elffile.num_sections() == 0: # No sections? We're done return self._emitline('\n Section to Segment mapping:') self._emitline(' Segment Sections...') for nseg, segment in enumerate(self.elffile.iter_segments()): self._emit(' %2.2d ' % nseg) for section in self.elffile.iter_sections(): if (not section.is_null() and segment.section_in_segment(section)): self._emit('%s ' % bytes2str(section.name)) self._emitline('')
def display_program_headers(self, show_heading=True): """ Display the ELF program headers. If show_heading is True, displays the heading for this information (Elf file type is...) """ self._emitline() if self.elffile.num_segments() == 0: self._emitline('There are no program headers in this file.') return elfheader = self.elffile.header if show_heading: self._emitline('Elf file type is %s' % describe_e_type(elfheader['e_type'])) self._emitline('Entry point is %s' % self._format_hex(elfheader['e_entry'])) # readelf weirness - why isn't e_phoff printed as hex? (for section # headers, it is...) self._emitline('There are %s program headers, starting at offset %s' % ( elfheader['e_phnum'], elfheader['e_phoff'])) self._emitline() self._emitline('Program Headers:') # Now comes the table of program headers with their attributes. Note # that due to different formatting constraints of 32-bit and 64-bit # addresses, there are some conditions on elfclass here. # # First comes the table heading # if self.elffile.elfclass == 32: self._emitline(' Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align') else: self._emitline(' Type Offset VirtAddr PhysAddr') self._emitline(' FileSiz MemSiz Flags Align') # Now the entries # for segment in self.elffile.iter_segments(): self._emit(' %-14s ' % describe_p_type(segment['p_type'])) if self.elffile.elfclass == 32: self._emitline('%s %s %s %s %s %-3s %s' % ( self._format_hex(segment['p_offset'], fieldsize=6), self._format_hex(segment['p_vaddr'], fullhex=True), self._format_hex(segment['p_paddr'], fullhex=True), self._format_hex(segment['p_filesz'], fieldsize=5), self._format_hex(segment['p_memsz'], fieldsize=5), describe_p_flags(segment['p_flags']), self._format_hex(segment['p_align']))) else: # 64 self._emitline('%s %s %s' % ( self._format_hex(segment['p_offset'], fullhex=True), self._format_hex(segment['p_vaddr'], fullhex=True), self._format_hex(segment['p_paddr'], fullhex=True))) self._emitline(' %s %s %-3s %s' % ( self._format_hex(segment['p_filesz'], fullhex=True), self._format_hex(segment['p_memsz'], fullhex=True), describe_p_flags(segment['p_flags']), # lead0x set to False for p_align, to mimic readelf. # No idea why the difference from 32-bit mode :-| self._format_hex(segment['p_align'], lead0x=False))) if isinstance(segment, InterpSegment): self._emitline(' [Requesting program interpreter: %s]' % bytes2str(segment.get_interp_name())) # Sections to segments mapping # if self.elffile.num_sections() == 0: # No sections? We're done return self._emitline('\n Section to Segment mapping:') self._emitline(' Segment Sections...') for nseg, segment in enumerate(self.elffile.iter_segments()): self._emit(' %2.2d ' % nseg) for section in self.elffile.iter_sections(): if ( not section.is_null() and segment.section_in_segment(section)): self._emit('%s ' % bytes2str(section.name)) self._emitline('')