miasm.loader.pe_init module
#! /usr/bin/env python from __future__ import print_function from builtins import range import array from functools import reduce import logging import struct from future.builtins import int as int_types from future.utils import PY3 from miasm.loader import pe from miasm.loader.strpatchwork import StrPatchwork log = logging.getLogger("peparse") console_handler = logging.StreamHandler() console_handler.setFormatter(logging.Formatter("[%(levelname)-8s]: %(message)s")) log.addHandler(console_handler) log.setLevel(logging.WARN) class ContentManager(object): def __get__(self, owner, _): if hasattr(owner, '_content'): return owner._content def __set__(self, owner, new_content): owner.resize(len(owner._content), len(new_content)) owner._content = new_content def __delete__(self, owner): self.__set__(owner, None) class ContectRva(object): def __init__(self, parent): self.parent = parent def get(self, rva_start, rva_stop=None): """ Get data in RVA view starting at @rva_start, stopping at @rva_stop @rva_start: rva start address @rva_stop: rva stop address """ if rva_start < 0: raise ValueError("Out of range") if rva_stop is not None: if rva_stop > len(self.parent.img_rva): rva_stop = len(self.parent.img_rva) if rva_start > len(self.parent.img_rva): raise ValueError("Out of range") return self.parent.img_rva[rva_start:rva_stop] if rva_start > len(self.parent.img_rva): raise ValueError("Out of range") return self.parent.img_rva[rva_start] def set(self, rva, data): """ Set @data in RVA view starting at @start @rva: rva start address @data: data to set """ if not isinstance(rva, int_types): raise ValueError('addr must be int/long') if rva < 0: raise ValueError("Out of range") if rva + len(data) > len(self.parent.img_rva): raise ValueError("Out of range") self.parent.img_rva[rva] = data def __getitem__(self, item): if isinstance(item, slice): assert(item.step is None) return self.get(item.start, item.stop) return self.get(item) def __setitem__(self, item, data): if isinstance(item, slice): rva = item.start else: rva = item self.set(rva, data) class ContentVirtual(object): def __init__(self, parent): self.parent = parent def __getitem__(self, item): raise DeprecationWarning("Replace code by virt.get(start, [stop])") def __setitem__(self, item, data): raise DeprecationWarning("Replace code by virt.set(start, data)") def __call__(self, ad_start, ad_stop=None, ad_step=None): raise DeprecationWarning("Replace code by virt.get(start, stop)") def get(self, virt_start, virt_stop=None): """ Get data in VIRTUAL view starting at @virt_start, stopping at @virt_stop @virt_start: virt start address @virt_stop: virt stop address """ rva_start = self.parent.virt2rva(virt_start) if virt_stop != None: rva_stop = self.parent.virt2rva(virt_stop) else: rva_stop = None return self.parent.rva.get(rva_start, rva_stop) def set(self, addr, data): """ Set @data in VIRTUAL view starting at @start @addr: virtual start address @data: data to set """ if not isinstance(addr, int_types): raise ValueError('addr must be int/long') self.parent.rva.set(self.parent.virt2rva(addr), data) def max_addr(self): section = self.parent.SHList[-1] length = section.addr + section.size + self.parent.NThdr.ImageBase return int(length) def find(self, pattern, start=0, end=None): if start != 0: start = self.parent.virt2rva(start) if end != None: end = self.parent.virt2rva(end) ret = self.parent.img_rva.find(pattern, start, end) if ret == -1: return -1 return self.parent.rva2virt(ret) def rfind(self, pattern, start=0, end=None): if start != 0: start = self.parent.virt2rva(start) if end != None: end = self.parent.virt2rva(end) ret = self.parent.img_rva.rfind(pattern, start, end) if ret == -1: return -1 return self.parent.rva2virt(ret) def is_addr_in(self, addr): return self.parent.is_in_virt_address(addr) def compute_crc(raw, olds): out = 0 data = raw[:] if len(raw) % 2: end = struct.unpack('B', data[-1:])[0] data = data[:-1] if (len(raw) & ~0x1) % 4: out += struct.unpack('H', data[:2])[0] data = data[2:] data = array.array('I', data) out = reduce(lambda x, y: x + y, data, out) out -= olds while out > 0xFFFFFFFF: out = (out >> 32) + (out & 0xFFFFFFFF) while out > 0xFFFF: out = (out & 0xFFFF) + ((out >> 16) & 0xFFFF) if len(raw) % 2: out += end out += len(data) return out # PE object class PE(object): content = ContentManager() def __init__(self, pestr=None, loadfrommem=False, parse_resources=True, parse_delay=True, parse_reloc=True, wsize=32, **kwargs): self._rva = ContectRva(self) self._virt = ContentVirtual(self) self.img_rva = StrPatchwork() if pestr is None: self._content = StrPatchwork() self._sex = 0 self._wsize = wsize self.Doshdr = pe.Doshdr(self) self.NTsig = pe.NTsig(self) self.Coffhdr = pe.Coffhdr(self) if self._wsize == 32: Opthdr = pe.Opthdr32 else: Opthdr = pe.Opthdr64 self.Opthdr = Opthdr(self) self.NThdr = pe.NThdr(self) self.NThdr.optentries = [pe.Optehdr(self) for _ in range(0x10)] self.NThdr.CheckSum = 0 self.SHList = pe.SHList(self) self.SHList.shlist = [] self.NThdr.sizeofheaders = 0x1000 self.DirImport = pe.DirImport(self) self.DirExport = pe.DirExport(self) self.DirDelay = pe.DirDelay(self) self.DirReloc = pe.DirReloc(self) self.DirRes = pe.DirRes(self) self.DirTls = pe.DirTls(self) self.Doshdr.magic = 0x5a4d self.Doshdr.lfanew = 0xe0 self.NTsig.signature = 0x4550 if wsize == 32: self.Opthdr.magic = 0x10b elif wsize == 64: self.Opthdr.magic = 0x20b else: raise ValueError('unknown pe size %r' % wsize) self.Opthdr.majorlinkerversion = 0x7 self.Opthdr.minorlinkerversion = 0x0 self.NThdr.filealignment = 0x1000 self.NThdr.sectionalignment = 0x1000 self.NThdr.majoroperatingsystemversion = 0x5 self.NThdr.minoroperatingsystemversion = 0x1 self.NThdr.MajorImageVersion = 0x5 self.NThdr.MinorImageVersion = 0x1 self.NThdr.majorsubsystemversion = 0x4 self.NThdr.minorsubsystemversion = 0x0 self.NThdr.subsystem = 0x3 if wsize == 32: self.NThdr.dllcharacteristics = 0x8000 else: self.NThdr.dllcharacteristics = 0x8000 # for createthread self.NThdr.sizeofstackreserve = 0x200000 self.NThdr.sizeofstackcommit = 0x1000 self.NThdr.sizeofheapreserve = 0x100000 self.NThdr.sizeofheapcommit = 0x1000 self.NThdr.ImageBase = 0x400000 self.NThdr.sizeofheaders = 0x1000 self.NThdr.numberofrvaandsizes = 0x10 self.NTsig.signature = 0x4550 if wsize == 32: self.Coffhdr.machine = 0x14c elif wsize == 64: self.Coffhdr.machine = 0x8664 else: raise ValueError('unknown pe size %r' % wsize) if wsize == 32: self.Coffhdr.characteristics = 0x10f self.Coffhdr.sizeofoptionalheader = 0xe0 else: self.Coffhdr.characteristics = 0x22 # 0x2f self.Coffhdr.sizeofoptionalheader = 0xf0 else: self._content = StrPatchwork(pestr) self.loadfrommem = loadfrommem self.parse_content(parse_resources=parse_resources, parse_delay=parse_delay, parse_reloc=parse_reloc) def isPE(self): if self.NTsig is None: return False return self.NTsig.signature == 0x4550 def parse_content(self, parse_resources=True, parse_delay=True, parse_reloc=True): off = 0 self._sex = 0 self._wsize = 32 self.Doshdr = pe.Doshdr.unpack(self.content, off, self) off = self.Doshdr.lfanew if off > len(self.content): log.warn('ntsig after eof!') self.NTsig = None return self.NTsig = pe.NTsig.unpack(self.content, off, self) self.DirImport = None self.DirExport = None self.DirDelay = None self.DirReloc = None self.DirRes = None if self.NTsig.signature != 0x4550: log.warn('not a valid pe!') return off += len(self.NTsig) self.Coffhdr, length = pe.Coffhdr.unpack_l(self.content, off, self) off += length self._wsize = ord(self.content[off+1]) * 32 if self._wsize == 32: Opthdr = pe.Opthdr32 else: Opthdr = pe.Opthdr64 if len(self.content) < 0x200: # Fix for very little PE self.content += (0x200 - len(self.content)) * b'\x00' self.Opthdr, length = Opthdr.unpack_l(self.content, off, self) self.NThdr = pe.NThdr.unpack(self.content, off + length, self) self.img_rva[0] = self.content[:self.NThdr.sizeofheaders] off += self.Coffhdr.sizeofoptionalheader self.SHList = pe.SHList.unpack(self.content, off, self) # load section data filealignment = self.NThdr.filealignment sectionalignment = self.NThdr.sectionalignment for section in self.SHList.shlist: virt_size = (section.size // sectionalignment + 1) * sectionalignment if self.loadfrommem: section.offset = section.addr if self.NThdr.sectionalignment > 0x1000: raw_off = 0x200 * (section.offset // 0x200) else: raw_off = section.offset if raw_off != section.offset: log.warn('unaligned raw section (%x %x)!', raw_off, section.offset) section.data = StrPatchwork() if section.rawsize == 0: rounded_size = 0 else: if section.rawsize % filealignment: rs = (section.rawsize // filealignment + 1) * filealignment else: rs = section.rawsize rounded_size = rs if rounded_size > virt_size: rounded_size = min(rounded_size, section.size) data = self.content[raw_off:raw_off + rounded_size] section.data = data # Pad data to page size 0x1000 length = len(data) data += b"\x00" * ((((length + 0xfff)) & 0xFFFFF000) - length) self.img_rva[section.addr] = data # Fix img_rva self.img_rva = self.img_rva try: self.DirImport = pe.DirImport.unpack(self.img_rva, self.NThdr.optentries[ pe.DIRECTORY_ENTRY_IMPORT].rva, self) except pe.InvalidOffset: log.warning('cannot parse DirImport, skipping') self.DirImport = pe.DirImport(self) try: self.DirExport = pe.DirExport.unpack(self.img_rva, self.NThdr.optentries[ pe.DIRECTORY_ENTRY_EXPORT].rva, self) except pe.InvalidOffset: log.warning('cannot parse DirExport, skipping') self.DirExport = pe.DirExport(self) if len(self.NThdr.optentries) > pe.DIRECTORY_ENTRY_DELAY_IMPORT: self.DirDelay = pe.DirDelay(self) if parse_delay: try: self.DirDelay = pe.DirDelay.unpack(self.img_rva, self.NThdr.optentries[ pe.DIRECTORY_ENTRY_DELAY_IMPORT].rva, self) except pe.InvalidOffset: log.warning('cannot parse DirDelay, skipping') if len(self.NThdr.optentries) > pe.DIRECTORY_ENTRY_BASERELOC: self.DirReloc = pe.DirReloc(self) if parse_reloc: try: self.DirReloc = pe.DirReloc.unpack(self.img_rva, self.NThdr.optentries[ pe.DIRECTORY_ENTRY_BASERELOC].rva, self) except pe.InvalidOffset: log.warning('cannot parse DirReloc, skipping') if len(self.NThdr.optentries) > pe.DIRECTORY_ENTRY_RESOURCE: self.DirRes = pe.DirRes(self) if parse_resources: self.DirRes = pe.DirRes(self) try: self.DirRes = pe.DirRes.unpack(self.img_rva, self.NThdr.optentries[ pe.DIRECTORY_ENTRY_RESOURCE].rva, self) except pe.InvalidOffset: log.warning('cannot parse DirRes, skipping') if len(self.NThdr.optentries) > pe.DIRECTORY_ENTRY_TLS: self.DirTls = pe.DirTls(self) try: self.DirTls = pe.DirTls.unpack( self.img_rva, self.NThdr.optentries[pe.DIRECTORY_ENTRY_TLS].rva, self ) except pe.InvalidOffset: log.warning('cannot parse DirTls, skipping') def resize(self, old, new): pass def __getitem__(self, item): return self.content[item] def __setitem__(self, item, data): self.content.__setitem__(item, data) return def getsectionbyrva(self, rva): if self.SHList is None: return None for section in self.SHList.shlist: """ TODO CHECK: some binaries have import rva outside section, but addresses seems to be rounded """ mask = self.NThdr.sectionalignment - 1 if section.addr <= rva < (section.addr + section.size + mask) & ~(mask): return section return None def getsectionbyvad(self, vad): return self.getsectionbyrva(self.virt2rva(vad)) def getsectionbyoff(self, off): if self.SHList is None: return None for section in self.SHList.shlist: if section.offset <= off < section.offset + section.rawsize: return section return None def getsectionbyname(self, name): if self.SHList is None: return None for section in self.SHList: if section.name.strip(b'\x00').decode() == name: return section return None def is_rva_ok(self, rva): return self.getsectionbyrva(rva) is not None def rva2off(self, rva): # Special case rva in header if rva < self.NThdr.sizeofheaders: return rva section = self.getsectionbyrva(rva) if section is None: raise pe.InvalidOffset('cannot get offset for 0x%X' % rva) soff = (section.offset // self.NThdr.filealignment) * self.NThdr.filealignment return rva - section.addr + soff def off2rva(self, off): section = self.getsectionbyoff(off) if section is None: return return off - section.offset + section.addr def virt2rva(self, addr): """ Return rva of virtual address @addr; None if addr is below ImageBase """ if addr is None: return None rva = addr - self.NThdr.ImageBase if rva < 0: return None return rva def rva2virt(self, rva): if rva is None: return return rva + self.NThdr.ImageBase def virt2off(self, addr): """ Return offset of virtual address @addr """ rva = self.virt2rva(addr) if rva is None: return None return self.rva2off(rva) def off2virt(self, off): return self.rva2virt(self.off2rva(off)) def is_in_virt_address(self, addr): if addr < self.NThdr.ImageBase: return False addr = self.virt2rva(addr) for section in self.SHList.shlist: if section.addr <= addr < section.addr + section.size: return True return False def get_drva(self): print('Deprecated: Use PE.rva instead of PE.drva') return self._rva def get_rva(self): return self._rva # TODO XXX remove drva api drva = property(get_drva) rva = property(get_rva) def get_virt(self): return self._virt virt = property(get_virt) def build_content(self): content = StrPatchwork() content[0] = bytes(self.Doshdr) for section in self.SHList.shlist: content[section.offset:section.offset + section.rawsize] = bytes(section.data) # fix image size section_last = self.SHList.shlist[-1] size = section_last.addr + section_last.size + (self.NThdr.sectionalignment - 1) size &= ~(self.NThdr.sectionalignment - 1) self.NThdr.sizeofimage = size off = self.Doshdr.lfanew content[off] = bytes(self.NTsig) off += len(self.NTsig) content[off] = bytes(self.Coffhdr) off += len(self.Coffhdr) off_shlist = off + self.Coffhdr.sizeofoptionalheader content[off] = bytes(self.Opthdr) off += len(self.Opthdr) content[off] = bytes(self.NThdr) off += len(self.NThdr) # content[off] = bytes(self.Optehdr) off = off_shlist content[off] = bytes(self.SHList) for section in self.SHList: if off + len(bytes(self.SHList)) > section.offset: log.warn("section offset overlap pe hdr 0x%x 0x%x" % (off + len(bytes(self.SHList)), section.offset)) self.DirImport.build_content(content) self.DirExport.build_content(content) self.DirDelay.build_content(content) self.DirReloc.build_content(content) self.DirRes.build_content(content) self.DirTls.build_content(content) if (self.Doshdr.lfanew + len(self.NTsig) + len(self.Coffhdr)) % 4: log.warn("non aligned coffhdr, bad crc calculation") crcs = compute_crc(bytes(content), self.NThdr.CheckSum) content[self.Doshdr.lfanew + len(self.NTsig) + len(self.Coffhdr) + 64] = struct.pack('I', crcs) return bytes(content) def __bytes__(self): return self.build_content() def __str__(self): if PY3: return repr(self) return self.__bytes__() def export_funcs(self): if self.DirExport is None: print('no export dir found') return None, None all_func = {} for i, export in enumerate(self.DirExport.f_names): all_func[export.name.name] = self.rva2virt( self.DirExport.f_address[self.DirExport.f_nameordinals[i].ordinal].rva) all_func[self.DirExport.f_nameordinals[i].ordinal + self.DirExport.expdesc.base] = self.rva2virt( self.DirExport.f_address[self.DirExport.f_nameordinals[i].ordinal].rva) # XXX todo: test if redirected export return all_func def reloc_to(self, imgbase): offset = imgbase - self.NThdr.ImageBase if self.DirReloc is None: log.warn('no relocation found!') for rel in self.DirReloc.reldesc: rva = rel.rva for reloc in rel.rels: reloc_type, off = reloc.rel if reloc_type == 0 and off == 0: continue if reloc_type != 3: raise NotImplementedError('Reloc type not supported') off += rva value = struct.unpack('I', self.rva.get(off, off + 4))[0] value += offset self.rva.set(off, struct.pack('I', value & 0xFFFFFFFF)) self.NThdr.ImageBase = imgbase
Module variables
var PY3
var console_handler
var log
Functions
def compute_crc(
raw, olds)
def compute_crc(raw, olds): out = 0 data = raw[:] if len(raw) % 2: end = struct.unpack('B', data[-1:])[0] data = data[:-1] if (len(raw) & ~0x1) % 4: out += struct.unpack('H', data[:2])[0] data = data[2:] data = array.array('I', data) out = reduce(lambda x, y: x + y, data, out) out -= olds while out > 0xFFFFFFFF: out = (out >> 32) + (out & 0xFFFFFFFF) while out > 0xFFFF: out = (out & 0xFFFF) + ((out >> 16) & 0xFFFF) if len(raw) % 2: out += end out += len(data) return out
Classes
class ContectRva
class ContectRva(object): def __init__(self, parent): self.parent = parent def get(self, rva_start, rva_stop=None): """ Get data in RVA view starting at @rva_start, stopping at @rva_stop @rva_start: rva start address @rva_stop: rva stop address """ if rva_start < 0: raise ValueError("Out of range") if rva_stop is not None: if rva_stop > len(self.parent.img_rva): rva_stop = len(self.parent.img_rva) if rva_start > len(self.parent.img_rva): raise ValueError("Out of range") return self.parent.img_rva[rva_start:rva_stop] if rva_start > len(self.parent.img_rva): raise ValueError("Out of range") return self.parent.img_rva[rva_start] def set(self, rva, data): """ Set @data in RVA view starting at @start @rva: rva start address @data: data to set """ if not isinstance(rva, int_types): raise ValueError('addr must be int/long') if rva < 0: raise ValueError("Out of range") if rva + len(data) > len(self.parent.img_rva): raise ValueError("Out of range") self.parent.img_rva[rva] = data def __getitem__(self, item): if isinstance(item, slice): assert(item.step is None) return self.get(item.start, item.stop) return self.get(item) def __setitem__(self, item, data): if isinstance(item, slice): rva = item.start else: rva = item self.set(rva, data)
Ancestors (in MRO)
- ContectRva
- builtins.object
Static methods
def __init__(
self, parent)
Initialize self. See help(type(self)) for accurate signature.
def __init__(self, parent): self.parent = parent
def get(
self, rva_start, rva_stop=None)
Get data in RVA view starting at @rva_start, stopping at @rva_stop @rva_start: rva start address @rva_stop: rva stop address
def get(self, rva_start, rva_stop=None): """ Get data in RVA view starting at @rva_start, stopping at @rva_stop @rva_start: rva start address @rva_stop: rva stop address """ if rva_start < 0: raise ValueError("Out of range") if rva_stop is not None: if rva_stop > len(self.parent.img_rva): rva_stop = len(self.parent.img_rva) if rva_start > len(self.parent.img_rva): raise ValueError("Out of range") return self.parent.img_rva[rva_start:rva_stop] if rva_start > len(self.parent.img_rva): raise ValueError("Out of range") return self.parent.img_rva[rva_start]
def set(
self, rva, data)
Set @data in RVA view starting at @start @rva: rva start address @data: data to set
def set(self, rva, data): """ Set @data in RVA view starting at @start @rva: rva start address @data: data to set """ if not isinstance(rva, int_types): raise ValueError('addr must be int/long') if rva < 0: raise ValueError("Out of range") if rva + len(data) > len(self.parent.img_rva): raise ValueError("Out of range") self.parent.img_rva[rva] = data
Instance variables
var parent
class ContentManager
class ContentManager(object): def __get__(self, owner, _): if hasattr(owner, '_content'): return owner._content def __set__(self, owner, new_content): owner.resize(len(owner._content), len(new_content)) owner._content = new_content def __delete__(self, owner): self.__set__(owner, None)
Ancestors (in MRO)
- ContentManager
- builtins.object
class ContentVirtual
class ContentVirtual(object): def __init__(self, parent): self.parent = parent def __getitem__(self, item): raise DeprecationWarning("Replace code by virt.get(start, [stop])") def __setitem__(self, item, data): raise DeprecationWarning("Replace code by virt.set(start, data)") def __call__(self, ad_start, ad_stop=None, ad_step=None): raise DeprecationWarning("Replace code by virt.get(start, stop)") def get(self, virt_start, virt_stop=None): """ Get data in VIRTUAL view starting at @virt_start, stopping at @virt_stop @virt_start: virt start address @virt_stop: virt stop address """ rva_start = self.parent.virt2rva(virt_start) if virt_stop != None: rva_stop = self.parent.virt2rva(virt_stop) else: rva_stop = None return self.parent.rva.get(rva_start, rva_stop) def set(self, addr, data): """ Set @data in VIRTUAL view starting at @start @addr: virtual start address @data: data to set """ if not isinstance(addr, int_types): raise ValueError('addr must be int/long') self.parent.rva.set(self.parent.virt2rva(addr), data) def max_addr(self): section = self.parent.SHList[-1] length = section.addr + section.size + self.parent.NThdr.ImageBase return int(length) def find(self, pattern, start=0, end=None): if start != 0: start = self.parent.virt2rva(start) if end != None: end = self.parent.virt2rva(end) ret = self.parent.img_rva.find(pattern, start, end) if ret == -1: return -1 return self.parent.rva2virt(ret) def rfind(self, pattern, start=0, end=None): if start != 0: start = self.parent.virt2rva(start) if end != None: end = self.parent.virt2rva(end) ret = self.parent.img_rva.rfind(pattern, start, end) if ret == -1: return -1 return self.parent.rva2virt(ret) def is_addr_in(self, addr): return self.parent.is_in_virt_address(addr)
Ancestors (in MRO)
- ContentVirtual
- builtins.object
Static methods
def __init__(
self, parent)
Initialize self. See help(type(self)) for accurate signature.
def __init__(self, parent): self.parent = parent
def find(
self, pattern, start=0, end=None)
def find(self, pattern, start=0, end=None): if start != 0: start = self.parent.virt2rva(start) if end != None: end = self.parent.virt2rva(end) ret = self.parent.img_rva.find(pattern, start, end) if ret == -1: return -1 return self.parent.rva2virt(ret)
def get(
self, virt_start, virt_stop=None)
Get data in VIRTUAL view starting at @virt_start, stopping at @virt_stop @virt_start: virt start address @virt_stop: virt stop address
def get(self, virt_start, virt_stop=None): """ Get data in VIRTUAL view starting at @virt_start, stopping at @virt_stop @virt_start: virt start address @virt_stop: virt stop address """ rva_start = self.parent.virt2rva(virt_start) if virt_stop != None: rva_stop = self.parent.virt2rva(virt_stop) else: rva_stop = None return self.parent.rva.get(rva_start, rva_stop)
def is_addr_in(
self, addr)
def is_addr_in(self, addr): return self.parent.is_in_virt_address(addr)
def max_addr(
self)
def max_addr(self): section = self.parent.SHList[-1] length = section.addr + section.size + self.parent.NThdr.ImageBase return int(length)
def rfind(
self, pattern, start=0, end=None)
def rfind(self, pattern, start=0, end=None): if start != 0: start = self.parent.virt2rva(start) if end != None: end = self.parent.virt2rva(end) ret = self.parent.img_rva.rfind(pattern, start, end) if ret == -1: return -1 return self.parent.rva2virt(ret)
def set(
self, addr, data)
Set @data in VIRTUAL view starting at @start @addr: virtual start address @data: data to set
def set(self, addr, data): """ Set @data in VIRTUAL view starting at @start @addr: virtual start address @data: data to set """ if not isinstance(addr, int_types): raise ValueError('addr must be int/long') self.parent.rva.set(self.parent.virt2rva(addr), data)
Instance variables
var parent
class PE
class PE(object): content = ContentManager() def __init__(self, pestr=None, loadfrommem=False, parse_resources=True, parse_delay=True, parse_reloc=True, wsize=32, **kwargs): self._rva = ContectRva(self) self._virt = ContentVirtual(self) self.img_rva = StrPatchwork() if pestr is None: self._content = StrPatchwork() self._sex = 0 self._wsize = wsize self.Doshdr = pe.Doshdr(self) self.NTsig = pe.NTsig(self) self.Coffhdr = pe.Coffhdr(self) if self._wsize == 32: Opthdr = pe.Opthdr32 else: Opthdr = pe.Opthdr64 self.Opthdr = Opthdr(self) self.NThdr = pe.NThdr(self) self.NThdr.optentries = [pe.Optehdr(self) for _ in range(0x10)] self.NThdr.CheckSum = 0 self.SHList = pe.SHList(self) self.SHList.shlist = [] self.NThdr.sizeofheaders = 0x1000 self.DirImport = pe.DirImport(self) self.DirExport = pe.DirExport(self) self.DirDelay = pe.DirDelay(self) self.DirReloc = pe.DirReloc(self) self.DirRes = pe.DirRes(self) self.DirTls = pe.DirTls(self) self.Doshdr.magic = 0x5a4d self.Doshdr.lfanew = 0xe0 self.NTsig.signature = 0x4550 if wsize == 32: self.Opthdr.magic = 0x10b elif wsize == 64: self.Opthdr.magic = 0x20b else: raise ValueError('unknown pe size %r' % wsize) self.Opthdr.majorlinkerversion = 0x7 self.Opthdr.minorlinkerversion = 0x0 self.NThdr.filealignment = 0x1000 self.NThdr.sectionalignment = 0x1000 self.NThdr.majoroperatingsystemversion = 0x5 self.NThdr.minoroperatingsystemversion = 0x1 self.NThdr.MajorImageVersion = 0x5 self.NThdr.MinorImageVersion = 0x1 self.NThdr.majorsubsystemversion = 0x4 self.NThdr.minorsubsystemversion = 0x0 self.NThdr.subsystem = 0x3 if wsize == 32: self.NThdr.dllcharacteristics = 0x8000 else: self.NThdr.dllcharacteristics = 0x8000 # for createthread self.NThdr.sizeofstackreserve = 0x200000 self.NThdr.sizeofstackcommit = 0x1000 self.NThdr.sizeofheapreserve = 0x100000 self.NThdr.sizeofheapcommit = 0x1000 self.NThdr.ImageBase = 0x400000 self.NThdr.sizeofheaders = 0x1000 self.NThdr.numberofrvaandsizes = 0x10 self.NTsig.signature = 0x4550 if wsize == 32: self.Coffhdr.machine = 0x14c elif wsize == 64: self.Coffhdr.machine = 0x8664 else: raise ValueError('unknown pe size %r' % wsize) if wsize == 32: self.Coffhdr.characteristics = 0x10f self.Coffhdr.sizeofoptionalheader = 0xe0 else: self.Coffhdr.characteristics = 0x22 # 0x2f self.Coffhdr.sizeofoptionalheader = 0xf0 else: self._content = StrPatchwork(pestr) self.loadfrommem = loadfrommem self.parse_content(parse_resources=parse_resources, parse_delay=parse_delay, parse_reloc=parse_reloc) def isPE(self): if self.NTsig is None: return False return self.NTsig.signature == 0x4550 def parse_content(self, parse_resources=True, parse_delay=True, parse_reloc=True): off = 0 self._sex = 0 self._wsize = 32 self.Doshdr = pe.Doshdr.unpack(self.content, off, self) off = self.Doshdr.lfanew if off > len(self.content): log.warn('ntsig after eof!') self.NTsig = None return self.NTsig = pe.NTsig.unpack(self.content, off, self) self.DirImport = None self.DirExport = None self.DirDelay = None self.DirReloc = None self.DirRes = None if self.NTsig.signature != 0x4550: log.warn('not a valid pe!') return off += len(self.NTsig) self.Coffhdr, length = pe.Coffhdr.unpack_l(self.content, off, self) off += length self._wsize = ord(self.content[off+1]) * 32 if self._wsize == 32: Opthdr = pe.Opthdr32 else: Opthdr = pe.Opthdr64 if len(self.content) < 0x200: # Fix for very little PE self.content += (0x200 - len(self.content)) * b'\x00' self.Opthdr, length = Opthdr.unpack_l(self.content, off, self) self.NThdr = pe.NThdr.unpack(self.content, off + length, self) self.img_rva[0] = self.content[:self.NThdr.sizeofheaders] off += self.Coffhdr.sizeofoptionalheader self.SHList = pe.SHList.unpack(self.content, off, self) # load section data filealignment = self.NThdr.filealignment sectionalignment = self.NThdr.sectionalignment for section in self.SHList.shlist: virt_size = (section.size // sectionalignment + 1) * sectionalignment if self.loadfrommem: section.offset = section.addr if self.NThdr.sectionalignment > 0x1000: raw_off = 0x200 * (section.offset // 0x200) else: raw_off = section.offset if raw_off != section.offset: log.warn('unaligned raw section (%x %x)!', raw_off, section.offset) section.data = StrPatchwork() if section.rawsize == 0: rounded_size = 0 else: if section.rawsize % filealignment: rs = (section.rawsize // filealignment + 1) * filealignment else: rs = section.rawsize rounded_size = rs if rounded_size > virt_size: rounded_size = min(rounded_size, section.size) data = self.content[raw_off:raw_off + rounded_size] section.data = data # Pad data to page size 0x1000 length = len(data) data += b"\x00" * ((((length + 0xfff)) & 0xFFFFF000) - length) self.img_rva[section.addr] = data # Fix img_rva self.img_rva = self.img_rva try: self.DirImport = pe.DirImport.unpack(self.img_rva, self.NThdr.optentries[ pe.DIRECTORY_ENTRY_IMPORT].rva, self) except pe.InvalidOffset: log.warning('cannot parse DirImport, skipping') self.DirImport = pe.DirImport(self) try: self.DirExport = pe.DirExport.unpack(self.img_rva, self.NThdr.optentries[ pe.DIRECTORY_ENTRY_EXPORT].rva, self) except pe.InvalidOffset: log.warning('cannot parse DirExport, skipping') self.DirExport = pe.DirExport(self) if len(self.NThdr.optentries) > pe.DIRECTORY_ENTRY_DELAY_IMPORT: self.DirDelay = pe.DirDelay(self) if parse_delay: try: self.DirDelay = pe.DirDelay.unpack(self.img_rva, self.NThdr.optentries[ pe.DIRECTORY_ENTRY_DELAY_IMPORT].rva, self) except pe.InvalidOffset: log.warning('cannot parse DirDelay, skipping') if len(self.NThdr.optentries) > pe.DIRECTORY_ENTRY_BASERELOC: self.DirReloc = pe.DirReloc(self) if parse_reloc: try: self.DirReloc = pe.DirReloc.unpack(self.img_rva, self.NThdr.optentries[ pe.DIRECTORY_ENTRY_BASERELOC].rva, self) except pe.InvalidOffset: log.warning('cannot parse DirReloc, skipping') if len(self.NThdr.optentries) > pe.DIRECTORY_ENTRY_RESOURCE: self.DirRes = pe.DirRes(self) if parse_resources: self.DirRes = pe.DirRes(self) try: self.DirRes = pe.DirRes.unpack(self.img_rva, self.NThdr.optentries[ pe.DIRECTORY_ENTRY_RESOURCE].rva, self) except pe.InvalidOffset: log.warning('cannot parse DirRes, skipping') if len(self.NThdr.optentries) > pe.DIRECTORY_ENTRY_TLS: self.DirTls = pe.DirTls(self) try: self.DirTls = pe.DirTls.unpack( self.img_rva, self.NThdr.optentries[pe.DIRECTORY_ENTRY_TLS].rva, self ) except pe.InvalidOffset: log.warning('cannot parse DirTls, skipping') def resize(self, old, new): pass def __getitem__(self, item): return self.content[item] def __setitem__(self, item, data): self.content.__setitem__(item, data) return def getsectionbyrva(self, rva): if self.SHList is None: return None for section in self.SHList.shlist: """ TODO CHECK: some binaries have import rva outside section, but addresses seems to be rounded """ mask = self.NThdr.sectionalignment - 1 if section.addr <= rva < (section.addr + section.size + mask) & ~(mask): return section return None def getsectionbyvad(self, vad): return self.getsectionbyrva(self.virt2rva(vad)) def getsectionbyoff(self, off): if self.SHList is None: return None for section in self.SHList.shlist: if section.offset <= off < section.offset + section.rawsize: return section return None def getsectionbyname(self, name): if self.SHList is None: return None for section in self.SHList: if section.name.strip(b'\x00').decode() == name: return section return None def is_rva_ok(self, rva): return self.getsectionbyrva(rva) is not None def rva2off(self, rva): # Special case rva in header if rva < self.NThdr.sizeofheaders: return rva section = self.getsectionbyrva(rva) if section is None: raise pe.InvalidOffset('cannot get offset for 0x%X' % rva) soff = (section.offset // self.NThdr.filealignment) * self.NThdr.filealignment return rva - section.addr + soff def off2rva(self, off): section = self.getsectionbyoff(off) if section is None: return return off - section.offset + section.addr def virt2rva(self, addr): """ Return rva of virtual address @addr; None if addr is below ImageBase """ if addr is None: return None rva = addr - self.NThdr.ImageBase if rva < 0: return None return rva def rva2virt(self, rva): if rva is None: return return rva + self.NThdr.ImageBase def virt2off(self, addr): """ Return offset of virtual address @addr """ rva = self.virt2rva(addr) if rva is None: return None return self.rva2off(rva) def off2virt(self, off): return self.rva2virt(self.off2rva(off)) def is_in_virt_address(self, addr): if addr < self.NThdr.ImageBase: return False addr = self.virt2rva(addr) for section in self.SHList.shlist: if section.addr <= addr < section.addr + section.size: return True return False def get_drva(self): print('Deprecated: Use PE.rva instead of PE.drva') return self._rva def get_rva(self): return self._rva # TODO XXX remove drva api drva = property(get_drva) rva = property(get_rva) def get_virt(self): return self._virt virt = property(get_virt) def build_content(self): content = StrPatchwork() content[0] = bytes(self.Doshdr) for section in self.SHList.shlist: content[section.offset:section.offset + section.rawsize] = bytes(section.data) # fix image size section_last = self.SHList.shlist[-1] size = section_last.addr + section_last.size + (self.NThdr.sectionalignment - 1) size &= ~(self.NThdr.sectionalignment - 1) self.NThdr.sizeofimage = size off = self.Doshdr.lfanew content[off] = bytes(self.NTsig) off += len(self.NTsig) content[off] = bytes(self.Coffhdr) off += len(self.Coffhdr) off_shlist = off + self.Coffhdr.sizeofoptionalheader content[off] = bytes(self.Opthdr) off += len(self.Opthdr) content[off] = bytes(self.NThdr) off += len(self.NThdr) # content[off] = bytes(self.Optehdr) off = off_shlist content[off] = bytes(self.SHList) for section in self.SHList: if off + len(bytes(self.SHList)) > section.offset: log.warn("section offset overlap pe hdr 0x%x 0x%x" % (off + len(bytes(self.SHList)), section.offset)) self.DirImport.build_content(content) self.DirExport.build_content(content) self.DirDelay.build_content(content) self.DirReloc.build_content(content) self.DirRes.build_content(content) self.DirTls.build_content(content) if (self.Doshdr.lfanew + len(self.NTsig) + len(self.Coffhdr)) % 4: log.warn("non aligned coffhdr, bad crc calculation") crcs = compute_crc(bytes(content), self.NThdr.CheckSum) content[self.Doshdr.lfanew + len(self.NTsig) + len(self.Coffhdr) + 64] = struct.pack('I', crcs) return bytes(content) def __bytes__(self): return self.build_content() def __str__(self): if PY3: return repr(self) return self.__bytes__() def export_funcs(self): if self.DirExport is None: print('no export dir found') return None, None all_func = {} for i, export in enumerate(self.DirExport.f_names): all_func[export.name.name] = self.rva2virt( self.DirExport.f_address[self.DirExport.f_nameordinals[i].ordinal].rva) all_func[self.DirExport.f_nameordinals[i].ordinal + self.DirExport.expdesc.base] = self.rva2virt( self.DirExport.f_address[self.DirExport.f_nameordinals[i].ordinal].rva) # XXX todo: test if redirected export return all_func def reloc_to(self, imgbase): offset = imgbase - self.NThdr.ImageBase if self.DirReloc is None: log.warn('no relocation found!') for rel in self.DirReloc.reldesc: rva = rel.rva for reloc in rel.rels: reloc_type, off = reloc.rel if reloc_type == 0 and off == 0: continue if reloc_type != 3: raise NotImplementedError('Reloc type not supported') off += rva value = struct.unpack('I', self.rva.get(off, off + 4))[0] value += offset self.rva.set(off, struct.pack('I', value & 0xFFFFFFFF)) self.NThdr.ImageBase = imgbase
Ancestors (in MRO)
- PE
- builtins.object
Class variables
var content
var drva
var rva
var virt
Static methods
def __init__(
self, pestr=None, loadfrommem=False, parse_resources=True, parse_delay=True, parse_reloc=True, wsize=32, **kwargs)
Initialize self. See help(type(self)) for accurate signature.
def __init__(self, pestr=None, loadfrommem=False, parse_resources=True, parse_delay=True, parse_reloc=True, wsize=32, **kwargs): self._rva = ContectRva(self) self._virt = ContentVirtual(self) self.img_rva = StrPatchwork() if pestr is None: self._content = StrPatchwork() self._sex = 0 self._wsize = wsize self.Doshdr = pe.Doshdr(self) self.NTsig = pe.NTsig(self) self.Coffhdr = pe.Coffhdr(self) if self._wsize == 32: Opthdr = pe.Opthdr32 else: Opthdr = pe.Opthdr64 self.Opthdr = Opthdr(self) self.NThdr = pe.NThdr(self) self.NThdr.optentries = [pe.Optehdr(self) for _ in range(0x10)] self.NThdr.CheckSum = 0 self.SHList = pe.SHList(self) self.SHList.shlist = [] self.NThdr.sizeofheaders = 0x1000 self.DirImport = pe.DirImport(self) self.DirExport = pe.DirExport(self) self.DirDelay = pe.DirDelay(self) self.DirReloc = pe.DirReloc(self) self.DirRes = pe.DirRes(self) self.DirTls = pe.DirTls(self) self.Doshdr.magic = 0x5a4d self.Doshdr.lfanew = 0xe0 self.NTsig.signature = 0x4550 if wsize == 32: self.Opthdr.magic = 0x10b elif wsize == 64: self.Opthdr.magic = 0x20b else: raise ValueError('unknown pe size %r' % wsize) self.Opthdr.majorlinkerversion = 0x7 self.Opthdr.minorlinkerversion = 0x0 self.NThdr.filealignment = 0x1000 self.NThdr.sectionalignment = 0x1000 self.NThdr.majoroperatingsystemversion = 0x5 self.NThdr.minoroperatingsystemversion = 0x1 self.NThdr.MajorImageVersion = 0x5 self.NThdr.MinorImageVersion = 0x1 self.NThdr.majorsubsystemversion = 0x4 self.NThdr.minorsubsystemversion = 0x0 self.NThdr.subsystem = 0x3 if wsize == 32: self.NThdr.dllcharacteristics = 0x8000 else: self.NThdr.dllcharacteristics = 0x8000 # for createthread self.NThdr.sizeofstackreserve = 0x200000 self.NThdr.sizeofstackcommit = 0x1000 self.NThdr.sizeofheapreserve = 0x100000 self.NThdr.sizeofheapcommit = 0x1000 self.NThdr.ImageBase = 0x400000 self.NThdr.sizeofheaders = 0x1000 self.NThdr.numberofrvaandsizes = 0x10 self.NTsig.signature = 0x4550 if wsize == 32: self.Coffhdr.machine = 0x14c elif wsize == 64: self.Coffhdr.machine = 0x8664 else: raise ValueError('unknown pe size %r' % wsize) if wsize == 32: self.Coffhdr.characteristics = 0x10f self.Coffhdr.sizeofoptionalheader = 0xe0 else: self.Coffhdr.characteristics = 0x22 # 0x2f self.Coffhdr.sizeofoptionalheader = 0xf0 else: self._content = StrPatchwork(pestr) self.loadfrommem = loadfrommem self.parse_content(parse_resources=parse_resources, parse_delay=parse_delay, parse_reloc=parse_reloc)
def build_content(
self)
def build_content(self): content = StrPatchwork() content[0] = bytes(self.Doshdr) for section in self.SHList.shlist: content[section.offset:section.offset + section.rawsize] = bytes(section.data) # fix image size section_last = self.SHList.shlist[-1] size = section_last.addr + section_last.size + (self.NThdr.sectionalignment - 1) size &= ~(self.NThdr.sectionalignment - 1) self.NThdr.sizeofimage = size off = self.Doshdr.lfanew content[off] = bytes(self.NTsig) off += len(self.NTsig) content[off] = bytes(self.Coffhdr) off += len(self.Coffhdr) off_shlist = off + self.Coffhdr.sizeofoptionalheader content[off] = bytes(self.Opthdr) off += len(self.Opthdr) content[off] = bytes(self.NThdr) off += len(self.NThdr) # content[off] = bytes(self.Optehdr) off = off_shlist content[off] = bytes(self.SHList) for section in self.SHList: if off + len(bytes(self.SHList)) > section.offset: log.warn("section offset overlap pe hdr 0x%x 0x%x" % (off + len(bytes(self.SHList)), section.offset)) self.DirImport.build_content(content) self.DirExport.build_content(content) self.DirDelay.build_content(content) self.DirReloc.build_content(content) self.DirRes.build_content(content) self.DirTls.build_content(content) if (self.Doshdr.lfanew + len(self.NTsig) + len(self.Coffhdr)) % 4: log.warn("non aligned coffhdr, bad crc calculation") crcs = compute_crc(bytes(content), self.NThdr.CheckSum) content[self.Doshdr.lfanew + len(self.NTsig) + len(self.Coffhdr) + 64] = struct.pack('I', crcs) return bytes(content)
def export_funcs(
self)
def export_funcs(self): if self.DirExport is None: print('no export dir found') return None, None all_func = {} for i, export in enumerate(self.DirExport.f_names): all_func[export.name.name] = self.rva2virt( self.DirExport.f_address[self.DirExport.f_nameordinals[i].ordinal].rva) all_func[self.DirExport.f_nameordinals[i].ordinal + self.DirExport.expdesc.base] = self.rva2virt( self.DirExport.f_address[self.DirExport.f_nameordinals[i].ordinal].rva) # XXX todo: test if redirected export return all_func
def get_drva(
self)
def get_drva(self): print('Deprecated: Use PE.rva instead of PE.drva') return self._rva
def get_rva(
self)
def get_rva(self): return self._rva
def get_virt(
self)
def get_virt(self): return self._virt
def getsectionbyname(
self, name)
def getsectionbyname(self, name): if self.SHList is None: return None for section in self.SHList: if section.name.strip(b'\x00').decode() == name: return section return None
def getsectionbyoff(
self, off)
def getsectionbyoff(self, off): if self.SHList is None: return None for section in self.SHList.shlist: if section.offset <= off < section.offset + section.rawsize: return section return None
def getsectionbyrva(
self, rva)
def getsectionbyrva(self, rva): if self.SHList is None: return None for section in self.SHList.shlist: """ TODO CHECK: some binaries have import rva outside section, but addresses seems to be rounded """ mask = self.NThdr.sectionalignment - 1 if section.addr <= rva < (section.addr + section.size + mask) & ~(mask): return section return None
def getsectionbyvad(
self, vad)
def getsectionbyvad(self, vad): return self.getsectionbyrva(self.virt2rva(vad))
def isPE(
self)
def isPE(self): if self.NTsig is None: return False return self.NTsig.signature == 0x4550
def is_in_virt_address(
self, addr)
def is_in_virt_address(self, addr): if addr < self.NThdr.ImageBase: return False addr = self.virt2rva(addr) for section in self.SHList.shlist: if section.addr <= addr < section.addr + section.size: return True return False
def is_rva_ok(
self, rva)
def is_rva_ok(self, rva): return self.getsectionbyrva(rva) is not None
def off2rva(
self, off)
def off2rva(self, off): section = self.getsectionbyoff(off) if section is None: return return off - section.offset + section.addr
def off2virt(
self, off)
def off2virt(self, off): return self.rva2virt(self.off2rva(off))
def parse_content(
self, parse_resources=True, parse_delay=True, parse_reloc=True)
def parse_content(self, parse_resources=True, parse_delay=True, parse_reloc=True): off = 0 self._sex = 0 self._wsize = 32 self.Doshdr = pe.Doshdr.unpack(self.content, off, self) off = self.Doshdr.lfanew if off > len(self.content): log.warn('ntsig after eof!') self.NTsig = None return self.NTsig = pe.NTsig.unpack(self.content, off, self) self.DirImport = None self.DirExport = None self.DirDelay = None self.DirReloc = None self.DirRes = None if self.NTsig.signature != 0x4550: log.warn('not a valid pe!') return off += len(self.NTsig) self.Coffhdr, length = pe.Coffhdr.unpack_l(self.content, off, self) off += length self._wsize = ord(self.content[off+1]) * 32 if self._wsize == 32: Opthdr = pe.Opthdr32 else: Opthdr = pe.Opthdr64 if len(self.content) < 0x200: # Fix for very little PE self.content += (0x200 - len(self.content)) * b'\x00' self.Opthdr, length = Opthdr.unpack_l(self.content, off, self) self.NThdr = pe.NThdr.unpack(self.content, off + length, self) self.img_rva[0] = self.content[:self.NThdr.sizeofheaders] off += self.Coffhdr.sizeofoptionalheader self.SHList = pe.SHList.unpack(self.content, off, self) # load section data filealignment = self.NThdr.filealignment sectionalignment = self.NThdr.sectionalignment for section in self.SHList.shlist: virt_size = (section.size // sectionalignment + 1) * sectionalignment if self.loadfrommem: section.offset = section.addr if self.NThdr.sectionalignment > 0x1000: raw_off = 0x200 * (section.offset // 0x200) else: raw_off = section.offset if raw_off != section.offset: log.warn('unaligned raw section (%x %x)!', raw_off, section.offset) section.data = StrPatchwork() if section.rawsize == 0: rounded_size = 0 else: if section.rawsize % filealignment: rs = (section.rawsize // filealignment + 1) * filealignment else: rs = section.rawsize rounded_size = rs if rounded_size > virt_size: rounded_size = min(rounded_size, section.size) data = self.content[raw_off:raw_off + rounded_size] section.data = data # Pad data to page size 0x1000 length = len(data) data += b"\x00" * ((((length + 0xfff)) & 0xFFFFF000) - length) self.img_rva[section.addr] = data # Fix img_rva self.img_rva = self.img_rva try: self.DirImport = pe.DirImport.unpack(self.img_rva, self.NThdr.optentries[ pe.DIRECTORY_ENTRY_IMPORT].rva, self) except pe.InvalidOffset: log.warning('cannot parse DirImport, skipping') self.DirImport = pe.DirImport(self) try: self.DirExport = pe.DirExport.unpack(self.img_rva, self.NThdr.optentries[ pe.DIRECTORY_ENTRY_EXPORT].rva, self) except pe.InvalidOffset: log.warning('cannot parse DirExport, skipping') self.DirExport = pe.DirExport(self) if len(self.NThdr.optentries) > pe.DIRECTORY_ENTRY_DELAY_IMPORT: self.DirDelay = pe.DirDelay(self) if parse_delay: try: self.DirDelay = pe.DirDelay.unpack(self.img_rva, self.NThdr.optentries[ pe.DIRECTORY_ENTRY_DELAY_IMPORT].rva, self) except pe.InvalidOffset: log.warning('cannot parse DirDelay, skipping') if len(self.NThdr.optentries) > pe.DIRECTORY_ENTRY_BASERELOC: self.DirReloc = pe.DirReloc(self) if parse_reloc: try: self.DirReloc = pe.DirReloc.unpack(self.img_rva, self.NThdr.optentries[ pe.DIRECTORY_ENTRY_BASERELOC].rva, self) except pe.InvalidOffset: log.warning('cannot parse DirReloc, skipping') if len(self.NThdr.optentries) > pe.DIRECTORY_ENTRY_RESOURCE: self.DirRes = pe.DirRes(self) if parse_resources: self.DirRes = pe.DirRes(self) try: self.DirRes = pe.DirRes.unpack(self.img_rva, self.NThdr.optentries[ pe.DIRECTORY_ENTRY_RESOURCE].rva, self) except pe.InvalidOffset: log.warning('cannot parse DirRes, skipping') if len(self.NThdr.optentries) > pe.DIRECTORY_ENTRY_TLS: self.DirTls = pe.DirTls(self) try: self.DirTls = pe.DirTls.unpack( self.img_rva, self.NThdr.optentries[pe.DIRECTORY_ENTRY_TLS].rva, self ) except pe.InvalidOffset: log.warning('cannot parse DirTls, skipping')
def reloc_to(
self, imgbase)
def reloc_to(self, imgbase): offset = imgbase - self.NThdr.ImageBase if self.DirReloc is None: log.warn('no relocation found!') for rel in self.DirReloc.reldesc: rva = rel.rva for reloc in rel.rels: reloc_type, off = reloc.rel if reloc_type == 0 and off == 0: continue if reloc_type != 3: raise NotImplementedError('Reloc type not supported') off += rva value = struct.unpack('I', self.rva.get(off, off + 4))[0] value += offset self.rva.set(off, struct.pack('I', value & 0xFFFFFFFF)) self.NThdr.ImageBase = imgbase
def resize(
self, old, new)
def resize(self, old, new): pass
def rva2off(
self, rva)
def rva2off(self, rva): # Special case rva in header if rva < self.NThdr.sizeofheaders: return rva section = self.getsectionbyrva(rva) if section is None: raise pe.InvalidOffset('cannot get offset for 0x%X' % rva) soff = (section.offset // self.NThdr.filealignment) * self.NThdr.filealignment return rva - section.addr + soff
def rva2virt(
self, rva)
def rva2virt(self, rva): if rva is None: return return rva + self.NThdr.ImageBase
def virt2off(
self, addr)
Return offset of virtual address @addr
def virt2off(self, addr): """ Return offset of virtual address @addr """ rva = self.virt2rva(addr) if rva is None: return None return self.rva2off(rva)
def virt2rva(
self, addr)
Return rva of virtual address @addr; None if addr is below ImageBase
def virt2rva(self, addr): """ Return rva of virtual address @addr; None if addr is below ImageBase """ if addr is None: return None rva = addr - self.NThdr.ImageBase if rva < 0: return None return rva
Instance variables
var drva
var img_rva
var rva
var virt