memorytool 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- memorytool-1.0.0/PKG-INFO +8 -0
- memorytool-1.0.0/memorytool/__init__.py +4 -0
- memorytool-1.0.0/memorytool/core.py +104 -0
- memorytool-1.0.0/memorytool/deobfuscator.py +26 -0
- memorytool-1.0.0/memorytool.egg-info/PKG-INFO +8 -0
- memorytool-1.0.0/memorytool.egg-info/SOURCES.txt +10 -0
- memorytool-1.0.0/memorytool.egg-info/dependency_links.txt +1 -0
- memorytool-1.0.0/memorytool.egg-info/requires.txt +1 -0
- memorytool-1.0.0/memorytool.egg-info/top_level.txt +1 -0
- memorytool-1.0.0/pyproject.toml +14 -0
- memorytool-1.0.0/setup.cfg +4 -0
- memorytool-1.0.0/setup.py +10 -0
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import ctypes
|
|
2
|
+
import ctypes.wintypes
|
|
3
|
+
import psutil
|
|
4
|
+
import threading
|
|
5
|
+
import time
|
|
6
|
+
import re
|
|
7
|
+
|
|
8
|
+
# Windows Constants
|
|
9
|
+
PROCESS_ALL_ACCESS = 0x1F0FFF
|
|
10
|
+
MEM_COMMIT = 0x1000
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class MemoryTool:
|
|
14
|
+
def __init__(self, process_name: str):
|
|
15
|
+
self.kernel32 = ctypes.windll.kernel32
|
|
16
|
+
self.process_name = process_name
|
|
17
|
+
self.process_handle = None
|
|
18
|
+
self.pid = None
|
|
19
|
+
self.unity_module = None
|
|
20
|
+
self.is_il2cpp = False
|
|
21
|
+
self._frozen_values = {}
|
|
22
|
+
|
|
23
|
+
self._attach()
|
|
24
|
+
self._detect_unity()
|
|
25
|
+
|
|
26
|
+
def _attach(self):
|
|
27
|
+
for proc in psutil.process_iter(['name', 'pid']):
|
|
28
|
+
if proc.info['name'].lower() == self.process_name.lower():
|
|
29
|
+
self.pid = proc.info['pid']
|
|
30
|
+
break
|
|
31
|
+
if not self.pid:
|
|
32
|
+
raise Exception(f"Process {self.process_name} not found.")
|
|
33
|
+
self.process_handle = self.kernel32.OpenProcess(PROCESS_ALL_ACCESS, False, self.pid)
|
|
34
|
+
|
|
35
|
+
def _detect_unity(self):
|
|
36
|
+
if self.get_module_base("GameAssembly.dll"):
|
|
37
|
+
self.is_il2cpp = True
|
|
38
|
+
self.unity_module = "GameAssembly.dll"
|
|
39
|
+
elif self.get_module_base("mono-2.0-bdwgc.dll"):
|
|
40
|
+
self.is_il2cpp = False
|
|
41
|
+
self.unity_module = "mono-2.0-bdwgc.dll"
|
|
42
|
+
else:
|
|
43
|
+
self.unity_module = "UnityPlayer.dll"
|
|
44
|
+
|
|
45
|
+
def get_module_base(self, module_name: str):
|
|
46
|
+
process = psutil.Process(self.pid)
|
|
47
|
+
for module in process.memory_maps(grouped=False):
|
|
48
|
+
if module_name.lower() in module.path.lower():
|
|
49
|
+
return int(module.addr.split('-')[0], 16)
|
|
50
|
+
return None
|
|
51
|
+
|
|
52
|
+
def dump_dlls(self):
|
|
53
|
+
modules = {}
|
|
54
|
+
process = psutil.Process(self.pid)
|
|
55
|
+
for module in process.memory_maps(grouped=False):
|
|
56
|
+
name = module.path.split('\\')[-1]
|
|
57
|
+
if name not in modules:
|
|
58
|
+
addr = module.addr.split('-')[0]
|
|
59
|
+
modules[name] = addr
|
|
60
|
+
return modules
|
|
61
|
+
|
|
62
|
+
def read_memory(self, address, var_type):
|
|
63
|
+
buffer = var_type()
|
|
64
|
+
if self.kernel32.ReadProcessMemory(self.process_handle, ctypes.c_void_p(address), ctypes.byref(buffer),
|
|
65
|
+
ctypes.sizeof(buffer), None):
|
|
66
|
+
return buffer.value
|
|
67
|
+
return None
|
|
68
|
+
|
|
69
|
+
def read_raw(self, address, size):
|
|
70
|
+
buffer = (ctypes.c_char * size)()
|
|
71
|
+
if self.kernel32.ReadProcessMemory(self.process_handle, ctypes.c_void_p(address), buffer, size, None):
|
|
72
|
+
return buffer.raw
|
|
73
|
+
return None
|
|
74
|
+
|
|
75
|
+
def write_memory(self, address, value, var_type):
|
|
76
|
+
buffer = var_type(value)
|
|
77
|
+
return self.kernel32.WriteProcessMemory(self.process_handle, ctypes.c_void_p(address), ctypes.byref(buffer),
|
|
78
|
+
ctypes.sizeof(buffer), None)
|
|
79
|
+
|
|
80
|
+
def get_pointer_address(self, base_address: int, offsets: list):
|
|
81
|
+
addr = base_address
|
|
82
|
+
ptr_type = ctypes.c_uint64 if ctypes.sizeof(ctypes.c_void_p) == 8 else ctypes.c_uint32
|
|
83
|
+
for i, offset in enumerate(offsets):
|
|
84
|
+
if i == len(offsets) - 1:
|
|
85
|
+
addr += offset
|
|
86
|
+
else:
|
|
87
|
+
addr = self.read_memory(addr + offset, ptr_type)
|
|
88
|
+
if not addr: return None
|
|
89
|
+
return addr
|
|
90
|
+
|
|
91
|
+
def _freeze_worker(self, address, value, var_type):
|
|
92
|
+
while address in self._frozen_values:
|
|
93
|
+
self.write_memory(address, value, var_type)
|
|
94
|
+
time.sleep(0.01)
|
|
95
|
+
|
|
96
|
+
def freeze_value(self, address, value, var_type=ctypes.c_int):
|
|
97
|
+
if address in self._frozen_values: self.unfreeze_value(address)
|
|
98
|
+
thread = threading.Thread(target=self._freeze_worker, args=(address, value, var_type), daemon=True)
|
|
99
|
+
self._frozen_values[address] = True
|
|
100
|
+
thread.start()
|
|
101
|
+
|
|
102
|
+
def unfreeze_value(self, address):
|
|
103
|
+
if address in self._frozen_values:
|
|
104
|
+
del self._frozen_values[address]
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
class StringDeobfuscator:
|
|
2
|
+
@staticmethod
|
|
3
|
+
def xor_cipher(data: bytes, key: int) -> bytes:
|
|
4
|
+
return bytes([b ^ key for b in data])
|
|
5
|
+
|
|
6
|
+
@staticmethod
|
|
7
|
+
def caesar_cipher(text: str, shift: int) -> str:
|
|
8
|
+
result = ""
|
|
9
|
+
for char in text:
|
|
10
|
+
if char.isalpha():
|
|
11
|
+
start = ord('a') if char.islower() else ord('A')
|
|
12
|
+
result += chr((ord(char) - start - shift) % 26 + start)
|
|
13
|
+
else: result += char
|
|
14
|
+
return result
|
|
15
|
+
|
|
16
|
+
@staticmethod
|
|
17
|
+
def read_unity_string(mem, address: int):
|
|
18
|
+
import ctypes
|
|
19
|
+
# Unity strings: Header(0x10) -> Length(4 bytes) -> Data(UTF-16)
|
|
20
|
+
ptr_size = ctypes.sizeof(ctypes.c_void_p)
|
|
21
|
+
len_addr = address + (0x10 if ptr_size == 8 else 0x8)
|
|
22
|
+
length = mem.read_memory(len_addr, ctypes.c_int)
|
|
23
|
+
if length and 0 < length < 1024:
|
|
24
|
+
raw = mem.read_raw(len_addr + 4, length * 2)
|
|
25
|
+
return raw.decode('utf-16')
|
|
26
|
+
return ""
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
pyproject.toml
|
|
2
|
+
setup.py
|
|
3
|
+
memorytool/__init__.py
|
|
4
|
+
memorytool/core.py
|
|
5
|
+
memorytool/deobfuscator.py
|
|
6
|
+
memorytool.egg-info/PKG-INFO
|
|
7
|
+
memorytool.egg-info/SOURCES.txt
|
|
8
|
+
memorytool.egg-info/dependency_links.txt
|
|
9
|
+
memorytool.egg-info/requires.txt
|
|
10
|
+
memorytool.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
psutil>=5.9.0
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
memorytool
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "memorytool"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
description = "A powerful Unity memory tool with deobfuscator"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
authors = [{name = "iceglock66", email = "iceglockk@email.com"}]
|
|
11
|
+
dependencies = [
|
|
12
|
+
"psutil>=5.9.0",
|
|
13
|
+
]
|
|
14
|
+
requires-python = ">=3.7"
|