Last active
December 14, 2015 01:19
-
-
Save warabanshi/5005372 to your computer and use it in GitHub Desktop.
make ELF part4
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pType = { | |
'NULL' : 0, | |
'LOAD' : 1, | |
'DYNAMIC' : 2, | |
'INTERP' : 3, | |
'NOTE' : 4, | |
'SHLIB' : 5, | |
'PHDR' : 6, | |
'TLS' : 7, | |
'NUM' : 8, | |
'LOOS' : 0x60000000, | |
'GNU_EH_FRAME' : 0x6474e550, | |
'GNU_STACK' : 0x6474e551, | |
'GNU_RELRO' : 0x6474e552, | |
'LOSUNW' : 0x6ffffffa, | |
'SUNWBSS' : 0x6ffffffa, | |
'SUNWSTACK' : 0x6ffffffb, | |
'HISUNW' : 0x6fffffff, | |
'HIOS' : 0x6fffffff, | |
'LOPROC' : 0x70000000, | |
'HIPROC' : 0x7fffffff, | |
} | |
pFlag = { | |
'X' : (1 << 0), | |
'W' : (1 << 1), | |
'R' : (1 << 2), | |
'MASKOS' : 0x0ff00000, | |
'MASKPROC' : 0xf0000000, | |
} | |
pFlags = { | |
'X' : pFlag['X'], | |
'W' : pFlag['W'], | |
'R' : pFlag['R'], | |
'RW' : pFlag['R'] | pFlag['W'], | |
'RX' : pFlag['R'] | pFlag['X'], | |
'RWX' : pFlag['R'] | pFlag['W'] | pFlag['X'], | |
} | |
shType = { | |
'NULL' : 0, | |
'PROGBITS' : 1, | |
'SYMTAB' : 2, | |
'STRTAB' : 3, | |
'RELA' : 4, | |
'HASH' : 5, | |
'DYNAMIC' : 6, | |
'NOTE' : 7, | |
'NOBITS' : 8, | |
'REL' : 9, | |
'SHLIB' : 10, | |
'DYNSYM' : 11, | |
'INIT_ARRAY' : 14, | |
'FINI_ARRAY' : 15, | |
'PREINIT_ARRAY' : 16, | |
'GROUP' : 17, | |
'SYMTAB_SHNDX' : 18, | |
'NUM' : 19, | |
'LOOS' : 0x60000000, | |
'GNU_ATTRIBUTES': 0x6ffffff5, | |
'GNU_HASH' : 0x6ffffff6, | |
'GNU_LIBLIST' : 0x6ffffff7, | |
'CHECKSUM' : 0x6ffffff8, | |
'LOSUNW' : 0x6ffffffa, | |
'SUNW_move' : 0x6ffffffa, | |
'SUNW_COMDAT' : 0x6ffffffb, | |
'SUNW_syminfo' : 0x6ffffffc, | |
'GNU_verdef' : 0x6ffffffd, | |
'GNU_verneed' : 0x6ffffffe, | |
'GNU_versym' : 0x6fffffff, | |
'HISUNW' : 0x6fffffff, | |
'HIOS' : 0x6fffffff, | |
'LOPROC' : 0x70000000, | |
'HIPROC' : 0x7fffffff, | |
'LOUSER' : 0x80000000, | |
'HIUSER' : 0x8fffffff, | |
} | |
shFlag = { | |
'WRITE' : (1 << 0), | |
'ALLOC' : (1 << 1), | |
'EXECINSTR' : (1 << 2), | |
'MERGE' : (1 << 4), | |
'STRINGS' : (1 << 5), | |
'INFO_LINK' : (1 << 6), | |
'LINK_ORDER': (1 << 7), | |
'OS_NONCONFORMING' : (1 << 8), | |
'GROUP' : (1 << 9), | |
'TLS' : (1 << 10), | |
'MASKOS' : 0x0ff00000, | |
'MASKPROC' : 0xf0000000, | |
'ORDERED' : (1 << 30), | |
'EXCLUDE' : (1 << 31), | |
} | |
shFlags = { | |
'A' : shFlag['ALLOC'], | |
'W' : shFlag['WRITE'], | |
'X' : shFlag['EXECINSTR'], | |
'AW' : shFlag['ALLOC'] | shFlag['WRITE'], | |
'AX' : shFlag['ALLOC'] | shFlag['EXECINSTR'], | |
'AWX' : shFlag['ALLOC'] | shFlag['WRITE'] | shFlag['EXECINSTR'], | |
} | |
correspondence = { | |
shFlags['A'] : pFlags['R'], | |
shFlags['W'] : pFlags['W'], | |
shFlags['X'] : pFlags['X'], | |
shFlags['AW'] : pFlags['RW'], | |
shFlags['AX'] : pFlags['RX'], | |
shFlags['AWX'] : pFlags['RWX'], | |
} | |
def getPhFlag(flag): | |
try: | |
return correspondence[flag] | |
except: | |
return None | |
def getPtype(name): | |
try: | |
return pType[name] | |
except: | |
return None |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from elf.Utils import * | |
class Header(object): | |
def __init__(self): | |
self.contents = {} | |
self.pos = 0 | |
def set(self, key, val): | |
self.contents[key] = val | |
def get(self, key): | |
return self.contents[key] | |
def resetPos(self, pos): | |
self.pos = pos | |
# bs: bytesize | |
def fetch(self, bs, byteList): | |
r = convBin(byteList[self.pos:self.pos+bs]) | |
self.pos += bs | |
return r | |
def getByte(self, byteList): | |
return self.fetch(1, byteList) | |
def getWord(self, byteList): | |
return self.fetch(2, byteList) | |
def getDw(self, byteList): | |
return self.fetch(4, byteList) | |
def getQw(self, byteList): | |
return self.fetch(8, byteList) | |
def retrieve(self): | |
raise('method retrieve() has to implement individualy') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from Header import Header | |
from elf.Utils import * | |
class Ph(Header): | |
def retrieve(self, binList, offset = 0): | |
self.resetPos(offset) | |
self.setBinList(binList) | |
self.set('segment_type', self.getDw()) | |
self.set('permission_flag', self.getDw()) | |
self.set('offset', self.getQw()) | |
self.set('virtual_addr', self.getQw()) | |
self.set('physical_addr', self.getQw()) | |
self.set('filesize', self.getQw()) | |
self.set('memory_size', self.getQw()) | |
self.set('align', self.getQw()) | |
self.clearBinList() | |
return self | |
def output(self): | |
r = [] | |
r += convLE(self.get('segment_type'), 4) | |
r += convLE(self.get('permission_flag'), 4) | |
r += convLE(self.get('offset'), 8) | |
r += convLE(self.get('virtual_addr'), 8) | |
r += convLE(self.get('physical_addr'), 8) | |
r += convLE(self.get('filesize'), 8) | |
r += convLE(self.get('memory_size'), 8) | |
r += convLE(self.get('align'), 8) | |
return r |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Section(object): | |
def __init__(self, byteList, name, sh): | |
self.byteList = byteList | |
self.name = name | |
self.sh = sh | |
def getBodyList(self): | |
return self.byteList | |
def getName(self): | |
return self.name | |
def getSh(self): | |
return self.sh | |
def setBodyList(self, byteList): | |
self.byteList = byteList | |
def setName(self, name): | |
self.name = name | |
def setSh(self, sh): | |
self.sh = sh | |
def setAddr(self, addr): | |
None # implement later | |
# method for debug | |
def echo(self): | |
lm = lambda n: (n, hex(n)) | |
try: | |
print('====== Section Header(%s) ======' % self.name) | |
except AttributeError: | |
print('====== Section Header(no name setting) ====') | |
print('name_index: %s' % self.sh.get('name_index')) | |
print('type: %s' % self.sh.get('type')) | |
print('flag: %s' % self.sh.get('flag')) | |
print('address: %s(%s)' % lm(self.sh.get('address'))) | |
print('offset: %s(%s)' % lm(self.sh.get('offset'))) | |
print('size: %s(%s)' % lm(self.sh.get('size'))) | |
print('link: %s' % self.sh.get('link')) | |
print('info: %s' % self.sh.get('info')) | |
print('address_align: %s' % self.sh.get('address_align')) | |
print('entry_table_size:%s' % self.sh.get('entry_table_size')) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from elf.Utils import * | |
from elf.components.headers.Sh import Sh | |
from elf.components.Section import Section | |
class SectionController(object): | |
def __init__(self): | |
self.sectionList = [] | |
def append(self, section): | |
self.sectionList.append(section) | |
def getSectionList(self): | |
nullSh = Sh() | |
nullSh.retrieve([0x00 for i in range(56)]) | |
nullSection = Section([], '', nullSh) | |
strSection = self.makeShStrSection() | |
return (nullSection, self.sectionList, strSection) | |
def makeShStrSection(self): | |
shStr = "\0" | |
for s in self.sectionList: | |
sh = s.getSh() | |
sh.set('name_index', len(shStr)) | |
shStr += s.getName() + "\0" | |
shStrIdx = len(shStr) | |
shStr += ".shstrtab\0" | |
shStrTab = map(ord, shStr) | |
shList = [] | |
shList += convLE(shStrIdx, 4) # name_index | |
shList += convLE(3, 4) # type | |
shList += [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] # flag | |
shList += [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] # address | |
shList += [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] # offset | |
shList += convLE(len(shStr), 8) # size | |
shList += [0x00, 0x00, 0x00, 0x00] # link | |
shList += [0x00, 0x00, 0x00, 0x00] # info | |
shList += convLE(1, 0) # address_align | |
shList += [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] # entry_table_size | |
sh = Sh().retrieve(shList) | |
return Section(shStrTab, '.shstrtab', sh) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Segment(object): | |
def __init__(self, ph, bodyList): | |
self.ph = ph | |
self.bodyList = bodyList | |
def getPh(self): | |
return self.ph | |
def getBodyList(self): | |
return self.bodyList |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from elf.Attributes import * | |
from elf.SectionOrder import * | |
from elf.components.headers.Ph import Ph | |
from elf.components.Segment import Segment | |
class SegmentController(object): | |
loadAlign = 0x200000 | |
orgAddr = 0x400000 | |
def __init__(self): | |
self.segmentList = [] | |
self.phSegment = None | |
self.startAddr = 0 | |
def makeSegment(self, sctList): | |
# separate sections by flag value and sort section order | |
segBaseTbl = {} | |
for sct in sctList: | |
name = sct.getName() | |
try: | |
segBaseTbl[sct.getSh().get('flag')].append((getOrder(name), sct)) | |
except: | |
segBaseTbl[sct.getSh().get('flag')] = [] | |
segBaseTbl[sct.getSh().get('flag')].append((getOrder(name), sct)) | |
segTbl = {} | |
for (flag, segList) in segBaseTbl.items(): | |
segTbl[flag] = sorted(segList, key=lambda x: x[0]) | |
# set base position | |
offset = 64 + 56 + 56 * len(segTbl) # EH + PHDR + PHs offset | |
addr = self.orgAddr + offset | |
phList = [] | |
for (flag, contentList) in segTbl.items(): | |
bodyList = [] | |
sctOff = offset | |
sctAddr = addr | |
for (order, sct) in contentList: | |
sct.getSh().set('address', sctAddr) | |
sct.getSh().set('offset', sctOff) | |
bodyList += sct.getBodyList() | |
align = sct.getSh().get('address_align') | |
if sct.getName() == '.text': | |
self.startAddr = addr | |
# padding 0x00 | |
if len(sct.getBodyList()) % align > 0: | |
bodyList += [0x0 for x in range(align - len(sct.getBodyList()) % align)] | |
sctOff = offset + len(bodyList) | |
sctAddr = addr + len(bodyList) | |
ph = Ph() | |
#ph.set('segment_type', getPhFlag(flag)) | |
ph.set('segment_type', 1) | |
ph.set('permission_flag', flag) | |
ph.set('offset', offset) | |
ph.set('virtual_addr', addr) | |
ph.set('physical_addr', addr) | |
ph.set('filesize', len(bodyList)) | |
ph.set('memory_size', len(bodyList)) | |
ph.set('align', self.loadAlign) | |
self.segmentList.append(Segment(ph, bodyList)) | |
phList.append(ph) | |
offset += len(bodyList) | |
addr += offset | |
# make PHDR | |
self.phSegment = self.setPhSegment([s.getPh() for s in self.segmentList], len(phList)) | |
return sctList | |
def getSegments(self): | |
return self.phSegment, self.segmentList | |
def getStartAddr(self): | |
return self.startAddr | |
def setPhSegment(self, phList, phNum): | |
ph = Ph() | |
ph.set('segment_type', pType['PHDR']) | |
ph.set('permission_flag', 6) | |
ph.set('offset', 0x40) | |
ph.set('virtual_addr', self.orgAddr + 0x40) | |
ph.set('physical_addr', self.orgAddr + 0x40) | |
ph.set('filesize', 56*phNum) | |
ph.set('memory_size', 56*phNum) | |
ph.set('align', 8) | |
bodyList = [] | |
for p in phList: | |
bodyList += p.output() | |
bodyList += ph.output() | |
return Segment(ph, bodyList) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from Header import Header | |
from elf.Utils import * | |
class Sh(Header): | |
def __init__(self): | |
Header.__init__(self) | |
self.contents = { | |
'name_index' : 0, | |
'type' : 0, | |
'flag' : 0, | |
'address' : 0, | |
'offset' : 0, | |
'size' : 0, | |
'link' : 0, | |
'info' : 0, | |
'address_align' : 0, | |
'entry_table_size': 0, | |
} | |
def retrieve(self, byteList, offset = 0): | |
self.resetPos(offset) | |
self.set('name_index', self.getDw(byteList)) | |
self.set('type', self.getDw(byteList)) | |
self.set('flag', self.getQw(byteList)) | |
self.set('address', self.getQw(byteList)) | |
self.set('offset', self.getQw(byteList)) | |
self.set('size', self.getQw(byteList)) | |
self.set('link', self.getDw(byteList)) | |
self.set('info', self.getDw(byteList)) | |
self.set('address_align', self.getQw(byteList)) | |
self.set('entry_table_size', self.getQw(byteList)) | |
return self | |
def output(self): | |
r = [] | |
r += convLE(self.get('name_index'), 4) | |
r += convLE(self.get('type'), 4) | |
r += convLE(self.get('flag'), 8) | |
r += convLE(self.get('address'), 8) | |
r += convLE(self.get('offset'), 8) | |
r += convLE(self.get('size'), 8) | |
r += convLE(self.get('link'), 4) | |
r += convLE(self.get('info'), 4) | |
r += convLE(self.get('address_align'), 8) | |
r += convLE(self.get('entry_table_size'), 8) | |
return r |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# convert val of specified number of byte to | |
# little endian list inlucdes each byte | |
def convLE(val, byteNum): | |
le = [] | |
for i in range(byteNum): | |
le.append((val >> i*8) & 0xff) | |
return le | |
# convert from list to little endian binary value | |
# regards list elements are single byte respectively | |
def convBin(li): | |
b = 0 | |
for byte in reversed(li): | |
b = (b << 8) | byte | |
return b |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import sys, struct | |
from elf.Utils import * | |
from elf.components.headers.ElfHeader import ElfHeader | |
from ctypes import * | |
class WriteElf: | |
def __init__(self): | |
self.sectionList = {} | |
self.segmentList = {} | |
self.startAddr = 0 | |
def setSection(self, sctNull, sctList, sctStr): | |
self.sectionList['null'] = sctNull | |
self.sectionList['list'] = sctList | |
self.sectionList['str'] = sctStr | |
def setSegment(self, segPhdr, segList): | |
self.segmentList['phdr'] = segPhdr | |
self.segmentList['list'] = segList | |
def setStartAddr(self, startAddr): | |
self.startAddr = startAddr | |
def make(self): | |
bodyLen = sum([len(s.bodyList) for s in self.segmentList['list']]) | |
shStrLen = len(self.sectionList['str'].getBodyList()) | |
shStrOff = 64 + 56 + 56 * len(self.segmentList['list']) + bodyLen | |
shOff = shStrOff + shStrLen | |
eh = self.makeEhBase() | |
eh.set('entry_addr', self.startAddr) | |
eh.set('ph_offset', 64) | |
eh.set('sh_offset', shOff) | |
eh.set('ph_num', len(self.segmentList['list'])+1) | |
eh.set('sh_num', len(self.sectionList['list'])+2) | |
eh.set('shstrndx', len(self.sectionList['list'])+1) | |
ph = self.segmentList['phdr'].getPh().output() | |
body = [] | |
for seg in self.segmentList['list']: | |
ph += seg.getPh().output() | |
body += seg.getBodyList() | |
sh = self.sectionList['null'].getSh().output() | |
for sec in self.sectionList['list']: | |
sh += sec.getSh().output() | |
body += self.sectionList['str'].getBodyList() | |
strSh = self.sectionList['str'].getSh() | |
strSh.set('offset', shStrOff) | |
sh += strSh.output() | |
result = eh.output() + ph + body + sh | |
p = (c_ubyte * len(result))() | |
p[:] = result | |
with open('write.out', 'wb') as fp: | |
fp.write(p) | |
# eh expects ElfHeader object | |
def makeEhBase(self): | |
eh = [] | |
eh += [0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01] # magic | |
eh += [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] | |
eh += convLE(2, 2) # e_type (EXEC) | |
eh += convLE(0x3e, 2) # e_machine (amd64) | |
eh += convLE(1, 4) # e_version (1) | |
eh += convLE(0, 8) # e_entry (set later) | |
eh += convLE(0, 8) # e_phoff (set later) | |
eh += convLE(0, 8) # e_shoff (set later) | |
eh += convLE(0, 4) # e_flags | |
eh += convLE(64, 2) # e_ehsize (64) | |
eh += convLE(56, 2) # e_phentsize (56) | |
eh += convLE(0, 2) # e_phnum (set later) | |
eh += convLE(64, 2) # e_shentsize (64) | |
eh += convLE(0, 2) # e_shnum (set later) | |
eh += convLE(0, 2) # e_shstrndx (set later) | |
e = ElfHeader() | |
e.retrieve(eh) | |
return e |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment