get_scan_results
Retrieve current memory scan results with values to identify and analyze game data patterns during reverse engineering.
Instructions
Get current scan results with values.
Args:
limit: Maximum results to return (default: 20)
Returns:
List of addresses and their current values.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No |
Implementation Reference
- The handler function for the 'get_scan_results' MCP tool. It reads the current values from memory addresses stored in the scan state using Frida scripts, unpacks them according to the scan value type, and returns a list of results with addresses, values, and hex representations.@mcp.tool() def get_scan_results(limit: int = 20) -> Dict[str, Any]: """ Get current scan results with values. Args: limit: Maximum results to return (default: 20) Returns: List of addresses and their current values. """ global _session if not _session.scan_state.scan_active: return {"error": "No active scan. Use scan_value() first."} if not _session.is_attached(): return {"error": "Not attached. Use attach() first."} try: value_type = _session.scan_state.value_type value_size = _get_value_size(value_type) addresses = _session.scan_state.results[:limit] if not addresses: return {"total": len(_session.scan_state.results), "shown": 0, "results": []} addr_list = ", ".join(f'"{hex(a)}"' for a in addresses) script_code = f""" var addresses = [{addr_list}]; var size = {value_size}; var results = []; for (var i = 0; i < addresses.length; i++) {{ try {{ var data = Memory.readByteArray(ptr(addresses[i]), size); var hex = ''; var bytes = new Uint8Array(data); for (var j = 0; j < bytes.length; j++) {{ hex += ('0' + bytes[j].toString(16)).slice(-2); }} results.push({{address: addresses[i], hex: hex}}); }} catch (e) {{ results.push({{address: addresses[i], error: e.toString()}}); }} }} 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": "Failed to get results"} import json raw_results = json.loads(result_data[0]) results = [] for r in raw_results: if 'error' not in r: try: current_value = _unpack_value(bytes.fromhex(r['hex']), value_type) results.append({"address": r['address'], "value": current_value, "hex": r['hex']}) except: pass return { "total": len(_session.scan_state.results), "shown": len(results), "value_type": value_type, "results": results } except Exception as e: return {"error": f"Failed to get results: {str(e)}"}
- Dataclass that maintains the scan state (results list, value type, last values, active status) used by get_scan_results and other scan tools.@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 unpack memory bytes into the appropriate value type (int, float, string), used in get_scan_results to convert hex data to readable values.def _unpack_value(data: bytes, value_type: str) -> Any: """Unpack bytes to value 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.unpack(fmt, data)[0] elif value_type == "string": return data.split(b'\x00')[0].decode('utf-8', errors='replace') return struct.unpack("<i", data)[0]
- Helper function to determine the byte size of the scan value type, used to read the correct amount of memory in get_scan_results.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)