iflow-mcp_bethington-cheat-engine-server-python 0.1.0__py3-none-any.whl

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.
Files changed (40) hide show
  1. iflow_mcp_bethington_cheat_engine_server_python-0.1.0.dist-info/METADATA +16 -0
  2. iflow_mcp_bethington_cheat_engine_server_python-0.1.0.dist-info/RECORD +40 -0
  3. iflow_mcp_bethington_cheat_engine_server_python-0.1.0.dist-info/WHEEL +5 -0
  4. iflow_mcp_bethington_cheat_engine_server_python-0.1.0.dist-info/entry_points.txt +2 -0
  5. iflow_mcp_bethington_cheat_engine_server_python-0.1.0.dist-info/licenses/LICENSE +21 -0
  6. iflow_mcp_bethington_cheat_engine_server_python-0.1.0.dist-info/top_level.txt +1 -0
  7. server/cheatengine/__init__.py +19 -0
  8. server/cheatengine/ce_bridge.py +1670 -0
  9. server/cheatengine/lua_interface.py +460 -0
  10. server/cheatengine/table_parser.py +1221 -0
  11. server/config/__init__.py +20 -0
  12. server/config/settings.py +347 -0
  13. server/config/whitelist.py +378 -0
  14. server/gui_automation/__init__.py +43 -0
  15. server/gui_automation/core/__init__.py +8 -0
  16. server/gui_automation/core/integration.py +951 -0
  17. server/gui_automation/demos/__init__.py +8 -0
  18. server/gui_automation/demos/basic_demo.py +754 -0
  19. server/gui_automation/demos/notepad_demo.py +460 -0
  20. server/gui_automation/demos/simple_demo.py +319 -0
  21. server/gui_automation/tools/__init__.py +8 -0
  22. server/gui_automation/tools/mcp_tools.py +974 -0
  23. server/main.py +519 -0
  24. server/memory/__init__.py +0 -0
  25. server/memory/analyzer.py +0 -0
  26. server/memory/reader.py +0 -0
  27. server/memory/scanner.py +0 -0
  28. server/memory/symbols.py +0 -0
  29. server/process/__init__.py +16 -0
  30. server/process/launcher.py +608 -0
  31. server/process/manager.py +185 -0
  32. server/process/monitors.py +202 -0
  33. server/process/permissions.py +131 -0
  34. server/process_whitelist.json +119 -0
  35. server/pyautogui/__init__.py +0 -0
  36. server/utils/__init__.py +37 -0
  37. server/utils/data_types.py +368 -0
  38. server/utils/formatters.py +430 -0
  39. server/utils/validators.py +340 -0
  40. server/window_automation/__init__.py +59 -0
@@ -0,0 +1,460 @@
1
+ """
2
+ Lua Interface Module
3
+ Handles Cheat Engine Lua script integration and execution
4
+ """
5
+
6
+ import logging
7
+ import re
8
+ import subprocess
9
+ import tempfile
10
+ import os
11
+ from typing import Dict, List, Optional, Any, Tuple
12
+ from dataclasses import dataclass
13
+
14
+ logger = logging.getLogger(__name__)
15
+
16
+ @dataclass
17
+ class LuaScript:
18
+ """Represents a Lua script from Cheat Engine"""
19
+ name: str
20
+ content: str
21
+ variables: List[str]
22
+ functions: List[str]
23
+ dependencies: List[str]
24
+ safe_to_execute: bool = False
25
+
26
+ class LuaInterface:
27
+ """Interface for Cheat Engine Lua script analysis and limited execution"""
28
+
29
+ def __init__(self):
30
+ self.lua_available = self._check_lua_availability()
31
+ self.safe_functions = self._get_safe_functions()
32
+ self.dangerous_patterns = self._get_dangerous_patterns()
33
+
34
+ def _check_lua_availability(self) -> bool:
35
+ """Check if Lua interpreter is available"""
36
+ try:
37
+ result = subprocess.run(['lua', '-v'], capture_output=True, text=True, timeout=5)
38
+ return result.returncode == 0
39
+ except (subprocess.TimeoutExpired, FileNotFoundError):
40
+ logger.info("Lua interpreter not available - script execution disabled")
41
+ return False
42
+
43
+ def _get_safe_functions(self) -> set:
44
+ """Get list of safe Lua functions that can be executed"""
45
+ return {
46
+ # Basic Lua functions
47
+ 'print', 'type', 'tostring', 'tonumber', 'pairs', 'ipairs',
48
+ 'next', 'select', 'unpack', 'rawget', 'rawset', 'rawlen',
49
+ 'getmetatable', 'setmetatable',
50
+
51
+ # Math functions
52
+ 'math.abs', 'math.acos', 'math.asin', 'math.atan', 'math.atan2',
53
+ 'math.ceil', 'math.cos', 'math.cosh', 'math.deg', 'math.exp',
54
+ 'math.floor', 'math.fmod', 'math.frexp', 'math.huge', 'math.ldexp',
55
+ 'math.log', 'math.log10', 'math.max', 'math.min', 'math.modf',
56
+ 'math.pi', 'math.pow', 'math.rad', 'math.random', 'math.randomseed',
57
+ 'math.sin', 'math.sinh', 'math.sqrt', 'math.tan', 'math.tanh',
58
+
59
+ # String functions
60
+ 'string.byte', 'string.char', 'string.dump', 'string.find',
61
+ 'string.format', 'string.gmatch', 'string.gsub', 'string.len',
62
+ 'string.lower', 'string.match', 'string.rep', 'string.reverse',
63
+ 'string.sub', 'string.upper',
64
+
65
+ # Table functions
66
+ 'table.concat', 'table.insert', 'table.maxn', 'table.remove',
67
+ 'table.sort', 'table.unpack'
68
+ }
69
+
70
+ def _get_dangerous_patterns(self) -> List[str]:
71
+ """Get patterns that indicate dangerous operations"""
72
+ return [
73
+ # File operations
74
+ r'\bio\b', r'\bfile\b', r'dofile', r'loadfile',
75
+
76
+ # Process/system operations
77
+ r'\bos\.\w+', r'\bexecute\b', r'\bsystem\b',
78
+
79
+ # Loading/requiring modules
80
+ r'\brequire\b', r'\bloadstring\b', r'\bload\b',
81
+
82
+ # Memory operations (CE specific)
83
+ r'\breadBytes\b', r'\bwriteBytes\b', r'\bgetAddress\b',
84
+ r'\bgetAddressList\b', r'\bmemoryrecord\b',
85
+
86
+ # Process manipulation
87
+ r'\bopenProcess\b', r'\bcloseHandle\b', r'\bVirtualAlloc\b',
88
+
89
+ # Registry operations
90
+ r'\bregistry\b', r'\breg_\w+',
91
+
92
+ # Network operations
93
+ r'\bsocket\b', r'\bhttp\b', r'\bftp\b',
94
+
95
+ # DLL operations
96
+ r'\bloadLibrary\b', r'\bgetProcAddress\b', r'\bcall\b'
97
+ ]
98
+
99
+ def analyze_script(self, script_content: str, script_name: str = "unknown") -> LuaScript:
100
+ """Analyze a Lua script for safety and extract information
101
+
102
+ Args:
103
+ script_content: The Lua script content
104
+ script_name: Name of the script
105
+
106
+ Returns:
107
+ LuaScript object with analysis results
108
+ """
109
+ try:
110
+ # Extract variables
111
+ variables = self._extract_variables(script_content)
112
+
113
+ # Extract functions
114
+ functions = self._extract_functions(script_content)
115
+
116
+ # Extract dependencies/requires
117
+ dependencies = self._extract_dependencies(script_content)
118
+
119
+ # Check safety
120
+ safe_to_execute = self._check_script_safety(script_content)
121
+
122
+ return LuaScript(
123
+ name=script_name,
124
+ content=script_content,
125
+ variables=variables,
126
+ functions=functions,
127
+ dependencies=dependencies,
128
+ safe_to_execute=safe_to_execute
129
+ )
130
+
131
+ except Exception as e:
132
+ logger.error(f"Error analyzing script {script_name}: {e}")
133
+ return LuaScript(
134
+ name=script_name,
135
+ content=script_content,
136
+ variables=[],
137
+ functions=[],
138
+ dependencies=[],
139
+ safe_to_execute=False
140
+ )
141
+
142
+ def _extract_variables(self, script_content: str) -> List[str]:
143
+ """Extract variable declarations from script"""
144
+ variables = []
145
+
146
+ # Look for local variable declarations
147
+ local_pattern = r'\blocal\s+([a-zA-Z_]\w*)'
148
+ matches = re.finditer(local_pattern, script_content)
149
+ for match in matches:
150
+ variables.append(match.group(1))
151
+
152
+ # Look for global variable assignments
153
+ global_pattern = r'^([a-zA-Z_]\w*)\s*='
154
+ matches = re.finditer(global_pattern, script_content, re.MULTILINE)
155
+ for match in matches:
156
+ var_name = match.group(1)
157
+ if var_name not in ['if', 'for', 'while', 'function', 'local', 'return']:
158
+ variables.append(var_name)
159
+
160
+ return list(set(variables)) # Remove duplicates
161
+
162
+ def _extract_functions(self, script_content: str) -> List[str]:
163
+ """Extract function definitions from script"""
164
+ functions = []
165
+
166
+ # Look for function definitions
167
+ function_pattern = r'\bfunction\s+([a-zA-Z_]\w*)\s*\('
168
+ matches = re.finditer(function_pattern, script_content)
169
+ for match in matches:
170
+ functions.append(match.group(1))
171
+
172
+ # Look for anonymous function assignments
173
+ anon_pattern = r'([a-zA-Z_]\w*)\s*=\s*function\s*\('
174
+ matches = re.finditer(anon_pattern, script_content)
175
+ for match in matches:
176
+ functions.append(match.group(1))
177
+
178
+ return functions
179
+
180
+ def _extract_dependencies(self, script_content: str) -> List[str]:
181
+ """Extract require statements and dependencies"""
182
+ dependencies = []
183
+
184
+ # Look for require statements
185
+ require_pattern = r'\brequire\s*\(\s*["\']([^"\']+)["\']\s*\)'
186
+ matches = re.finditer(require_pattern, script_content)
187
+ for match in matches:
188
+ dependencies.append(match.group(1))
189
+
190
+ return dependencies
191
+
192
+ def _check_script_safety(self, script_content: str) -> bool:
193
+ """Check if script is safe to execute"""
194
+
195
+ # Check for dangerous patterns
196
+ for pattern in self.dangerous_patterns:
197
+ if re.search(pattern, script_content, re.IGNORECASE):
198
+ logger.warning(f"Dangerous pattern found: {pattern}")
199
+ return False
200
+
201
+ # Check for suspicious function calls
202
+ suspicious_calls = [
203
+ 'os.execute', 'os.remove', 'os.rename', 'os.exit',
204
+ 'io.open', 'io.close', 'io.read', 'io.write',
205
+ 'debug.debug', 'debug.getfenv', 'debug.setfenv'
206
+ ]
207
+
208
+ for call in suspicious_calls:
209
+ if call in script_content:
210
+ logger.warning(f"Suspicious function call found: {call}")
211
+ return False
212
+
213
+ return True
214
+
215
+ def execute_safe_script(self, script: LuaScript, context: Dict[str, Any] = None) -> Dict[str, Any]:
216
+ """Execute a safe Lua script in a sandboxed environment
217
+
218
+ Args:
219
+ script: LuaScript object to execute
220
+ context: Optional context variables to provide to script
221
+
222
+ Returns:
223
+ Dictionary with execution results
224
+ """
225
+ if not self.lua_available:
226
+ return {
227
+ 'success': False,
228
+ 'error': 'Lua interpreter not available',
229
+ 'output': '',
230
+ 'variables': {}
231
+ }
232
+
233
+ if not script.safe_to_execute:
234
+ return {
235
+ 'success': False,
236
+ 'error': 'Script marked as unsafe for execution',
237
+ 'output': '',
238
+ 'variables': {}
239
+ }
240
+
241
+ try:
242
+ # Create sandboxed script
243
+ sandboxed_script = self._create_sandboxed_script(script.content, context)
244
+
245
+ # Execute in temporary file
246
+ with tempfile.NamedTemporaryFile(mode='w', suffix='.lua', delete=False) as f:
247
+ f.write(sandboxed_script)
248
+ temp_file = f.name
249
+
250
+ try:
251
+ # Execute with timeout
252
+ result = subprocess.run(
253
+ ['lua', temp_file],
254
+ capture_output=True,
255
+ text=True,
256
+ timeout=10 # 10 second timeout
257
+ )
258
+
259
+ return {
260
+ 'success': result.returncode == 0,
261
+ 'error': result.stderr if result.returncode != 0 else '',
262
+ 'output': result.stdout,
263
+ 'variables': self._extract_output_variables(result.stdout)
264
+ }
265
+
266
+ finally:
267
+ # Clean up temp file
268
+ try:
269
+ os.unlink(temp_file)
270
+ except OSError:
271
+ pass
272
+
273
+ except subprocess.TimeoutExpired:
274
+ return {
275
+ 'success': False,
276
+ 'error': 'Script execution timed out',
277
+ 'output': '',
278
+ 'variables': {}
279
+ }
280
+ except Exception as e:
281
+ return {
282
+ 'success': False,
283
+ 'error': f'Execution error: {e}',
284
+ 'output': '',
285
+ 'variables': {}
286
+ }
287
+
288
+ def _create_sandboxed_script(self, script_content: str, context: Dict[str, Any] = None) -> str:
289
+ """Create a sandboxed version of the script"""
290
+
291
+ sandbox_header = """
292
+ -- Sandboxed Lua execution environment
293
+ -- Disable dangerous functions
294
+ os = nil
295
+ io = nil
296
+ debug = nil
297
+ dofile = nil
298
+ loadfile = nil
299
+ loadstring = nil
300
+ load = nil
301
+
302
+ -- Provide safe context variables
303
+ """
304
+
305
+ # Add context variables if provided
306
+ context_vars = ""
307
+ if context:
308
+ for key, value in context.items():
309
+ if isinstance(value, str):
310
+ context_vars += f'{key} = "{value}"\n'
311
+ elif isinstance(value, (int, float)):
312
+ context_vars += f'{key} = {value}\n'
313
+ elif isinstance(value, bool):
314
+ context_vars += f'{key} = {str(value).lower()}\n'
315
+
316
+ return sandbox_header + context_vars + "\n-- Original script:\n" + script_content
317
+
318
+ def _extract_output_variables(self, output: str) -> Dict[str, Any]:
319
+ """Extract variables from script output"""
320
+ variables = {}
321
+
322
+ # Look for variable = value patterns in output
323
+ var_pattern = r'^(\w+)\s*=\s*(.+)$'
324
+
325
+ for line in output.split('\n'):
326
+ match = re.match(var_pattern, line.strip())
327
+ if match:
328
+ var_name = match.group(1)
329
+ var_value = match.group(2).strip()
330
+
331
+ # Try to parse the value
332
+ try:
333
+ if var_value.startswith('"') and var_value.endswith('"'):
334
+ variables[var_name] = var_value[1:-1] # String
335
+ elif var_value in ['true', 'false']:
336
+ variables[var_name] = var_value == 'true' # Boolean
337
+ elif '.' in var_value:
338
+ variables[var_name] = float(var_value) # Float
339
+ else:
340
+ variables[var_name] = int(var_value) # Integer
341
+ except ValueError:
342
+ variables[var_name] = var_value # Keep as string
343
+
344
+ return variables
345
+
346
+ def convert_ce_script_to_mcp(self, script: LuaScript) -> Dict[str, Any]:
347
+ """Convert a CE Lua script to MCP-compatible operations
348
+
349
+ Args:
350
+ script: LuaScript object to convert
351
+
352
+ Returns:
353
+ Dictionary with MCP-compatible operations
354
+ """
355
+ operations = []
356
+
357
+ # Analyze script content for memory operations
358
+ memory_reads = self._extract_memory_reads(script.content)
359
+ memory_writes = self._extract_memory_writes(script.content)
360
+ address_calculations = self._extract_address_calculations(script.content)
361
+
362
+ # Convert to MCP operations
363
+ for read_op in memory_reads:
364
+ operations.append({
365
+ 'type': 'read_memory',
366
+ 'address': read_op.get('address'),
367
+ 'size': read_op.get('size', 4),
368
+ 'data_type': read_op.get('type', 'uint32')
369
+ })
370
+
371
+ # Note: Write operations are not included for safety
372
+
373
+ return {
374
+ 'script_name': script.name,
375
+ 'safe_operations': operations,
376
+ 'variables': script.variables,
377
+ 'functions': script.functions,
378
+ 'original_safe': script.safe_to_execute
379
+ }
380
+
381
+ def _extract_memory_reads(self, script_content: str) -> List[Dict[str, Any]]:
382
+ """Extract memory read operations from script"""
383
+ reads = []
384
+
385
+ # Look for common CE memory read patterns
386
+ patterns = [
387
+ r'readBytes\(([^,]+),\s*(\d+)\)',
388
+ r'readInteger\(([^)]+)\)',
389
+ r'readFloat\(([^)]+)\)',
390
+ r'readString\(([^,]+),\s*(\d+)\)'
391
+ ]
392
+
393
+ for pattern in patterns:
394
+ matches = re.finditer(pattern, script_content)
395
+ for match in matches:
396
+ reads.append({
397
+ 'address': match.group(1).strip(),
398
+ 'size': int(match.group(2)) if len(match.groups()) > 1 else 4,
399
+ 'type': 'bytes' if 'Bytes' in pattern else 'integer'
400
+ })
401
+
402
+ return reads
403
+
404
+ def _extract_memory_writes(self, script_content: str) -> List[Dict[str, Any]]:
405
+ """Extract memory write operations from script"""
406
+ writes = []
407
+
408
+ # Look for write operations (for analysis only - not executed)
409
+ patterns = [
410
+ r'writeBytes\(([^,]+),\s*([^)]+)\)',
411
+ r'writeInteger\(([^,]+),\s*([^)]+)\)',
412
+ r'writeFloat\(([^,]+),\s*([^)]+)\)'
413
+ ]
414
+
415
+ for pattern in patterns:
416
+ matches = re.finditer(pattern, script_content)
417
+ for match in matches:
418
+ writes.append({
419
+ 'address': match.group(1).strip(),
420
+ 'value': match.group(2).strip(),
421
+ 'type': 'bytes' if 'Bytes' in pattern else 'integer'
422
+ })
423
+
424
+ return writes
425
+
426
+ def _extract_address_calculations(self, script_content: str) -> List[Dict[str, Any]]:
427
+ """Extract address calculation patterns"""
428
+ calculations = []
429
+
430
+ # Look for pointer arithmetic patterns
431
+ pointer_patterns = [
432
+ r'getAddress\(([^)]+)\)',
433
+ r'(\w+)\s*\+\s*0x([0-9A-Fa-f]+)',
434
+ r'\[\[([^\]]+)\]\s*\+\s*0x([0-9A-Fa-f]+)\]'
435
+ ]
436
+
437
+ for pattern in pointer_patterns:
438
+ matches = re.finditer(pattern, script_content)
439
+ for match in matches:
440
+ calculations.append({
441
+ 'expression': match.group(0),
442
+ 'base': match.group(1) if len(match.groups()) > 0 else None,
443
+ 'offset': match.group(2) if len(match.groups()) > 1 else None
444
+ })
445
+
446
+ return calculations
447
+
448
+ def get_script_summary(self, script: LuaScript) -> Dict[str, Any]:
449
+ """Get a summary of the script analysis"""
450
+ return {
451
+ 'name': script.name,
452
+ 'safe_to_execute': script.safe_to_execute,
453
+ 'variable_count': len(script.variables),
454
+ 'function_count': len(script.functions),
455
+ 'dependency_count': len(script.dependencies),
456
+ 'content_length': len(script.content),
457
+ 'variables': script.variables[:10], # First 10 variables
458
+ 'functions': script.functions,
459
+ 'dependencies': script.dependencies
460
+ }