Source code for malduck.procmem.procmemelf
from .region import Region
from .binmem import ProcessMemoryBinary
import elftools
import elftools.elf.elffile
import io
__all__ = ["ProcessMemoryELF", "procmemelf"]
[docs]class ProcessMemoryELF(ProcessMemoryBinary):
"""
Representation of memory-mapped ELF file
Short name: `procmemelf`
ELF files can be read directly using inherited :py:meth:`ProcessMemory.from_file` with `image` argument set
(look at :py:meth:`from_memory` method).
"""
__magic__ = b"\x7fELF"
def __init__(self, buf, base=0, regions=None, image=False, detect_image=False):
self._elf = None
super(ProcessMemoryELF, self).__init__(
buf, base=base, regions=regions, image=image, detect_image=detect_image
)
def _elf_direct_load(self):
offset = self.v2p(self.imgbase)
# Stream required for ELFFile()
stream = io.BytesIO(self.readp(offset))
elf = elftools.elf.elffile.ELFFile(stream)
# Try to iter_segments to check whether ELFFile is really correct
list(elf.iter_segments())
return elf
[docs] def is_valid(self):
if self.readv(self.imgbase, 4) != self.__magic__:
return False
try:
self._elf_direct_load()
return True
except Exception:
return False
def _reload_as_image(self):
page_size = 0x1000
# Reset regions
self.imgbase = None
self.regions = []
# Load image segments
for segment in self.elf.iter_segments():
if segment.header["p_type"] == "PT_LOAD":
if segment.header["p_offset"] == 0:
# virtual address of ELF file header
self.imgbase = segment.header["p_vaddr"]
if page_size is None:
presegment_len = 0
postsegment_len = 0
else:
presegment_len = segment.header["p_vaddr"] % page_size
postsegment_len = (
page_size
- (segment.header["p_vaddr"] + segment.header["p_filesz"])
% page_size
)
self.regions.append(
Region(
segment.header["p_vaddr"] - presegment_len,
segment.header["p_filesz"] + presegment_len + postsegment_len,
0,
segment.header["p_type"],
0, # TODO: protect flags
segment.header["p_offset"] - presegment_len,
)
)
if len(self.regions) == 0:
raise elftools.elf.elffile.ELFError("No regions in ELF file!")
@property
def elf(self):
"""Related :class:`ELFFile` object"""
if not self._elf:
self._elf = self._elf_direct_load()
return self._elf
[docs] def is_image_loaded_as_memdump(self):
raise NotImplementedError()
@property
def imgend(self):
"""Address where ELF image ends"""
lastSegment = self.elf.get_segment(self.elf.num_segment() - 1)
return lastSegment.header["p_vaddr"] + lastSegment.header["p_memsz"]
procmemelf = ProcessMemoryELF