#!/usr/bin/python '''analyze and create ELF executables see /usr/include/linux/elf.h''' import sys, os, struct MAGIC = '\x7f' + 'ELF' + ('\1' * 3) + ('\0' * 9) # ELF "magic" header EHSIZE = 52 # kinda must be known before even attempting to parse class reducible(str): def __sub__(self, other): start = self.find(other) if start == -1: return self else: return reducible(self[0:start] + self[start + len(other):]) class elf: pass def main(): 'run the program' elffile = reducible(readall('minimal.exe')) e = elf() (e.magic, e.type, e.machine, e.version, e.entry, e.phoff, e.shoff, e.flags, e.ehsize, e.phentsize, e.phnum, e.shentsize, e.shnum, e.shstrndx, remainder) = elfheader(elffile) print dir(e) if e.magic != MAGIC: raise Exception, 'not an ELF file' dump(e) #print 'remainder: ', repr(remainder) pheaders = elffile[e.phoff:e.phoff + (e.phnum * e.phentsize)] sheaders = elffile[e.shoff:e.shoff + (e.shnum * e.shentsize)] shstrhdr = sheaders[e.shstrndx * e.shentsize:(e.shstrndx + 1) * e.shentsize] shstrtab = elfdata(elffile, elf_shdr(shstrhdr)[4:6]) print 'section string table', repr(shstrtab) remainder = remainder - pheaders - sheaders for i in range(e.phnum): pheader = pheaders[i * e.phentsize:(i + 1) * e.phentsize] print 'pheader', hex(elf_phdr(pheader)) for i in range(e.shnum): sheader = sheaders[i * e.shentsize:(i + 1) * e.shentsize] sheader_values = elf_shdr(sheader) print 'sheader', hex(elf_shdr(sheader)) section_data = elffile[sheader_values[4]:sheader_values[4] + \ sheader_values[5]] print 'section data', repr(section_data) if sheader_values[1] == 2: # symbol table for j in range(0, len(section_data), 16): print 'symbol', hex(sym(section_data[j:j + 16])) remainder -= section_data print 'remainder: ', repr(remainder) def elfdata(elffile, whatpart): start, size = whatpart return elffile[start:start + size] def elfheader(elffile): 'return parsed header and remainder of file' format = '<16s 2H 5L 6H' return struct.unpack(format, elffile[:EHSIZE]) + (reducible(elffile[EHSIZE:]),) def elf_phdr(data): 'return parsed program header' format = '<8L' return struct.unpack(format, data) def hex(data): return map(lambda n: '0x%x' % n, data) def elf_shdr(data): format = '<10L' return struct.unpack(format, data) def sym(data): format = '<3L 2B H' return struct.unpack(format, data) def readall(filename): 'get contents of a file, closing it properly' input = open(filename) data = input.read() input.close() return data def debug(message): 'print debugging message to stderr' if True: # change to False when done debugging print >>sys.stderr, message def dump(object): for attribute in dir(object): if not attribute.startswith('_'): value = getattr(object, attribute) if isinstance(value, int): print attribute, '0x%x' % value else: print attribute, repr(value) if __name__ == '__main__': main()