import struct
import sys
class ElfPHdr(object):
FMT = '<8I'
def __init__(self, idx):
self.idx = idx
self.type = None
self.offset = None
self.vaddr = None
self.paddr = None
self.filesz = None
self.memsz = None
self.flags = None
self.align = None
def load(self, f):
self.type, self.offset, self.vaddr, self.paddr, self.filesz, self.memsz, self.flags, self.align = struct.unpack(ElfPHdr.FMT, f.read(struct.calcsize(ElfPHdr.FMT)))
class ElfSHdr(object):
FMT = '<10I'
def __init__(self, idx):
self.idx = idx
self.name = None
self.name_end = None
self.name_len = None
self.type = None
self.flags = None
self.addr = None
self.offset = None
self.size = None
self.link = None
self.info = None
self.align = None
self.entsize = None
def load(self, f):
self.name, self.type, self.flags, self.addr, self.offset, self.size, self.link, self.info, self.align, self.entsize = struct.unpack(ElfSHdr.FMT, f.read(struct.calcsize(ElfSHdr.FMT)))
class ElfEHdr(object):
FMT = '<4s5B6xB'
EX_FMT = '<2HI3II6H'
def __init__(self):
self.magic = None
self.machine_class = None
self.data_encoding = None
self.version = None
self.os_abi = None
self.abi_version = None
self.nident_size = None
self.type = None
self.machine = None
self.version = None
self.entry = None
self.phoff = None
self.shoff = None
self.flags = None
self.ehsize = None
self.phentsize = None
self.phnum = None
self.shentsize = None
self.shnum = None
self.shstridx = None
def load(self, f):
self.magic, self.machine_class, self.data_encoding, self.version, self.os_abi, self.abi_version, self.nident_size = struct.unpack(ElfEHdr.FMT, f.read(struct.calcsize(ElfEHdr.FMT)))
self.type, self.machine, self.version, self.entry, self.phoff, self.shoff, self.flags, self.ehsize, self.phentsize, self.phnum, self.shentsize, self.shnum, self.shstridx = struct.unpack(ElfEHdr.EX_FMT, f.read(struct.calcsize(ElfEHdr.EX_FMT)))
def has_segments(self):
return self.phentsize > 0 and self.phnum > 0
def has_sections(self):
return self.shentsize > 0 and self.shnum > 0
class ElfFile(object):
def __init__(self):
self.ehdr = None
self.phdrs = None
self.shdrs = None
self.file_size = None
self.segments = None
self.sections = None
self.shstrtab = None
self.shstrtab_offset = None
def load(self, f):
start_offset = f.tell()
data = f.read()
self.file_size = len(data)
f.seek(start_offset)
self.ehdr = ElfEHdr()
self.ehdr.load(f)
self.phdrs = []
self.segments = []
if self.ehdr.has_segments():
for i in xrange(self.ehdr.phnum):
#print "[*] ElfPHdr Offset: %x" % (start_offset + self.ehdr.phoff + i * self.ehdr.phentsize)
f.seek(start_offset + self.ehdr.phoff + i * self.ehdr.phentsize)
phdr = ElfPHdr(i)
phdr.load(f)
self.phdrs.append(phdr)
if phdr.filesz > 0:
f.seek(start_offset + phdr.offset)
data = f.read(phdr.filesz)
else:
data = ''
self.segments.append(data)
self.shdrs = []
self.sections = []
if self.ehdr.has_sections():
for i in xrange(self.ehdr.shnum):
#print "[*] ElfSHdr Offset: %x" % (start_offset + self.ehdr.shoff + i * self.ehdr.shentsize)
f.seek(start_offset + self.ehdr.shoff + i * self.ehdr.shentsize)
shdr = ElfSHdr(i)
shdr.load(f)
self.shdrs.append(shdr)
for i in xrange(self.ehdr.shnum):
if self.shdrs[i].type == 3 and self.shdrs[i].size > 1:#self.shdrs[i].name_len == 9: # shstrtab
self.shstrtab_offset = self.shdrs[i].offset
print "[*] shstrtab found at: 0x%x" % self.shstrtab_offset
f.seek(self.shstrtab_offset)
self.shstrtab = f.read(self.shdrs[i].size)
#print self.shstrtab
for i in xrange(self.ehdr.shnum):
if i > 0:
self.shdrs[i-1].name_end = self.shdrs[i].name - 1
self.shdrs[i-1].name_len = self.shdrs[i-1].name_end - self.shdrs[i-1].name
#print "%d name_end - name - name_len: %x - %x = %x" % (i,self.shdrs[i-1].name_end, self.shdrs[i-1].name, self.shdrs[i-1].name_len)
if i == self.ehdr.shnum-1:
self.shdrs[i].name_end = len(self.shstrtab) - 1
self.shdrs[i].name_len = self.shdrs[i].name_end - self.shdrs[i].name
#print "%d name_end - name - name_len: %x - %x = %x" % (i, self.shdrs[i].name_end, self.shdrs[i].name, self.shdrs[i].name_len)
if len(sys.argv) < 2:
print "python fix_elf.py <in_elf>"
sys.exit(0)
print "[.] Opening file %s..." % sys.argv[1]
f = open(sys.argv[1], "rb")
#f = open("ULUS10491.BIN", "rb")
#f = open("NPEZ00311.BIN", "rb")
#f = open("ULUS10567.BIN", "rb")
#f = open("NPUG80248.BIN", "rb")
#f = open("ULES00193.BIN", "rb")
elf_file = ElfFile()
elf_file.load(f)
print "[*] magic: %s" % elf_file.ehdr.magic
print "[*] machine_class: %x" % elf_file.ehdr.machine_class
print "[*] data_encoding: %x" % elf_file.ehdr.data_encoding
print "[*] version: %x" % elf_file.ehdr.version
print "[*] os_abi: %x" % elf_file.ehdr.os_abi
print "[*] abi_version: %x" % elf_file.ehdr.abi_version
print "[*] nident_size: %x" % elf_file.ehdr.nident_size
print "[*] type: 0x%x" % elf_file.ehdr.type
print "[*] machine: %x" % elf_file.ehdr.machine
print "[*] version: %x" % elf_file.ehdr.version
print "[*] entry: 0x%x" % elf_file.ehdr.entry
print "[*] phoff: 0x%x" % elf_file.ehdr.phoff
print "[*] shoff: 0x%x" % elf_file.ehdr.shoff
print "[*] flags: 0x%x" % elf_file.ehdr.flags
print "[*] ehsize: 0x%x" % elf_file.ehdr.ehsize
print "[*] phentsize: 0x%x" % elf_file.ehdr.phentsize
print "[*] phnum: 0x%x" % elf_file.ehdr.phnum
print "[*] shentsize: 0x%x" % elf_file.ehdr.shentsize
print "[*] shnum: 0x%x" % elf_file.ehdr.shnum
print "[*] shstridx: %x" % elf_file.ehdr.shstridx
# Check first name if empty or not to determine fixing
if elf_file.shstrtab[elf_file.shdrs[1].name:elf_file.shdrs[1].name_end].replace('\x00',"") == "":
print "[!] No Section header names found!"
print "[.] attempting to identify required sections..."
PF_WRITE = 0x1
PF_READ = 0x2
PF_EXEC = 0x4
PF_READ_EXEC = PF_READ | PF_EXEC
PF_READ_WRITE = PF_READ | PF_WRITE
to_fix = 5
for i in xrange(elf_file.ehdr.shnum):
if (elf_file.shdrs[i].flags & PF_READ_EXEC) == PF_READ_EXEC and elf_file.shdrs[i].name_len == len(".text"):
print "[!] found .text at section %d" % i
elf_file.shstrtab = elf_file.shstrtab[:elf_file.shdrs[i].name] + ".text" + elf_file.shstrtab[elf_file.shdrs[i].name_end:]
to_fix -= 1
if elf_file.shdrs[i].type == 8 and elf_file.shdrs[i].name_len == len(".bss"):
print "[!] found .bss at section %d" % i
elf_file.shstrtab = elf_file.shstrtab[:elf_file.shdrs[i].name] + ".bss" + elf_file.shstrtab[elf_file.shdrs[i].name_end:]
to_fix -= 1
if elf_file.shdrs[i].type == 1 and elf_file.shdrs[i].flags == 3 and elf_file.shdrs[i].name_len == len(".data"):
print "[!] found .data at section %d" % i
elf_file.shstrtab = elf_file.shstrtab[:elf_file.shdrs[i].name] + ".data" + elf_file.shstrtab[elf_file.shdrs[i].name_end:]
to_fix -= 1
if elf_file.shdrs[i].type == 1 and elf_file.shdrs[i].size == 0x34 and elf_file.shdrs[i].name_len == len(".rodata.sceModuleInfo"):
print "[!] found .rodata.sceModuleInfo at section %d" % i
elf_file.shstrtab = elf_file.shstrtab[:elf_file.shdrs[i].name] + ".rodata.sceModuleInfo" + elf_file.shstrtab[elf_file.shdrs[i].name_end:]
to_fix -= 1
if elf_file.shdrs[i].type == 3 and elf_file.shdrs[i].size > 1 and elf_file.shdrs[i].name_len == len(".shstrtab"):
print "[!] found .shstrtab at section %d" % i
elf_file.shstrtab = elf_file.shstrtab[:elf_file.shdrs[i].name] + ".shstrtab" + elf_file.shstrtab[elf_file.shdrs[i].name_end:]
to_fix -= 1
if to_fix == 0:
print "[.] Writing new file..."
f.seek(0)
data = f.read()
data = data[:elf_file.shstrtab_offset] + elf_file.shstrtab + data[elf_file.shstrtab_offset+len(elf_file.shstrtab):]
open(sys.argv[1] + ".new", "wb").write(data)
else:
print "[!] Error. Could not identify required sections."
print "Section Headers:"
print " [Nr] Name Type Addr Off Size Flg Lk Inf Al"
for i in xrange(elf_file.ehdr.shnum):
print " %02d %-15.15s (%02x) %08x %08x %06x %06x %x" % (i, elf_file.shstrtab[elf_file.shdrs[i].name:elf_file.shdrs[i].name_end].replace('\x00',""),elf_file.shdrs[i].name_len, elf_file.shdrs[i].type,elf_file.shdrs[i].addr,elf_file.shdrs[i].offset,elf_file.shdrs[i].size,elf_file.shdrs[i].flags)
f.close()
print "[.] done."