scan_value
Perform initial memory scans to locate specific values in game processes for reverse engineering and modification purposes.
Instructions
Scan memory for exact value (initial scan).
Args:
value: Value to search for
value_type: Type ("int8", "int16", "int32", "int64", "float", "double", "string")
scan_regions: Memory protection to scan (default: "rw-" for data)
Returns:
Number of addresses found.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| value | Yes | ||
| value_type | No | int32 | |
| scan_regions | No | rw- |
Implementation Reference
- Core handler for the 'scan_value' MCP tool. Initializes scan state, packs the target value into bytes, injects Frida script to scan memory regions using Memory.scanSync, collects matching addresses, stores them in session state, and returns count of found addresses.@mcp.tool() def scan_value(value: Union[int, float, str], value_type: str = "int32", scan_regions: str = "rw-") -> Dict[str, Any]: """ Scan memory for exact value (initial scan). Args: value: Value to search for value_type: Type ("int8", "int16", "int32", "int64", "float", "double", "string") scan_regions: Memory protection to scan (default: "rw-" for data) Returns: Number of addresses found. """ global _session if not _session.is_attached(): return {"error": "Not attached. Use attach() first."} try: _session.scan_state = ScanState() _session.scan_state.value_type = value_type _session.scan_state.scan_active = True if value_type == "string": search_pattern = value.encode('utf-8').hex() else: search_pattern = _pack_value(value, value_type).hex() script_code = f""" var results = []; var pattern = "{search_pattern}"; var ranges = Process.enumerateRanges("{scan_regions}"); for (var i = 0; i < ranges.length && results.length < 100000; i++) {{ try {{ var matches = Memory.scanSync(ranges[i].base, ranges[i].size, pattern); for (var j = 0; j < matches.length && results.length < 100000; j++) {{ results.push(matches[j].address.toString()); }} }} catch (e) {{ }} }} send(JSON.stringify(results)); """ result_data = [] def on_message(message, data): if message['type'] == 'send': result_data.append(message['payload']) script = _session.session.create_script(script_code) script.on('message', on_message) script.load() script.unload() if not result_data: return {"error": "Scan failed"} import json addresses = json.loads(result_data[0]) _session.scan_state.results = [int(a, 16) for a in addresses] for addr in _session.scan_state.results[:1000]: _session.scan_state.last_values[addr] = value return { "success": True, "value": value, "value_type": value_type, "found": len(_session.scan_state.results), "message": f"Found {len(_session.scan_state.results)} addresses. Use scan_next() to narrow." } except Exception as e: return {"error": f"Scan failed: {str(e)}"}
- Dataclass that manages persistent scan state across scan_value, scan_next, etc. Used by scan_value to store results and value_type.@dataclass class ScanState: """Tracks memory scan state for Cheat Engine-style scanning.""" value_type: str = "" results: List[int] = field(default_factory=list) last_values: Dict[int, Any] = field(default_factory=dict) scan_active: bool = False
- Helper function to convert Python value to bytes in little-endian format based on value_type, used in scan_value to prepare search pattern.def _pack_value(value: Any, value_type: str) -> bytes: """Pack value to bytes based on type.""" formats = { "int8": "<b", "uint8": "<B", "int16": "<h", "uint16": "<H", "int32": "<i", "uint32": "<I", "int64": "<q", "uint64": "<Q", "float": "<f", "double": "<d" } fmt = formats.get(value_type) if fmt: return struct.pack(fmt, value) elif value_type == "string": return value.encode('utf-8') + b'\x00' return struct.pack("<i", int(value))
- Helper to get size in bytes for value types, used in subsequent scans like scan_next.def _get_value_size(value_type: str) -> int: """Get byte size for value type.""" sizes = { "int8": 1, "uint8": 1, "int16": 2, "uint16": 2, "int32": 4, "uint32": 4, "int64": 8, "uint64": 8, "float": 4, "double": 8 } return sizes.get(value_type, 4)