### Development setup: create virtual environment and install dev dependencies Source: https://pymemoryeditor.readthedocs.io/en/latest/contributing.html Creates a Python virtual environment, activates it (with a Windows alternative), and installs the package in editable mode with the 'dev' extra, which includes the full toolchain and GUI dependencies. ```bash python -m venv venv source venv/bin/activate # On Windows: venv\Scripts\activate make install-dev # pip install -e ".[dev]" ``` -------------------------------- ### Run pymemoryeditor-mcp manually Source: https://pymemoryeditor.readthedocs.io/en/latest/mcp.html Examples of starting the server with different security and process-approval configurations. The server communicates over stdin/stdout and will wait for client input. ```bash pymemoryeditor-mcp # asks to attach; writes allowed pymemoryeditor-mcp --read-only # can never modify a target pymemoryeditor-mcp --allow-process game.exe # never asks for game.exe pymemoryeditor-mcp --allow-any-process # never asks at all (scripts/CI) ``` -------------------------------- ### Install the library Source: https://pymemoryeditor.readthedocs.io/en/latest/installation.html Standard installation of the core PyMemoryEditor library. ```bash pip install PyMemoryEditor ``` -------------------------------- ### Install from source Source: https://pymemoryeditor.readthedocs.io/en/latest/installation.html Clones the repository and installs the library in editable mode with development dependencies. ```bash git clone https://github.com/JeanExtreme002/PyMemoryEditor.git cd PyMemoryEditor pip install -e ".[dev]" ``` -------------------------------- ### Install with the bundled GUI app Source: https://pymemoryeditor.readthedocs.io/en/latest/installation.html Installs the library with the PySide6-based GUI. Launch the app using the provided command. ```bash pip install "PyMemoryEditor[app]" ``` ```bash pymemoryeditor ``` -------------------------------- ### Verify the installation Source: https://pymemoryeditor.readthedocs.io/en/latest/installation.html Checks the installation by importing the library and printing its version. ```python import PyMemoryEditor print(PyMemoryEditor.__version__) ``` -------------------------------- ### Install with the MCP server Source: https://pymemoryeditor.readthedocs.io/en/latest/installation.html Installs the library with the Model Context Protocol server for AI assistant integration. ```bash pip install "PyMemoryEditor[mcp]" ``` ```bash claude mcp add pymemoryeditor -- pymemoryeditor-mcp ``` ```json { "mcpServers": { "pymemoryeditor": { "command": "pymemoryeditor-mcp", "args": [] } } } ``` -------------------------------- ### Install PyMemoryEditor with MCP support Source: https://pymemoryeditor.readthedocs.io/en/latest/mcp.html Install the library with the mcp extra to include the necessary dependencies. ```bash pip install "PyMemoryEditor[mcp]" ``` -------------------------------- ### Install with scan acceleration Source: https://pymemoryeditor.readthedocs.io/en/latest/installation.html Installs the library with NumPy support to accelerate typed numeric scans. ```bash pip install "PyMemoryEditor[speed]" ``` -------------------------------- ### Example log output Source: https://pymemoryeditor.readthedocs.io/en/latest/guide/logging.html Sample output messages generated when logging is enabled. ```text DEBUG PyMemoryEditor: skipping region 0x7FFD0000–0x7FFD2000 (read failed) WARNING PyMemoryEditor: mach_vm_protect could not restore protection at 0x14010F4F4 ``` -------------------------------- ### PointerPath string representation example Source: https://pymemoryeditor.readthedocs.io/en/latest/api/pointer-path.html Example output of the __str__ method, showing a Cheat Engine-style textual representation of a pointer path. ```text "game.exe"+0x10F4F4 -> [+0x0] -> +0x158 ``` -------------------------------- ### Install PyMemoryEditor with GUI dependencies Source: https://pymemoryeditor.readthedocs.io/en/latest/app.html Install the PyMemoryEditor package with the 'app' extra to include PySide6 and other GUI dependencies. The core library remains dependency-free. ```bash pip install "PyMemoryEditor[app]" ``` -------------------------------- ### Process attachment prompt example Source: https://pymemoryeditor.readthedocs.io/en/latest/mcp.html The visual prompt displayed to the user when the assistant requests to attach to a process. ```text Allow PyMemoryEditor to attach to "game.exe" (pid 4821)? This gives the assistant read access to that process's memory. Writes are ENABLED on this server, so it can also change values in it. [ ] remember (Approve) (Decline) ``` -------------------------------- ### Opening the Current Process on macOS Source: https://pymemoryeditor.readthedocs.io/en/latest/platform-notes.html Example demonstrating that opening the current process via OpenProcess always succeeds on macOS without requiring special entitlements. ```python import os from PyMemoryEditor import OpenProcess with OpenProcess(pid=os.getpid()) as process: # Always works on macOS, no entitlement needed. for region in process.get_memory_regions(): ... ``` -------------------------------- ### Full Control Windows Process Handle Source: https://pymemoryeditor.readthedocs.io/en/latest/platform-notes.html Example of requesting full access rights for a process handle. ```python OpenProcess(name="game.exe", permission=ProcessOperationsEnum.PROCESS_ALL_ACCESS) ``` -------------------------------- ### Launch the PyMemoryEditor GUI Source: https://pymemoryeditor.readthedocs.io/en/latest/app.html Run the 'pymemoryeditor' command from any terminal to start the GUI application. The app opens with the Open Process dialog. ```bash pymemoryeditor ``` -------------------------------- ### Read-Only Windows Process Handle Source: https://pymemoryeditor.readthedocs.io/en/latest/platform-notes.html Example of narrowing the permission mask to read-only access for a specific process. ```python from PyMemoryEditor import OpenProcess, ProcessOperationsEnum with OpenProcess( name="notepad.exe", permission=ProcessOperationsEnum.PROCESS_VM_READ | ProcessOperationsEnum.PROCESS_QUERY_INFORMATION, ) as process: ... ``` -------------------------------- ### Allocate and free memory in a process Source: https://pymemoryeditor.readthedocs.io/en/latest/guide/allocate-free.html This example shows how to use the OpenProcess context manager to allocate 128 bytes of memory, perform read and write operations, and ensure the memory is freed in a finally block. ```python from PyMemoryEditor import OpenProcess with OpenProcess(name="game.exe") as process: address = process.allocate_memory(128) try: # Write something to it process.write_process_memory(address, str, 128, "Hello from PyMemoryEditor!") # Read it back msg = process.read_process_memory(address, str, 128) print(msg.split("\x00", 1)[0]) finally: process.free_memory(address) ``` -------------------------------- ### ClosedProcess example Source: https://pymemoryeditor.readthedocs.io/en/latest/api/errors.html Demonstrates that calling any method on a process after its handle has been closed (manually or by leaving the with block) raises ClosedProcess. The example shows a with block that exits and then attempts to read memory. ```python with OpenProcess(pid=1234) as process: pass process.read_process_memory(0x1000, int) # raises ClosedProcess ``` -------------------------------- ### Tune scan parameters with scan_pointer_paths Source: https://pymemoryeditor.readthedocs.io/en/latest/guide/pointer-scan.html Starts with shallow depth and small offset to limit candidates. max_depth grows exponentially in cost, so keep it low initially. ```python for path in process.scan_pointer_paths( address, max_depth=2, # start shallow max_offset=0x100, # smaller struct window max_results=20, # don't enumerate forever ): print(path) ``` -------------------------------- ### search_by_value_between(pytype, bufflength=None, start=..., end=..., *, not_between=False, progress_information=False, writeable_only=False, memory_regions=None) Source: https://pymemoryeditor.readthedocs.io/en/latest/guide/searching.html Iterates over memory addresses whose value lies within the inclusive range [start, end] (or outside when not_between is True). bufflength is optional for numeric types; start and end must be passed by keyword if bufflength is omitted. ```APIDOC ## search_by_value_between ### Description Search the process memory for addresses whose value is between `start` and `end` (inclusive), or outside when `not_between=True`. Returns a generator of addresses. ### Method Signature search_by_value_between(_pytype_ , _bufflength =None_, _start =..._, _end =..._, _*_ , _not_between =False_, _progress_information =False_, _writeable_only =False_, _memory_regions =None_) ### Parameters - **pytype** (type) - Required - The type of the value to search for (e.g., `int`). - **bufflength** (int) - Optional - Value size in bytes. Defaults to `None` (inferred for numeric types: int→4, float→8, bool→1). `str`/`bytes` require explicit size. - **start** - Required - The lower inclusive boundary of the range. - **end** - Required - The upper inclusive boundary of the range. - **not_between** (bool) - Optional - When `True`, returns values outside the range. Defaults to `False`. - **progress_information** (bool) - Optional - Show progress during search. Defaults to `False`. - **writeable_only** (bool) - Optional - Only search writable memory regions. Defaults to `False`. - **memory_regions** - Optional - Snapshot of memory regions. ### Request Example ```python for address in process.search_by_value_between(int, 4, 100, 200): print(hex(address)) ``` ### Notes - `start` and `end` are inclusive. - When `bufflength` is omitted, pass `start` and `end` by keyword, e.g., `search_by_value_between(int, start=100, end=200)`. ``` -------------------------------- ### Use ScanTypesEnum in search_by_value Source: https://pymemoryeditor.readthedocs.io/en/latest/api/enums.html Example of using ScanTypesEnum.BIGGER_THAN to filter memory search results. ```python from PyMemoryEditor import OpenProcess, ScanTypesEnum with OpenProcess(name="game.exe") as process: for address in process.search_by_value(int, value=1000, scan_type=ScanTypesEnum.BIGGER_THAN): print(hex(address)) ``` -------------------------------- ### Using base_address as a pointer-chain root Source: https://pymemoryeditor.readthedocs.io/en/latest/api/module-info.html Use the module's base address as a starting point for resolving a pointer chain. ```python module = next(m for m in process.get_modules() if m.name == "game.exe") hp_addr = process.resolve_pointer_chain( module.base_address + 0x10F4F4, [0x0, 0x158], ) ``` -------------------------------- ### Create a RemotePointer handle with process.get_pointer Source: https://pymemoryeditor.readthedocs.io/en/latest/guide/pointers.html Creates a reusable handle to a value behind a pointer chain. Every access to .value re-walks the chain, so the handle stays valid even if the target moves memory. The example reads and writes the player's HP. ```python # A handle to the player's HP, behind a two-level pointer. hp_ptr = process.get_pointer( base + 0x10F4F4, [0x0, 0x158], pytype=int, bufflength=4, ) print(hp_ptr.value) # read it hp_ptr.value = 9999 # write it ``` -------------------------------- ### NumPy acceleration internal logic Source: https://pymemoryeditor.readthedocs.io/en/latest/guide/searching.html Example of how PyMemoryEditor internally processes regions using NumPy for vectorized comparisons. ```python arr = np.frombuffer(region, dtype=" int32 array, no copy mask = arr > target # one C-level comparison offsets = np.flatnonzero(mask) * 4 # match positions -> byte offsets ``` -------------------------------- ### Resolve a pointer chain with resolve_pointer_chain Source: https://pymemoryeditor.readthedocs.io/en/latest/guide/pointers.html Walks a known pointer chain from a module base plus static offset, applying offsets [0x0, 0x158] to obtain the final address, then reads an integer from it. The example assumes a process handle and a module named 'game.exe'. ```python # Cheat-table entry: "game.exe" + 0x10F4F4 -> [+0x0] -> [+0x158] module = next(m for m in process.get_modules() if m.name == "game.exe") base = module.base_address + 0x10F4F4 hp_address = process.resolve_pointer_chain(base, [0x0, 0x158]) hp = process.read_int(hp_address) ``` -------------------------------- ### Pointer arithmetic: subtract to get byte distance Source: https://pymemoryeditor.readthedocs.io/en/latest/guide/pointers.html Subtracting two RemotePointer instances returns the byte distance between their resolved addresses. The example computes the distance between mp_ptr and hp_ptr, which is 4. ```python distance = mp_ptr - hp_ptr # 4 ``` -------------------------------- ### OpenProcess(name=None, pid=None, permission=, case_sensitive=, exact_match=True, strict_bitness=False) Source: https://pymemoryeditor.readthedocs.io/en/latest/api/openprocess.html Opens a target process. This is the unified entry point that resolves to the platform-specific backend. Parameters include name, pid, permission (Windows only), case_sensitive, exact_match, and strict_bitness. Raises ProcessNotFoundError, ProcessIDNotExistsError, AmbiguousProcessNameError, TypeError, or PermissionError on failure. ```APIDOC ## OpenProcess(name=None, pid=None, permission=, case_sensitive=, exact_match=True, strict_bitness=False) ### Description Opens a target process. `OpenProcess` resolves to the concrete backend for the host OS (WindowsProcess, LinuxProcess, or MacProcess). The `permission` and `case_sensitive` defaults are platform-specific: on Windows `permission` defaults to the read+write mask and `case_sensitive` to `False`; on Linux/macOS `permission` defaults to `None` (ignored) and `case_sensitive` to `True`. ### Parameters - **name** (str) - Optional - Name of the target process. - **pid** (int) - Optional - Process ID. Takes precedence over `name`. - **permission** (ProcessOperationsEnum or int) - Optional - Windows only. Defaults to read+write (`PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION | PROCESS_QUERY_INFORMATION`). On Linux and macOS this argument is accepted for API parity but ignored; passing a non-None value emits `UserWarning`. - **case_sensitive** (bool) - Optional - When `False`, `name` matching ignores case. Default is `False` on Windows, `True` elsewhere. - **exact_match** (bool) - Optional - When `False`, `name` matches as a substring (e.g., `"chrome"` matches `"chrome.exe"`). - **strict_bitness** (bool) - Optional - When `True`, `is_64bit` raises `BitnessDetectionError` if the target's 32-/64-bit width can't be read from its headers, instead of falling back to the host word size. ### Raises - **ProcessNotFoundError** - No process matches `name`. - **ProcessIDNotExistsError** - `pid` doesn't exist. - **AmbiguousProcessNameError** - More than one process matches. - **TypeError** - Neither `name` nor `pid` was provided. - **PermissionError** - The OS denied access. ### Examples ```python # By name with OpenProcess(name="game.exe") as process: ... # By PID with OpenProcess(pid=1234) as process: ... # Partial, case-insensitive name match (Windows-friendly) with OpenProcess(name="chrome", case_sensitive=False, exact_match=False) as process: ... # Read-only handle (Windows only) from PyMemoryEditor import ProcessOperationsEnum with OpenProcess( name="game.exe", permission=ProcessOperationsEnum.PROCESS_VM_READ | ProcessOperationsEnum.PROCESS_QUERY_INFORMATION, ) as process: ... ``` ``` -------------------------------- ### Using MemoryToolset directly in Python Source: https://pymemoryeditor.readthedocs.io/en/latest/mcp.html Demonstrates initializing a MemoryToolset and performing a memory scan and refinement workflow. Consent for process access is implicit when using the toolset directly. ```python from PyMemoryEditor.mcp import MemoryToolset, ServerConfig # allow_any_process: there is no MCP client here to show an approval prompt, # and you are the one calling, so consent is implicit. Writes are on by # default; pass allow_write=False for a read-only toolset. tools = MemoryToolset(ServerConfig(allow_any_process=True)) session = tools.open_process(name="game.exe")["session_id"] scan = tools.scan_value(session, "int", "100", bufflength=4) print(scan["count"], "candidates ->", scan["scan_id"]) # ...after the value changes in the target: refined = tools.refine_scan(scan["scan_id"], value="87") print(tools.list_scan_results(refined["scan_id"])["results"]) ``` -------------------------------- ### Listing every module Source: https://pymemoryeditor.readthedocs.io/en/latest/api/module-info.html Iterate through all modules loaded in a process and print their name, base address, and size. ```python with OpenProcess(name="game.exe") as process: for module in process.get_modules(): print(f"{module.name:32} 0x{module.base_address:016X} {module.size:>12}") ``` -------------------------------- ### make_predicate(scan_type, target, start, end) Source: https://pymemoryeditor.readthedocs.io/en/latest/api/utilities.html Creates a predicate function for a scan type comparison. ```APIDOC ## make_predicate(scan_type, target, start, end) ### Description Returns a single-value predicate `value -> bool` implementing one of the eight `ScanTypesEnum` comparisons. This is the one place those semantics are defined; the three scan loops share it, and so does the MCP server's `refine_scan`. ### Parameters - **scan_type** (ScanTypesEnum) - Required - The comparison type to implement. - **target** - Required - The target value to compare against. - **start** - Required - Only consulted by `VALUE_BETWEEN` and `NOT_VALUE_BETWEEN`; pass `target` for the other six. - **end** - Required - Only consulted by `VALUE_BETWEEN` and `NOT_VALUE_BETWEEN`; pass `target` for the other six. ``` -------------------------------- ### Open a process and perform memory operations Source: https://pymemoryeditor.readthedocs.io/en/latest/index.html Demonstrates opening a process by name, scanning for a specific integer value, and performing read/write operations on memory addresses. ```python from PyMemoryEditor import OpenProcess with OpenProcess(name="game.exe") as process: # Scan the whole process for every address holding the value 100. for address in process.search_by_value(int, value=100): print(f"Found at 0x{address:X}") # Read the current value, then write a new one back. current = process.read_int(address) process.write_int(address, current + 500) ``` -------------------------------- ### Building a live handle from a saved path Source: https://pymemoryeditor.readthedocs.io/en/latest/api/pointer-path.html Load a saved pointer path, rebase it, and create a RemotePointer to read/write the target value. ```python loaded = process.load_pointer_paths("pointers.json") hp_ptr = loaded[0].rebase(process).to_pointer(process, pytype=int, bufflength=4) hp_ptr.value = 9999 ``` -------------------------------- ### Open a process using a with block Source: https://pymemoryeditor.readthedocs.io/en/latest/quickstart.html The recommended pattern for opening a process, as it ensures the handle is closed automatically. ```python with OpenProcess(name="notepad.exe") as process: ... ``` -------------------------------- ### __enter__ and __exit__ Source: https://pymemoryeditor.readthedocs.io/en/latest/api/openprocess.html The process is also a context manager — prefer the with block. ```APIDOC ## __enter__ and __exit__ ### Description The process is also a context manager — prefer the `with` block. ### Method __enter__ / __exit__ ### Parameters - **exc_type** (type) - Required for __exit__ - Exception type. - **exc_value** (Exception) - Required for __exit__ - Exception value. - **exc_traceback** (traceback) - Required for __exit__ - Exception traceback. ### Returns For __enter__: the process object. For __exit__: None. ``` -------------------------------- ### Create chained handle from cheat-table entry Source: https://pymemoryeditor.readthedocs.io/en/latest/api/remote-pointer.html Creates a pointer handle for a multi-level pointer chain starting from a module base address. ```python # "game.exe" + 0x10F4F4 -> [+0x0] -> [+0x158] module = next(m for m in process.get_modules() if m.name == "game.exe") hp = process.get_pointer( module.base_address + 0x10F4F4, [0x0, 0x158], pytype=int, bufflength=4, ) hp.value -= 10 ``` -------------------------------- ### Using typed shortcuts for memory operations Source: https://pymemoryeditor.readthedocs.io/en/latest/guide/read-write.html Demonstrates reading and writing various data types using typed shortcut methods like read_int, read_uint, read_float, write_int, and write_bool. ```python with OpenProcess(name="game.exe") as process: hp = process.read_int(0x7FF40010) # signed, 4 bytes gold = process.read_uint(0x7FF40014) # unsigned, 4 bytes speed = process.read_float(0x7FF40018) # 32-bit float process.write_int(0x7FF40010, hp + 100) # heal up process.write_bool(0x7FF4001C, True) # toggle a flag ``` -------------------------------- ### Read and write strings Source: https://pymemoryeditor.readthedocs.io/en/latest/guide/read-write.html Demonstrates writing a string to a process memory address and reading it back, with automatic UTF-8 handling. ```python with OpenProcess(name="game.exe") as process: # Write your text — UTF-8 encoding (accents, emoji…) is handled for you. process.write_string(0x7FF40020, "Pedro") # Read it back: read a 32-byte field, stop at the first NUL terminator. name = process.read_string(0x7FF40020, 32) # -> "Pedro" ``` -------------------------------- ### RemotePointer.__init__ Source: https://pymemoryeditor.readthedocs.io/en/latest/api/remote-pointer.html Constructor for the RemotePointer class. ```APIDOC ## RemotePointer(process, base_address, offsets=None, *, pytype=int, bufflength=None, ptr_size=None) ### Description Constructs a re-resolving, read/write handle to a typed value in a target process. Most users build a RemotePointer through process.get_pointer(...). The constructor is documented here for completeness. ### Parameters - **process** (AbstractProcess) - Required - The open process the value lives in. - **base_address** (int) - Required - Starting address. For a direct handle this is the address of the value itself; for a pointer chain it is typically module_base + static_offset. - **offsets** (Sequence[int] | None) - Optional - How to reach the value from base_address. None (default) means direct handle; a sequence (including empty list) means the value sits at the end of a pointer chain. - **pytype** (Type) - Optional - How to interpret the bytes: bool, int, float, str, or bytes. Defaults to int. - **bufflength** (int) - Optional - Value size in bytes. Optional for numeric types (int→4, float→8, bool→1). For str/bytes it is required only to read; writing accepts None and stores the whole value, while a set bufflength caps the width (truncating). - **ptr_size** (int) - Optional - Pointer width used when walking offsets: 8 for 64-bit targets, 4 for 32-bit. Leave None to use the target's pointer_size, detected automatically. Ignored for direct handles. ``` -------------------------------- ### Build a snapshot for the refine loop Source: https://pymemoryeditor.readthedocs.io/en/latest/api/memory-region.html Create a MemoryRegionSnapshot and reuse it across multiple scans to skip region enumeration. ```python snapshot = process.snapshot_memory_regions() assert isinstance(snapshot, MemoryRegionSnapshot) # Reuse across many scans: for addr in process.search_by_value(int, value=100, memory_regions=snapshot): ... ``` -------------------------------- ### Register with Claude Code Source: https://pymemoryeditor.readthedocs.io/en/latest/mcp.html Add the PyMemoryEditor MCP server to Claude Code. ```bash claude mcp add pymemoryeditor -- pymemoryeditor-mcp ``` -------------------------------- ### Pointer arithmetic: add to get a new handle Source: https://pymemoryeditor.readthedocs.io/en/latest/guide/pointers.html Adding an integer to a RemotePointer returns a new handle pointing n bytes ahead, without touching memory. Here, Mana is stored right after HP, so stepping 4 bytes forward gives a handle to Mana. ```python # Mana is stored right after HP, so just step 4 bytes forward. mp_ptr = hp_ptr + 4 print(mp_ptr.value) ``` -------------------------------- ### Allocate memory and write an integer Source: https://pymemoryeditor.readthedocs.io/en/latest/guide/allocate-free.html Reserves 64 bytes in the target process and writes the integer 1337 to the returned address. The OS may round the size up to the page size. ```python with OpenProcess(name="game.exe") as process: address = process.allocate_memory(64) process.write_int(address, 1337) ``` -------------------------------- ### Combine ProcessOperationsEnum flags Source: https://pymemoryeditor.readthedocs.io/en/latest/api/enums.html Demonstrates how to combine Windows process access rights using the bitwise OR operator. ```python from PyMemoryEditor import ProcessOperationsEnum mask = ( ProcessOperationsEnum.PROCESS_VM_READ | ProcessOperationsEnum.PROCESS_QUERY_INFORMATION ) ``` -------------------------------- ### OpenProcess with sufficient permissions Source: https://pymemoryeditor.readthedocs.io/en/latest/troubleshooting.html Ensure the process is opened with the necessary permission mask, such as PROCESS_VM_OPERATION, to perform memory allocation. ```python from PyMemoryEditor import OpenProcess, ProcessOperationsEnum # Need PROCESS_VM_OPERATION for allocate_memory. with OpenProcess( name="game.exe", permission=ProcessOperationsEnum.PROCESS_VM_READ | ProcessOperationsEnum.PROCESS_VM_WRITE | ProcessOperationsEnum.PROCESS_VM_OPERATION | ProcessOperationsEnum.PROCESS_QUERY_INFORMATION, ) as process: address = process.allocate_memory(64) ``` -------------------------------- ### PointerPath.rebase(process) Source: https://pymemoryeditor.readthedocs.io/en/latest/api/pointer-path.html Returns a copy with base_address recomputed from the live module base in process, making a saved path valid again after ASLR. ```APIDOC ## PointerPath.rebase(process) ### Description Return a copy with `base_address` recomputed from the live module base in `process` — the call that makes a saved path valid again after a restart moved the module (ASLR). ### Method rebase ### Parameters - **process** (AbstractProcess) - Required - The open process. ### Returns - **PointerPath** - A new PointerPath with updated base_address. ### Raises - **ValueError** - If this path has no associated module (its base came from a caller-supplied static range), so it cannot be rebased. - **LookupError** - If the module is not loaded in `process`. ``` -------------------------------- ### Open process with full control permissions Source: https://pymemoryeditor.readthedocs.io/en/latest/guide/opening-process.html Opens a process with full control (`PROCESS_ALL_ACCESS`). The `permission` argument is Windows-only; on Linux and macOS it is ignored and emits a `UserWarning`. ```python OpenProcess( name="notepad.exe", permission=ProcessOperationsEnum.PROCESS_ALL_ACCESS, ) ``` -------------------------------- ### Save, restart, rescan pointer paths Source: https://pymemoryeditor.readthedocs.io/en/latest/guide/pointer-scan.html Two-run workflow: scan and save, then after restarting the target, rescan with the saved file and new address to keep only surviving paths. ```python # Run 1 — scan and save. pointer_paths = process.scan_pointer_paths(address) process.save_pointer_paths(pointer_paths, "scan.json") # ... close the target, restart it, find the value's new address again ... # Run 2 — keep only the saved paths that still reach it. survivors = process.rescan_pointer_paths("scan.json", new_address) process.save_pointer_paths(survivors, "scan.json") ``` -------------------------------- ### Read and write pointer values Source: https://pymemoryeditor.readthedocs.io/en/latest/api/remote-pointer.html Demonstrates reading from and writing to a RemotePointer instance. ```python hp_ptr.value # read hp_ptr.value = 9999 # write ``` -------------------------------- ### Import PyMemoryEditor.util helpers Source: https://pymemoryeditor.readthedocs.io/en/latest/api/utilities.html Imports the utility functions and constants from PyMemoryEditor.util for direct byte-level operations. ```python from PyMemoryEditor.util import ( resolve_bufflength, resolve_bufflength_for_value, convert_from_byte_array, value_to_bytes, values_to_bytes, get_c_type_of, compile_pattern, decode_scan_target, iter_region_chunks, make_predicate, scan_memory, scan_memory_for_exact_value, PatternLike, DEFAULT_MAX_REGION_CHUNK, NUMPY_AVAILABLE, ) ``` -------------------------------- ### Allocate memory on macOS with VM_PROT bitmask Source: https://pymemoryeditor.readthedocs.io/en/latest/guide/allocate-free.html Demonstrates allocating memory on macOS by passing a bitmask of VM_PROT constants. Note that requesting executable allocations may fail under the hardened runtime on Apple Silicon. ```python from PyMemoryEditor.macos.types import ( VM_PROT_READ, VM_PROT_WRITE, VM_PROT_EXECUTE, ) # read+write+execute (may fail under the hardened runtime). process.allocate_memory(4096, permission=VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE) ``` -------------------------------- ### Lint with make lint Source: https://pymemoryeditor.readthedocs.io/en/latest/contributing.html Runs flake8 on the PyMemoryEditor package and tests directory. ```bash make lint # flake8 PyMemoryEditor tests ``` -------------------------------- ### OpenProcess and scan for a value with PyMemoryEditor Source: https://pymemoryeditor.readthedocs.io/en/latest/why.html Opens a process by name and scans the entire process for every address holding the value 100, then reads and writes an integer at the found address. Uses the OpenProcess context manager and the search_by_value, read_int, and write_int methods. ```python from PyMemoryEditor import OpenProcess with OpenProcess(name="game.exe") as process: # Scan the whole process for every address holding the value 100. for address in process.search_by_value(int, value=100): print(f"Found at 0x{address:X}") # Read the current value, then write a new one back. current = process.read_int(address) process.write_int(address, current + 500) ``` -------------------------------- ### OpenProcess with partial, case-insensitive matching Source: https://pymemoryeditor.readthedocs.io/en/latest/api/openprocess.html Opens a process using a substring match that ignores case, which is particularly useful on Windows. ```python # Partial, case-insensitive name match (Windows-friendly) with OpenProcess(name="chrome", case_sensitive=False, exact_match=False) as process: ... ``` -------------------------------- ### Open process with read-only permissions Source: https://pymemoryeditor.readthedocs.io/en/latest/guide/opening-process.html Opens a process with a read-only handle, useful for static analysis. The `permission` argument is Windows-only; on Linux and macOS it is ignored and emits a `UserWarning`. ```python from PyMemoryEditor import OpenProcess, ProcessOperationsEnum OpenProcess( name="notepad.exe", permission=ProcessOperationsEnum.PROCESS_VM_READ | ProcessOperationsEnum.PROCESS_QUERY_INFORMATION, ) ``` -------------------------------- ### Open a process by name or PID Source: https://pymemoryeditor.readthedocs.io/en/latest/quickstart.html Use the OpenProcess entry point to target a process by its name or PID. ```python from PyMemoryEditor import OpenProcess # By process name process = OpenProcess(name="notepad.exe") # Or by PID process = OpenProcess(pid=1234) ``` -------------------------------- ### Typed Shortcuts (read_* / write_*) Source: https://pymemoryeditor.readthedocs.io/en/latest/api/openprocess.html Convenience methods for reading and writing specific data types with fixed sizes and signedness. Each read method has a corresponding write method. ```APIDOC ## Typed Shortcuts (read_* / write_*) ### Description Convenience read_* / write_* pairs with the size and signedness baked into the name. Widths are fixed and identical on every platform. ### Methods - **read_char(address)** - Read a signed 8-bit integer (1 byte). Pair: write_char(address, value). - **read_short(address)** - Read a signed 16-bit integer (2 bytes). Pair: write_short. - **read_int(address)** - Read a signed 32-bit integer (4 bytes). Pair: write_int. - **read_long(address)** - Read a signed 32-bit integer (4 bytes, Win32 LONG). Pair: write_long. - **read_longlong(address)** - Read a signed 64-bit integer (8 bytes). Pair: write_longlong. - **read_uchar(address)** - Read an unsigned 8-bit integer (1 byte). Pair: write_uchar. - **read_ushort(address)** - Read an unsigned 16-bit integer (2 bytes). Pair: write_ushort. - **read_uint(address)** - Read an unsigned 32-bit integer (4 bytes). Pair: write_uint. - **read_ulong(address)** - Read an unsigned 32-bit integer (4 bytes). Pair: write_ulong. - **read_ulonglong(address)** - Read an unsigned 64-bit integer (8 bytes). Pair: write_ulonglong. - **read_float(address)** - Read a 32-bit float (4 bytes). Pair: write_float. - **read_double(address)** - Read a 64-bit double (8 bytes). Pair: write_double. - **read_bool(address)** - Read a boolean (1 byte). Pair: write_bool. - **read_string(address, byte_count)** - Read exactly byte_count bytes, decode UTF-8, and return text up to the first NUL. Pair: write_string(address, text, *, null_terminator=False). - **read_bytes(address, length)** - Read length raw bytes. Pair: write_bytes(address, data). ``` -------------------------------- ### Register with MCP clients via JSON Source: https://pymemoryeditor.readthedocs.io/en/latest/mcp.html Configure the MCP server in the mcpServers JSON configuration for clients like Claude Desktop. ```json { "mcpServers": { "pymemoryeditor": { "command": "pymemoryeditor-mcp", "args": [] } } } ``` -------------------------------- ### Run the test suite with make test Source: https://pymemoryeditor.readthedocs.io/en/latest/contributing.html Runs the test suite using pytest. Tests read and write the memory of the test process itself and should run on any supported platform without elevated privileges. ```bash make test # pytest tests -v ``` -------------------------------- ### Import ThreadInfo Source: https://pymemoryeditor.readthedocs.io/en/latest/api/thread-info.html Import the ThreadInfo class from the PyMemoryEditor package. ```python from PyMemoryEditor import ThreadInfo ``` -------------------------------- ### Open process with default read+write permissions Source: https://pymemoryeditor.readthedocs.io/en/latest/guide/opening-process.html Opens a process with the default read+write permission mask on Windows. The `permission` argument maps directly to the `PROCESS_*` access rights of `OpenProcess`. On Linux and macOS, the argument is ignored and emits a `UserWarning`. ```python # Default — same as: OpenProcess( name="notepad.exe", permission=( ProcessOperationsEnum.PROCESS_VM_READ | ProcessOperationsEnum.PROCESS_VM_WRITE | ProcessOperationsEnum.PROCESS_VM_OPERATION | ProcessOperationsEnum.PROCESS_QUERY_INFORMATION ), ) ``` -------------------------------- ### PointerPath.recipe() Source: https://pymemoryeditor.readthedocs.io/en/latest/api/pointer-path.html Returns the ASLR-independent identity of the path: (module, module_offset, offsets). ```APIDOC ## PointerPath.recipe() ### Description The ASLR-independent identity of this path: `(module, module_offset, offsets)`. Two paths from different runs describe the _same_ pointer when their recipes are equal. ### Method recipe ### Returns - **tuple** - A tuple of (module, module_offset, offsets). ``` -------------------------------- ### Scan, rescan, and load pointer paths Source: https://pymemoryeditor.readthedocs.io/en/latest/quickstart.html Use pointer scanning to find paths that survive process restarts, save them to a file, and use them to access memory. ```python # 1. Scan — find pointer paths that resolve to the target address. with OpenProcess(name="game.exe") as process: # ... search for the address paths = list(process.scan_pointer_paths(target_address, max_depth=3)) process.save_pointer_paths(paths, "health.json") # ... restart the game, find the value's new address again .. # 2. Rescan — keep only paths that still resolve to the new address. with OpenProcess(name="game.exe") as process: # ... search for the new address again survivors = process.rescan_pointer_paths("health.json", new_target_address) process.save_pointer_paths(survivors, "health.json") # 3. Load — use the saved paths directly. with OpenProcess(name="game.exe") as process: paths = process.load_pointer_paths("health.json") pointer = paths[0].rebase(process).to_pointer(process) pointer.write(9999) ``` -------------------------------- ### Allocate memory on Windows with MemoryProtectionsEnum Source: https://pymemoryeditor.readthedocs.io/en/latest/guide/allocate-free.html Demonstrates allocating a read-only buffer on Windows by passing a MemoryProtectionsEnum value to the allocate_memory method. ```python from PyMemoryEditor import OpenProcess from PyMemoryEditor.win32.enums.memory_protections import MemoryProtectionsEnum with OpenProcess(name="game.exe") as process: # Allocate a read-only buffer. address = process.allocate_memory(64, permission=MemoryProtectionsEnum.PAGE_READONLY) ``` -------------------------------- ### Run pre-commit checks: lint, type-check, and tests Source: https://pymemoryeditor.readthedocs.io/en/latest/contributing.html Runs lint, type-check, and the test suite in one command. The CI pipeline runs the same checks and blocks merges on failure. ```bash make pre-commit # lint + type-check + test ``` -------------------------------- ### allocate_memory(size, *, permission=None) Source: https://pymemoryeditor.readthedocs.io/en/latest/guide/allocate-free.html Reserves a new memory region in the target process's address space and returns its base address. The size is rounded up to the OS page size. ```APIDOC ## allocate_memory(size, *, permission=None) ### Description Reserve and commit `size` bytes inside the target process's address space and return the base address of the new region. ### Method allocate_memory ### Parameters - **size** (int) - Required - Number of bytes to allocate (rounded up to the OS page size by the kernel). - **permission** (optional) - Optional - Platform-specific protection for the new region. ### Returns - The base address of the new region. ### Raises - **NotImplementedError** - On Linux. ### Example ```python with OpenProcess(name="game.exe") as process: address = process.allocate_memory(64) process.write_int(address, 1337) ``` ``` -------------------------------- ### Configure MCP server with absolute path Source: https://pymemoryeditor.readthedocs.io/en/latest/mcp.html Use the Python interpreter path if the console script is not found on the system PATH. ```json {"command": "/path/to/venv/bin/python", "args": ["-m", "PyMemoryEditor.mcp"]} ``` -------------------------------- ### Saving and reloading pointer paths Source: https://pymemoryeditor.readthedocs.io/en/latest/api/pointer-path.html Workflow to scan pointer paths, save them to a JSON file, then load and rebase them in a later run to resolve live addresses. ```python paths = list(process.scan_pointer_paths(address)) process.save_pointer_paths(paths, "pointers.json") # Later, in a different run: loaded = process.load_pointer_paths("pointers.json") for path in loaded: live = path.rebase(process) print(live.resolve(process)) ``` -------------------------------- ### PointerPath.to_pointer(process, *, pytype=int, bufflength=None) Source: https://pymemoryeditor.readthedocs.io/en/latest/api/pointer-path.html Builds a live RemotePointer for the value at the end of this path. ```APIDOC ## PointerPath.to_pointer(process, *, pytype=int, bufflength=None) ### Description Build a live `RemotePointer` for the value at the end of this path. ### Method to_pointer ### Parameters - **process** (AbstractProcess) - Required - The open process. - **pytype** (type) - Optional - The Python type to interpret the value as. Defaults to `int`. - **bufflength** (int) - Optional - The buffer length for the pointer. ### Returns - **RemotePointer** - A `RemotePointer` re-resolving on every access. ``` -------------------------------- ### Iterate memory regions with OpenProcess Source: https://pymemoryeditor.readthedocs.io/en/latest/api/memory-region.html Iterate over memory regions of a target process and print their address and size. ```python with OpenProcess(name="game.exe") as process: for region in process.get_memory_regions(): print(f"0x{region.address:016X} {region.size:>12,}") ``` -------------------------------- ### make_region(_address_, _size_, _struct_, _*_, _path='') Source: https://pymemoryeditor.readthedocs.io/en/latest/api/utilities.html Constructs a MemoryRegion from a platform descriptor, computing boolean flags and path. ```APIDOC ## make_region(_address_, _size_, _struct_, _*_, _path='') ### Description Builds a fully-populated MemoryRegion from a platform struct. The four boolean fields and path are computed once via the predicates. When path is non-empty it overrides the struct-based region_path() lookup. ### Parameters - **address** (int) - Required - The address of the region. - **size** (int) - Required - The size of the region. - **struct** (platform descriptor) - Required - A raw platform struct (e.g., MEMORY_BASIC_INFORMATION_32/64 on Windows, MEMORY_BASIC_INFORMATION on Linux, VM struct on macOS). - **path** (str) - Optional - Overrides the struct-based path lookup when non-empty. ### Returns - **MemoryRegion** - A fully-populated MemoryRegion object. ``` -------------------------------- ### Import ScanTypesEnum Source: https://pymemoryeditor.readthedocs.io/en/latest/api/enums.html Import the ScanTypesEnum class to use in memory search operations. ```python from PyMemoryEditor import ScanTypesEnum ``` -------------------------------- ### Refine-scan workflow with memory snapshots Source: https://pymemoryeditor.readthedocs.io/en/latest/guide/searching.html Enumerate memory regions once and reuse the snapshot across multiple scan calls to improve performance on large targets. ```python with OpenProcess(pid=1234) as process: regions = process.snapshot_memory_regions() # First pass — every address holding 100. candidates = list(process.search_by_value(int, value=100, memory_regions=regions)) # Refine — keep only those that now hold 95. refined = [ addr for addr, value in process.search_by_addresses(int, addresses=candidates, memory_regions=regions) if value == 95 ] ``` -------------------------------- ### OpenProcess by name Source: https://pymemoryeditor.readthedocs.io/en/latest/api/openprocess.html Opens a target process by its name. ```python # By name with OpenProcess(name="game.exe") as process: ... ``` -------------------------------- ### Iterate over loaded modules Source: https://pymemoryeditor.readthedocs.io/en/latest/guide/modules-threads.html Iterate through all modules loaded into a process and print their name, base address, size, and path. ```python with OpenProcess(name="game.exe") as process: for module in process.get_modules(): print( module.name, hex(module.base_address), module.size, module.path, ) ``` -------------------------------- ### Treat ResourceWarning as an error Source: https://pymemoryeditor.readthedocs.io/en/latest/guide/logging.html Configure the warnings module to treat ResourceWarning as an error to ensure macOS write-side-effect issues are not missed. ```python import warnings # Treat the warning as an error so you don't miss it. warnings.filterwarnings("error", category=ResourceWarning) ``` -------------------------------- ### Import ModuleInfo Source: https://pymemoryeditor.readthedocs.io/en/latest/api/module-info.html Import the ModuleInfo class from the PyMemoryEditor package. ```python from PyMemoryEditor import ModuleInfo ``` -------------------------------- ### get_pointer Source: https://pymemoryeditor.readthedocs.io/en/latest/api/openprocess.html Build a RemotePointer bound to this process — a live, re-resolving handle. ```APIDOC ## get_pointer ### Description Build a `RemotePointer` bound to this process — a live, re-resolving handle. ### Method get_pointer ### Parameters - **base_address** (int) - Required - The base address. - **offsets** (list) - Optional - List of offsets. - **pytype** (type) - Optional - Type of the pointed value, default is int. - **bufflength** (int) - Optional - Buffer length. - **ptr_size** (int) - Optional - Pointer size. ### Returns RemotePointer object. ``` -------------------------------- ### Open a process by name with OpenProcess Source: https://pymemoryeditor.readthedocs.io/en/latest/guide/opening-process.html Opens a process by name using the context manager, which automatically closes the handle on exit. The `with` block calls `process.close()` when leaving it, releasing any OS handle acquired by the backend. ```python from PyMemoryEditor import OpenProcess with OpenProcess(name="notepad.exe") as process: print("PID:", process.pid) ``` -------------------------------- ### Project layout: PyMemoryEditor directory structure Source: https://pymemoryeditor.readthedocs.io/en/latest/contributing.html Shows the top-level directory structure of the PyMemoryEditor package, including the public API, enums, platform-specific implementations, and the PySide6 demo app. ```text PyMemoryEditor/ ├── __init__.py # Public API + platform dispatch ├── enums.py # ScanTypesEnum (cross-platform) ├── process/ # Abstract base, errors, process info, util ├── util/ # Cross-platform helpers: scan and type conversion ├── win32/ # Windows implementation (kernel32, user32) ├── linux/ # Linux implementation (process_vm_readv/writev, /proc//maps) ├── macos/ # macOS implementation (task_for_pid, mach_vm_*) └── app/ # PySide6 (Qt) demo app exposed as `pymemoryeditor` CLI ``` -------------------------------- ### Read and write memory using typed shortcuts Source: https://pymemoryeditor.readthedocs.io/en/latest/quickstart.html Use typed methods like read_int and write_int to access memory values by address. ```python from PyMemoryEditor import OpenProcess with OpenProcess(name="notepad.exe") as process: address = 0x0005000C value = process.read_int(address) # read a 4-byte int print("Current:", value) process.write_int(address, value + 7) # write it back ``` -------------------------------- ### Compile patterns with standalone helper Source: https://pymemoryeditor.readthedocs.io/en/latest/guide/pattern-scan.html Uses the compile_pattern utility to test IDA-style signatures without a live process. ```python from PyMemoryEditor.util.pattern import compile_pattern regex, byte_length = compile_pattern("48 8B ? 00 00") print(repr(regex.pattern), byte_length) # b'H\x8b.\x00\x00' 5 ``` -------------------------------- ### OpenProcess with case-insensitive matching Source: https://pymemoryeditor.readthedocs.io/en/latest/troubleshooting.html Use exact_match=False and case_sensitive=False to find processes when the name match is ambiguous or case-sensitive issues occur. ```python OpenProcess(name="chrome", exact_match=False, case_sensitive=False) ``` -------------------------------- ### Perform a Cheat Engine style scan and refine workflow Source: https://pymemoryeditor.readthedocs.io/en/latest/quickstart.html Scan for an initial value, refine the results after the value changes in the target, and then perform read/write operations on the survivors. ```python with OpenProcess(name="game.exe") as process: # 1. First scan — every address currently holding 100. candidates = list(process.search_by_value(int, value=100)) # 3. After the value drops to 95 in-game, keep only the matches that agree. survivors = [ address for address, value in process.search_by_addresses(int, addresses=candidates) if value == 95 ] # 4. Overwrite the survivors back to a high value. for address in survivors: process.write_int(address, 9999) ``` -------------------------------- ### Perform a basic pointer scan Source: https://pymemoryeditor.readthedocs.io/en/latest/guide/pointer-scan.html Iterate through discovered PointerPath objects for a given dynamic address and resolve them to verify the current value. ```python # The value is at this address right now (e.g. from search_by_value). for path in process.scan_pointer_paths(0x1FA3C140): print(path) # "game.exe"+0x10F4F4 -> [+0x0] -> +0x158 print(hex(path.resolve(process))) ``` -------------------------------- ### get_modules Source: https://pymemoryeditor.readthedocs.io/en/latest/api/openprocess.html Yield a ModuleInfo for every loaded module. ```APIDOC ## get_modules ### Description Yield a `ModuleInfo` for every loaded module. ### Method get_modules ### Parameters None ### Returns Yields ModuleInfo objects. ``` -------------------------------- ### Import MemoryProtectionsEnum Source: https://pymemoryeditor.readthedocs.io/en/latest/api/enums.html Import the MemoryProtectionsEnum class to access Win32 page-protection constants. ```python from PyMemoryEditor.win32.enums.memory_protections import MemoryProtectionsEnum ``` -------------------------------- ### Print a complete memory map Source: https://pymemoryeditor.readthedocs.io/en/latest/guide/memory-regions.html A script to print a formatted textual memory map including address, size, permissions, and file path. ```python from PyMemoryEditor import OpenProcess with OpenProcess(name="game.exe") as process: print(f"{'ADDRESS':<18}{'SIZE':>14} RWX Source") for region in process.get_memory_regions(): rwx = "".join([ "R" if region.is_readable else "-", "W" if region.is_writable else "-", "X" if region.is_executable else "-", ]) print( f"0x{region.address:016X} " f"{region.size:>12,} {rwx} " f"{region.path or ''}" ) ``` -------------------------------- ### Track search progress Source: https://pymemoryeditor.readthedocs.io/en/latest/guide/searching.html Enables progress tracking by setting progress_information to True, which yields tuples containing the address and a progress dictionary. ```python for address, info in process.search_by_value(int, 4, target, progress_information=True): pct = info["progress"] * 100 print(f"0x{address:X} | {pct:5.1f}%") ``` -------------------------------- ### Load saved paths with load_pointer_paths Source: https://pymemoryeditor.readthedocs.io/en/latest/guide/pointer-scan.html Loads a refined scan file directly without rescanning, then rebases and writes to the first pointer. ```python paths = process.load_pointer_paths("scan.json") pointer = paths[0].rebase(process).to_pointer(process) pointer.write(9999) ```