103 lines
2.4 KiB
Python
103 lines
2.4 KiB
Python
|
|
from enum import Enum, Flag
|
||
|
|
import struct
|
||
|
|
|
||
|
|
class ELFPType(Enum):
|
||
|
|
NULL = 0
|
||
|
|
LOAD = 1
|
||
|
|
DYNAMIC = 2
|
||
|
|
INTERP = 3
|
||
|
|
NOTE = 4
|
||
|
|
SHLIB = 5
|
||
|
|
PHDR = 6
|
||
|
|
TLS = 7
|
||
|
|
|
||
|
|
|
||
|
|
class ELFPFlag(Flag):
|
||
|
|
NONE = 0
|
||
|
|
EXEC = 1
|
||
|
|
WRITE = 2
|
||
|
|
READ = 4
|
||
|
|
|
||
|
|
|
||
|
|
class ELFEndian(Enum):
|
||
|
|
LITTLE = 1
|
||
|
|
BIG = 2
|
||
|
|
|
||
|
|
|
||
|
|
class ELF64Phdr:
|
||
|
|
def __init__(self):
|
||
|
|
self.type = ELFPType.NULL
|
||
|
|
self.flags = 0
|
||
|
|
self.offset = 0
|
||
|
|
self.vaddr = 0
|
||
|
|
self.paddr = 0
|
||
|
|
self.filesz = 0
|
||
|
|
self.memsz = 0
|
||
|
|
self.align = 0
|
||
|
|
|
||
|
|
return
|
||
|
|
|
||
|
|
def parse(self, buf, endian):
|
||
|
|
endian_marker = '>' if endian == ELFEndian.BIG else '<'
|
||
|
|
entry = struct.unpack('{}IIQQQQQQ'.format(endian_marker), buf)
|
||
|
|
|
||
|
|
self.type = ELFPType(entry[0])
|
||
|
|
self.flags = ELFPFlag.NONE
|
||
|
|
self.offset = entry[2]
|
||
|
|
self.vaddr = entry[3]
|
||
|
|
self.paddr = entry[4]
|
||
|
|
self.filesz = entry[5]
|
||
|
|
self.memsz = entry[6]
|
||
|
|
self.align = entry[7]
|
||
|
|
|
||
|
|
if entry[1] & ELFPFlag.READ.value: self.flags |= ELFPFlag.READ
|
||
|
|
if entry[1] & ELFPFlag.WRITE.value: self.flags |= ELFPFlag.WRITE
|
||
|
|
if entry[1] & ELFPFlag.EXEC.value: self.flags |= ELFPFlag.EXEC
|
||
|
|
|
||
|
|
|
||
|
|
class ELF64Image:
|
||
|
|
def __init__(self):
|
||
|
|
self.ph_list = []
|
||
|
|
self.text = None
|
||
|
|
self.data = None
|
||
|
|
self.entry = None
|
||
|
|
|
||
|
|
def load(self, path):
|
||
|
|
f = open(path, mode='rb')
|
||
|
|
ident_bytes = f.read(16)
|
||
|
|
|
||
|
|
ident = struct.unpack('BBBBBBBBBBBBBBBB', ident_bytes)
|
||
|
|
|
||
|
|
if ident[0] != 0x7F or ident[1] != ord('E') or ident[2] != ord('L') or ident[3] != ord('F'):
|
||
|
|
f.close()
|
||
|
|
return -1
|
||
|
|
|
||
|
|
endian = ELFEndian(ident[5])
|
||
|
|
endian_marker = '>' if endian == ELFEndian.BIG else '<'
|
||
|
|
|
||
|
|
hdr_bytes = f.read(48)
|
||
|
|
hdr = struct.unpack('{}HHIQQQIHHHHHH'.format(endian_marker), hdr_bytes)
|
||
|
|
|
||
|
|
self.entry = hdr[3]
|
||
|
|
phoff = hdr[4]
|
||
|
|
phnum = hdr[9]
|
||
|
|
phentsize = hdr[8]
|
||
|
|
|
||
|
|
for i in range(0, phnum):
|
||
|
|
f.seek(phoff + (i * phentsize))
|
||
|
|
phdr_bytes = f.read(phentsize)
|
||
|
|
|
||
|
|
phdr = ELF64Phdr()
|
||
|
|
phdr.parse(phdr_bytes, endian)
|
||
|
|
|
||
|
|
if phdr.flags == ELFPFlag.READ | ELFPFlag.EXEC:
|
||
|
|
self.text = phdr
|
||
|
|
if phdr.flags == ELFPFlag.READ | ELFPFlag.WRITE:
|
||
|
|
self.data = phdr
|
||
|
|
|
||
|
|
self.ph_list.append(phdr)
|
||
|
|
|
||
|
|
f.close()
|
||
|
|
return 0
|
||
|
|
|