def _phdr_hack2(self): ''' Try to repurpose the GNU_STACK entry. I.e., delete it, freeing room for one additional entry. At one point I was convinced that in most cases, this entry is not needed. Could be wrong. ''' logger.info("Trying method 2...") if self.num_adtl_segments != 1: logger.info( "Method 2 does not apply: Would only provide one additional segment" ) return False for idx, segment in enumerate(self.elf.iter_segments()): # TODO: why are we not calling self._update_phdr_entry like in Method 1?? if describe_p_type(segment['p_type']) == "GNU_STACK": # keep the old base and max number of entries self.phdrs['base'] = self.ehdr['e_phoff'] self.phdrs['max_num'] = len(self.phdrs['entries']) # remove this entry, freeing up room for one user defined entry logger.debug("removing GNU_STACK pdhr entry") del self.phdrs['entries'][idx] self.ehdr['e_phnum'] -= 1 # assert describe_p_type(gnu_stack_entry.p_type) == "GNU_STACK" logger.info("should have room to add one section/segment") return True else: logger.info("Method 2 does not apply: No GNU_STACK entry") return False
def elf_program_headers(self): program_headers = [] def add_info(dic): program_headers.append(dic) if self.elffile.num_segments() == 0: return None for segment in self.elffile.iter_segments(): program_hdr = {} program_hdr['Type'] = describe_p_type(segment['p_type']) program_hdr['Offset'] = self._format_hex(segment['p_offset'], fieldsize=6) program_hdr['VirtAddr'] = self._format_hex(segment['p_vaddr'], fullhex=True) program_hdr['PhysAddr'] = self._format_hex(segment['p_paddr'], fullhex=True) program_hdr['FileSiz'] = self._format_hex(segment['p_filesz'], fieldsize=5) program_hdr['MemSiz'] = self._format_hex(segment['p_memsz'], fieldsize=5) program_hdr['Flg'] = describe_p_flags(segment['p_flags']) program_hdr['Align'] = self._format_hex(segment['p_align']) add_info(program_hdr) return program_headers
def run(self, args): file_path = idaapi.get_input_file_path() if not file_path: print('Input file path was not found') return try: fd = open(file_path, "rb") elf = ELFFile(fd) except Exception as x: print(x) return eh_frame_phdr = next( (segment for segment in elf.iter_segments() if describe_p_type(segment['p_type']) == 'GNU_EH_FRAME'), None) if not eh_frame_phdr: print("[-] Executable was not compiled with exception unwinding information") return eh_frame_hdr_data = EhFrameHdr(eh_frame_phdr, elf) fde_count = eh_frame_hdr_data.decode_pointer(eh_frame_hdr_data.fde_count_enc, eh_frame_hdr_data.fde_count, pc=eh_frame_phdr['p_vaddr'] + 8) block_map = [] for i in range(0, fde_count): (initial_loc, fde_entry_offset) = unpack("2I", GetManyBytes(eh_frame_hdr_data.fde_table_vaddr + 8 * i, 8)) (function_vaddr, function_size) = eh_frame_hdr_data.decode_pointer(eh_frame_hdr_data.table_enc, initial_loc, fde_entry_offset) block_map.append({'function_address': function_vaddr, 'function_size': function_size}) block_form = BlockForm0(block_map) block_form.Show('GNU_EH_FRAME functions')
def _get_program_headers(self) -> List[Dict[str, str]]: return [ { "type": describe_p_type(segment["p_type"]), "addr": self._print_addr(segment["p_vaddr"]), "flags": describe_p_flags(segment["p_flags"]).strip(), "size": segment["p_memsz"], } for segment in self.elf.iter_segments() ]
def _get_program_headers(self): program_headers = [] for segment in self.elf.iter_segments(): program_headers.append({ "type": describe_p_type(segment["p_type"]), "addr": self._print_addr(segment["p_vaddr"]), "flags": describe_p_flags(segment["p_flags"]).strip(), "size": segment["p_memsz"], }) return program_headers
def _get_program_headers(self): program_headers = [] for segment in self.elf.iter_segments(): program_headers.append({ "type": describe_p_type(segment["p_type"]), "addr": self._print_addr(segment["p_vaddr"]), "flags": describe_p_flags(segment["p_flags"]).strip(), "size": segment["p_memsz"], }) return program_headers
def get_program_header(self): header = [] if self._elf.num_segments() == 0: return [] for segment in self._elf.iter_segments(): result = {} result['p_type'] = describe_p_type(segment['p_type']) if self._elf.elfclass == 32: result['p_offset'] = segment['p_offset'] result['p_vaddr'] = segment['p_vaddr'] result['p_paddr'] = segment['p_paddr'] result['p_filesz'] = segment['p_filesz'] result['p_memsz'] = segment['p_memsz'] result['p_flags'] = describe_p_flags(segment['p_flags']) result['p_align'] = segment['p_align'] else: # 64 result['p_offset'] = segment['p_offset'] result['p_vaddr'] = segment['p_vaddr'] result['p_paddr'] = segment['p_paddr'] result['p_filesz'] = segment['p_filesz'] result['p_memsz'] = segment['p_memsz'] result['p_flags'] = describe_p_flags(segment['p_flags']) result['p_align'] = segment['p_align'] if isinstance(segment, InterpSegment): result['interp_name'] = segment.get_interp_name() result['include_section'] = [] for section in self._elf.iter_sections(): if (not section.is_null() and segment.section_in_segment(section)): result['include_section'].append(section.name) #NoteSegment if isinstance(segment, NoteSegment): result['special_type'] = 'note' result['note'] = [] for note in segment.iter_notes(): note_dic = {} note_dic['n_offset'] = note['n_offset'] note_dic['n_size'] = note['n_size'] note_dic['n_name'] = note['n_name'] note_dic['n_descsz'] = note['n_descsz'] note_dic['note'] = describe_note(note) result['note'].append(note_dic) header.append(result) return header
def load_elf_and_run(f): elffile = ELFFile(f) for segment in elffile.iter_segments(): t = describe_p_type(segment['p_type']) print "Program Header: Size: %d, Virtual Address: 0x%x, Type: %s" % ( segment['p_filesz'], segment['p_vaddr'], t) if not (segment['p_vaddr'] & 0x80000000): continue if segment['p_filesz'] == 0 or segment['p_vaddr'] == 0: print "Skipped" continue write_ram(0xa0000000 | segment['p_vaddr'], segment.data(), True) print "Entry: 0x%x" % elffile['e_entry'] go_ram(elffile['e_entry'])
def main(): if(len(sys.argv)!=3): print "Usage: %s <ELF filename> <output filename>" % sys.argv[0] return print "Opening ELF file: %s" % sys.argv[1] elffile = ELFFile(open(sys.argv[1],'r')) print "Entry point: 0x%x" % elffile.header['e_entry'] loadsegments = list() for segment in elffile.iter_segments(): segtype = describe_p_type(segment['p_type']) if(segtype=="LOAD"): loadsegments.append(segment) imgsize = 0 for segment in loadsegments: if(elffile.elfclass == 32): print "Load offset " + str(describe_p_flags(segment['p_flags'])) + \ " 0x%08x at 0x%08x, align 0x%0x" % \ (segment['p_offset'], segment['p_vaddr'], segment['p_align']) else: print "Load offset " + str(describe_p_flags(segment['p_flags'])) + \ " 0x%016x at 0x%016x, align 0x%0x" % \ (segment['p_offset'], segment['p_vaddr'], segment['p_align']) print "\tFile size: 0x%x\tMem size: 0x%x" % (segment['p_filesz'], segment['p_memsz']) imgsize = max(imgsize,segment['p_vaddr']+segment['p_memsz']) print "Image size: 0x%x" % imgsize buf = ctypes.create_string_buffer(imgsize) for segment in loadsegments: offset = segment['p_vaddr'] data = segment.data() for i in range(len(segment.data())): buf[offset+i] = data[i] outfile = file(sys.argv[2],'w') for char in buf: outfile.write(char)
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('')
with open(sys.argv[1], "rb") as file_handle: binary_content = file_handle.read() elf_file = ELFFile(file_handle) entry_point = elf_file['e_entry'] #print(entry_point) print("Entry point: %08X\n" % (entry_point)) print("Retrieving appropriated offset...") start_offset = -1 for segment in elf_file.iter_segments(): start = segment['p_vaddr'] size = segment['p_filesz'] print("Segment '%s' starting at %08X with size of %d bytes" % (describe_p_type(segment['p_type']), segment['p_vaddr'], segment['p_filesz'])) if(entry_point >= start and entry_point < (start+size)): print("\t*** Entry point is located here! ***") start_offset = segment['p_offset'] + (entry_point - start) if start_offset >= 0: print("Start offset computed at %08X" % (start_offset)) with open("%s.asm" % (sys.argv[1]), "w") as output_asm_file: output_asm_file.write("bits 32\n\n") i = 0 for c in binary_content: if i == start_offset: output_asm_file.write("_start:\n") output_asm_file.write("\tdb 0x%02X\n" % (c & 0xff))