Skip to main content
Glama
RuoJi6

Memory Shell Detector MCP

by RuoJi6

remove_memory_shell

Remove a specified memory shell class from a running JVM process without restart, after AI analysis confirms it is malicious.

Instructions

执行 memory-shell-detector-cli.jar 从 JVM 内存中移除指定的内存马类

底层命令: java -jar memory-shell-detector-cli.jar -r <class_name> -p

此工具通过 Java Agent 技术从运行中的 JVM 进程中卸载/禁用指定的恶意类, 实现不重启服务的情况下清除内存马。

移除机制:

  • 对于 Filter/Servlet/Listener:从 Web 容器中注销

  • 对于 Spring 组件:从 Spring 容器中移除 Bean

  • 对于 Agent 类型:尝试还原被 hook 的方法

安全机制:首次调用时会先反编译目标类源码供 AI 分析确认, 确认是内存马后需设置 ai_confirmed=True 再次调用才会执行移除。

Args: class_name: 要移除的内存马完整类名 pid: 目标 Java 进程的 PID tools_dir: 检测工具 jar 包所在目录 ai_confirmed: AI 是否已确认该类为内存马(首次调用设为 False) use_ssh: 是否通过 SSH 在远程服务器执行 ssh_host/ssh_username/ssh_password/ssh_key_path/ssh_port: SSH 连接参数

Returns: 首次调用返回反编译源码供分析,确认后返回移除结果

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
class_nameYes
pidYes
tools_dirNo
ai_confirmedNo
use_sshNo
ssh_hostNo
ssh_usernameNo
ssh_passwordNo
ssh_key_pathNo
ssh_portNo

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Implementation Reference

  • The main handler function for the remove_memory_shell tool. Uses Java CLI jar to remove a memory shell class from a JVM process. Has a two-step safety mechanism: first call (ai_confirmed=False) shows decompiled source code for AI analysis, second call (ai_confirmed=True) executes the actual removal via 'java -jar cli.jar -r class_name -p pid'. Supports both local execution and SSH remote execution.
    @mcp.tool()
    def remove_memory_shell(
        class_name: str,
        pid: int,
        tools_dir: Optional[str] = None,
        ai_confirmed: bool = False,
        use_ssh: bool = False,
        ssh_host: Optional[str] = None,
        ssh_username: Optional[str] = None,
        ssh_password: Optional[str] = None,
        ssh_key_path: Optional[str] = None,
        ssh_port: int = 22
    ) -> dict:
        """
        执行 memory-shell-detector-cli.jar 从 JVM 内存中移除指定的内存马类
        
        底层命令: java -jar memory-shell-detector-cli.jar -r <class_name> -p <pid>
        
        此工具通过 Java Agent 技术从运行中的 JVM 进程中卸载/禁用指定的恶意类,
        实现不重启服务的情况下清除内存马。
        
        移除机制:
        - 对于 Filter/Servlet/Listener:从 Web 容器中注销
        - 对于 Spring 组件:从 Spring 容器中移除 Bean
        - 对于 Agent 类型:尝试还原被 hook 的方法
        
        安全机制:首次调用时会先反编译目标类源码供 AI 分析确认,
        确认是内存马后需设置 ai_confirmed=True 再次调用才会执行移除。
        
        Args:
            class_name: 要移除的内存马完整类名
            pid: 目标 Java 进程的 PID
            tools_dir: 检测工具 jar 包所在目录
            ai_confirmed: AI 是否已确认该类为内存马(首次调用设为 False)
            use_ssh: 是否通过 SSH 在远程服务器执行
            ssh_host/ssh_username/ssh_password/ssh_key_path/ssh_port: SSH 连接参数
        
        Returns:
            首次调用返回反编译源码供分析,确认后返回移除结果
        """
        if use_ssh:
            ssh_host, ssh_username, ssh_password, ssh_key_path, ssh_port = resolve_ssh_params(
                ssh_host, ssh_username, ssh_password, ssh_key_path, ssh_port
            )
            if not ssh_host or not ssh_username:
                return {"success": False, "action": "错误", "message": "SSH模式需要提供ssh_host和ssh_username,或设置SSH_HOST和SSH_USERNAME环境变量"}
        
        if not tools_dir:
            tools_dir = os.environ.get("TOOLS_DIR")
        if not tools_dir:
            return {"success": False, "action": "错误", "message": "未指定tools_dir,请先调用download_detector_tools或设置TOOLS_DIR环境变量"}
        
        cli_jar = os.path.join(tools_dir, "memory-shell-detector-cli.jar") if not use_ssh else f"{tools_dir}/memory-shell-detector-cli.jar"
        # SSH 连接到远程服务器通常是 Linux,本地执行根据当前系统判断
        is_windows = not use_ssh and platform.system().lower() == "windows"
        escaped_class_name = escape_class_name(class_name, for_windows=is_windows)
        
        if not ai_confirmed:
            view_cmd = f'java -jar "{cli_jar}" -v {escaped_class_name} -p {pid}'
            if use_ssh:
                result = execute_ssh_command(host=ssh_host, username=ssh_username, command=view_cmd, password=ssh_password, key_path=ssh_key_path, port=ssh_port)
            else:
                result = execute_local_command(view_cmd)
            
            return {
                "success": True,
                "action": "需要AI确认",
                "message": "请分析以下源代码,确认是否为内存马。如果确认是内存马,请再次调用此工具并设置ai_confirmed=True",
                "source_code": result["stdout"],
                "class_name": class_name,
                "pid": pid
            }
        
        remove_cmd = f'echo "y" | java -jar "{cli_jar}" -r {escaped_class_name} -p {pid}'
        
        if use_ssh:
            result = execute_ssh_command(host=ssh_host, username=ssh_username, command=remove_cmd, password=ssh_password, key_path=ssh_key_path, port=ssh_port)
        else:
            result = execute_local_command(remove_cmd)
        
        return {
            "success": result["success"],
            "action": "移除内存马",
            "result": result["stdout"],
            "error": result["stderr"] if not result["success"] else None,
            "class_name": class_name,
            "pid": pid
        }
  • The tool is registered via the @mcp.tool() decorator on the FastMCP instance named 'memory-shell-detector' (line 26). The FastMCP framework automatically registers the function as an MCP tool.
    @mcp.tool()
    def remove_memory_shell(
        class_name: str,
        pid: int,
        tools_dir: Optional[str] = None,
        ai_confirmed: bool = False,
        use_ssh: bool = False,
        ssh_host: Optional[str] = None,
        ssh_username: Optional[str] = None,
        ssh_password: Optional[str] = None,
        ssh_key_path: Optional[str] = None,
        ssh_port: int = 22
    ) -> dict:
  • Helper function used by remove_memory_shell to escape Java inner class names ($ separator) appropriately for the shell environment (Windows vs Unix).
    def escape_class_name(class_name: str, for_windows: bool = False) -> str:
        """
        转义类名中的特殊字符,防止 shell 解释
        
        Java 内部类使用 $ 分隔符(如 com.example.Outer$Inner),
        但 $ 在 Unix shell 中是变量引用符号,需要转义。
        Windows cmd/PowerShell 中 $ 不需要转义。
        
        Args:
            class_name: Java 完整类名
            for_windows: 是否为 Windows 系统
        
        Returns:
            转义后的类名
        """
        if for_windows:
            # Windows cmd 中 $ 不是特殊字符,无需转义
            return class_name
        else:
            # Unix shell (bash/zsh) 中需要转义 $
            return class_name.replace("$", "\\$")
  • Helper function used by remove_memory_shell to resolve SSH connection parameters, falling back to environment variables if not provided directly.
    def resolve_ssh_params(
        ssh_host: Optional[str],
        ssh_username: Optional[str],
        ssh_password: Optional[str],
        ssh_key_path: Optional[str],
        ssh_port: int
    ) -> tuple:
        """解析SSH参数,优先使用传入值,否则从环境变量读取"""
        ssh_config = get_ssh_config()
        return (
            ssh_host or ssh_config["host"],
            ssh_username or ssh_config["username"],
            ssh_password or ssh_config["password"],
            ssh_key_path or ssh_config["key_path"],
            ssh_port if ssh_port != 22 else ssh_config["port"]
        )
  • Helper function used by remove_memory_shell to execute commands locally via subprocess. Used for both the view/decompile step (ai_confirmed=False) and the removal step (ai_confirmed=True).
    def execute_local_command(command: str, timeout: int = 300) -> dict:
        """本地执行命令"""
        try:
            result = subprocess.run(
                command,
                shell=True,
                capture_output=True,
                text=True,
                timeout=timeout
            )
            return {
                "success": result.returncode == 0,
                "stdout": result.stdout,
                "stderr": result.stderr,
                "return_code": result.returncode
            }
        except subprocess.TimeoutExpired:
            return {
                "success": False,
                "stdout": "",
                "stderr": f"命令执行超时({timeout}秒)",
                "return_code": -1
            }
        except Exception as e:
            return {
                "success": False,
                "stdout": "",
                "stderr": str(e),
                "return_code": -1
            }
Behavior5/5

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

Without annotations, the description fully discloses behavior: it uses Java Agent to unload/disable classes, explains removal mechanisms per type (Filter/Servlet/Listener, Spring, Agent), and describes the two-phase safety mechanism. It also states return values for each phase. No contradictions.

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

Conciseness4/5

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

The description is well-structured with sections for purpose, command, mechanism, security, args, and returns. It is front-loaded with the main purpose. While it is somewhat long, every sentence adds value, and no redundancy is present. A slight further tightening could improve, but it's already effective.

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

Completeness5/5

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

The tool has an output schema, but the description covers the two-phase return. It addresses complexity: removal mechanisms, security confirmation, remote execution via SSH. No critical details are missing for an agent to use correctly. It is complete for the tool's purpose.

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

Parameters5/5

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

Schema coverage is 0%, so the description must compensate. It provides clear explanations for all 10 parameters in the 'Args' section, including the ai_confirmed workflow and SSH connection parameters. It adds meaning beyond the schema by explaining the roles of tools_dir and the ai_confirmed flag.

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 explicitly states the tool removes memory shells from JVM processes, using a specific verb ('remove') and resource ('memory shell'). It distinguishes from siblings (e.g., scan_process detects, this removes) and provides the underlying command.

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

Usage Guidelines5/5

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

The description details a two-step usage pattern: first call with ai_confirmed=False to decompile and confirm, then second call with ai_confirmed=True to execute removal. It also clarifies when to use (after detection) and implies when not (without prior confirmation). Siblings like view_class_code or scan_process are for different phases.

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/RuoJi6/memory-shell-mcp'

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