Skip to main content

A Python library for memory manipulation in Windows

Project description

PyWin-Memr

GitHub License Build Status PyPI - Version PyPI - Python Version OS GitHub repo size

PyMym is a Python memory manipulation library that allows quick and easy memory manipulation using Python and C++ on Windows machines. While initially it was created to allow a Gymnasium environment to directly access state information from a process, it slowly became a full-fledged library with memory scanning and manipulation features, including a lightweight process wrapper for accessing memory in a Pythonic way.

Table of Contents


Features

  • C++ Core Performance: Native execution for memory-intensive operations, bypassing the overhead of traditional Python wrappers.
  • Pattern Matching: High-speed Array of Bytes scanning to find stable hooks in frequently updating applications.
  • Zero-Config Installation: Pre-compiled binary wheels for Windows mean no local compiler is required for most users.
  • Flexibility: Simple Pythonic process wrapping for seamless memory manipulation or stand-alone memory manipulation without needing to use a class

How to Use

Memory Scanning

import PyMym as pm

name = "some_application.exe"
pid = pm.get_pid(name)

# different pattern types for convenience
hex_pattern = "AA 00 AB AC 00 FF FF"
string_pattern = "Hello, world!"
list_pattern = pattern = [0x00, 0xAA, 0xAB, 0x00, 0xFF, 0xB3]
hex_mask = "x?xx?xx"
list_mask = "?xx?xx"

# pid or application_name can be used
address = pm.heap_aob_scan(
    pid=pid,
    pattern=hex_pattern,
    mask=hex_mask,
    hex_string=True
)

# masks are optional
address = pm.stack_aob_scan(
    application_name=name,
    pattern=string_pattern
)

mods = pm.get_modules(application_name=name)
address = pm.module_aob_scan(
    pid=pid,
    module_name=mods[0],
    pattern=list_pattern,
    mask=list_mask
)

Memory Reading and Manipulation

PyMym offers reading and writing functions that align with C data types using the ctypes library, the current supported types are listed below with their respective functions.

Data Type Read Function Write Function C++ Equivalent
Bytes read_bytes write_bytes unsigned char[]
Short read_short write_short short
Unsigned Short read_ushort write_ushort unsigned short
Int read_int write_int int
Unsigned Int read_uint write_uint unsigned int
Long read_long write_long long
Unsigned Long read_ulong write_ulong unsigned long
Long Long read_longlong write_longlong long long
Unsigned Long Long read_ulonglong write_ulonglong unsigned long long
Float read_float write_float float
Double read_double write_double double

Examples

import PyMym as pm

## READING EXAMPLES
# All the following can be used with pid= or application_name=
name = "some_application.exe"
pid = pm.get_pid(name)
mem_addr = 0xFF00 # Example address

# Read functions can return singular values
byte_val = pm.read_bytes(application_name=name, memory_address=mem_addr)
short_val = pm.read_short(application_name=name, memory_address=mem_addr)

# Read functions can take an optional n parameter to return a list of n items
byte_list = pm.read_bytes(pid=pid, memory_address=mem_addr, n=16)
short_list = pm.read_short(pid=pid, memory_address=mem_addr, n=5)

## WRITING EXAMPLES
btw = "AF BE 3D DD"
# write_bytes returns True if all bytes were written, False otherwise
if not pm.write_bytes(pid=pid, memory_address=mem_addr, val=btw, hex_string=True):
    return -1

# write_bytes can take same types as the searches can
btw = "Hello, world!"
pm.write_bytes(application_name=name, memory_address=mem_addr, val=btw)

# Optional n parameter will fill extra unwritten bytes with 0x00
# So n - len(btw) bytes will be 0x00
pm.write_bytes(application_name=name, memory_address=mem_addr, val=btw, n=16)

# All write functions can take lists as well as singular values
pm.write_short(pid=pid, memory_address=mem_addr, val=[125, 126, 127])
# All write functions have the optional parameter n
# Which will write n - len(val) 0s to memory, matching the data type used
pm.write_short(pid=pid, memory_address=mem_addr, val=155, n=2)

Packing and Unpacking of Data

PyMym has functions for packing and unpacking data types into bytes and vice versa, with the same data type support as the read and write functions.

import PyMym as pm
import ctypes

# values can be packed into bytes for use with search functions
name = "some_application.exe"
pid = pm.get_pid(name)

val = 101
pval = pm.pack_int(val=val)

addr = pm.heap_aob_scan(pid=pid, pattern=pval)
# read functions will automatically unpack for you
ri = pm.read_int(application_name=name, memory_address=addr)
# but read bytes can be used instead to keep values as bytes
rb = pm.read_bytes(
    application_name=name,
    memory_address=addr,
    n=ctypes.sizeof(ctypes.c_int)
)

ui = pm.unpack_int(rb)

Pythonic Process Wrapping

The ProcessWrapper class contains methods that allow for scanning and memory manipulation, like the stand-alone functions did, and allows for shorter argument lists. Besides the original read and write methods, there is also indexing and slicing specific data types to allow Pythonic access to memory.

Data Type Accessor C++ Equivalent
Bytes pw[start:end] unsigned char[]
Short pw.short[start:end] short
Unsigned Short pw.ushort[start:end] unsigned short
Int pw.int[start:end] int
Unsigned Int pw.uint[start:end] unsigned int
Long pw.long[start:end] long
Unsigned Long pw.ulong[start:end] unsigned long
Long Long pw.longlong[start:end] long long
Unsigned Long Long pw.ulonglong[start:end] unsigned long long
Float pw.float[start:end] float
Double pw.double[start:end] double
import PyMym as pm

name = "some_application.exe"
pid = pm.get_pid(name)

# We can use pid=pid or application_name=name here
with ProcessWrapper(application_name=name) as pw:
    addr = pw.heap_aob_scan(pattern=pval)
    rb = pw.read_bytes(memory_address=addr, n=16)

    # Alternative, quick and Pythonic
    rb = pw[addr: addr + 16]

    # The same goes for other data types
    # Here we read 2 integers
    ri = pw.read_int(memory_address=addr, n=2)
    ri = pw.int[addr: addr + 2]

    # We can also write in a similar fashion
    pw.int[addr] = 500
    # Same goes for multiple values at once
    # Here we are writing 4 integers
    pw.int[addr: addr + 4] = [400, 500, 200, 100]

    # We can retrieve basic information about the process
    pid = pw.get_pid()
    name = pw.get_application_name()
    modules = pw.get_modules()
    endian = pw.get_endian()

    # We can also change the way we interpret the values
    if endian == "little":
        pw.set_endian(new_endian="big")
    else:
        pw.set_endian(new_endian="little")

Roadmap

  • Refactoring of backend C++ code
  • Wide character and UTF-16 support
  • Get addresses of specific modules
  • Get main thread ID as well as a list of thread IDs
  • More data types, char, uchar, int32, int16, etc.
  • Stronger exception and error handling
  • ProcessWrapper.get_base_module and .get_address
  • Stronger testing for dev branch
  • Searching for list of instances rather than the first instance
  • Strict and loose name search for modules and processes

Contribution

Feel free to suggest improvements or report issues in the repository.

License

This project is open-source and available under the MIT License.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

pymym-1.0.2-cp314-cp314-win_amd64.whl (148.1 kB view details)

Uploaded CPython 3.14Windows x86-64

pymym-1.0.2-cp313-cp313-win_amd64.whl (146.9 kB view details)

Uploaded CPython 3.13Windows x86-64

pymym-1.0.2-cp312-cp312-win_amd64.whl (146.8 kB view details)

Uploaded CPython 3.12Windows x86-64

pymym-1.0.2-cp311-cp311-win_amd64.whl (146.2 kB view details)

Uploaded CPython 3.11Windows x86-64

pymym-1.0.2-cp310-cp310-win_amd64.whl (145.2 kB view details)

Uploaded CPython 3.10Windows x86-64

File details

Details for the file pymym-1.0.2-cp314-cp314-win_amd64.whl.

File metadata

  • Download URL: pymym-1.0.2-cp314-cp314-win_amd64.whl
  • Upload date:
  • Size: 148.1 kB
  • Tags: CPython 3.14, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pymym-1.0.2-cp314-cp314-win_amd64.whl
Algorithm Hash digest
SHA256 d7c0c87ad98f3cdcf001145e48ded19d84055fe38219f47d261c7c0c385ffe74
MD5 069cc3ba056c897f95757843cd36fb19
BLAKE2b-256 6b952d90a68e76f3f15ec7cf682ec1bcd8e7f70edd6d821bbc484209325f755b

See more details on using hashes here.

File details

Details for the file pymym-1.0.2-cp313-cp313-win_amd64.whl.

File metadata

  • Download URL: pymym-1.0.2-cp313-cp313-win_amd64.whl
  • Upload date:
  • Size: 146.9 kB
  • Tags: CPython 3.13, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pymym-1.0.2-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 8fe8b7ce52c45009a0c2bb48a7ce59aaa4989146c7f2796932b3719a6dc881be
MD5 3d506baf6744f02b3fbe0430e96487b8
BLAKE2b-256 e5da3a164d32e1fe75c04f4015b06b68bd72ee140ad70defc8c55772c3183d00

See more details on using hashes here.

File details

Details for the file pymym-1.0.2-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: pymym-1.0.2-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 146.8 kB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pymym-1.0.2-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 4eda00ad8374bb9895fedd377ecbb3d978e28c63e864a5e3020fad921f5796e5
MD5 638c7c6365f3cc2de9b71b3812bb6b84
BLAKE2b-256 e3607eba06700f13be65ad892219645b3572aa165ff840cb3c0b9d94790a6422

See more details on using hashes here.

File details

Details for the file pymym-1.0.2-cp311-cp311-win_amd64.whl.

File metadata

  • Download URL: pymym-1.0.2-cp311-cp311-win_amd64.whl
  • Upload date:
  • Size: 146.2 kB
  • Tags: CPython 3.11, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pymym-1.0.2-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 2a31e0525ba95508d19e56cfb83abc978d44ecaedf8032a82d1efbeefd9a4adf
MD5 1065bf7f217b641ef2058fc59604ff4a
BLAKE2b-256 26cc2deefe25893c5d01ff4c67c979219c79a394b140ae9c9dfb8a01a2e2c9e8

See more details on using hashes here.

File details

Details for the file pymym-1.0.2-cp310-cp310-win_amd64.whl.

File metadata

  • Download URL: pymym-1.0.2-cp310-cp310-win_amd64.whl
  • Upload date:
  • Size: 145.2 kB
  • Tags: CPython 3.10, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pymym-1.0.2-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 5acd82e368a7ded5d6411e87a31d0be065711a09c9a23c3cd265cb1933b7fa6d
MD5 9a3b7cfc54eca93c6ce314be67989a82
BLAKE2b-256 cf2106997c9ca8408270b5c49ad074f1e3942b44093c28bcc68b9badc88bf538

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page