Skip to main content
Glama
0xhackerfren

Frida Game Hacking MCP

by 0xhackerfren

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
NameRequiredDescriptionDefault
valueYes
value_typeNoint32
scan_regionsNorw-

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultYes

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)
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden of behavioral disclosure. It mentions scanning memory and returning the number of addresses found, but does not cover critical aspects like whether this requires specific permissions, if it's read-only or destructive, potential side effects, rate limits, or error handling. For a memory scanning tool with zero annotation coverage, this is a significant gap in transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is appropriately sized and front-loaded, with the purpose stated first, followed by a structured breakdown of args and returns. Every sentence earns its place by providing essential information without redundancy, making it easy to parse and understand quickly.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (memory scanning with 3 parameters), no annotations, and an output schema that likely covers return values, the description is mostly complete. It explains the purpose, parameters, and return value, but lacks behavioral details like safety or performance implications. With the output schema handling returns, the description adequately covers core aspects but could improve on context.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It adds meaningful semantics beyond the schema by explaining each parameter: 'value' as the value to search for, 'value_type' with specific type options, and 'scan_regions' as memory protection with a default. This provides clear context that the schema lacks, though it could detail format constraints for 'scan_regions'.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Scan memory for exact value (initial scan).' It specifies the verb ('scan'), resource ('memory'), and scope ('exact value'), distinguishing it from siblings like scan_changed, scan_next, scan_pattern, and scan_unchanged. The mention of 'initial scan' further clarifies its role in a scanning workflow.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage context by noting it's for an 'initial scan,' suggesting it's the first step in a scanning process. However, it does not explicitly state when to use alternatives like scan_pattern or scan_next, nor does it provide exclusions or prerequisites. The context is clear but lacks explicit guidance on tool selection.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/0xhackerfren/frida-game-hacking-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server