ntobjmanager-mcp:把 Windows RPC 攻击面研究接进 AI agent

· 2026-09-30 08:00 · 27 阅读

原创 侠盗鲁平 2026-09-30 08:00 日本

GitHub: https://github.com/lupingQAQ/ntobjmanager-mcp

WeChat: IndexSec

获取

git clone https://github.com/lupingQAQ/ntobjmanager-mcp.git
# 依赖装一次
Install-Module NtObjectManager -Scope CurrentUser -Force
pip install -r requirements.txt          # mcp>=1.2.0
# 自检:三套测试,全绿再接客户端
python tests\smoke_test.py               # 17 项,MCP stdio 全链路
python tests\var_test.py                 # 10 项,store_as / __var__ 机制
python tests\audit.py                    # 43 项,恶意输入、并发、引擎杀死重启
# 起服务
python server.py                         # stdio MCP

Claude Code 一行接入:

claude mcp add ntobjectmanager-rpc -- python C:\path\to\ntobjmanager-mcp\server.py

OpenCode / 其它 MCP 客户端在配置里把 command 指到 python server.py 即可。

0x00 这是什么

一个 MCP server,22 个工具,底层是 James Forshaw 的 NtObjectManager(NtCoreLib)。AI agent 通过它拿到的是活的 Windows RPC 攻击面研究能力:解析 DLL 里的 RPC 服务器、查端点映射、生成客户端、真连上去调方法。

做两件事:

  1. 有状态的 RPC 连接。常驻 PowerShell 引擎把解析出的 RpcServer 对象、连上的客户端、调用产生的返回值全部留在进程里——rpc_connect 连一次,rpc_call 调多次,认证握手、上下文把手、会话变量跨工具调用不丢。

  2. 把固定流程做成固定工具。解析、连端点、找把手、查劫持面这类每次研究都要走的步骤,是一个工具调用,不用靠提示词现场拼 PowerShell。

每次工具调用都追加写入 output/mcp_audit.log,事后可审计。

0x01 一次工具调用经过什么

AI agent(Claude Code / OpenCode / 任意 MCP 客户端)
 └─ MCP stdio(server.py,22 个工具)
     └─ snippets.py(PowerShell 模板:@@TOKEN@@ 渲染 + ps_str 转义)
         └─ ps_engine.py(常驻 powershell.exe:base64 命令 + __MCP_DONE__ 完成标记 + 超时)
             └─ wrapper.ps1(状态全部放在 $RPCMCP = @{ Servers; Clients; vars })
                 └─ NtObjectManager / NtCoreLib → RPC 运行时(ALPC / 命名管道 / TCP)

引擎协议很简单:Python 侧把 PowerShell 命令 base64 编码后写进常驻进程的标准输入,等 __MCP_DONE__ 标记回来说明执行完,超时可杀可重启。状态模型三样东西——解析过的服务器、连着的客户端、store_as 存下来的对象——全挂在 $RPCMCP 上,进程活着就在。

0x02 工具清单

核心有状态管线(9 个):

工具

作用

rpc_parse

解析 PE 里的 RPC 服务器,缓存(键 file_N),可挂符号服务器解析函数名

rpc_state

列缓存的服务器 + 活着的会话

rpc_get_interface

过程、NDR 参数、上下文把手、strict 标记

rpc_query_endpoints

查端点映射,本地或远程(search_binding)

rpc_running_servers

按进程 / 服务枚举在跑的 RPC 服务器

rpc_connect

生成 C# 客户端并真连上(可走 EPM 自动发现绑定)

rpc_methods

方法签名带 opnum 映射

rpc_call

反射调用;{"__var__":...} 直接传上一次存的对象

rpc_disconnect

断开会话

方法论工具(13 个):

工具

干什么

rpc_scan_context_handles

上下文把手扫描,标出生产者([out] ctx)/ 消费者([in] ctx)对——CVE-2025-48815 同型面

rpc_inventory

攻击面清单 + 与端点映射交叉核对

rpc_fuzz

原语参数默认值试探,按 ok / 拒绝 / 报错分类;默认 dry-run

rpc_find_hijackable

找已停服务未注册的接口(EPM 投毒 / 抢注面)

rpc_etw_unreachable

ETW 抓"客户端在调不存在的服务"(要管理员)

rpc_interface_security

查 ALPC 端口安全描述符、匿名 ACE

rpc_decode_flagsRpcServerRegisterIf3

 注册标志位解码

rpc_format_client

导出生成的 C# 客户端源码,离线 grep 用

rpc_new_struct

构造 NDR 复杂类型存成会话变量

rpc_alpc_squat

ALPC 端口抢占 + 连接捕获(验证竞态用)

rpc_accessible_tasks

列当前用户可启动的 SYSTEM 计划任务

rpc_vars

 / rpc_clear_cache

会话变量与缓存管理(上限 150)

0x03 核心原语:返回值跨调用直传

rpc_call 带 store_as="h" 会把返回对象原样存进会话;下一次调用用 {"__var__":"h"} 直接引用。RPC 返回的对象不做序列化往返——上下文把手的生产者→消费者链测试正需要这个:拿到 A 类型的裸句柄,原样喂给收 B 类型把手的函数。

一套 CVE-2025-48815 同型的完整流程:

1. rpc_parse                 C:\Windows\System32\target.dll
2. rpc_scan_context_handles  ["C:\\Windows\\System32\\target.dll"]
3. rpc_get_interface         target_0        → 看 [out]/[in] 把手配对
4. rpc_connect               s1 target_0     → EPM 自动发现绑定并连上
5. rpc_methods               s1              → 带 opnum 的签名
6. rpc_call                  s1 <开把手方法> store_as="h"
7. rpc_call                  s1 <关把手方法> [{"__var__":"h"}]

第 6 步拿到的句柄对象,第 7 步原样传进去,中间没有任何转换。

0x04 能力边界

说法

实际情况

跨工具调用的有状态客户端

是,常驻引擎 + $RPCMCP

生产者→消费者把手链

是,store_as / __var__ 裸对象直传

自动确认类型混淆

否

——NDR 证明不了把手的多个类型,要靠逆向验证(见 XactSrv 那条)

完整恶意 RPC 服务端托管

否

——NtObjectManager 2.0.1 没有服务端构建器,rpc_alpc_squat 只覆盖竞态捕获

ETW 追踪 / ALPC SDDL 读取

要管理员权限

符号解析的函数名

看环境(symsrv 链),不行就落到启发式命名

0x06 免责声明

仅用于合法的安全研究、教学与获得明确授权的渗透测试。rpc_call 会真实调用 RPC 方法、可能打崩服务——只在隔离虚拟机上跑,不要对生产机或日常主机使用。

跳转微信打开

本文转载自微信公众号「Security丨Art」,查看原文。版权归原作者所有,如有侵权请联系删除。