Source code for pymem.ptypes

import ctypes
import struct

import pymem.memory
import pymem.exception


[docs]class RemotePointer(object): """Pointer capable of reading the value mapped into another process memory. Parameters ---------- handle: int Handle to the process v: int, RemotePointer, any ctypes type The address value endianess: str The endianess of the remote pointer, defaulting to little-endian Raises ------ PymemAlignmentError If endianess is not a valid alignment Notes ----- The bool of RemotePointer checks if the internal value is 0 """ ALIGNMENTS = { 'little-endian': '<', 'big-endian': '>' } def __init__(self, handle, v, endianess='little-endian'): self._set_value(v) if endianess not in RemotePointer.ALIGNMENTS: # TODO: maybe make this a ValueError in next major version raise pymem.exception.PymemAlignmentError( "{endianess} is not a valid alignment, it should be one from: {alignments}".format(**{ 'endianess': endianess, 'alignments': ', '.join(RemotePointer.ALIGNMENTS.keys()) }) ) self.endianess = endianess self.handle = handle self._memory_value = None def __bool__(self): return bool(self.value) def _set_value(self, v): """Given a v value will set up the internal kitchen to map internal v to the correct type. self.v has to be a ctype instance. """ if isinstance(v, RemotePointer): self.v = v.cvalue elif isinstance(v, int) and not hasattr(v, 'value'): if v > 2147483647: self.v = ctypes.c_ulonglong(v) else: self.v = ctypes.c_uint(v) elif isinstance(v, ctypes._SimpleCData): self.v = v else: raise pymem.exception.PymemTypeError( "{type} is not an allowed type, it should be one from: {allowed_types}".format(**{ 'type': 'None' if not v else str(type(v)), 'allowed_types': ', '.join([ 'RemotePointer', 'ctypes', 'int' ]) })) def __add__(self, a): self._memory_value = self.value + a return self.cvalue @property def value(self): """Reads targeted process memory and returns the value pointed by the given address. Returns ------- int The value pointed at by this remote pointer """ if self._memory_value: return self._memory_value content = pymem.memory.read_bytes( self.handle, self.v.value, struct.calcsize(self.v._type_) ) fmt = '{alignment}{type}'.format(**{ 'alignment': RemotePointer.ALIGNMENTS[self.endianess], 'type': self.v._type_ }) content = struct.unpack(fmt, content) self._memory_value = content[0] return self._memory_value @property def cvalue(self): """Reads targeted process memory and returns the value pointed by the given address. Returns ------- a ctypes type The value pointed at by this remote pointer as a ctypes type instance """ v = self.v.__class__(self.value) return v