def parse(self, data, vm=None): # Parse signature if not data.startswith('\x7fELF'): raise ContainerSignatureException() # Build executable instance try: if vm is not None: self._executable = vm_load_elf(vm, filename) else: self._executable = elf_init.ELF(data) except Exception, error: raise ContainerParsingException('Cannot read ELF: %s' % error)
def parse(self, data, vm=None): from miasm2.jitter.loader.elf import vm_load_elf, guess_arch from elfesteem import elf_init # Parse signature if not data.startswith('\x7fELF'): raise ContainerSignatureException() # Build executable instance try: if vm is not None: self._executable = vm_load_elf(vm, data) else: self._executable = elf_init.ELF(data) except Exception, error: raise ContainerParsingException('Cannot read ELF: %s' % error)
def extract_section(data, section=False): # Extract text sections from know containers # elfesteem has to be installed try: import elfesteem except ImportError: return data magic = (0x7f, 0x45, 0x4c, 0x46) if data.startswith(struct.pack("%dB" % len(magic), *magic)): from elfesteem import elf_init e = elf_init.ELF(data) res = struct.pack("") for sh in e.sh: if (section == 'text' and sh.sh.name.startswith('.text') ) or sh.sh.name == section: res += data[sh.sh.offset:sh.sh.offset + sh.sh.size] if len(res): return res magic = (0x4d, 0x5a) if data.startswith(struct.pack("%dB" % len(magic), *magic)): if section == 'text': section = '.text' from elfesteem import pe_init e = pe_init.PE(data) for sh in e.SHList: if sh.name.strip('\0') == section: return data[sh.offset:sh.offset + sh.rawsize] magic = ((0xce, 0xfa, 0xed, 0xfe), (0xcf, 0xfa, 0xed, 0xfe)) if data.startswith(tuple([struct.pack("4B", *_) for _ in magic])): if section == 'text': section = '__TEXT' from elfesteem import macho_init e = macho_init.MACHO(data, parseSymbols=False) for s in e.sect.sect: if s.sh.segname == section: return data[s.sh.offset:s.sh.offset + s.sh.size] try: from elfesteem import pe_init, pe e = pe_init.Coff(data) if section == 'text': section = '.text' for sh in e.SHList: if sh.name.strip('\0') == section: return data[sh.offset:sh.offset + sh.rawsize] except ValueError: pass return data
parser.add_argument('-g', '--section-groups', dest='options', action='append_const', const='groups', help='Display the section groups') parser.add_argument('file', nargs='+', help='ELF file(s)') args = parser.parse_args() if args.options == None: args.options = [] for file in args.file: if len(args.file) > 1: print("\nFile: %s" % file) raw = open(file, 'rb').read() e = elf_init.ELF(raw) if 'headers' in args.options: display_headers(e) if 'sections' in args.options: print(e.sh.readelf_display()) if 'reltab' in args.options: for sh in e.sh: if not 'rel' in dir(sh): continue print("\n" + sh.readelf_display()) if 'symtab' in args.options or 'dynsym' in args.options: display_symbols(e.getsectionsbytype(elf.SHT_DYNSYM)) if 'symtab' in args.options: display_symbols(e.getsectionsbytype(elf.SHT_SYMTAB)) if 'dynamic' in args.options: display_dynamic(e) if 'program' in args.options:
def mk_bin_file(symbols): import sys symbols.resolve() relocs = {} label_func = [ label for label in symbols.symbols if getattr(label, 'type', None) == 'function' ] if len(label_func): relocs[".eh_frame"] = [] for pos, label, r_type, section in symbols.list_relocs(): if not section in relocs: relocs[section] = [] relocs[section].append((pos, label, r_type)) section_groups = [] sections = [".text", ".data", ".bss"] for label in symbols.symbols: section = getattr(label, 'section', '') if section.startswith(".rodata") and not section in sections: sections.append(section) for label in symbols.symbols: section = getattr(label, 'section', '') if section.startswith(".data") and not section in sections: sections.append(section) for label in symbols.symbols: section = getattr(label, 'section', '') if section.startswith(".text.") and not section in sections: section_groups.append(section) if section in symbols.sections.asm_name: if 'comdat' in symbols.sections.asm_name[section]: sections.insert(0, '.group') sections.append(section) sections += [".comment", ".note.GNU-stack"] if len(label_func): sections += [".eh_frame"] # Creates a relocatable ELF file CPU = symbols.arch.CPU if CPU == 'I386': CPU = '386' from elfesteem import elf, elf_init e = elf_init.ELF(e_type=elf.ET_REL, e_machine=elf.__dict__['EM_' + CPU], sections=sections, relocs=relocs.keys()) # The symbol table, first local and then global and weak # Local symbols begin with an empty symbol and the file name, # then sections until bss, then local object or func, # then other sections, with ".comment" at the end symtab = e.getsectionbyname(".symtab") symtab[0] = elf.Sym32(parent=symtab, name="") symtab_local_file = [] symtab_local_symb = [] symtab_globl_symb = [] for label in symbols.symbols: bind = getattr(label, 'bind', None) if bind in [None, 'weak']: pass elif getattr(label, 'type', None) == 'endofsymbol': pass elif bind == 'file': symtab_local_file.append(label) elif bind == 'local': symtab_local_symb.append(label) elif bind == 'globl': symtab_globl_symb.append(label) else: FAIL symtab_sect = [[]] for v, s in enumerate(e.sh.shlist): if not s.sh.type in [elf.SHT_PROGBITS, elf.SHT_NOBITS]: continue if s.sh.name == '.comment': continue symtab_sect[-1].append( elf.Sym32(parent=symtab, info=elf.STT_SECTION, shndx=v)) if s.sh.name == '.bss': symtab_sect.append([]) symtab_sect.append([]) v = e.sh.shlist.index(e.getsectionbyname(".comment")) symtab_sect[-1].append( elf.Sym32(parent=symtab, info=elf.STT_SECTION, shndx=v)) for v, s in enumerate(e.sh.shlist): if s.sh.name != '.group': continue symtab_sect[-1].append( elf.Sym32(parent=symtab, info=elf.STT_SECTION, shndx=v)) def get_props(label): props = { 'shndx': 0, 'size': getattr(label, 'size', 0), 'value': 0, } props['info'] = { None: elf.STT_NOTYPE, 'object': elf.STT_OBJECT, 'function': elf.STT_FUNC, 'tls_object': elf.STT_TLS, }[getattr(label, 'type', None)] props['other'] = { None: elf.STV_DEFAULT, 'hidden': elf.STV_HIDDEN, }[getattr(label, 'visibility', None)] if not hasattr(label, 'section'): pass elif label.section == comm_symbol_section: props['shndx'] = elf.SHN_COMMON props['value'] = label.align elif label.section.startswith('__'): section = { '__TEXT,__text': '.text', '__DATA,__data': '.data', }[label.section] props['shndx'] = e.sh.shlist.index(e.getsectionbyname(section)) props['value'] = label.address else: section = label.section.split(',')[0] props['shndx'] = e.sh.shlist.index(e.getsectionbyname(section)) props['value'] = label.address return props idx = 1 label_idx = {} for label in symtab_local_file: symtab[idx] = elf.Sym32(parent=symtab, name=label.name, info=elf.STT_FILE, shndx=elf.SHN_ABS) idx += 1 for sym in symtab_sect[0]: symtab[idx] = sym label_idx[e.sh.shlist[sym.shndx].sh.name] = idx idx += 1 for label in symtab_local_symb: props = get_props(label) if props['info'] == elf.STT_NOTYPE: continue symtab[idx] = elf.Sym32(parent=symtab, name=label.name, **props) label_idx[label] = idx idx += 1 for sym in symtab_sect[1]: symtab[idx] = sym label_idx[e.sh.shlist[sym.shndx].sh.name] = idx idx += 1 for label in symtab_local_symb: props = get_props(label) if props['info'] != elf.STT_NOTYPE: continue symtab[idx] = elf.Sym32(parent=symtab, name=label.name, **props) label_idx[label] = idx idx += 1 for sym in symtab_sect[2]: symtab[idx] = sym label_idx[e.sh.shlist[sym.shndx].sh.name] = idx idx += 1 for label in symtab_globl_symb: props = get_props(label) props['info'] |= elf.STB_GLOBAL << 4 symtab[idx] = elf.Sym32(parent=symtab, name=label.name, **props) label_idx[label] = idx idx += 1 for label in symbols.symbols: if getattr(label, 'bind', None) is not None: continue if getattr(label, 'type', None) == 'padding': continue if not label.is_symbol(): continue if label.name.endswith('@PLT') or label.name.endswith('@GOT') \ or label.name.endswith('@GOTOFF'): continue if hasattr(label, 'reference'): continue info = elf.STB_GLOBAL << 4 symtab[idx] = elf.Sym32(parent=symtab, name=label.name, info=info, shndx=0, size=0, value=0) label_idx[label] = idx idx += 1 meta = symbols.get_meta() if 'ident' in meta: s = e.getsectionbyname(".comment") s.content[0] = '\0' + meta['ident'] + '\0' # eh_frame data structure is quite complicated # here, we create a null eh_frame and ad hoc rel.eh_frame if len(label_func): s = e.getsectionbyname(".eh_frame") s.content[0] = '\0' * meta.get('eh_frame_size', 0x18 + 0x20 * len(label_func)) if 'eh_frame_relocs' in meta: eh_reloc = meta['eh_frame_relocs'].sortedkeys else: eh_reloc = [0x20 * (idx + 1) for idx in range(len(label_func))] for idx, pos in enumerate(eh_reloc): if ',' in section: section = label_func[idx].section.split(',')[0] relocs[".eh_frame"].append( (pos, section, (elf.EM_386, elf.R_386_PC32))) # Section relocations from plasmasm.symbols import section_type for section in relocs: s = e.getsectionbyname(".rel" + section) if s is None: continue for idx, (pos, label, r_type) in enumerate(relocs[section]): cpu, info = r_type # For some symbols, the relocation shall refer to the start of # the section, not to the symbol itself. l_sect = getattr(label, 'section', None) if (cpu, info) == (elf.EM_386, elf.R_386_GOTOFF): if section_type(section) == 'text' \ and getattr(label, 'bind', None) == 'local' \ and not label.name.startswith('.LC'): label = l_sect elif not hasattr(label, 'bind'): label = l_sect if (cpu, info) == (elf.EM_386, elf.R_386_32): if not getattr(label, 'bind', None) == 'globl': label = l_sect if (cpu, info) == (elf.EM_386, elf.R_386_PC32): if not getattr(label, 'bind', 'globl') == 'globl': label = l_sect if label in label_idx: info += label_idx[label] << 8 s.content[8 * idx] = elf.Rel32(parent=s, offset=pos, info=info).pack() # Section alignment, does not mimic exactly GNU as align = {'.data': (4, 0), '.bss': (4, 0), '.rodata': (1, 0)} for label in symbols.symbols: section = getattr(label, 'section', None) if not section in align: continue value = getattr(label, 'align', getattr(label, 'size', 0)) al, sz = align[section] for v in [4, 8, 32]: if label.address % v == 0 and al < v <= value: al = v align[section] = (al, sz + value) for section in align: s = e.getsectionbyname(section) if s is None: continue al, sz = align[section] if section == '.data' and al >= sz: continue s.sh.addralign = al # Section content for section in sections: if not section_type(section) in ["text", "data", "rodata", "bss"]: continue s = e.getsectionbyname(section) if s is None: continue if section in [ '.text.__i686.get_pc_thunk.bx', '.text.__i686.get_pc_thunk.cx' ]: for label in symbols.symbols: if not getattr(label, 'section', '').startswith(section): continue s.content[label.address] = label.pack() for o in symbols.object_list(): label = o[0] if label.section != section: continue if hasattr(label, 'align'): end = len(s.content) if (end % label.align) != 0: for c in range(label.align - (end % label.align)): s.content += struct.pack("B", 0) data = struct.pack("") for bloc in o: data += bloc.pack() size = len(data) if hasattr(label, 'size') and label.size != size: log.warning("%s has size %d != %d", label, label.size, size) # This might be cause by p2align directives else: symbols.setattr(name=label.name, size=size) if not hasattr(label, 'address'): log.warning("%s has no address", label) # This should have been addressed by symbols.resolve() label.address = 0 symbols.setattr(name=label.name, address=0) s.content[label.address] = data # Section groups for s in e.sh: if s.sh.type != elf.SHT_GROUP: continue ref = section_groups.pop(0) if 'comdat' in symbols.sections.asm_name.get(ref, ''): s.flags = elf.GRP_COMDAT shndx = e.sh.shlist.index(e.getsectionbyname(ref.split(',')[0])) s.sections = [shndx] if not ',' in ref: # TODO continue label = ref.split(',')[3] s.sh.info = symtab.symtab.index(symtab[label]) return e.pack()
def extract_text(filename): """Extrait la section .text d'un ELF""" from elfesteem import elf_init e = elf_init.ELF(open(filename, "rb").read()) s = e.getsectionbyname('.text') return str(s.content)