From c35fcb0118213ad18a4daa4351c660bdaab0b0b4 Mon Sep 17 00:00:00 2001 From: Nicholas Brochu Date: Wed, 29 Nov 2023 14:14:37 -0500 Subject: [PATCH] no need to vendor pymem if we are targeting official repo inclusion --- .../game_state_manager.py | 4 +- worlds/zork_grand_inquisitor/requirements.txt | 1 + .../zork_grand_inquisitor/vendor/__init__.py | 0 .../vendor/pymem/LICENSE | 21 - .../vendor/pymem/__init__.py | 1434 ----------------- .../vendor/pymem/exception.py | 58 - .../vendor/pymem/memory.py | 1120 ------------- .../vendor/pymem/pattern.py | 178 -- .../vendor/pymem/process.py | 450 ------ .../vendor/pymem/ptypes.py | 112 -- .../vendor/pymem/ressources/__init__.py | 29 - .../vendor/pymem/ressources/advapi32.py | 65 - .../vendor/pymem/ressources/kernel32.py | 290 ---- .../vendor/pymem/ressources/ntdll.py | 26 - .../vendor/pymem/ressources/psapi.py | 36 - .../vendor/pymem/ressources/structure.py | 624 ------- .../vendor/pymem/thread.py | 58 - 17 files changed, 3 insertions(+), 4503 deletions(-) create mode 100644 worlds/zork_grand_inquisitor/requirements.txt delete mode 100644 worlds/zork_grand_inquisitor/vendor/__init__.py delete mode 100644 worlds/zork_grand_inquisitor/vendor/pymem/LICENSE delete mode 100644 worlds/zork_grand_inquisitor/vendor/pymem/__init__.py delete mode 100644 worlds/zork_grand_inquisitor/vendor/pymem/exception.py delete mode 100644 worlds/zork_grand_inquisitor/vendor/pymem/memory.py delete mode 100644 worlds/zork_grand_inquisitor/vendor/pymem/pattern.py delete mode 100644 worlds/zork_grand_inquisitor/vendor/pymem/process.py delete mode 100644 worlds/zork_grand_inquisitor/vendor/pymem/ptypes.py delete mode 100644 worlds/zork_grand_inquisitor/vendor/pymem/ressources/__init__.py delete mode 100644 worlds/zork_grand_inquisitor/vendor/pymem/ressources/advapi32.py delete mode 100644 worlds/zork_grand_inquisitor/vendor/pymem/ressources/kernel32.py delete mode 100644 worlds/zork_grand_inquisitor/vendor/pymem/ressources/ntdll.py delete mode 100644 worlds/zork_grand_inquisitor/vendor/pymem/ressources/psapi.py delete mode 100644 worlds/zork_grand_inquisitor/vendor/pymem/ressources/structure.py delete mode 100644 worlds/zork_grand_inquisitor/vendor/pymem/thread.py diff --git a/worlds/zork_grand_inquisitor/game_state_manager.py b/worlds/zork_grand_inquisitor/game_state_manager.py index d2252f26b64b..6aaeeceeedeb 100644 --- a/worlds/zork_grand_inquisitor/game_state_manager.py +++ b/worlds/zork_grand_inquisitor/game_state_manager.py @@ -1,5 +1,5 @@ -from .vendor.pymem import Pymem -from .vendor.pymem.process import close_handle +from pymem import Pymem +from pymem.process import close_handle class GameStateManager: diff --git a/worlds/zork_grand_inquisitor/requirements.txt b/worlds/zork_grand_inquisitor/requirements.txt new file mode 100644 index 000000000000..fe25267f6705 --- /dev/null +++ b/worlds/zork_grand_inquisitor/requirements.txt @@ -0,0 +1 @@ +Pymem>=1.13.0 \ No newline at end of file diff --git a/worlds/zork_grand_inquisitor/vendor/__init__.py b/worlds/zork_grand_inquisitor/vendor/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/worlds/zork_grand_inquisitor/vendor/pymem/LICENSE b/worlds/zork_grand_inquisitor/vendor/pymem/LICENSE deleted file mode 100644 index e25e3a766297..000000000000 --- a/worlds/zork_grand_inquisitor/vendor/pymem/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2020 pymem - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file diff --git a/worlds/zork_grand_inquisitor/vendor/pymem/__init__.py b/worlds/zork_grand_inquisitor/vendor/pymem/__init__.py deleted file mode 100644 index 06f8255b0fc7..000000000000 --- a/worlds/zork_grand_inquisitor/vendor/pymem/__init__.py +++ /dev/null @@ -1,1434 +0,0 @@ -import ctypes -import ctypes.util -import functools -import logging -import platform -import struct -import sys -import typing - -import pymem.exception -import pymem.memory -import pymem.process -import pymem.ressources.kernel32 -import pymem.ressources.structure -import pymem.ressources.psapi -import pymem.thread -import pymem.pattern - - -# Configure pymem's handler to the lowest level possible so everything is cached and could be later displayed -logger = logging.getLogger(__name__) -logger.setLevel(logging.DEBUG) -logger.addHandler(logging.NullHandler()) - - -class Pymem(object): - """Initialize the Pymem class. - If process_name is given, will open the process and retrieve a handle over it. - - Parameters - ---------- - process_name: - The name or process id of the process to be opened - exact_match: - Defaults to False, is the full name match or just part of it expected? - ignore_case: - Default to True, should ignore process name case? - """ - - def __init__( - self, - process_name: typing.Union[str, int] = None, - exact_match: bool = False, - ignore_case: bool = True, - ): - self.process_id = None - self.process_handle = None - self.thread_handle = None - self.is_WoW64 = None - self.py_run_simple_string = None - self._python_injected = None - - if process_name is not None: - if isinstance(process_name, str): - self.open_process_from_name(process_name, exact_match, ignore_case) - elif isinstance(process_name, int): - self.open_process_from_id(process_name) - else: - raise TypeError( - f"process_name must be of type int or string not {type(process_name).__name__}" - ) - - self.check_wow64() - - def check_wow64(self): - """Check if a process is running under WoW64. - """ - self.is_WoW64 = pymem.process.is_64_bit(self.process_handle) - - def list_modules(self): - """List a process loaded modules. - - Returns - ------- - list(MODULEINFO) - List of process loaded modules - """ - modules = pymem.process.enum_process_module(self.process_handle) - return modules - - def resolve_offsets(self, base_offset, offsets): - """Resolves a list of pointers; commonly one from cheat engine - - Args: - base_offset (int): The base address offset - offsets (list[int]): List of offsets - """ - if self.is_WoW64: - read_method = self.read_ulonglong - else: - read_method = self.read_uint - - addr = read_method(self.base_address + base_offset) - for offset in offsets[:-1]: - addr = read_method(addr + offset) - - return addr + offsets[-1] - - def inject_python_interpreter(self, initsigs=1): - """Inject python interpreter into target process and call Py_InitializeEx. - """ - - def find_existing_interpreter(_python_version): - _local_handle = pymem.ressources.kernel32.GetModuleHandleW(_python_version) - module = pymem.process.module_from_name(self.process_handle, _python_version) - - self.py_run_simple_string = ( - module.lpBaseOfDll + ( - pymem.ressources.kernel32.GetProcAddress(_local_handle, b'PyRun_SimpleString') - _local_handle - ) - ) - self._python_injected = True - pymem.logger.debug('PyRun_SimpleString loc: 0x%08x' % self.py_run_simple_string) - return module.lpBaseOfDll - - if self._python_injected: - return - - # find the python library - python_version = "python{0}{1}.dll".format(sys.version_info.major, sys.version_info.minor) - python_lib = pymem.process.get_python_dll(python_version) - if not python_lib: - raise pymem.exception.PymemError('Could not find python library') - - # Find or inject python module - python_module = pymem.process.module_from_name(self.process_handle, python_version) - if python_module: - python_lib_h = find_existing_interpreter(python_version) - else: - python_lib_h = pymem.process.inject_dll(self.process_handle, bytes(python_lib, 'ascii')) - if not python_lib_h: - raise pymem.exception.PymemError('Inject dll failed') - - local_handle = pymem.ressources.kernel32.GetModuleHandleW(python_version) - py_initialize_ex = ( - python_lib_h + ( - pymem.ressources.kernel32.GetProcAddress(local_handle, b'Py_InitializeEx') - local_handle - ) - ) - self.py_run_simple_string = ( - python_lib_h + ( - pymem.ressources.kernel32.GetProcAddress(local_handle, b'PyRun_SimpleString') - local_handle - ) - ) - if not py_initialize_ex: - raise pymem.exception.PymemError('Empty py_initialize_ex') - if not self.py_run_simple_string: - raise pymem.exception.PymemError('Empty py_run_simple_string') - - param_addr = self.allocate(4) - self.write_int(param_addr, initsigs) - self.start_thread(py_initialize_ex, param_addr) - self._python_injected = True - - pymem.logger.debug('Py_InitializeEx loc: 0x%08x' % py_initialize_ex) - pymem.logger.debug('PyRun_SimpleString loc: 0x%08x' % self.py_run_simple_string) - - def inject_python_shellcode(self, shellcode): - """Inject a python shellcode into memory and execute it. - - Parameters - ---------- - shellcode: str - A string with python instructions. - """ - shellcode = shellcode.encode('ascii') - shellcode_addr = pymem.ressources.kernel32.VirtualAllocEx( - self.process_handle, - None, - len(shellcode), - pymem.ressources.structure.MEMORY_STATE.MEM_COMMIT.value | pymem.ressources.structure.MEMORY_STATE.MEM_RESERVE.value, - pymem.ressources.structure.MEMORY_PROTECTION.PAGE_EXECUTE_READWRITE.value - ) - if not shellcode_addr or ctypes.get_last_error(): - raise RuntimeError('Could not allocate memory for shellcode') - pymem.logger.debug('shellcode_addr loc: 0x%08x' % shellcode_addr) - written = ctypes.c_ulonglong(0) if '64bit' in platform.architecture() else ctypes.c_ulong(0) - pymem.ressources.kernel32.WriteProcessMemory( - self.process_handle, - shellcode_addr, - shellcode, - len(shellcode), - ctypes.byref(written) - ) - # check written - self.start_thread(self.py_run_simple_string, shellcode_addr) - - def start_thread(self, address, params=None): - """Create a new thread within the current debugged process. - - Parameters - ---------- - address: int - An address from where the thread starts - params: int - An optional address with thread parameters - - Returns - ------- - int - The new thread identifier - """ - - params = params or 0 - NULL_SECURITY_ATTRIBUTES = ctypes.cast(0, pymem.ressources.structure.LPSECURITY_ATTRIBUTES) - thread_h = pymem.ressources.kernel32.CreateRemoteThread( - self.process_handle, - NULL_SECURITY_ATTRIBUTES, - 0, - address, - params, - 0, - ctypes.byref(ctypes.c_ulong(0)) - ) - last_error = ctypes.windll.kernel32.GetLastError() - if last_error: - pymem.logger.warning('Got an error in start thread, code: %s' % last_error) - pymem.ressources.kernel32.WaitForSingleObject(thread_h, -1) - pymem.logger.debug('New thread_id: 0x%08x' % thread_h) - return thread_h - - def open_process_from_name( - self, - process_name: str, - exact_match: bool = False, - ignore_case: bool = True, - ): - """Open process given its name and stores the handle into process_handle - - Parameters - ---------- - process_name: - The name of the process to be opened - exact_match: - Defaults to False, is the full name match or just part of it expected? - ignore_case: - Default to True, should ignore process name case? - - Raises - ------ - TypeError - If process name is not valid or search parameters are of the wrong type - ProcessNotFound - If process name is not found - CouldNotOpenProcess - If process cannot be opened - """ - - if not process_name or not isinstance(process_name, str): - raise TypeError('Invalid argument: {}'.format(process_name)) - - if not isinstance(exact_match, bool): - raise TypeError('Invalid argument: {}'.format(exact_match)) - - if not isinstance(ignore_case, bool): - raise TypeError('Invalid argument: {}'.format(ignore_case)) - - process32 = pymem.process.process_from_name( - process_name, - exact_match, - ignore_case, - ) - - if not process32: - raise pymem.exception.ProcessNotFound(process_name) - self.process_id = process32.th32ProcessID - self.open_process_from_id(self.process_id) - - def open_process_from_id(self, process_id): - """Open process given its name and stores the handle into `self.process_handle`. - - Parameters - ---------- - process_id: int - The unique process identifier - - Raises - ------ - TypeError - If process identifier is not an integer - CouldNotOpenProcess - If process cannot be opened - """ - if not process_id or not isinstance(process_id, int): - raise TypeError('Invalid argument: {}'.format(process_id)) - self.process_id = process_id - self.process_handle = pymem.process.open(self.process_id) - if not self.process_handle: - raise pymem.exception.CouldNotOpenProcess(self.process_id) - pymem.logger.debug('Process {} is being debugged'.format( - process_id - )) - - def close_process(self): - """Close the current opened process - - Raises - ------ - ProcessError - If there is no process opened - """ - if not self.process_handle: - raise pymem.exception.ProcessError('You must open a process before calling this method') - pymem.process.close_handle(self.process_handle) - self.process_handle = None - self.process_id = None - self.is_WoW64 = None - self.py_run_simple_string = None - self._python_injected = None - if self.thread_handle: - pymem.process.close_handle(self.thread_handle) - - def allocate(self, size): - """Allocate memory into the current opened process. - - Parameters - ---------- - size: int - The size of the region of memory to allocate, in bytes. - - Raises - ------ - ProcessError - If there is no process opened - TypeError - If size is not an integer - - Returns - ------- - int - The base address of the current process. - """ - if not size or not isinstance(size, int): - raise TypeError('Invalid argument: {}'.format(size)) - if not self.process_handle: - raise pymem.exception.ProcessError('You must open a process before calling this method') - address = pymem.memory.allocate_memory(self.process_handle, size) - return address - - def free(self, address): - """Free memory from the current opened process given an address. - - Parameters - ---------- - address: int - An address of the region of memory to be freed. - - Raises - ------ - ProcessError - If there is no process opened - TypeError - If address is not an integer - """ - if not address or not isinstance(address, int): - raise TypeError('Invalid argument: {}'.format(address)) - if not self.process_handle: - raise pymem.exception.ProcessError('You must open a process before calling this method') - return pymem.memory.free_memory(self.process_handle, address) - - def pattern_scan_all(self, pattern, *, return_multiple=False): - """Scan the entire address space of this process for a regex pattern - - Parameters - ---------- - pattern: bytes - The regex pattern to search for - return_multiple: bool - If multiple results should be returned - - Returns - ------- - int, list, optional - Memory address of given pattern, or None if one was not found - or a list of found addresses in return_multiple is True - """ - return pymem.pattern.pattern_scan_all(self.process_handle, pattern, return_multiple=return_multiple) - - def pattern_scan_module(self, pattern, module, *, return_multiple=False): - """Scan a module for a regex pattern - - Parameters - ---------- - pattern: bytes - The regex pattern to search for - module: str, MODULEINFO - Name of the module to search for, or a MODULEINFO object - return_multiple: bool - If multiple results should be returned - - Returns - ------- - int, list, optional - Memory address of given pattern, or None if one was not found - or a list of found addresses in return_multiple is True - """ - if isinstance(module, str): - module = pymem.process.module_from_name(self.process_handle, module) - - return pymem.pattern.pattern_scan_module( - self.process_handle, - module, - pattern, - return_multiple=return_multiple - ) - - @property - def process_base(self): - """Lookup process base Module. - - Raises - ------ - TypeError - process_id is not an integer - ProcessError - Could not find process first module address - - Returns - ------- - MODULEINFO - Base module information - """ - if not self.process_id: - raise TypeError('You must open a process before calling this property') - base_module = pymem.process.base_module(self.process_handle) - if not base_module: - raise pymem.exception.ProcessError("Could not find process first module") - return base_module - - @property - def base_address(self): - """Gets the memory address where the main module was loaded (ie address of exe file in memory) - - Raises - ------ - TypeError - If process_id is not an integer - ProcessError - Could not find process first module address - - Returns - ------- - int - Address of main module - """ - return self.process_base.lpBaseOfDll - - @property - @functools.lru_cache(maxsize=1) - def main_thread(self): - """Retrieve ThreadEntry32 of main thread given its creation time. - - Raises - ------ - ProcessError - If there is no process opened or could not list process thread - - Returns - ------- - Thread - Process main thread - """ - if not self.process_id: - raise pymem.exception.ProcessError('You must open a process before calling this method') - threads = pymem.process.enum_process_thread(self.process_id) - threads = sorted(threads, key=lambda k: k.creation_time) - - if not threads: - raise pymem.exception.ProcessError('Could not list process thread') - - main_thread = threads[0] - main_thread = pymem.thread.Thread(self.process_handle, main_thread) - return main_thread - - @property - @functools.lru_cache(maxsize=1) - def main_thread_id(self): - """Retrieve th32ThreadID from main thread - - Raises - ------ - ProcessError - If there is no process opened or could not list process thread - - Returns - ------- - int - Main thread identifier - """ - if not self.process_id: - raise pymem.exception.ProcessError('You must open a process before calling this method') - return self.main_thread.thread_id - - def read_bytes(self, address, length): - """Reads bytes from an area of memory in a specified process. - - Parameters - ---------- - address: int - An address of the region of memory to be read. - length: int - Number of bytes to be read - - Raises - ------ - ProcessError - If there is no opened process - MemoryReadError - If ReadProcessMemory failed - - Returns - ------- - bytes - the raw value read - """ - if not self.process_handle: - raise pymem.exception.ProcessError('You must open a process before calling this method') - try: - value = pymem.memory.read_bytes(self.process_handle, address, length) - except pymem.exception.WinAPIError as e: - raise pymem.exception.MemoryReadError(address, length, e.error_code) - return value - - def read_ctype(self, address, ctype, *, get_py_value=True, raw_bytes=False): - """ - Read a ctype basic type or structure from
- - Parameters - ---------- - address: int - An address of the region of memory to be read. - ctype: - A simple ctypes type or structure - get_py_value: bool - If the corrosponding python type should be used instead of returning the ctype - This is automatically set to False for ctypes.Structure or ctypes.Array instances - raw_bytes: bool - If we should return the raw ctype bytes - - Raises - ------ - WinAPIError - If ReadProcessMemory failed - - Returns - ------- - Any - Return will be either the ctype with the read value if get_py_value is false or - the corropsonding python type - """ - if not self.process_handle: - raise pymem.exception.ProcessError('You must open a process before calling this method') - try: - value = pymem.memory.read_ctype(self.process_handle, address, ctype, get_py_value=get_py_value, raw_bytes=raw_bytes) - except pymem.exception.WinAPIError as e: - raise pymem.exception.MemoryReadError(address, ctypes.sizeof(ctype), e.error_code) - return value - - def read_bool(self, address): - """Reads 1 byte from an area of memory in a specified process. - - Parameters - ---------- - address: int - An address of the region of memory to be read. - - Raises - ------ - ProcessError - If there is no opened process - MemoryReadError - If ReadProcessMemory failed - TypeError - If address is not a valid integer - - Returns - ------- - bool - returns the value read - """ - if not self.process_handle: - raise pymem.exception.ProcessError('You must open a process before calling this method') - try: - value = pymem.memory.read_bool(self.process_handle, address) - except pymem.exception.WinAPIError as e: - raise pymem.exception.MemoryReadError(address, struct.calcsize('?'), e.error_code) - return value - - def read_char(self, address): - """Reads 1 byte from an area of memory in a specified process. - - Parameters - ---------- - address: int - An address of the region of memory to be read. - - Raises - ------ - ProcessError - If there is no opened process - MemoryReadError - If ReadProcessMemory failed - TypeError - If address is not a valid integer - - Returns - ------- - str - returns the value read - """ - if not self.process_handle: - raise pymem.exception.ProcessError('You must open a process before calling this method') - try: - value = pymem.memory.read_char(self.process_handle, address) - except pymem.exception.WinAPIError as e: - raise pymem.exception.MemoryReadError(address, struct.calcsize('b'), e.error_code) - return value - - def read_uchar(self, address): - """Reads 1 byte from an area of memory in a specified process. - - Parameters - ---------- - address: int - An address of the region of memory to be read. - - Raises - ------ - ProcessError - If there is no opened process - MemoryReadError - If ReadProcessMemory failed - TypeError - If address is not a valid integer - - Returns - ------- - str - returns the value read - """ - if not self.process_handle: - raise pymem.exception.ProcessError('You must open a process before calling this method') - try: - value = pymem.memory.read_uchar(self.process_handle, address) - except pymem.exception.WinAPIError as e: - raise pymem.exception.MemoryReadError(address, struct.calcsize('B'), e.error_code) - return value - - def read_int(self, address): - """Reads 4 byte from an area of memory in a specified process. - - Parameters - ---------- - address: int - An address of the region of memory to be read. - - Raises - ------ - ProcessError - If there is no opened process - MemoryReadError - If ReadProcessMemory failed - TypeError - If address is not a valid integer - - Returns - ------- - int - returns the value read - """ - if not self.process_handle: - raise pymem.exception.ProcessError('You must open a process before calling this method') - try: - value = pymem.memory.read_int(self.process_handle, address) - except pymem.exception.WinAPIError as e: - raise pymem.exception.MemoryReadError(address, struct.calcsize('i'), e.error_code) - return value - - def read_uint(self, address): - """Reads 4 byte from an area of memory in a specified process. - - Parameters - ---------- - address: int - An address of the region of memory to be read. - - Raises - ------ - ProcessError - If there is no opened process - MemoryReadError - If ReadProcessMemory failed - TypeError - If address is not a valid integer - - Returns - ------- - int - returns the value read - """ - if not self.process_handle: - raise pymem.exception.ProcessError('You must open a process before calling this method') - try: - value = pymem.memory.read_uint(self.process_handle, address) - except pymem.exception.WinAPIError as e: - raise pymem.exception.MemoryReadError(address, struct.calcsize('I'), e.error_code) - return value - - def read_short(self, address): - """Reads 2 byte from an area of memory in a specified process. - - Parameters - ---------- - address: int - An address of the region of memory to be read. - - Raises - ------ - ProcessError - If there is no opened process - MemoryReadError - If ReadProcessMemory failed - TypeError - If address is not a valid integer - - Returns - ------- - int - returns the value read - """ - if not self.process_handle: - raise pymem.exception.ProcessError('You must open a process before calling this method') - try: - value = pymem.memory.read_short(self.process_handle, address) - except pymem.exception.WinAPIError as e: - raise pymem.exception.MemoryReadError(address, struct.calcsize('h'), e.error_code) - return value - - def read_ushort(self, address): - """Reads 2 byte from an area of memory in a specified process. - - Parameters - ---------- - address: int - An address of the region of memory to be read. - - Raises - ------ - ProcessError - If there is no opened process - MemoryReadError - If ReadProcessMemory failed - TypeError - If address is not a valid integer - - Returns - ------- - int - returns the value read - """ - if not self.process_handle: - raise pymem.exception.ProcessError('You must open a process before calling this method') - try: - value = pymem.memory.read_ushort(self.process_handle, address) - except pymem.exception.WinAPIError as e: - raise pymem.exception.MemoryReadError(address, struct.calcsize('H'), e.error_code) - return value - - def read_float(self, address): - """Reads 4 byte from an area of memory in a specified process. - - Parameters - ---------- - address: int - An address of the region of memory to be read. - - Raises - ------ - ProcessError - If there is no opened process - MemoryReadError - If ReadProcessMemory failed - TypeError - If address is not a valid integer - - Returns - ------- - float - returns the value read - """ - if not self.process_handle: - raise pymem.exception.ProcessError('You must open a process before calling this method') - try: - value = pymem.memory.read_float(self.process_handle, address) - except pymem.exception.WinAPIError as e: - raise pymem.exception.MemoryReadError(address, struct.calcsize('f'), e.error_code) - return value - - def read_long(self, address): - """Reads 4 byte from an area of memory in a specified process. - - Parameters - ---------- - address: int - An address of the region of memory to be read. - - Raises - ------ - ProcessError - If there is no opened process - MemoryReadError - If ReadProcessMemory failed - TypeError - If address is not a valid integer - - Returns - ------- - int - returns the value read - """ - if not self.process_handle: - raise pymem.exception.ProcessError('You must open a process before calling this method') - try: - value = pymem.memory.read_long(self.process_handle, address) - except pymem.exception.WinAPIError as e: - raise pymem.exception.MemoryReadError(address, struct.calcsize('l'), e.error_code) - return value - - def read_ulong(self, address): - """Reads 4 byte from an area of memory in a specified process. - - Parameters - ---------- - address: int - An address of the region of memory to be read. - - Raises - ------ - ProcessError - If there is no opened process - MemoryReadError - If ReadProcessMemory failed - TypeError - If address is not a valid integer - - Returns - ------- - int - returns the value read - """ - if not self.process_handle: - raise pymem.exception.ProcessError('You must open a process before calling this method') - try: - value = pymem.memory.read_ulong(self.process_handle, address) - except pymem.exception.WinAPIError as e: - raise pymem.exception.MemoryReadError(address, struct.calcsize('L'), e.error_code) - return value - - def read_longlong(self, address): - """Reads 8 byte from an area of memory in a specified process. - - Parameters - ---------- - address: int - An address of the region of memory to be read. - - Raises - ------ - ProcessError - If there is no opened process - MemoryReadError - If ReadProcessMemory failed - TypeError - If address is not a valid integer - - Returns - ------- - int - returns the value read - """ - if not self.process_handle: - raise pymem.exception.ProcessError('You must open a process before calling this method') - try: - value = pymem.memory.read_longlong(self.process_handle, address) - except pymem.exception.WinAPIError as e: - raise pymem.exception.MemoryReadError(address, struct.calcsize('q'), e.error_code) - return value - - def read_ulonglong(self, address): - """Reads 8 byte from an area of memory in a specified process. - - Parameters - ---------- - address: int - An address of the region of memory to be read. - - Raises - ------ - ProcessError - If there is no opened process - MemoryReadError - If ReadProcessMemory failed - TypeError - If address is not a valid integer - - Returns - ------- - int - returns the value read - """ - if not self.process_handle: - raise pymem.exception.ProcessError('You must open a process before calling this method') - try: - value = pymem.memory.read_ulonglong(self.process_handle, address) - except pymem.exception.WinAPIError as e: - raise pymem.exception.MemoryReadError(address, struct.calcsize('Q'), e.error_code) - return value - - def read_double(self, address): - """Reads 8 byte from an area of memory in a specified process. - - Parameters - ---------- - address: int - An address of the region of memory to be read. - - Raises - ------ - ProcessError - If there is no opened process - MemoryReadError - If ReadProcessMemory failed - TypeError - If address is not a valid integer - - Returns - ------- - int - returns the value read - """ - if not self.process_handle: - raise pymem.exception.ProcessError('You must open a process before calling this method') - try: - value = pymem.memory.read_double(self.process_handle, address) - except pymem.exception.WinAPIError as e: - raise pymem.exception.MemoryReadError(address, struct.calcsize('d'), e.error_code) - return value - - def read_string(self, address, byte=50): - """Reads n `byte` from an area of memory in a specified process. - - Parameters - ---------- - address: int - An address of the region of memory to be read. - byte: int - Amount of bytes to be read - - Raises - ------ - ProcessError - If there is no opened process - MemoryReadError - If ReadProcessMemory failed - TypeError - If address is not a valid integer - - Returns - ------- - str - returns the value read - """ - if not self.process_handle: - raise pymem.exception.ProcessError('You must open a process before calling this method') - if not byte or not isinstance(byte, int): - raise TypeError('Invalid argument: {}'.format(byte)) - try: - value = pymem.memory.read_string(self.process_handle, address, byte) - except pymem.exception.WinAPIError as e: - raise pymem.exception.MemoryReadError(address, byte, e.error_code) - return value - - # TODO: make length optional, remove in 2.0 - def write_bytes(self, address, value, length): - """Write `value` to the given `address` into the current opened process. - - Parameters - ---------- - address: int - An address of the region of memory to be written. - value: bytes - the value to be written - length: int - Number of bytes to be written - - Raises - ------ - ProcessError - If there is no opened process - MemoryWriteError - If WriteProcessMemory failed - TypeError - If address is not a valid integer - """ - if not self.process_handle: - raise pymem.exception.ProcessError('You must open a process before calling this method') - if value is None or not isinstance(value, bytes): - raise TypeError('Invalid argument: {}'.format(value)) - try: - pymem.memory.write_bytes(self.process_handle, address, value, length) - except pymem.exception.WinAPIError as e: - raise pymem.exception.MemoryWriteError(address, value, e.error_code) - - def write_ctype(self, address, ctype): - """ - Write a ctype basic type or structure to
- - Parameters - ---------- - address: int - An address of the region of memory to be written. - ctype: - A simple ctypes type or structure - - Raises - ------ - WinAPIError - If WriteProcessMemory failed - - Returns - ------- - bool - A boolean indicating a successful write. - """ - if not self.process_handle: - raise pymem.exception.ProcessError('You must open a process before calling this method') - try: - pymem.memory.write_ctype(self.process_handle, address, ctype) - except pymem.exception.WinAPIError as e: - raise pymem.exception.MemoryWriteError(address, ctype, e.error_code) - - def write_bool(self, address, value): - """Write `value` to the given `address` into the current opened process. - - Parameters - ---------- - address: int - An address of the region of memory to be written. - value: bool - the value to be written - - Raises - ------ - ProcessError - If there is no opened process - MemoryWriteError - If WriteProcessMemory failed - TypeError - If address is not a valid integer - """ - if not self.process_handle: - raise pymem.exception.ProcessError('You must open a process before calling this method') - if value is None or not isinstance(value, bool): - raise TypeError('Invalid argument: {}'.format(value)) - try: - pymem.memory.write_bool(self.process_handle, address, value) - except pymem.exception.WinAPIError as e: - raise pymem.exception.MemoryWriteError(address, value, e.error_code) - - def write_int(self, address, value): - """Write `value` to the given `address` into the current opened process. - - Parameters - ---------- - address: int - An address of the region of memory to be written. - value: int - the value to be written - - Raises - ------ - ProcessError - If there is no opened process - MemoryWriteError - If WriteProcessMemory failed - TypeError - If address is not a valid integer - """ - if not self.process_handle: - raise pymem.exception.ProcessError('You must open a process before calling this method') - if value is None or not isinstance(value, int): - raise TypeError('Invalid argument: {}'.format(value)) - try: - pymem.memory.write_int(self.process_handle, address, value) - except pymem.exception.WinAPIError as e: - raise pymem.exception.MemoryWriteError(address, value, e.error_code) - - def write_uint(self, address, value): - """Write `value` to the given `address` into the current opened process. - - Parameters - ---------- - address: int - An address of the region of memory to be written. - value: int - the value to be written - - Raises - ------ - ProcessError - If there is no opened process - MemoryWriteError - If WriteProcessMemory failed - TypeError - If address is not a valid integer - """ - if not self.process_handle: - raise pymem.exception.ProcessError('You must open a process before calling this method') - if value is None or not isinstance(value, int): - raise TypeError('Invalid argument: {}'.format(value)) - try: - pymem.memory.write_uint(self.process_handle, address, value) - except pymem.exception.WinAPIError as e: - raise pymem.exception.MemoryWriteError(address, value, e.error_code) - - def write_short(self, address, value): - """Write `value` to the given `address` into the current opened process. - - Parameters - ---------- - address: int - An address of the region of memory to be written. - value: int - the value to be written - - Raises - ------ - ProcessError - If there is no opened process - MemoryWriteError - If WriteProcessMemory failed - TypeError - If address is not a valid integer - """ - if not self.process_handle: - raise pymem.exception.ProcessError('You must open a process before calling this method') - if value is None or not isinstance(value, int): - raise TypeError('Invalid argument: {}'.format(value)) - try: - pymem.memory.write_short(self.process_handle, address, value) - except pymem.exception.WinAPIError as e: - raise pymem.exception.MemoryWriteError(address, value, e.error_code) - - def write_ushort(self, address, value): - """Write `value` to the given `address` into the current opened process. - - Parameters - ---------- - address: int - An address of the region of memory to be written. - value: int - the value to be written - - Raises - ------ - ProcessError - If there is no opened process - MemoryWriteError - If WriteProcessMemory failed - TypeError - If address is not a valid integer - """ - if not self.process_handle: - raise pymem.exception.ProcessError('You must open a process before calling this method') - if value is None or not isinstance(value, int): - raise TypeError('Invalid argument: {}'.format(value)) - try: - pymem.memory.write_ushort(self.process_handle, address, value) - except pymem.exception.WinAPIError as e: - raise pymem.exception.MemoryWriteError(address, value, e.error_code) - - def write_float(self, address, value): - """Write `value` to the given `address` into the current opened process. - - Parameters - ---------- - address: int - An address of the region of memory to be written. - value: float - the value to be written - - Raises - ------ - ProcessError - If there is no opened process - MemoryWriteError - If WriteProcessMemory failed - TypeError - If address is not a valid integer - """ - if not self.process_handle: - raise pymem.exception.ProcessError('You must open a process before calling this method') - if value is None or not isinstance(value, float): - raise TypeError('Invalid argument: {}'.format(value)) - try: - pymem.memory.write_float(self.process_handle, address, value) - except pymem.exception.WinAPIError as e: - raise pymem.exception.MemoryWriteError(address, value, e.error_code) - - def write_long(self, address, value): - """Write `value` to the given `address` into the current opened process. - - Parameters - ---------- - address: int - An address of the region of memory to be written. - value: int - the value to be written - - Raises - ------ - ProcessError - If there is no opened process - MemoryWriteError - If WriteProcessMemory failed - TypeError - If address is not a valid integer - """ - if not self.process_handle: - raise pymem.exception.ProcessError('You must open a process before calling this method') - if value is None or not isinstance(value, int): - raise TypeError('Invalid argument: {}'.format(value)) - try: - pymem.memory.write_long(self.process_handle, address, value) - except pymem.exception.WinAPIError as e: - raise pymem.exception.MemoryWriteError(address, value, e.error_code) - - def write_ulong(self, address, value): - """Write `value` to the given `address` into the current opened process. - - Parameters - ---------- - address: int - An address of the region of memory to be written. - value: int - the value to be written - - Raises - ------ - ProcessError - If there is no opened process - MemoryWriteError - If WriteProcessMemory failed - TypeError - If address is not a valid integer - """ - if not self.process_handle: - raise pymem.exception.ProcessError('You must open a process before calling this method') - if value is None or not isinstance(value, int): - raise TypeError('Invalid argument: {}'.format(value)) - try: - pymem.memory.write_ulong(self.process_handle, address, value) - except pymem.exception.WinAPIError as e: - raise pymem.exception.MemoryWriteError(address, value, e.error_code) - - def write_longlong(self, address, value): - """Write `value` to the given `address` into the current opened process. - - Parameters - ---------- - address: int - An address of the region of memory to be written. - value: int - the value to be written - - Raises - ------ - ProcessError - If there is no opened process - MemoryWriteError - If WriteProcessMemory failed - TypeError - If address is not a valid integer - """ - if not self.process_handle: - raise pymem.exception.ProcessError('You must open a process before calling this method') - if value is None or not isinstance(value, int): - raise TypeError('Invalid argument: {}'.format(value)) - try: - pymem.memory.write_longlong(self.process_handle, address, value) - except pymem.exception.WinAPIError as e: - raise pymem.exception.MemoryWriteError(address, value, e.error_code) - - def write_ulonglong(self, address, value): - """Write `value` to the given `address` into the current opened process. - - Parameters - ---------- - address: int - An address of the region of memory to be written. - value: int - the value to be written - - Raises - ------ - ProcessError - If there is no opened process - MemoryWriteError - If WriteProcessMemory failed - TypeError - If address is not a valid integer - """ - if not self.process_handle: - raise pymem.exception.ProcessError('You must open a process before calling this method') - if value is None or not isinstance(value, int): - raise TypeError('Invalid argument: {}'.format(value)) - try: - pymem.memory.write_ulonglong(self.process_handle, address, value) - except pymem.exception.WinAPIError as e: - raise pymem.exception.MemoryWriteError(address, value, e.error_code) - - def write_double(self, address, value): - """Write `value` to the given `address` into the current opened process. - - Parameters - ---------- - address: int - An address of the region of memory to be written. - value: float - the value to be written - - Raises - ------ - ProcessError - If there is no opened process - MemoryWriteError - If WriteProcessMemory failed - TypeError - If address is not a valid integer - """ - if not self.process_handle: - raise pymem.exception.ProcessError('You must open a process before calling this method') - if value is None or not isinstance(value, float): - raise TypeError('Invalid argument: {}'.format(value)) - try: - pymem.memory.write_double(self.process_handle, address, value) - except pymem.exception.WinAPIError as e: - raise pymem.exception.MemoryWriteError(address, value, e.error_code) - - def write_string(self, address, value): - """Write `value` to the given `address` into the current opened process. - - Parameters - ---------- - address: int - An address of the region of memory to be written. - value: str - the value to be written - - Raises - ------ - ProcessError - If there is no opened process - MemoryWriteError - If WriteProcessMemory failed - TypeError - If address is not a valid integer - """ - if not self.process_handle: - raise pymem.exception.ProcessError('You must open a process before calling this method') - if value is None or not isinstance(value, str): - raise TypeError('Invalid argument: {}'.format(value)) - value = value.encode() - try: - pymem.memory.write_string(self.process_handle, address, value) - except pymem.exception.WinAPIError as e: - raise pymem.exception.MemoryWriteError(address, value, e.error_code) - - def write_char(self, address, value): - """Write `value` to the given `address` into the current opened process. - - Parameters - ---------- - address: int - An address of the region of memory to be written. - value: str - the value to be written - - Raises - ------ - ProcessError - If there is no opened process - MemoryWriteError - If WriteProcessMemory failed - TypeError - If address is not a valid integer - """ - if not self.process_handle: - raise pymem.exception.ProcessError('You must open a process before calling this method') - if value is None or not isinstance(value, str): - raise TypeError('Invalid argument: {}'.format(value)) - value = value.encode() - try: - pymem.memory.write_char(self.process_handle, address, value) - except pymem.exception.WinAPIError as e: - raise pymem.exception.MemoryWriteError(address, value, e.error_code) - - def write_uchar(self, address, value): - """Write `value` to the given `address` into the current opened process. - - Parameters - ---------- - address: int - An address of the region of memory to be written. - value: int - the value to be written - - Raises - ------ - ProcessError - If there is no opened process - MemoryWriteError - If WriteProcessMemory failed - TypeError - If address is not a valid integer - """ - if not self.process_handle: - raise pymem.exception.ProcessError('You must open a process before calling this method') - if value is None or not isinstance(value, int): - raise TypeError('Invalid argument: {}'.format(value)) - try: - pymem.memory.write_uchar(self.process_handle, address, value) - except pymem.exception.WinAPIError as e: - raise pymem.exception.MemoryWriteError(address, value, e.error_code) diff --git a/worlds/zork_grand_inquisitor/vendor/pymem/exception.py b/worlds/zork_grand_inquisitor/vendor/pymem/exception.py deleted file mode 100644 index 39d52a380912..000000000000 --- a/worlds/zork_grand_inquisitor/vendor/pymem/exception.py +++ /dev/null @@ -1,58 +0,0 @@ -class WinAPIError(Exception): - def __init__(self, error_code): - self.error_code = error_code - message = 'Windows api error, error_code: {}'.format(self.error_code) - super(WinAPIError, self).__init__(message) - - -class PymemError(Exception): - def __init__(self, message): - super(PymemError, self).__init__(message) - - -class ProcessError(PymemError): - def __init__(self, message): - super(ProcessError, self).__init__(message) - - -class ProcessNotFound(ProcessError): - def __init__(self, process_name): - message = 'Could not find process: {}'.format(process_name) - super(ProcessNotFound, self).__init__(message) - - -class CouldNotOpenProcess(ProcessError): - def __init__(self, process_id): - message = 'Could not open process: {}'.format(process_id) - super(CouldNotOpenProcess, self).__init__(message) - - -class PymemMemoryError(PymemError): - def __init__(self, message): - super(PymemMemoryError, self).__init__(message) - - -class MemoryReadError(PymemMemoryError): - def __init__(self, address, length, error_code=None): - message = 'Could not read memory at: {}, length: {}'.format(address, length) - if error_code: - message += ' - GetLastError: {}'.format(error_code) - super(MemoryReadError, self).__init__(message) - - -class MemoryWriteError(PymemMemoryError): - def __init__(self, address, value, error_code=None): - message = 'Could not write memory at: {}, length: {}'.format(address, value) - if error_code: - message += ' - GetLastError: {}'.format(error_code) - super(MemoryWriteError, self).__init__(message) - - -class PymemAlignmentError(PymemError): - def __init__(self, message): - super(PymemAlignmentError, self).__init__(message) - - -class PymemTypeError(PymemError): - def __init__(self, message): - super(PymemTypeError, self).__init__(message) diff --git a/worlds/zork_grand_inquisitor/vendor/pymem/memory.py b/worlds/zork_grand_inquisitor/vendor/pymem/memory.py deleted file mode 100644 index b60ea37f94fe..000000000000 --- a/worlds/zork_grand_inquisitor/vendor/pymem/memory.py +++ /dev/null @@ -1,1120 +0,0 @@ -import ctypes -import struct - -import pymem.exception -import pymem.ressources.kernel32 -import pymem.ressources.structure - - -def allocate_memory(handle, size, allocation_type=None, protection_type=None): - """Reserves or commits a region of memory within the virtual address space of a specified process. - The function initializes the memory it allocates to zero, unless MEM_RESET is used. - - https://msdn.microsoft.com/en-us/library/windows/desktop/aa366890%28v=vs.85%29.aspx - - Parameters - ---------- - handle: int - The handle to a process. The function allocates memory within the virtual address space of this process. - The handle must have the PROCESS_VM_OPERATION access right. - size: int - The size of the region of memory to allocate, in bytes. - allocation_type: MEMORY_STATE - The type of memory allocation. - protection_type: MEMORY_PROTECTION - The memory protection for the region of pages to be allocated. - - Returns - ------- - int - The address of the allocated region of pages. - """ - if not allocation_type: - allocation_type = pymem.ressources.structure.MEMORY_STATE.MEM_COMMIT.value - if not protection_type: - protection_type = pymem.ressources.structure.MEMORY_PROTECTION.PAGE_EXECUTE_READWRITE.value - pymem.ressources.kernel32.SetLastError(0) - address = pymem.ressources.kernel32.VirtualAllocEx(handle, None, size, allocation_type, protection_type) - return address - - -def free_memory(handle, address, free_type=None): - """Releases, decommits, or releases and decommits a region of memory within the virtual address space of a specified - process. - - https://msdn.microsoft.com/en-us/library/windows/desktop/aa366894%28v=vs.85%29.aspx - - Parameters - ---------- - handle: int - The handle to a process. The function allocates memory within the virtual address space of this process. - The handle must have the PROCESS_VM_OPERATION access right. - address: int - An address of the region of memory to be freed. - free_type: MEMORY_PROTECTION - The type of free operation. - - Returns - ------- - int - A boolean indicating if the call was a success. - """ - if not free_type: - free_type = pymem.ressources.structure.MEMORY_STATE.MEM_RELEASE - pymem.ressources.kernel32.SetLastError(0) - ret = pymem.ressources.kernel32.VirtualFreeEx(handle, address, 0, free_type) - return ret - - -def read_bytes(handle, address, byte): - """Reads data from an area of memory in a specified process. - The entire area to be read must be accessible or the operation fails. - - https://msdn.microsoft.com/en-us/library/windows/desktop/ms680553%28v=vs.85%29.aspx - - Parameters - ---------- - handle: int - The handle to a process. The function allocates memory within the virtual address space of this process. - The handle must have the PROCESS_VM_OPERATION access right. - address: int - An address of the region of memory to be read. - byte: int - Number of bytes to be read - - Raises - ------ - TypeError - If address is not a valid integer - WinAPIError - If ReadProcessMemory failed - - Returns - ------- - bytes - The raw value read as bytes - """ - return read_ctype(handle, address, (byte * ctypes.c_char)(), get_py_value=False).raw - - -def read_ctype(handle, address, ctype, *, get_py_value=True, raw_bytes=False): - """ - Read a ctype basic type or structure from
- - Parameters - ---------- - handle: int - The handle to a process. The function allocates memory within the virtual address space of this process. - The handle must have the PROCESS_VM_OPERATION access right. - address: int - An address of the region of memory to be read. - ctype: - A simple ctypes type or structure - get_py_value: bool - If the corrosponding python type should be used instead of returning the ctype - This is automatically set to False for ctypes.Structure or ctypes.Array instances - raw_bytes: bool - If we should return the raw ctype bytes - - Raises - ------ - WinAPIError - If ReadProcessMemory failed - - Returns - ------- - Any - Return will be either the ctype with the read value if get_py_value is false or - the corropsonding python type - """ - if raw_bytes: - return read_bytes(handle, address, ctypes.sizeof(ctype)) - - if isinstance(ctype, (ctypes.Structure, ctypes.Array)): - get_py_value = False - - pymem.ressources.kernel32.SetLastError(0) - - result = pymem.ressources.kernel32.ReadProcessMemory( - handle, - ctypes.c_void_p(address), - ctypes.byref(ctype), - ctypes.sizeof(ctype), - None, - ) - - if result == 0: - error_code = ctypes.windll.kernel32.GetLastError() - raise pymem.exception.WinAPIError(error_code) - - if get_py_value: - return ctype.value - - return ctype - - -def read_bool(handle, address): - """Reads 1 byte from an area of memory in a specified process. - The entire area to be read must be accessible or the operation fails. - - https://msdn.microsoft.com/en-us/library/windows/desktop/ms680553%28v=vs.85%29.aspx - - Parameters - ---------- - handle: int - The handle to a process. The function allocates memory within the virtual address space of this process. - The handle must have the PROCESS_VM_OPERATION access right. - address: int - An address of the region of memory to be read. - - Raises - ------ - TypeError - If address is not a valid integer - WinAPIError - If ReadProcessMemory failed - - Returns - ------- - bool - The raw value read as a bool - """ - return read_ctype(handle, address, ctypes.c_bool()) - - -def read_char(handle, address): - """Reads 1 byte from an area of memory in a specified process. - The entire area to be read must be accessible or the operation fails. - - https://msdn.microsoft.com/en-us/library/windows/desktop/ms680553%28v=vs.85%29.aspx - - Parameters - ---------- - handle: int - The handle to a process. The function allocates memory within the virtual address space of this process. - The handle must have the PROCESS_VM_OPERATION access right. - address: int - An address of the region of memory to be read. - - Raises - ------ - TypeError - If address is not a valid integer - WinAPIError - If ReadProcessMemory failed - - Returns - ------- - str - The raw value read as a string - """ - return read_ctype(handle, address, ctypes.c_char()).decode() - - -def read_uchar(handle, address): - """Reads 1 byte from an area of memory in a specified process. - The entire area to be read must be accessible or the operation fails. - - https://msdn.microsoft.com/en-us/library/windows/desktop/ms680553%28v=vs.85%29.aspx - - Parameters - ---------- - handle: int - The handle to a process. The function allocates memory within the virtual address space of this process. - The handle must have the PROCESS_VM_OPERATION access right. - address: int - An address of the region of memory to be read. - - Raises - ------ - TypeError - If address is not a valid integer - WinAPIError - If ReadProcessMemory failed - - Returns - ------- - int - The raw value read as an int - """ - return read_ctype(handle, address, ctypes.c_ubyte()) - - -def read_short(handle, address): - """Reads 2 byte from an area of memory in a specified process. - The entire area to be read must be accessible or the operation fails. - - https://msdn.microsoft.com/en-us/library/windows/desktop/ms680553%28v=vs.85%29.aspx - - Parameters - ---------- - handle: int - The handle to a process. The function allocates memory within the virtual address space of this process. - The handle must have the PROCESS_VM_OPERATION access right. - address: int - An address of the region of memory to be read. - - Raises - ------ - TypeError - If address is not a valid integer - WinAPIError - If ReadProcessMemory failed - - Returns - ------- - int - The raw value read as an int - """ - return read_ctype(handle, address, ctypes.c_short()) - - -def read_ushort(handle, address): - """Reads 2 byte from an area of memory in a specified process. - The entire area to be read must be accessible or the operation fails. - - https://msdn.microsoft.com/en-us/library/windows/desktop/ms680553%28v=vs.85%29.aspx - - Parameters - ---------- - handle: int - The handle to a process. The function allocates memory within the virtual address space of this process. - The handle must have the PROCESS_VM_OPERATION access right. - address: int - An address of the region of memory to be read. - - Raises - ------ - TypeError - If address is not a valid integer - WinAPIError - If ReadProcessMemory failed - - Returns - ------- - int - The raw value read as an int - """ - return read_ctype(handle, address, ctypes.c_ushort()) - - -def read_int(handle, address): - """Reads 4 byte from an area of memory in a specified process. - The entire area to be read must be accessible or the operation fails. - - https://msdn.microsoft.com/en-us/library/windows/desktop/ms680553%28v=vs.85%29.aspx - - Parameters - ---------- - handle: int - The handle to a process. The function allocates memory within the virtual address space of this process. - The handle must have the PROCESS_VM_OPERATION access right. - address: int - An address of the region of memory to be read. - - Raises - ------ - TypeError - If address is not a valid integer - WinAPIError - If ReadProcessMemory failed - - Returns - ------- - int - The raw value read as an int - """ - return read_ctype(handle, address, ctypes.c_int()) - - -def read_uint(handle, address, is_64=False): - """Reads 4 byte from an area of memory in a specified process. - The entire area to be read must be accessible or the operation fails. - - https://msdn.microsoft.com/en-us/library/windows/desktop/ms680553%28v=vs.85%29.aspx - - Parameters - ---------- - handle: int - The handle to a process. The function allocates memory within the virtual address space of this process. - The handle must have the PROCESS_VM_OPERATION access right. - address: int - An address of the region of memory to be read. - is_64: bool - Should we unpack as big-endian - - Raises - ------ - TypeError - If address is not a valid integer - WinAPIError - If ReadProcessMemory failed - - Returns - ------- - int - The raw value read as an int - """ - if not is_64: - return read_ctype(handle, address, ctypes.c_uint()) - - # should this just be c_uint64? the doc string says to read as big-endian - raw = read_bytes(handle, address, struct.calcsize('I')) - return struct.unpack('>I', raw)[0] - - -def read_float(handle, address): - """Reads 4 byte from an area of memory in a specified process. - The entire area to be read must be accessible or the operation fails. - - https://msdn.microsoft.com/en-us/library/windows/desktop/ms680553%28v=vs.85%29.aspx - - Parameters - ---------- - handle: int - The handle to a process. The function allocates memory within the virtual address space of this process. - The handle must have the PROCESS_VM_OPERATION access right. - address: int - An address of the region of memory to be read. - - Raises - ------ - TypeError - If address is not a valid integer - WinAPIError - If ReadProcessMemory failed - - Returns - ------- - float - The raw value read as a float - """ - return read_ctype(handle, address, ctypes.c_float()) - - -def read_long(handle, address): - """Reads 4 byte from an area of memory in a specified process. - The entire area to be read must be accessible or the operation fails. - - https://msdn.microsoft.com/en-us/library/windows/desktop/ms680553%28v=vs.85%29.aspx - - Parameters - ---------- - handle: int - The handle to a process. The function allocates memory within the virtual address space of this process. - The handle must have the PROCESS_VM_OPERATION access right. - address: int - An address of the region of memory to be read. - - Raises - ------ - TypeError - If address is not a valid integer - WinAPIError - If ReadProcessMemory failed - - Returns - ------- - int - The raw value read as an int - """ - return read_ctype(handle, address, ctypes.c_long()) - - -def read_ulong(handle, address): - """Reads 4 byte from an area of memory in a specified process. - The entire area to be read must be accessible or the operation fails. - - https://msdn.microsoft.com/en-us/library/windows/desktop/ms680553%28v=vs.85%29.aspx - - Parameters - ---------- - handle: int - The handle to a process. The function allocates memory within the virtual address space of this process. - The handle must have the PROCESS_VM_OPERATION access right. - address: int - An address of the region of memory to be read. - - Raises - ------ - TypeError - If address is not a valid integer - WinAPIError - If ReadProcessMemory failed - - Returns - ------- - int - The raw value read as an int - """ - return read_ctype(handle, address, ctypes.c_ulong()) - - -def read_longlong(handle, address): - """Reads 8 byte from an area of memory in a specified process. - The entire area to be read must be accessible or the operation fails. - - https://msdn.microsoft.com/en-us/library/windows/desktop/ms680553%28v=vs.85%29.aspx - - Parameters - ---------- - handle: int - The handle to a process. The function allocates memory within the virtual address space of this process. - The handle must have the PROCESS_VM_OPERATION access right. - address: int - An address of the region of memory to be read. - - Raises - ------ - TypeError - If address is not a valid integer - WinAPIError - If ReadProcessMemory failed - - Returns - ------- - int - The raw value read as an int - """ - return read_ctype(handle, address, ctypes.c_longlong()) - - -def read_ulonglong(handle, address): - """Reads 8 byte from an area of memory in a specified process. - The entire area to be read must be accessible or the operation fails. - - https://msdn.microsoft.com/en-us/library/windows/desktop/ms680553%28v=vs.85%29.aspx - - Parameters - ---------- - handle: int - The handle to a process. The function allocates memory within the virtual address space of this process. - The handle must have the PROCESS_VM_OPERATION access right. - address: int - An address of the region of memory to be read. - - Raises - ------ - TypeError - If address is not a valid integer - WinAPIError - If ReadProcessMemory failed - - Returns - ------- - int - The raw value read as an int - """ - return read_ctype(handle, address, ctypes.c_ulonglong()) - - -def read_double(handle, address): - """Reads 8 byte from an area of memory in a specified process. - The entire area to be read must be accessible or the operation fails. - - https://msdn.microsoft.com/en-us/library/windows/desktop/ms680553%28v=vs.85%29.aspx - - Parameters - ---------- - handle: int - The handle to a process. The function allocates memory within the virtual address space of this process. - The handle must have the PROCESS_VM_OPERATION access right. - address: int - An address of the region of memory to be read. - - Raises - ------ - TypeError - If address is not a valid integer - WinAPIError - If ReadProcessMemory failed - - Returns - ------- - float - The raw value read as a float - """ - return read_ctype(handle, address, ctypes.c_double()) - - -def read_string(handle, address, byte=50): - """Reads n `byte` from an area of memory in a specified process. - The entire area to be read must be accessible or the operation fails. - - https://msdn.microsoft.com/en-us/library/windows/desktop/ms680553%28v=vs.85%29.aspx - - Parameters - ---------- - handle: int - The handle to a process. The function allocates memory within the virtual address space of this process. - The handle must have the PROCESS_VM_OPERATION access right. - address: int - An address of the region of memory to be read. - byte: int, default=50 - max number of bytes to check for null terminator, defaults to 50 - - Raises - ------ - TypeError - If address is not a valid integer - WinAPIError - If ReadProcessMemory failed - - Returns - ------- - str - The raw value read as a string - """ - buff = read_bytes(handle, address, byte) - i = buff.find(b'\x00') - if i != -1: - buff = buff[:i] - buff = buff.decode() - return buff - - -def write_bytes(handle, address, data, length): - """Writes data to an area of memory in a specified process. - The entire area to be written to must be accessible or the operation fails. - - Casts address using ctypes.c_char_p. - - https://msdn.microsoft.com/en-us/library/windows/desktop/ms681674%28v=vs.85%29.aspx - - Parameters - ---------- - handle: int - The handle to a process. The function allocates memory within the virtual address space of this process. - The handle must have the PROCESS_VM_OPERATION access right. - address: int - An address of the region of memory to be written. - data: void - A buffer that contains data to be written - length: int - Number of bytes to be written. - - Raises - ------ - TypeError - If address is not a valid integer - WinAPIError - if WriteProcessMemory failed - - Returns - ------- - bool - A boolean indicating a successful write. - """ - buffer = (length * ctypes.c_char)() - buffer.value = data - return write_ctype(handle, address, buffer) - - -def write_ctype(handle, address, ctype): - """ - Write a ctype basic type or structure to
- - Parameters - ---------- - handle: int - The handle to a process. The function allocates memory within the virtual address space of this process. - The handle must have the PROCESS_VM_OPERATION access right. - address: int - An address of the region of memory to be written. - ctype: - A simple ctypes type or structure - - Raises - ------ - WinAPIError - If WriteProcessMemory failed - - Returns - ------- - bool - A boolean indicating a successful write. - """ - pymem.ressources.kernel32.SetLastError(0) - - result = pymem.ressources.kernel32.WriteProcessMemory( - handle, - ctypes.cast(address, ctypes.c_void_p), - ctypes.cast(ctypes.byref(ctype), ctypes.c_void_p), - ctypes.sizeof(ctype), - None - ) - - if result == 0: - error_code = ctypes.windll.kernel32.GetLastError() - raise pymem.exception.WinAPIError(error_code) - - # TODO: remove in next breaking change - # there isn't much point in returning this as it will always be true/1 (error raised otherwise) - return result - - -def write_bool(handle, address, value): - """Writes 1 byte to an area of memory in a specified process. - The entire area to be written to must be accessible or the operation fails. - - https://msdn.microsoft.com/en-us/library/windows/desktop/ms681674%28v=vs.85%29.aspx - - Parameters - ---------- - handle: int - The handle to a process. The function allocates memory within the virtual address space of this process. - The handle must have the PROCESS_VM_OPERATION access right. - address: int - An address of the region of memory to be written. - value: bool - A boolean representing the value to be written - - Raises - ------ - TypeError - If address is not a valid integer - WinAPIError - if WriteProcessMemory failed - - Returns - ------- - bool - A boolean indicating a successful write. - """ - return write_ctype(handle, address, ctypes.c_bool(value)) - - -def write_char(handle, address, value): - """Writes 1 byte to an area of memory in a specified process. - The entire area to be written to must be accessible or the operation fails. - - https://msdn.microsoft.com/en-us/library/windows/desktop/ms681674%28v=vs.85%29.aspx - - Parameters - ---------- - handle: int - The handle to a process. The function allocates memory within the virtual address space of this process. - The handle must have the PROCESS_VM_OPERATION access right. - address: int - An address of the region of memory to be written. - value: str - A buffer that contains data to be written - - Raises - ------ - TypeError - If address is not a valid integer - WinAPIError - if WriteProcessMemory failed - - Returns - ------- - bool - A boolean indicating a successful write. - """ - return write_ctype(handle, address, ctypes.c_char(value)) - - -def write_uchar(handle, address, value): - """Writes 1 byte to an area of memory in a specified process. - The entire area to be written to must be accessible or the operation fails. - - https://msdn.microsoft.com/en-us/library/windows/desktop/ms681674%28v=vs.85%29.aspx - - Parameters - ---------- - handle: int - The handle to a process. The function allocates memory within the virtual address space of this process. - The handle must have the PROCESS_VM_OPERATION access right. - address: int - An address of the region of memory to be written. - value: str - A buffer that contains data to be written - - Raises - ------ - TypeError - If address is not a valid integer - WinAPIError - if WriteProcessMemory failed - - Returns - ------- - bool - A boolean indicating a successful write. - """ - return write_ctype(handle, address, ctypes.c_ubyte(value)) - - -def write_short(handle, address, value): - """Writes 2 bytes to an area of memory in a specified process. - The entire area to be written to must be accessible or the operation fails. - - https://msdn.microsoft.com/en-us/library/windows/desktop/ms681674%28v=vs.85%29.aspx - - Parameters - ---------- - handle: int - The handle to a process. The function allocates memory within the virtual address space of this process. - The handle must have the PROCESS_VM_OPERATION access right. - address: int - An address of the region of memory to be written. - value: int - A buffer that contains data to be written - - Raises - ------ - TypeError - If address is not a valid integer - WinAPIError - if WriteProcessMemory failed - - Returns - ------- - bool - A boolean indicating a successful write. - """ - return write_ctype(handle, address, ctypes.c_short(value)) - - -def write_ushort(handle, address, value): - """Writes 2 bytes to an area of memory in a specified process. - The entire area to be written to must be accessible or the operation fails. - - https://msdn.microsoft.com/en-us/library/windows/desktop/ms681674%28v=vs.85%29.aspx - - Parameters - ---------- - handle: int - The handle to a process. The function allocates memory within the virtual address space of this process. - The handle must have the PROCESS_VM_OPERATION access right. - address: int - An address of the region of memory to be written. - value: int - A buffer that contains data to be written - - Raises - ------ - TypeError - If address is not a valid integer - WinAPIError - if WriteProcessMemory failed - - Returns - ------- - bool - A boolean indicating a successful write. - """ - return write_ctype(handle, address, ctypes.c_ushort(value)) - - -def write_int(handle, address, value): - """Writes 4 bytes to an area of memory in a specified process. - The entire area to be written to must be accessible or the operation fails. - - https://msdn.microsoft.com/en-us/library/windows/desktop/ms681674%28v=vs.85%29.aspx - - Parameters - ---------- - handle: int - The handle to a process. The function allocates memory within the virtual address space of this process. - The handle must have the PROCESS_VM_OPERATION access right. - address: int - An address of the region of memory to be written. - value: int - A buffer that contains data to be written - - Raises - ------ - TypeError - If address is not a valid integer - WinAPIError - if WriteProcessMemory failed - - Returns - ------- - bool - A boolean indicating a successful write. - """ - return write_ctype(handle, address, ctypes.c_int(value)) - - -def write_uint(handle, address, value): - """Writes 4 bytes to an area of memory in a specified process. - The entire area to be written to must be accessible or the operation fails. - - https://msdn.microsoft.com/en-us/library/windows/desktop/ms681674%28v=vs.85%29.aspx - - Parameters - ---------- - handle: int - The handle to a process. The function allocates memory within the virtual address space of this process. - The handle must have the PROCESS_VM_OPERATION access right. - address: int - An address of the region of memory to be written. - value: int - A buffer that contains data to be written - - Raises - ------ - TypeError - If address is not a valid integer - WinAPIError - if WriteProcessMemory failed - - Returns - ------- - bool - A boolean indicating a successful write. - """ - return write_ctype(handle, address, ctypes.c_uint(value)) - - -def write_float(handle, address, value): - """Writes 4 bytes to an area of memory in a specified process. - The entire area to be written to must be accessible or the operation fails. - - https://msdn.microsoft.com/en-us/library/windows/desktop/ms681674%28v=vs.85%29.aspx - - Parameters - ---------- - handle: int - The handle to a process. The function allocates memory within the virtual address space of this process. - The handle must have the PROCESS_VM_OPERATION access right. - address: int - An address of the region of memory to be written. - value: float - A buffer that contains data to be written - - Raises - ------ - TypeError - If address is not a valid integer - WinAPIError - if WriteProcessMemory failed - - Returns - ------- - bool - A boolean indicating a successful write. - """ - return write_ctype(handle, address, ctypes.c_float(value)) - - -def write_long(handle, address, value): - """Writes 4 bytes to an area of memory in a specified process. - The entire area to be written to must be accessible or the operation fails. - - https://msdn.microsoft.com/en-us/library/windows/desktop/ms681674%28v=vs.85%29.aspx - - Parameters - ---------- - handle: int - The handle to a process. The function allocates memory within the virtual address space of this process. - The handle must have the PROCESS_VM_OPERATION access right. - address: int - An address of the region of memory to be written. - value: int - A buffer that contains data to be written - - Raises - ------ - TypeError - If address is not a valid integer - WinAPIError - if WriteProcessMemory failed - - Returns - ------- - bool - A boolean indicating a successful write. - """ - return write_ctype(handle, address, ctypes.c_long(value)) - - -def write_ulong(handle, address, value): - """Writes 4 bytes to an area of memory in a specified process. - The entire area to be written to must be accessible or the operation fails. - - https://msdn.microsoft.com/en-us/library/windows/desktop/ms681674%28v=vs.85%29.aspx - - Parameters - ---------- - handle: int - The handle to a process. The function allocates memory within the virtual address space of this process. - The handle must have the PROCESS_VM_OPERATION access right. - address: int - An address of the region of memory to be written. - value: int - A buffer that contains data to be written - - Raises - ------ - TypeError - If address is not a valid integer - WinAPIError - if WriteProcessMemory failed - - Returns - ------- - bool - A boolean indicating a successful write. - """ - return write_ctype(handle, address, ctypes.c_ulong(value)) - - -def write_longlong(handle, address, value): - """Writes 8 bytes to an area of memory in a specified process. - The entire area to be written to must be accessible or the operation fails. - - https://msdn.microsoft.com/en-us/library/windows/desktop/ms681674%28v=vs.85%29.aspx - - Parameters - ---------- - handle: int - The handle to a process. The function allocates memory within the virtual address space of this process. - The handle must have the PROCESS_VM_OPERATION access right. - address: int - An address of the region of memory to be written. - value: int - A buffer that contains data to be written - - Raises - ------ - TypeError - If address is not a valid integer - WinAPIError - if WriteProcessMemory failed - - Returns - ------- - bool - A boolean indicating a successful write. - """ - return write_ctype(handle, address, ctypes.c_longlong(value)) - - -def write_ulonglong(handle, address, value): - """Writes 8 bytes to an area of memory in a specified process. - The entire area to be written to must be accessible or the operation fails. - - https://msdn.microsoft.com/en-us/library/windows/desktop/ms681674%28v=vs.85%29.aspx - - Parameters - ---------- - handle: int - The handle to a process. The function allocates memory within the virtual address space of this process. - The handle must have the PROCESS_VM_OPERATION access right. - address: int - An address of the region of memory to be written. - value: int - A buffer that contains data to be written - - Raises - ------ - TypeError - If address is not a valid integer - WinAPIError - if WriteProcessMemory failed - - Returns - ------- - bool - A boolean indicating a successful write. - """ - return write_ctype(handle, address, ctypes.c_ulonglong(value)) - - -def write_double(handle, address, value): - """Writes 8 bytes to an area of memory in a specified process. - The entire area to be written to must be accessible or the operation fails. - - https://msdn.microsoft.com/en-us/library/windows/desktop/ms681674%28v=vs.85%29.aspx - - Parameters - ---------- - handle: int - The handle to a process. The function allocates memory within the virtual address space of this process. - The handle must have the PROCESS_VM_OPERATION access right. - address: int - An address of the region of memory to be written. - value: float - A buffer that contains data to be written - - Raises - ------ - TypeError - If address is not a valid integer - WinAPIError - if WriteProcessMemory failed - - Returns - ------- - bool - A boolean indicating a successful write. - """ - return write_ctype(handle, address, ctypes.c_double(value)) - - -def write_string(handle, address, bytecode): - """Writes n `bytes` of len(`bytecode`) to an area of memory in a specified process. - The entire area to be written to must be accessible or the operation fails. - - https://msdn.microsoft.com/en-us/library/windows/desktop/ms681674%28v=vs.85%29.aspx - - Parameters - ---------- - handle: int - The handle to a process. The function allocates memory within the virtual address space of this process. - The handle must have the PROCESS_VM_OPERATION access right. - address: int - An address of the region of memory to be written. - bytecode: str, bytes - A buffer that contains data to be written - - Raises - ------ - TypeError - If address is not a valid integer - WinAPIError - if WriteProcessMemory failed - - Returns - ------- - bool - A boolean indicating a successful write. - """ - if isinstance(bytecode, str): - bytecode = bytecode.encode() - - return write_bytes(handle, address, bytecode, len(bytecode)) - - -def virtual_query(handle, address): - """Retrieves information about a range of pages within the virtual address space - of a specified process. - - https://msdn.microsoft.com/en-us/library/windows/desktop/aa366775(v=vs.85).aspx - https://msdn.microsoft.com/en-us/library/windows/desktop/aa366907(v=vs.85).aspx - - Parameters - ---------- - handle: int - The handle to a process. The function allocates memory within the virtual address space of this process. - The handle must have the PROCESS_VM_OPERATION access right. - address: int - An address of the region of to be read. - - Returns - ------- - MEMORY_BASIC_INFORMATION - A memory basic information object - """ - mbi = pymem.ressources.structure.MEMORY_BASIC_INFORMATION() - pymem.ressources.kernel32.SetLastError(0) - pymem.ressources.kernel32.VirtualQueryEx(handle, address, ctypes.byref(mbi), ctypes.sizeof(mbi)) - error_code = ctypes.windll.kernel32.GetLastError() - if error_code: - pymem.ressources.kernel32.SetLastError(0) - raise pymem.exception.WinAPIError(error_code) - return mbi diff --git a/worlds/zork_grand_inquisitor/vendor/pymem/pattern.py b/worlds/zork_grand_inquisitor/vendor/pymem/pattern.py deleted file mode 100644 index afbee6b83aea..000000000000 --- a/worlds/zork_grand_inquisitor/vendor/pymem/pattern.py +++ /dev/null @@ -1,178 +0,0 @@ -import sys - -import pymem.memory -import pymem.ressources.kernel32 -import pymem.ressources.structure - -try: - # faster than builtin re - import regex as re -except ImportError: - import re - - -# TODO: warn that pattern is a regex and may need to be escaped -# TODO: 2.0 rename to pattern_scan_page -def scan_pattern_page(handle, address, pattern, *, return_multiple=False): - """Search a byte pattern given a memory location. - Will query memory location information and search over until it reaches the - length of the memory page. If nothing is found the function returns the - next page location. - - Parameters - ---------- - handle: int - Handle to an open object - address: int - An address to search from - pattern: bytes - A regex byte pattern to search for - return_multiple: bool - If multiple results should be returned instead of stopping on the first - - Returns - ------- - tuple - next_region, found address - - found address may be None if one was not found, or we didn't have permission to scan - the region - - if return_multiple is True found address will instead be a list of found addresses - or an empty list if no results - - Examples - -------- - >>> pm = pymem.Pymem("Notepad.exe") - >>> address_reference = 0x7ABC00001 - # Here the "." means that the byte can be any byte; a "wildcard" - # also note that this pattern may be outdated - >>> bytes_pattern = b".\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00" \\ - ... b"\\x00\\x00\\x00\\x00\\x00\\x00..\\x00\\x00..\\x00\\x00\\x64\\x04" - >>> character_count_address = pymem.pattern.scan_pattern_page(pm.process_handle, address_reference, bytes_pattern) - """ - mbi = pymem.memory.virtual_query(handle, address) - next_region = mbi.BaseAddress + mbi.RegionSize - allowed_protections = [ - pymem.ressources.structure.MEMORY_PROTECTION.PAGE_EXECUTE, - pymem.ressources.structure.MEMORY_PROTECTION.PAGE_EXECUTE_READ, - pymem.ressources.structure.MEMORY_PROTECTION.PAGE_EXECUTE_READWRITE, - pymem.ressources.structure.MEMORY_PROTECTION.PAGE_READWRITE, - pymem.ressources.structure.MEMORY_PROTECTION.PAGE_READONLY, - ] - if mbi.state != pymem.ressources.structure.MEMORY_STATE.MEM_COMMIT or mbi.protect not in allowed_protections: - return next_region, None - - page_bytes = pymem.memory.read_bytes(handle, address, mbi.RegionSize) - - if not return_multiple: - found = None - match = re.search(pattern, page_bytes, re.DOTALL) - - if match: - found = address + match.span()[0] - - else: - found = [] - - for match in re.finditer(pattern, page_bytes, re.DOTALL): - found_address = address + match.span()[0] - found.append(found_address) - - return next_region, found - - -def pattern_scan_module(handle, module, pattern, *, return_multiple=False): - """Given a handle over an opened process and a module will scan memory after - a byte pattern and return its corresponding memory address. - - Parameters - ---------- - handle: int - Handle to an open object - module: MODULEINFO - An instance of a given module - pattern: bytes - A regex byte pattern to search for - return_multiple: bool - If multiple results should be returned instead of stopping on the first - - Returns - ------- - int, list, optional - Memory address of given pattern, or None if one was not found - or a list of found addresses in return_multiple is True - - Examples - -------- - >>> pm = pymem.Pymem("Notepad.exe") - # Here the "." means that the byte can be any byte; a "wildcard" - # also note that this pattern may be outdated - >>> bytes_pattern = b".\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00" \\ - ... b"\\x00\\x00\\x00\\x00\\x00\\x00..\\x00\\x00..\\x00\\x00\\x64\\x04" - >>> module_notepad = pymem.process.module_from_name(pm.process_handle, "Notepad.exe") - >>> character_count_address = pymem.pattern.pattern_scan_module(pm.process_handle, module_notepad, bytes_pattern) - """ - base_address = module.lpBaseOfDll - max_address = module.lpBaseOfDll + module.SizeOfImage - page_address = base_address - - if not return_multiple: - found = None - while page_address < max_address: - page_address, found = scan_pattern_page(handle, page_address, pattern) - - if found: - break - - else: - found = [] - while page_address < max_address: - page_address, new_found = scan_pattern_page(handle, page_address, pattern, return_multiple=True) - - if new_found: - found += new_found - - return found - - -def pattern_scan_all(handle, pattern, *, return_multiple=False): - """Scan the entire address space for a given regex pattern - - Parameters - ---------- - handle: int - Handle to an open process - pattern: bytes - A regex bytes pattern to search for - return_multiple: bool - If multiple results should be returned - - Returns - ------- - int, list, optional - Memory address of given pattern, or None if one was not found - or a list of found addresses in return_multiple is True - """ - next_region = 0 - - found = [] - user_space_limit = 0x7FFFFFFF0000 if sys.maxsize > 2**32 else 0x7fff0000 - while next_region < user_space_limit: - next_region, page_found = scan_pattern_page( - handle, - next_region, - pattern, - return_multiple=return_multiple - ) - - if not return_multiple and page_found: - return page_found - - if page_found: - found += page_found - - if not return_multiple: - return None - - return found diff --git a/worlds/zork_grand_inquisitor/vendor/pymem/process.py b/worlds/zork_grand_inquisitor/vendor/pymem/process.py deleted file mode 100644 index 984a09048693..000000000000 --- a/worlds/zork_grand_inquisitor/vendor/pymem/process.py +++ /dev/null @@ -1,450 +0,0 @@ -import ctypes -import locale -import logging -import os - -import pymem.ressources.advapi32 -import pymem.ressources.kernel32 -import pymem.ressources.psapi -import pymem.ressources.structure - - -logger = logging.getLogger(__name__) - - -def get_python_dll(version): - """Given a python dll version will find its path using the current process as a placeholder - - Parameters - ---------- - version: str - A string representation of python version as a dll (python38.dll) - - Returns - ------- - str - The full path of dll - """ - current_process_id = os.getpid() - current_process_handle = pymem.process.open(current_process_id) - for module in pymem.process.enum_process_module(current_process_handle): - if module.name == version: - return module.filename - - -def inject_dll(handle, filepath): - """Inject a dll into opened process. - - Parameters - ---------- - handle: int - Handle to an open object - filepath: bytes - Dll to be injected filepath - - Returns - ------- - DWORD - The address of injected dll - """ - filepath_address = pymem.ressources.kernel32.VirtualAllocEx( - handle, - 0, - len(filepath), - pymem.ressources.structure.MEMORY_STATE.MEM_COMMIT.value | pymem.ressources.structure.MEMORY_STATE.MEM_RESERVE.value, - pymem.ressources.structure.MEMORY_PROTECTION.PAGE_EXECUTE_READWRITE.value - ) - pymem.ressources.kernel32.WriteProcessMemory(handle, filepath_address, filepath, len(filepath), None) - kernel32_handle = pymem.ressources.kernel32.GetModuleHandleW("kernel32.dll") - load_library_a_address = pymem.ressources.kernel32.GetProcAddress(kernel32_handle, b"LoadLibraryA") - thread_h = pymem.ressources.kernel32.CreateRemoteThread( - handle, None, 0, load_library_a_address, filepath_address, 0, None - ) - pymem.ressources.kernel32.WaitForSingleObject(thread_h, -1) - pymem.ressources.kernel32.VirtualFreeEx( - handle, filepath_address, len(filepath), pymem.ressources.structure.MEMORY_STATE.MEM_RELEASE.value - ) - dll_name = os.path.basename(filepath) - dll_name = dll_name.decode('ascii') - module_address = pymem.ressources.kernel32.GetModuleHandleW(dll_name) - return module_address - - -def get_luid(name): - """Get the LUID for the SeCreateSymbolicLinkPrivilege - """ - luid = pymem.ressources.structure.LUID() - res = pymem.ressources.advapi32.LookupPrivilegeValue(None, name, luid) - if not res > 0: - raise RuntimeError("Couldn't lookup privilege value") - return luid - - -def get_process_token(): - """Get the current process token - """ - token = ctypes.c_void_p() - res = pymem.ressources.advapi32.OpenProcessToken( - ctypes.windll.kernel32.GetCurrentProcess(), - pymem.ressources.structure.TOKEN.TOKEN_ALL_ACCESS, - token - ) - if not res > 0: - raise RuntimeError("Couldn't get process token") - return token - - -def set_debug_privilege(lpszPrivilege, bEnablePrivilege): - """Leverage current process privileges. - - Parameters - ---------- - lpszPrivilege: str - Privilege name - bEnablePrivilege: bool - Enable privilege - - Returns - ------- - bool - If privileges have been leveraged - """ - # create a space in memory for a TOKEN_PRIVILEGES structure - # with one element - size = ctypes.sizeof(pymem.ressources.structure.TOKEN_PRIVILEGES) - size += ctypes.sizeof(pymem.ressources.structure.LUID_AND_ATTRIBUTES) - buffer = ctypes.create_string_buffer(size) - - tp = ctypes.cast(buffer, ctypes.POINTER(pymem.ressources.structure.TOKEN_PRIVILEGES)).contents - tp.count = 1 - tp.get_array()[0].LUID = get_luid(lpszPrivilege) - tp.get_array()[0].Attributes = ( - pymem.ressources.structure.SE_TOKEN_PRIVILEGE.SE_PRIVILEGE_ENABLED if bEnablePrivilege else 0 - ) - token = get_process_token() - res = pymem.ressources.advapi32.AdjustTokenPrivileges(token, False, tp, 0, None, None) - if res == 0: - raise RuntimeError("AdjustTokenPrivileges error: 0x%08x\n" % ctypes.GetLastError()) - - ERROR_NOT_ALL_ASSIGNED = 1300 - return ctypes.windll.kernel32.GetLastError() != ERROR_NOT_ALL_ASSIGNED - - -def base_module(handle): - """Returns process base module - - Parameters - ---------- - handle: int - A valid handle to an open object - - Returns - ------- - MODULEINFO - The base module of the process - """ - hModules = (ctypes.c_void_p * 1024)() - process_module_success = pymem.ressources.psapi.EnumProcessModulesEx( - handle, - ctypes.byref(hModules), - ctypes.sizeof(hModules), - ctypes.byref(ctypes.c_ulong()), - pymem.ressources.structure.EnumProcessModuleEX.LIST_MODULES_ALL - ) - if not process_module_success: - return # xxx - module_info = pymem.ressources.structure.MODULEINFO(handle) - pymem.ressources.psapi.GetModuleInformation( - handle, - ctypes.c_void_p(hModules[0]), - ctypes.byref(module_info), - ctypes.sizeof(module_info) - ) - return module_info - - -def open(process_id, debug=True, process_access=None): - """Open a process given its process_id. - By default, the process is opened with full access and in debug mode. - - https://msdn.microsoft.com/en-us/library/windows/desktop/ms684320%28v=vs.85%29.aspx - https://msdn.microsoft.com/en-us/library/windows/desktop/aa379588%28v=vs.85%29.aspx - - Parameters - ---------- - process_id: int - The identifier of the process to be opened - debug: bool - If the process should be opened in debug mode - process_access: pymem.ressources.structure.PROCESS - Desired access level, defaulting to all access - - Returns - ------- - int - A handle to the opened process - """ - if not process_access: - process_access = pymem.ressources.structure.PROCESS.PROCESS_ALL_ACCESS.value - if debug: - set_debug_privilege('SeDebugPrivilege', True) - process_handle = pymem.ressources.kernel32.OpenProcess(process_access, False, process_id) - return process_handle - - -def open_main_thread(process_id): - """List given process threads and return a handle to first created one. - - Parameters - ---------- - process_id: int - The identifier of the process - - Returns - ------- - int - A handle to the main thread - """ - threads = enum_process_thread(process_id) - threads = sorted(threads, key=lambda t32: t32.creation_time) - - if not threads: - return # todo: raise exception - - main_thread = threads[0] - thread_handle = open_thread(main_thread.th32ThreadID) - return thread_handle - - -# TODO: impl enum for thread access levels -def open_thread(thread_id, thread_access=None): - """Opens an existing thread object. - https://msdn.microsoft.com/en-us/library/windows/desktop/ms684335%28v=vs.85%29.aspx - - Parameters - ---------- - thread_id: int - The identifier of the thread to be opened - thread_access: int - Desired access level, defaulting to all access - - Returns - ------- - int - A handle to the opened thread - """ - if thread_access is None: - thread_access = 0x001F03FF - thread_handle = pymem.ressources.kernel32.OpenThread(thread_access, 0, thread_id) - return thread_handle - - -def close_handle(handle): - """Closes an open object handle. - https://msdn.microsoft.com/en-us/library/windows/desktop/ms724211%28v=vs.85%29.aspx - - Parameters - ---------- - handle: int - A valid handle to an open object - - Returns - ------- - bool - If the closure succeeded - """ - if not handle: - return - success = pymem.ressources.kernel32.CloseHandle(handle) - return success != 0 - - -def list_processes(): - """List all processes - https://msdn.microsoft.com/en-us/library/windows/desktop/ms682489%28v=vs.85%29.aspx - https://msdn.microsoft.com/en-us/library/windows/desktop/ms684834%28v=vs.85%29.aspx - - Returns - ------- - list[ProcessEntry32] - A list of open process entries - """ - SNAPPROCESS = 0x00000002 - hSnap = pymem.ressources.kernel32.CreateToolhelp32Snapshot(SNAPPROCESS, 0) - process_entry = pymem.ressources.structure.ProcessEntry32() - process_entry.dwSize = ctypes.sizeof(process_entry) - p32 = pymem.ressources.kernel32.Process32First(hSnap, ctypes.byref(process_entry)) - if p32: - yield process_entry - while p32: - yield process_entry - p32 = pymem.ressources.kernel32.Process32Next(hSnap, ctypes.byref(process_entry)) - pymem.ressources.kernel32.CloseHandle(hSnap) - - -def process_from_name( - name: str, - exact_match: bool = False, - ignore_case: bool = True, -): - """Open a process given its name. - - Parameters - ---------- - name: - The name of the process to be opened - exact_match: - Defaults to False, is the full name match or just part of it expected? - ignore_case: - Default to True, should ignore process name case? - - Returns - ------- - ProcessEntry32 - The process entry of the opened process - """ - - if ignore_case: - name = name.lower() - - processes = list_processes() - for process in processes: - process_name = process.szExeFile.decode(locale.getpreferredencoding()) - - if ignore_case: - process_name = process_name.lower() - - if exact_match: - if process_name == name: - return process - else: - if name in process_name: - return process - - -def process_from_id(process_id): - """Open a process given its name. - - Parameters - ---------- - process_id: int - The identifier of the process to be opened - - Returns - ------- - ProcessEntry32 - The process entry of the opened process - """ - processes = list_processes() - for process in processes: - if process_id == process.th32ProcessID: - return process - - -def module_from_name(process_handle, module_name): - """Retrieve a module loaded by given process. - - Parameters - ---------- - process_handle: int - Handle to the process to get the module from - module_name: str - Name of the module to get - - Returns - ------- - MODULEINFO - The retrieved module - - Examples - -------- - >>> d3d9 = module_from_name(process_handle, 'd3d9') - """ - module_name = module_name.lower() - modules = enum_process_module(process_handle) - for module in modules: - if module.name.lower() == module_name: - return module - - -def enum_process_thread(process_id): - """List all threads of given processes_id - - Parameters - ---------- - process_id: int - Identifier of the process to enum the threads of - - Returns - ------- - list[ThreadEntry32] - The process's threads - """ - TH32CS_SNAPTHREAD = 0x00000004 - hSnap = pymem.ressources.kernel32.CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0) - thread_entry = pymem.ressources.structure.ThreadEntry32() - ret = pymem.ressources.kernel32.Thread32First(hSnap, ctypes.byref(thread_entry)) - - if not ret: - raise pymem.exception.PymemError('Could not get Thread32First') - - while ret: - if thread_entry.th32OwnerProcessID == process_id: - yield thread_entry - ret = pymem.ressources.kernel32.Thread32Next(hSnap, ctypes.byref(thread_entry)) - pymem.ressources.kernel32.CloseHandle(hSnap) - - -def enum_process_module(handle): - """List and retrieves the base names of the specified loaded module within a process - https://msdn.microsoft.com/en-us/library/windows/desktop/ms682633(v=vs.85).aspx - https://msdn.microsoft.com/en-us/library/windows/desktop/ms683196(v=vs.85).aspx - - Parameters - ---------- - handle: int - Handle of the process to enum the modules of - - Returns - ------- - list[MODULEINFO] - The process's modules - """ - hModules = (ctypes.c_void_p * 1024)() - process_module_success = pymem.ressources.psapi.EnumProcessModulesEx( - handle, - ctypes.byref(hModules), - ctypes.sizeof(hModules), - ctypes.byref(ctypes.c_ulong()), - pymem.ressources.structure.EnumProcessModuleEX.LIST_MODULES_ALL - ) - if process_module_success: - hModules = iter(m for m in hModules if m) - for hModule in hModules: - module_info = pymem.ressources.structure.MODULEINFO(handle) - pymem.ressources.psapi.GetModuleInformation( - handle, - ctypes.c_void_p(hModule), - ctypes.byref(module_info), - ctypes.sizeof(module_info) - ) - yield module_info - - -# TODO: should this be named is_wow64? -def is_64_bit(handle): - """Determines whether the specified process is running under WOW64 (emulation). - - Parameters - ---------- - handle: int - Handle of the process to check wow64 status of - - Returns - ------- - bool - If the process is running under wow64 - """ - Wow64Process = ctypes.c_long() - pymem.ressources.kernel32.IsWow64Process(handle, ctypes.byref(Wow64Process)) - return bool(Wow64Process.value) diff --git a/worlds/zork_grand_inquisitor/vendor/pymem/ptypes.py b/worlds/zork_grand_inquisitor/vendor/pymem/ptypes.py deleted file mode 100644 index e07f5523883b..000000000000 --- a/worlds/zork_grand_inquisitor/vendor/pymem/ptypes.py +++ /dev/null @@ -1,112 +0,0 @@ -import ctypes -import struct - -import pymem.memory -import pymem.exception - - -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 diff --git a/worlds/zork_grand_inquisitor/vendor/pymem/ressources/__init__.py b/worlds/zork_grand_inquisitor/vendor/pymem/ressources/__init__.py deleted file mode 100644 index d77c1c31bc97..000000000000 --- a/worlds/zork_grand_inquisitor/vendor/pymem/ressources/__init__.py +++ /dev/null @@ -1,29 +0,0 @@ -import ctypes - -# ctypes.wintypes is available on linux? might not be in older versions -# so not touching for now -# various Mock that allows the doc to be build on darwin/linux -try: - import ctypes.wintypes -except ValueError: - from unittest.mock import Mock - - ctypes.wintypes = Mock() - ctypes.wintypes.MAX_PATH = 1 - ctypes.WinDLL = Mock() - -# Allows docs to be built with ci tools that run on linux -try: - getattr(ctypes, "WinDLL") -except AttributeError: - class MockObject: - def __init__(self, *args, **kwargs): - return - - def __call__(self, *args, **kwargs): - return self - - def __getattr__(self, item): - return self - - ctypes.Windll = MockObject() diff --git a/worlds/zork_grand_inquisitor/vendor/pymem/ressources/advapi32.py b/worlds/zork_grand_inquisitor/vendor/pymem/ressources/advapi32.py deleted file mode 100644 index eaa8615bd237..000000000000 --- a/worlds/zork_grand_inquisitor/vendor/pymem/ressources/advapi32.py +++ /dev/null @@ -1,65 +0,0 @@ -import ctypes - -import pymem.ressources.structure - -try: - dll = ctypes.WinDLL('advapi32.dll') -except AttributeError: - class MockObject: - def __getattr__(self, item): - return self - - dll = MockObject() - -#: The LookupPrivilegeValue function retrieves the locally unique identifier (LUID) used on a specified system to -#: locally represent the specified privilege name. -#: -#: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-lookupprivilegevaluea -LookupPrivilegeValue = dll.LookupPrivilegeValueW -LookupPrivilegeValue.argtypes = ( - ctypes.c_wchar_p, # system name - ctypes.c_wchar_p, # name - ctypes.POINTER(pymem.ressources.structure.LUID), -) -LookupPrivilegeValue.restype = ctypes.c_long - -#: The LookupPrivilegeName function retrieves the name that corresponds to the privilege represented on a specific -#: system by a specified locally unique identifier (LUID). -#: -#: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-lookupprivilegenamea -LookupPrivilegeName = dll.LookupPrivilegeNameW -LookupPrivilegeName.argtypes = ( - ctypes.c_wchar_p, # lpSystemName - ctypes.POINTER(pymem.ressources.structure.LUID), # lpLuid - ctypes.c_wchar_p, # lpName - ctypes.POINTER(ctypes.c_ulong), # cchName -) -LookupPrivilegeName.restype = ctypes.c_long - - -#: The OpenProcessToken function opens the access token associated with a process. -#: -#: https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-openprocesstoken -OpenProcessToken = dll.OpenProcessToken -OpenProcessToken.argtypes = ( - ctypes.c_void_p, - ctypes.c_ulong, - ctypes.POINTER(ctypes.c_void_p) -) -OpenProcessToken.restype = ctypes.c_long - - -#: The AdjustTokenPrivileges function enables or disables privileges in the specified access token. -#: Enabling or disabling privileges in an access token requires TOKEN_ADJUST_PRIVILEGES access. -#: -#: https://docs.microsoft.com/en-us/windows/win32/api/securitybaseapi/nf-securitybaseapi-adjusttokenprivileges -AdjustTokenPrivileges = dll.AdjustTokenPrivileges -AdjustTokenPrivileges.restype = ctypes.c_long -AdjustTokenPrivileges.argtypes = ( - ctypes.c_void_p, # TokenHandle - ctypes.c_long, # DisableAllPrivileges - pymem.ressources.structure.PTOKEN_PRIVILEGES, # NewState (optional) - ctypes.c_ulong, # BufferLength of PreviousState - pymem.ressources.structure.PTOKEN_PRIVILEGES, # PreviousState (out, optional) - ctypes.POINTER(ctypes.c_ulong), # ReturnLength -) diff --git a/worlds/zork_grand_inquisitor/vendor/pymem/ressources/kernel32.py b/worlds/zork_grand_inquisitor/vendor/pymem/ressources/kernel32.py deleted file mode 100644 index 805ecbdff95f..000000000000 --- a/worlds/zork_grand_inquisitor/vendor/pymem/ressources/kernel32.py +++ /dev/null @@ -1,290 +0,0 @@ -import ctypes - -import pymem.ressources.structure - -try: - dll = ctypes.WinDLL('kernel32.dll') -except AttributeError: - class MockObject: - def __getattr__(self, item): - return self - - - dll = MockObject() - -#: Opens an existing local process object. -#: -#: https://msdn.microsoft.com/en-us/library/windows/desktop/ms684320%28v=vs.85%29.aspx -OpenProcess = dll.OpenProcess -OpenProcess.restype = ctypes.c_void_p - -#: Terminates the specified process and all of its threads. -#: -#: https://msdn.microsoft.com/en-us/library/windows/desktop/ms686714%28v=vs.85%29.aspx -TerminateProcess = dll.TerminateProcess -TerminateProcess.restype = ctypes.c_ulong - -#: Closes an open object handle. -#: -#: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724211%28v=vs.85%29.aspx -CloseHandle = dll.CloseHandle -CloseHandle.restype = ctypes.c_long -CloseHandle.argtypes = [ - ctypes.c_void_p -] - -#: Retrieves the calling thread's last-error code value. The last-error code is maintained on a per-thread basis. -#: Multiple threads do not overwrite each other's last-error code. -#: -#: https://msdn.microsoft.com/en-us/library/windows/desktop/ms679360%28v=vs.85%29.aspx -GetLastError = dll.GetLastError -GetLastError.restype = ctypes.c_ulong - -#: Sets the last-error code for the calling thread. -#: -#: https://docs.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-setlasterror -SetLastError = dll.SetLastError -SetLastError.argtypes = [ctypes.c_ulong] - -#: Retrieves a pseudo handle for the current process. -#: -#: https://msdn.microsoft.com/en-us/library/windows/desktop/ms683179%28v=vs.85%29.aspx -GetCurrentProcess = dll.GetCurrentProcess -GetCurrentProcess.argtypes = [] -GetCurrentProcess.restype = ctypes.c_ulong - -#: Reads data from an area of memory in a specified process. -# The entire area to be read must be accessible or the operation fails. -#: -#: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680553%28v=vs.85%29.aspx -ReadProcessMemory = dll.ReadProcessMemory -ReadProcessMemory.argtypes = ( - ctypes.c_void_p, - ctypes.c_void_p, - ctypes.c_void_p, - ctypes.c_size_t, - ctypes.POINTER(ctypes.c_size_t) -) -ReadProcessMemory.restype = ctypes.c_long - -#: Writes data to an area of memory in a specified process. -#: The entire area to be written to must be accessible or the operation fails. -#: -#: https://msdn.microsoft.com/en-us/library/windows/desktop/ms684320%28v=vs.85%29.aspx -WriteProcessMemory = dll.WriteProcessMemory -WriteProcessMemory.argtypes = [ - ctypes.c_void_p, - ctypes.c_void_p, - ctypes.c_void_p, - ctypes.c_size_t, - ctypes.POINTER(ctypes.c_size_t) -] -WriteProcessMemory.restype = ctypes.c_long - -#: Enables a debugger to attach to an active process and debug it. -#: -#: https://msdn.microsoft.com/en-us/library/windows/desktop/ms679295%28v=vs.85%29.aspx -DebugActiveProcess = dll.DebugActiveProcess -DebugActiveProcess.restype = ctypes.c_long - -#: Reserves or commits a region of memory within the virtual address space of a specified process. -#: The function initializes the memory it allocates to zero, unless MEM_RESET is used. -#: -#: https://msdn.microsoft.com/en-us/library/windows/desktop/aa366890%28v=vs.85%29.aspx -VirtualAllocEx = dll.VirtualAllocEx -VirtualAllocEx.restype = ctypes.c_void_p -VirtualAllocEx.argtypes = ( - ctypes.c_void_p, - ctypes.c_void_p, - ctypes.c_ulong, - ctypes.c_ulong, - ctypes.c_ulong -) - -#: Changes the protection on a region of committed pages in the virtual address space of a specified process. -#: -#: https://msdn.microsoft.com/en-us/library/windows/desktop/aa366899%28v=vs.85%29.aspx -VirtualProtectEx = dll.VirtualProtectEx -VirtualProtectEx.restype = ctypes.c_long - -#: Takes a snapshot of the specified processes, as well as the heaps, modules, and threads used by these processes. -#: -#: https://msdn.microsoft.com/en-us/library/windows/desktop/ms682489%28v=vs.85%29.aspx -CreateToolhelp32Snapshot = dll.CreateToolhelp32Snapshot -CreateToolhelp32Snapshot.restype = ctypes.c_void_p -CreateToolhelp32Snapshot.argtypes = (ctypes.c_ulong, ctypes.c_ulong) - -#: Retrieves information about the first module associated with a process. -#: -#: https://msdn.microsoft.com/en-us/library/windows/desktop/ms684218%28v=vs.85%29.aspx -Module32First = dll.Module32First -Module32First.restype = ctypes.c_ulonglong -Module32First.argtypes = (ctypes.c_void_p, pymem.ressources.structure.LPMODULEENTRY32) - -#: Retrieves information about the next module associated with a process or thread. -#: -#: https://msdn.microsoft.com/en-us/library/windows/desktop/ms684221%28v=vs.85%29.aspx -Module32Next = dll.Module32Next -Module32Next.restype = ctypes.c_ulonglong -Module32Next.argtypes = (ctypes.c_void_p, pymem.ressources.structure.LPMODULEENTRY32) - -#: Retrieves information about the first process encountered in a system snapshot. -#: -#: https://msdn.microsoft.com/en-us/library/windows/desktop/ms684834%28v=vs.85%29.aspx -Process32First = dll.Process32First -Process32First.restype = ctypes.c_long - -#: Retrieves information about the next process recorded in a system snapshot. -#: -#: https://msdn.microsoft.com/en-us/library/windows/desktop/ms684836%28v=vs.85%29.aspx -Process32Next = dll.Process32Next -Process32Next.restype = ctypes.c_long - -#: Retrieves information about the first thread of any process encountered in a system snapshot. -#: -#: https://msdn.microsoft.com/en-us/library/windows/desktop/ms686728%28v=vs.85%29.aspx -Thread32First = dll.Thread32First -Thread32First.restype = ctypes.c_long -Thread32First.argtypes = [ - ctypes.c_void_p, - ctypes.POINTER(pymem.ressources.structure.ThreadEntry32) -] - -#: Retrieves information about the next thread of any process encountered in the system memory snapshot. -#: -#: https://msdn.microsoft.com/en-us/library/windows/desktop/ms686731%28v=vs.85%29.aspx -Thread32Next = dll.Thread32Next -Thread32Next.restype = ctypes.c_long -Thread32Next.argtypes = [ - ctypes.c_void_p, - ctypes.POINTER(pymem.ressources.structure.ThreadEntry32) -] - -#: Opens an existing thread object. -#: -#: https://msdn.microsoft.com/en-us/library/windows/desktop/ms684335%28v=vs.85%29.aspx -OpenThread = dll.OpenThread -OpenThread.restype = ctypes.c_void_p -OpenThread.argtypes = [ - ctypes.c_ulong, - ctypes.c_long, - ctypes.c_ulong -] - -#: Suspends the specified thread. -#: -#: https://msdn.microsoft.com/en-us/library/windows/desktop/ms686345%28v=vs.85%29.aspx -SuspendThread = dll.SuspendThread -SuspendThread.restype = ctypes.c_ulong - -#: Decrements a thread's suspend count. When the suspend count is decremented to zero, -# the execution of the thread is resumed. -#: -#: https://msdn.microsoft.com/en-us/library/windows/desktop/ms685086%28v=vs.85%29.aspx -ResumeThread = dll.ResumeThread -ResumeThread.restype = ctypes.c_ulong - -#: Retrieves the context of the specified thread. -#: -#: https://msdn.microsoft.com/en-us/library/windows/desktop/ms679362%28v=vs.85%29.aspx -GetThreadContext = dll.GetThreadContext -GetThreadContext.restype = ctypes.c_long - -#: Sets the context for the specified thread. -#: -#: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680632%28v=vs.85%29.aspx -SetThreadContext = dll.SetThreadContext -SetThreadContext.restype = ctypes.c_long - -#: Releases, decommits, or releases and decommits a region of memory within the virtual address space -# of a specified process. -#: -#: https://msdn.microsoft.com/en-us/library/windows/desktop/aa366894%28v=vs.85%29.aspx -VirtualFreeEx = dll.VirtualFreeEx -VirtualFreeEx.restype = ctypes.c_long - -#: Retrieves information about a range of pages in the virtual address space of the calling process. -#: -#: https://msdn.microsoft.com/en-us/library/windows/desktop/aa366907(v=vs.85).aspx -VirtualQueryEx = dll.VirtualQueryEx -VirtualQueryEx.argtypes = [ - ctypes.c_void_p, - ctypes.c_void_p, - ctypes.c_void_p, - ctypes.c_size_t -] -VirtualQueryEx.restype = ctypes.c_ulong - -#: Determines whether the specified process is running under WOW64. -#: -#: https://msdn.microsoft.com/en-us/library/ms684139(v=vs.85).aspx -IsWow64Process = dll.IsWow64Process -IsWow64Process.argtypes = [ - ctypes.c_void_p, - ctypes.POINTER(ctypes.c_long) -] -IsWow64Process.restype = ctypes.c_long - -#: Retrieves information about the current system. -#: -#: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724381(v=vs.85).aspx -GetSystemInfo = dll.GetSystemInfo -GetSystemInfo.restype = ctypes.c_void_p - -GetModuleHandleW = dll.GetModuleHandleW -GetModuleHandleW.restype = ctypes.c_void_p -GetModuleHandleW.argtypes = [ctypes.c_wchar_p] - -GetProcAddress = dll.GetProcAddress -GetProcAddress.restype = ctypes.c_void_p -GetProcAddress.argtypes = (ctypes.c_void_p, ctypes.c_char_p) - -CreateRemoteThread = dll.CreateRemoteThread -CreateRemoteThread.restype = ctypes.c_void_p -CreateRemoteThread.argtypes = ( - ctypes.c_void_p, - pymem.ressources.structure.LPSECURITY_ATTRIBUTES, - ctypes.c_size_t, - ctypes.c_void_p, - ctypes.c_void_p, - ctypes.c_ulong, - ctypes.POINTER(ctypes.c_ulong) -) - -GetFullPathNameA = dll.GetFullPathNameA -GetFullPathNameA.restype = ctypes.c_ulong -GetFullPathNameA.argtypes = [ - ctypes.c_char_p, ctypes.c_ulong, ctypes.c_char_p, ctypes.POINTER(ctypes.c_char_p) -] - -WaitForSingleObject = dll.WaitForSingleObject -WaitForSingleObject.restype = ctypes.c_ulong -WaitForSingleObject.argtypes = [ - ctypes.c_void_p, ctypes.c_ulong -] - -GetExitCodeThread = dll.GetExitCodeThread -GetExitCodeThread.restype = ctypes.c_long -GetExitCodeThread.argtypes = [ - ctypes.c_void_p, - ctypes.POINTER(ctypes.c_ulong) -] - -VirtualFreeEx = dll.VirtualFreeEx -VirtualFreeEx.restype = ctypes.c_long -VirtualFreeEx.argtypes = [ - ctypes.c_void_p, - ctypes.c_void_p, - ctypes.c_size_t, - ctypes.c_ulong -] - -GetThreadTimes = dll.GetThreadTimes -GetThreadTimes.restype = ctypes.c_long -GetThreadTimes.artypes = [ - ctypes.c_void_p, - ctypes.POINTER(pymem.ressources.structure.FILETIME), - ctypes.POINTER(pymem.ressources.structure.FILETIME), - ctypes.POINTER(pymem.ressources.structure.FILETIME), - ctypes.POINTER(pymem.ressources.structure.FILETIME) -] diff --git a/worlds/zork_grand_inquisitor/vendor/pymem/ressources/ntdll.py b/worlds/zork_grand_inquisitor/vendor/pymem/ressources/ntdll.py deleted file mode 100644 index bebdff53047b..000000000000 --- a/worlds/zork_grand_inquisitor/vendor/pymem/ressources/ntdll.py +++ /dev/null @@ -1,26 +0,0 @@ -import ctypes - -try: - dll = ctypes.WinDLL('ntdll.dll') -except AttributeError: - class MockObject: - def __getattr__(self, item): - return self - - dll = MockObject() - -NTSTATUS = ctypes.c_ulong -THREADINFOCLASS = ctypes.c_ulong - -#: Retrieves information about the specified thread. -#: -#: https://msdn.microsoft.com/en-us/library/windows/desktop/ms684283.aspx -NtQueryInformationThread = dll.NtQueryInformationThread -NtQueryInformationThread.restype = NTSTATUS -NtQueryInformationThread.argtypes = [ - ctypes.c_void_p, - THREADINFOCLASS, - ctypes.c_void_p, - ctypes.c_ulong, - ctypes.POINTER(ctypes.c_ulong) -] diff --git a/worlds/zork_grand_inquisitor/vendor/pymem/ressources/psapi.py b/worlds/zork_grand_inquisitor/vendor/pymem/ressources/psapi.py deleted file mode 100644 index dfc4fbac26d7..000000000000 --- a/worlds/zork_grand_inquisitor/vendor/pymem/ressources/psapi.py +++ /dev/null @@ -1,36 +0,0 @@ -import ctypes - -try: - dll = ctypes.WinDLL('psapi.dll') -except AttributeError: - class MockObject: - def __getattr__(self, item): - return self - - dll = MockObject() - -#: Retrieves a handle for each module in the specified process that meets the specified filter criteria. -#: -#: https://msdn.microsoft.com/en-us/library/windows/desktop/ms682633(v=vs.85).aspx -EnumProcessModulesEx = dll.EnumProcessModulesEx -EnumProcessModulesEx.restype = ctypes.c_bool - - -#: Retrieves a handle for each module in the specified process that meets the specified filter criteria. -#: -#: https://msdn.microsoft.com/en-us/library/windows/desktop/ms683196(v=vs.85).aspx -GetModuleBaseNameA = dll.GetModuleBaseNameA -GetModuleBaseNameA.restype = ctypes.c_ulonglong - - -#: Retrieves information about the specified module in the MODULEINFO structure. -#: -#: https://msdn.microsoft.com/en-us/library/windows/desktop/ms683201(v=vs.85).aspx -GetModuleInformation = dll.GetModuleInformation -GetModuleInformation.restype = ctypes.c_bool - -#: Retrieves information about the specified module in the MODULEINFO structure. -#: -#: https://msdn.microsoft.com/en-us/library/windows/desktop/ms683198(v=vs.85).aspx -GetModuleFileNameExA = dll.GetModuleFileNameExA -GetModuleFileNameExA.restype = ctypes.c_ulong diff --git a/worlds/zork_grand_inquisitor/vendor/pymem/ressources/structure.py b/worlds/zork_grand_inquisitor/vendor/pymem/ressources/structure.py deleted file mode 100644 index bdcfcfcc4e5a..000000000000 --- a/worlds/zork_grand_inquisitor/vendor/pymem/ressources/structure.py +++ /dev/null @@ -1,624 +0,0 @@ -import enum -import locale -import struct -import ctypes -# these are available on linux also (doc ci building) -import ctypes.wintypes - -import pymem.ressources.psapi -import pymem.ressources.ntdll - - -class LUID(ctypes.Structure): - _fields_ = [ - ("LowPart", ctypes.c_ulong), - ("HighPart", ctypes.c_long) - ] - - -class LUID_AND_ATTRIBUTES(ctypes.Structure): - _fields_ = [ - ("Luid", LUID), - ("Attributes", ctypes.c_ulong), - ] - - def is_enabled(self): - return bool(self.attributes & SE_TOKEN_PRIVILEGE.SE_PRIVILEGE_ENABLED) - - def enable(self): - self.attributes |= SE_TOKEN_PRIVILEGE.SE_PRIVILEGE_ENABLED - - def get_name(self): - import pymem.ressources.advapi32 - - size = ctypes.c_ulong(10240) - buf = ctypes.create_unicode_buffer(size.value) - res = pymem.ressources.advapi32.LookupPrivilegeName(None, self.LUID, buf, size) - if res == 0: - raise RuntimeError("Could not LookupPrivilegeName") - return buf[:size.value] - - def __str__(self): - res = self.get_name() - if self.is_enabled(): - res += ' (enabled)' - return res - - -class TOKEN_PRIVILEGES(ctypes.Structure): - _fields_ = [ - ("count", ctypes.c_ulong), - ("Privileges", LUID_AND_ATTRIBUTES * 0) - ] - - def get_array(self): - array_type = LUID_AND_ATTRIBUTES * self.count - privileges = ctypes.cast(self.Privileges, ctypes.POINTER(array_type)).contents - return privileges - - def __iter__(self): - return iter(self.get_array()) - - -PTOKEN_PRIVILEGES = ctypes.POINTER(TOKEN_PRIVILEGES) - -MAX_MODULE_NAME32 = 255 - - -class ModuleEntry32(ctypes.Structure): - """Describes an entry from a list of the modules belonging to the specified process. - - https://msdn.microsoft.com/en-us/library/windows/desktop/ms684225%28v=vs.85%29.aspx - """ - _fields_ = [ - ('dwSize', ctypes.c_ulong), - ('th32ModuleID', ctypes.c_ulong), - ('th32ProcessID', ctypes.c_ulong), - ('GlblcntUsage', ctypes.c_ulong), - ('ProccntUsage', ctypes.c_ulong), - ('modBaseAddr', ctypes.POINTER(ctypes.c_ulonglong)), - ('modBaseSize', ctypes.c_ulong), - ('hModule', ctypes.c_ulong), - ('szModule', ctypes.c_char * (MAX_MODULE_NAME32 + 1)), - ('szExePath', ctypes.c_char * ctypes.wintypes.MAX_PATH) - ] - - def __init__(self, *args, **kwds): - super(ModuleEntry32, self).__init__(*args, **kwds) - self.dwSize = ctypes.sizeof(self) - - @property - def base_address(self): - return ctypes.addressof(self.modBaseAddr.contents) - - @property - def name(self): - return self.szModule.decode(locale.getpreferredencoding()) - - -LPMODULEENTRY32 = ctypes.POINTER(ModuleEntry32) - - -class ProcessEntry32(ctypes.Structure): - """Describes an entry from a list of the processes residing in the system address space when a snapshot was taken. - - https://msdn.microsoft.com/en-us/library/windows/desktop/ms684839(v=vs.85).aspx - """ - _fields_ = [ - ('dwSize', ctypes.c_ulong), - ('cntUsage', ctypes.c_ulong), - ('th32ProcessID', ctypes.c_ulong), - ('th32DefaultHeapID', ctypes.POINTER(ctypes.c_ulong)), - ('th32ModuleID', ctypes.c_ulong), - ('cntThreads', ctypes.c_ulong), - ('th32ParentProcessID', ctypes.c_ulong), - ('pcPriClassBase', ctypes.c_ulong), - ('dwFlags', ctypes.c_ulong), - ('szExeFile', ctypes.c_char * ctypes.wintypes.MAX_PATH) - ] - - @property - def szExeFile(self): - return self.szExeFile.decode(locale.getpreferredencoding()) - - def __init__(self, *args, **kwds): - super(ProcessEntry32, self).__init__(*args, **kwds) - self.dwSize = ctypes.sizeof(self) - - -class FILETIME(ctypes.Structure): - _fields_ = [ - ("dwLowDateTime", ctypes.c_ulong), - ("dwHighDateTime", ctypes.c_ulong) - ] - - @property - def value(self): - v = struct.unpack('>Q', struct.pack('>LL', self.dwHighDateTime, self.dwLowDateTime)) - v = v[0] - return v - - -class ThreadEntry32(ctypes.Structure): - """Describes an entry from a list of the threads executing in the system when a snapshot was taken. - - https://msdn.microsoft.com/en-us/library/windows/desktop/ms686735(v=vs.85).aspx - """ - - _fields_ = [ - ('dwSize', ctypes.c_ulong), - ("cntUsage", ctypes.c_ulong), - ("th32ThreadID", ctypes.c_ulong), - ("th32OwnerProcessID", ctypes.c_ulong), - ("tpBasePri", ctypes.c_ulong), - ("tpDeltaPri", ctypes.c_ulong), - ("dwFlags", ctypes.c_ulong) - ] - - @property - def szExeFile(self): - return self.szExeFile.decode(locale.getpreferredencoding()) - - # XXX: save it somehow - @property - def creation_time(self): - THREAD_QUERY_INFORMATION = 0x0040 - handle = pymem.ressources.kernel32.OpenThread( - THREAD_QUERY_INFORMATION, False, self.th32ThreadID - ) - - ctime = FILETIME() - etime = FILETIME() - ktime = FILETIME() - utime = FILETIME() - - pymem.ressources.kernel32.GetThreadTimes( - handle, ctypes.pointer(ctime), ctypes.pointer(etime), ctypes.pointer(ktime), ctypes.pointer(utime) - ) - pymem.ressources.kernel32.CloseHandle(handle) - return ctime.value - - def __init__(self, *args, **kwds): - super(ThreadEntry32, self).__init__(*args, **kwds) - self.dwSize = ctypes.sizeof(self) - - -class PROCESS(enum.IntEnum): - """Process manipulation flags""" - - #: Required to create a process. - PROCESS_CREATE_PROCESS = 0x0080 - #: Required to create a thread. - PROCESS_CREATE_THREAD = 0x0002 - #: PROCESS_DUP_HANDLE - PROCESS_DUP_HANDLE = 0x0040 - #: Required to retrieve certain information about a process, such as its token, exit code, - # and priority class (see OpenProcessToken). - PROCESS_QUERY_INFORMATION = 0x0400 - #: Required to retrieve certain information about a process - # (see GetExitCodeProcess, GetPriorityClass, IsProcessInJob, QueryFullProcessImageName). - PROCESS_QUERY_LIMITED_INFORMATION = 0x1000 - #: Required to set certain information about a process, such as its priority class (see SetPriorityClass). - PROCESS_SET_INFORMATION = 0x0200 - #: Required to set memory limits using SetProcessWorkingSetSize. - PROCESS_SET_QUOTA = 0x0100 - #: Required to suspend or resume a process. - PROCESS_SUSPEND_RESUME = 0x0800 - #: Required to terminate a process using TerminateProcess. - PROCESS_TERMINATE = 0x0001 - #: Required to perform an operation on the address space of a process (see VirtualProtectEx and WriteProcessMemory). - PROCESS_VM_OPERATION = 0x0008 - #: Required to read memory in a process using ReadProcessMemory. - PROCESS_VM_READ = 0x0010 - #: Required to write to memory in a process using WriteProcessMemory. - PROCESS_VM_WRITE = 0x0020 - #: Required to wait for the process to terminate using the wait functions. - SYNCHRONIZE = 0x00100000 - #: Combines DELETE, READ_CONTROL, WRITE_DAC, and WRITE_OWNER access. - STANDARD_RIGHTS_REQUIRED = 0x000F0000 - #: All possible access rights for a process object. - PROCESS_ALL_ACCESS = ( - STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFF - ) - #: Required to delete the object. - DELETE = 0x00010000 - #: Required to read information in the security descriptor for the object, not including the information in the - #: SACL. To read or write the SACL, you must request the ACCESS_SYSTEM_SECURITY access right. For more information - #: see SACL Access Right. - READ_CONTROL = 0x00020000 - #: Required to modify the DACL in the security descriptor for the object. - WRITE_DAC = 0x00040000 - #: Required to change the owner in the security descriptor for the object. - WRITE_OWNER = 0x00080000 - - -class TOKEN(enum.IntEnum): - STANDARD_RIGHTS_REQUIRED = 0x000F0000 - TOKEN_ASSIGN_PRIMARY = 0x0001 - TOKEN_DUPLICATE = 0x0002 - TOKEN_IMPERSONATE = 0x0004 - TOKEN_QUERY = 0x0008 - TOKEN_QUERY_SOURCE = 0x0010 - TOKEN_ADJUST_PRIVILEGES = 0x0020 - TOKEN_ADJUST_GROUPS = 0x0040 - TOKEN_ADJUST_DEFAULT = 0x0080 - TOKEN_ADJUST_SESSIONID = 0x0100 - TOKEN_ALL_ACCESS = ( - STANDARD_RIGHTS_REQUIRED | - TOKEN_ASSIGN_PRIMARY | - TOKEN_DUPLICATE | - TOKEN_IMPERSONATE | - TOKEN_QUERY | - TOKEN_QUERY_SOURCE | - TOKEN_ADJUST_PRIVILEGES | - TOKEN_ADJUST_GROUPS | - TOKEN_ADJUST_DEFAULT - ) - - -class SE_TOKEN_PRIVILEGE(enum.IntEnum): - """An access token contains the security information for a logon session. - The system creates an access token when a user logs on, and every process executed on behalf of the user has a copy - of the token. - """ - - SE_PRIVILEGE_ENABLED_BY_DEFAULT = 0x00000001 - SE_PRIVILEGE_ENABLED = 0x00000002 - SE_PRIVILEGE_REMOVED = 0x00000004 - SE_PRIVILEGE_USED_FOR_ACCESS = 0x80000000 - - -class MEMORY_STATE(enum.IntEnum): - """The type of memory allocation""" - #: Allocates memory charges (from the overall size of memory and the paging files on disk) - # for the specified reserved memory pages. The function also guarantees that when the caller later - # initially accesses the memory, the contents will be zero. - # Actual physical pages are not allocated unless/until the virtual addresses are actually accessed. - MEM_COMMIT = 0x1000 - #: XXX - MEM_FREE = 0x10000 - #: XXX - MEM_RESERVE = 0x2000 - #: Decommits the specified region of committed pages. After the operation, the pages are in the reserved state. - #: https://msdn.microsoft.com/en-us/library/windows/desktop/aa366894(v=vs.85).aspx - MEM_DECOMMIT = 0x4000 - #: Releases the specified region of pages. After the operation, the pages are in the free state. - #: https://msdn.microsoft.com/en-us/library/windows/desktop/aa366894(v=vs.85).aspx - MEM_RELEASE = 0x8000 - - -class MEMORY_TYPES(enum.IntEnum): - #: XXX - MEM_IMAGE = 0x1000000 - #: XXX - MEM_MAPPED = 0x40000 - #: XXX - MEM_PRIVATE = 0x20000 - - -class MEMORY_PROTECTION(enum.IntEnum): - """The following are the memory-protection options; - you must specify one of the following values when allocating or protecting a page in memory - https://msdn.microsoft.com/en-us/library/windows/desktop/aa366786(v=vs.85).aspx""" - - #: Enables execute access to the committed region of pages. - # An attempt to write to the committed region results in an access violation. - PAGE_EXECUTE = 0x10 - #: Enables execute or read-only access to the committed region of pages. - # An attempt to write to the committed region results in an access violation. - PAGE_EXECUTE_READ = 0x20 - #: Enables execute, read-only, or read/write access to the committed region of pages. - PAGE_EXECUTE_READWRITE = 0x40 - #: Enables execute, read-only, or copy-on-write access to a mapped view of a file mapping object. - # An attempt to write to a committed copy-on-write page results in a private - # copy of the page being made for the process. - # The private page is marked as PAGE_EXECUTE_READWRITE, and the change is written to the new page. - PAGE_EXECUTE_WRITECOPY = 0x80 - #: Disables all access to the committed region of pages. - # An attempt to read from, write to, or execute the committed region results in an access violation. - PAGE_NOACCESS = 0x01 - #: Enables read-only access to the committed region of pages. - # An attempt to write to the committed region results in an access violation. - # If Data Execution Prevention is enabled, - # an attempt to execute code in the committed region results in an access violation. - PAGE_READONLY = 0x02 - #: Enables read-only or read/write access to the committed region of pages. - # If Data Execution Prevention is enabled, attempting to execute code in the - # committed region results in an access violation. - PAGE_READWRITE = 0x04 - #: Enables read-only or copy-on-write access to a mapped view of a file mapping object. - # An attempt to write to a committed copy-on-write page results in a private copy of - # the page being made for the process. The private page is marked as PAGE_READWRITE, - # and the change is written to the new page. If Data Execution Prevention is enabled, - # attempting to execute code in the committed region results in an access violation. - PAGE_WRITECOPY = 0x08 - #: Pages in the region become guard pages. - # Any attempt to access a guard page causes the system to - # raise a STATUS_GUARD_PAGE_VIOLATION exception and turn off the guard page status. - # Guard pages thus act as a one-time access alarm. For more information, see Creating Guard Pages. - PAGE_GUARD = 0x100 - #: Sets all pages to be non-cachable. - # Applications should not use this attribute except when explicitly required for a device. - # Using the interlocked functions with memory that is mapped with - # SEC_NOCACHE can result in an EXCEPTION_ILLEGAL_INSTRUCTION exception. - PAGE_NOCACHE = 0x200 - #: Sets all pages to be write-combined. - #: Applications should not use this attribute except when explicitly required for a device. - # Using the interlocked functions with memory that is mapped as write-combined can result in an - # EXCEPTION_ILLEGAL_INSTRUCTION exception. - PAGE_WRITECOMBINE = 0x400 - - -SIZE_OF_80387_REGISTERS = 80 - - -class FLOATING_SAVE_AREA(ctypes.Structure): - """Undocumented ctypes.Structure used for ThreadContext.""" - _fields_ = [ - ('ControlWord', ctypes.c_uint), - ('StatusWord', ctypes.c_uint), - ('TagWord', ctypes.c_uint), - ('ErrorOffset', ctypes.c_uint), - ('ErrorSelector', ctypes.c_uint), - ('DataOffset', ctypes.c_uint), - ('DataSelector', ctypes.c_uint), - ('RegisterArea', ctypes.c_byte * SIZE_OF_80387_REGISTERS), - ('Cr0NpxState', ctypes.c_uint) - ] - - -MAXIMUM_SUPPORTED_EXTENSION = 512 - - -class ThreadContext(ctypes.Structure): - """Represents a thread context""" - - _fields_ = [ - ('ContextFlags', ctypes.c_uint), - ('Dr0', ctypes.c_uint), - ('Dr1', ctypes.c_uint), - ('Dr2', ctypes.c_uint), - ('Dr3', ctypes.c_uint), - ('Dr6', ctypes.c_uint), - ('Dr7', ctypes.c_uint), - ('FloatSave', FLOATING_SAVE_AREA), - ('SegGs', ctypes.c_uint), - ('SegFs', ctypes.c_uint), - ('SegEs', ctypes.c_uint), - ('SegDs', ctypes.c_uint), - ('Edi', ctypes.c_uint), - ('Esi', ctypes.c_uint), - ('Ebx', ctypes.c_uint), - ('Edx', ctypes.c_uint), - ('Ecx', ctypes.c_uint), - ('Eax', ctypes.c_uint), - ('Ebp', ctypes.c_uint), - ('Eip', ctypes.c_uint), - ('SegCs', ctypes.c_uint), - ('EFlags', ctypes.c_uint), - ('Esp', ctypes.c_uint), - ('SegSs', ctypes.c_uint), - ('ExtendedRegisters', ctypes.c_byte * MAXIMUM_SUPPORTED_EXTENSION) - ] - - -class MODULEINFO(ctypes.Structure): - """Contains the module load address, size, and entry point. - - attributes: - lpBaseOfDll - SizeOfImage - EntryPoint - - https://msdn.microsoft.com/en-us/library/windows/desktop/ms684229(v=vs.85).aspx - """ - - _fields_ = [ - ("lpBaseOfDll", ctypes.c_void_p), # remote pointer - ("SizeOfImage", ctypes.c_ulong), - ("EntryPoint", ctypes.c_void_p), # remote pointer - ] - - def __init__(self, handle): - self.process_handle = handle - - @property - def name(self): - modname = ctypes.c_buffer(ctypes.wintypes.MAX_PATH) - pymem.ressources.psapi.GetModuleBaseNameA( - self.process_handle, - ctypes.c_void_p(self.lpBaseOfDll), - modname, - ctypes.sizeof(modname) - ) - return modname.value.decode(locale.getpreferredencoding()) - - @property - def filename(self): - _filename = ctypes.c_buffer(ctypes.wintypes.MAX_PATH) - pymem.ressources.psapi.GetModuleFileNameExA( - self.process_handle, - ctypes.c_void_p(self.lpBaseOfDll), - _filename, - ctypes.sizeof(_filename) - ) - return _filename.value.decode(locale.getpreferredencoding()) - - -class SYSTEM_INFO(ctypes.Structure): - """Contains information about the current computer system. - This includes the architecture and type of the processor, the number - of processors in the system, the page size, and other such information. - - https://msdn.microsoft.com/en-us/library/windows/desktop/ms724958(v=vs.85).aspx - """ - - _fields_ = [ - ("wProcessorArchitecture", ctypes.c_ushort), - ("wReserved", ctypes.c_ushort), - ("dwPageSize", ctypes.c_ulong), - ("lpMinimumApplicationAddress", ctypes.c_ulong), - ("lpMaximumApplicationAddress", ctypes.c_ulonglong), - ("dwActiveProcessorMask", ctypes.c_ulong), - ("dwNumberOfProcessors", ctypes.c_ulong), - ("dwProcessorType", ctypes.c_ulong), - ("dwAllocationGranularity", ctypes.c_ulong), - ("wProcessorLevel", ctypes.c_ushort), - ("wProcessorRevision", ctypes.c_ushort) - ] - - -class MEMORY_BASIC_INFORMATION32(ctypes.Structure): - """Contains information about a range of pages in the virtual address space of a process. - The VirtualQuery and VirtualQueryEx functions use this structure. - - https://msdn.microsoft.com/en-us/library/windows/desktop/aa366775(v=vs.85).aspx - """ - _fields_ = [ - ("BaseAddress", ctypes.c_ulong), - ("AllocationBase", ctypes.c_ulong), - ("AllocationProtect", ctypes.c_ulong), - ("RegionSize", ctypes.c_ulong), - ("State", ctypes.c_ulong), - ("Protect", ctypes.c_ulong), - ("Type", ctypes.c_ulong) - ] - - @property - def type(self): - enum_type = [e for e in MEMORY_TYPES if e.value == self.Type] or None - enum_type = enum_type[0] if enum_type else None - return enum_type - - @property - def state(self): - enum_type = [e for e in MEMORY_STATE if e.value == self.State] or None - enum_type = enum_type[0] if enum_type else None - return enum_type - - @property - def protect(self): - enum_type = [e for e in MEMORY_PROTECTION if e.value == self.Protect] - enum_type = enum_type[0] if enum_type else None - return enum_type - - -class MEMORY_BASIC_INFORMATION64(ctypes.Structure): - _fields_ = [ - ("BaseAddress", ctypes.c_ulonglong), - ("AllocationBase", ctypes.c_ulonglong), - ("AllocationProtect", ctypes.c_ulong), - ("__alignment1", ctypes.c_ulong), - ("RegionSize", ctypes.c_ulonglong), - ("State", ctypes.c_ulong), - ("Protect", ctypes.c_ulong), - ("Type", ctypes.c_ulong), - ("__alignment2", ctypes.c_ulong), - ] - - @property - def type(self): - enum_type = [e for e in MEMORY_TYPES if e.value == self.Type] or None - enum_type = enum_type[0] if enum_type else None - return enum_type - - @property - def state(self): - enum_type = [e for e in MEMORY_STATE if e.value == self.State] or None - enum_type = enum_type[0] if enum_type else None - return enum_type - - @property - def protect(self): - enum_type = [e for e in MEMORY_PROTECTION if e.value == self.Protect] - enum_type = enum_type[0] if enum_type else None - return enum_type - - -PTR_SIZE = ctypes.sizeof(ctypes.c_void_p) -if PTR_SIZE == 8: # 64-bit python - MEMORY_BASIC_INFORMATION = MEMORY_BASIC_INFORMATION64 -elif PTR_SIZE == 4: # 32-bit python - MEMORY_BASIC_INFORMATION = MEMORY_BASIC_INFORMATION32 - - -class EnumProcessModuleEX(object): - """The following are the EnumProcessModuleEX flags - - https://msdn.microsoft.com/ru-ru/library/windows/desktop/ms682633(v=vs.85).aspx - """ - #: List the 32-bit modules - LIST_MODULES_32BIT = 0x01 - #: List the 64-bit modules. - LIST_MODULES_64BIT = 0x02 - #: List all modules. - LIST_MODULES_ALL = 0x03 - #: Use the default behavior. - LIST_MODULES_DEFAULT = 0x00 - - -class SECURITY_ATTRIBUTES(ctypes.Structure): - """The SECURITY_ATTRIBUTES structure contains the security descriptor for an - object and specifies whether the handle retrieved by specifying this structure - is inheritable. - - https://msdn.microsoft.com/en-us/library/windows/desktop/aa379560(v=vs.85).aspx - """ - _fields_ = [('nLength', ctypes.c_ulong), - ('lpSecurityDescriptor', ctypes.c_void_p), - ('bInheritHandle', ctypes.c_long) - ] - - -LPSECURITY_ATTRIBUTES = ctypes.POINTER(SECURITY_ATTRIBUTES) - - -class CLIENT_ID(ctypes.Structure): - #: http://terminus.rewolf.pl/terminus/structures/ntdll/_CLIENT_ID64_x64.html - _fields_ = [ - ("UniqueProcess", ctypes.c_void_p), - ("UniqueThread", ctypes.c_void_p), - ] - - -class THREAD_BASIC_INFORMATION(ctypes.Structure): - _fields_ = [ - ("ExitStatus", pymem.ressources.ntdll.NTSTATUS), - ("TebBaseAddress", ctypes.c_void_p), - ("ClientId", CLIENT_ID), - ("AffinityMask", ctypes.c_long), - ("Priority", ctypes.c_long), - ("BasePriority", ctypes.c_long) - ] - - -# TEB -class TIB_UNION(ctypes.Union): - _fields_ = [ - ("FiberData", ctypes.c_void_p), - ("Version", ctypes.c_ulong), - ] - - -class NT_TIB(ctypes.Structure): - _fields_ = [ - ("ExceptionList", ctypes.c_void_p), # PEXCEPTION_REGISTRATION_RECORD - ("StackBase", ctypes.c_void_p), - ("StackLimit", ctypes.c_void_p), - ("SubSystemTib", ctypes.c_void_p), - ("u", TIB_UNION), - ("ArbitraryUserPointer", ctypes.c_void_p), - ("Self", ctypes.c_void_p), # PNTTIB - ] - - -class SMALL_TEB(ctypes.Structure): - _pack_ = 1 - - _fields_ = [ - ("NtTib", NT_TIB), - ("EnvironmentPointer", ctypes.c_void_p), - ("ClientId", CLIENT_ID), - ("ActiveRpcHandle", ctypes.c_void_p), - ("ThreadLocalStoragePointer", ctypes.c_void_p) - ] diff --git a/worlds/zork_grand_inquisitor/vendor/pymem/thread.py b/worlds/zork_grand_inquisitor/vendor/pymem/thread.py deleted file mode 100644 index dd9a15930395..000000000000 --- a/worlds/zork_grand_inquisitor/vendor/pymem/thread.py +++ /dev/null @@ -1,58 +0,0 @@ -import ctypes - -import pymem.memory -import pymem.ressources.kernel32 -import pymem.ressources.ntdll -import pymem.ressources.structure - - -class Thread(object): - """ - Provides basic thread information such as TEB. - - Parameters - ---------- - process_handle: int - A handle to an opened process - th_entry_32: ThreadEntry32 - Target thread's entry object - """ - - def __init__(self, process_handle, th_entry_32): - self.process_handle = process_handle - self.thread_id = th_entry_32.th32ThreadID - self.th_entry_32 = th_entry_32 - self.teb_address = None - # teb should be tested, not working on x64 - # self.teb = self._query_teb() - - def _query_teb(self): - """Query current thread information to extract the TEB structure. - - :return: TEB information - :rtype: pymem.ressources.structure.SMALL_TEB - """ - THREAD_QUERY_INFORMATION = 0x0040 - - thread_handle = pymem.ressources.kernel32.OpenThread( - THREAD_QUERY_INFORMATION, False, self.th_entry_32.th32ThreadID - ) - res = pymem.ressources.structure.THREAD_BASIC_INFORMATION() - ThreadBasicInformation = 0x0 - - pymem.ressources.ntdll.NtQueryInformationThread( - thread_handle, - ThreadBasicInformation, - ctypes.byref(res), - ctypes.sizeof(res), - None - ) - self.teb_address = res.TebBaseAddress - data = pymem.memory.read_bytes( - self.process_handle, - res.TebBaseAddress, - ctypes.sizeof(pymem.ressources.structure.SMALL_TEB) - ) - teb = pymem.ressources.structure.SMALL_TEB.from_buffer_copy(data) - pymem.ressources.kernel32.CloseHandle(thread_handle) - return teb