关于 hopper-debugger
hopper-debugger 是使用 Hopper 反汇编器分析二进制文件并排查问题的开发技能,面向结合源码和运行时证据进行调试的开发者。它通过 mcporter 调用 Hopper 内置 MCP 服务,并提供查询、验证和故障处理流程。
主要功能
- 01查询反汇编文档
- 02搜索过程与字符串
- 03查看伪代码和过程信息
- 04结合 LLDB 与运行时证据验证
- 05排查 MCP 调用问题
适用场景
- 01检查二进制中的符号实现
- 02调查 macOS 框架行为
- 03用运行时探测验证反汇编假设
MCP 相关
通过 mcporter 连接 Hopper 6.0+ 自带的 MCP 服务,以 stdio 调用反汇编查询工具。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ steipete/ agent-scripts --skill hopper-debugger安装后在 Claude Code 中输入/hopper-debugger确认已加载。
附带文件agents/openai.yaml
详细介绍
Hopper 调试器
通过 mcporter 将 Hopper 用作可查询的反汇编器,再结合本地源码、LLDB、日志和针对性复现来分析。
设置(一次性)
Hopper 6.0+ 自带 MCP 服务。请勿安装第三方服务。
mcporter config add hopper --scope home \
--command "/Applications/Hopper Disassembler.app/Contents/MacOS/HopperMCPServer" \
--description "Hopper Disassembler built-in MCP server (stdio)"
必须使用 --scope home。默认范围是 project,会将 config/mcporter.json 写入当前所在的仓库(造成未跟踪文件污染,且会随工作树一起丢失)。
验证:
MCPORTER_LIST_TIMEOUT=25000 timeout 40 mcporter list hopper --brief
调用约定——最容易踩坑的地方
始终通过 --args 传递参数。切勿使用 --params。 mcporter 会静默接受未知的 --params 标志,丢弃载荷,导致调用不带参数。随后 Hopper 会返回 Document not found.,看起来像是许可证或状态问题,实际上并非如此。
# WRONG — arguments silently dropped, fails with "Document not found."
mcporter call hopper.list_segments --params '{"document":"AppKit"}'
# RIGHT
mcporter call hopper.list_segments --args '{"document":"AppKit"}'
另外,服务不会回退到当前文档。即使 current_document 返回了有效名称,不带 document 参数的调用也会失败。每次进行文档范围调用时都要传入 document。
文档名称来自 list_documents,且不带 .hop 扩展名(窗口标题 AppKit.hop → 文档名称 AppKit)。
如果调用仍然失败,请直接通过 stdio 驱动服务以查看原始 JSON-RPC——这会完全绕过 mcporter,并隔离问题所在:
"/Applications/Hopper Disassembler.app/Contents/MacOS/HopperMCPServer" <<'EOF'
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"p","version":"1"}}}
{"jsonrpc":"2.0","method":"notifications/initialized"}
{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"list_documents","arguments":{}}}
EOF
许可证——不要误判
Hopper 6.x 仍使用 bundle id 和偏好设置域 com.cryptic-apps.hopper-web-4。没有 hopper-web-6 域并不意味着应用未授权。请在“关于”面板中查看实际状态(Hopper Disassembler > About Hopper Disassembler);面板会显示被许可人、订单 ID 和更新计划到期时间。Hopper 6 中没有“注册/许可证”菜单项。
Peter 的许可证:订单 HOP140213-7833-95831,更新有效期至 2027-05-17。.hopperLicense 文件位于 1Password 中(Molty vault,文档条目 "Hopper Disassembler License (HOP140213-7833-95831)");加载 $one-password 即可取回。用 Hopper 打开 .hopperLicense 文件不会注册许可证——Hopper 会将其作为文档反汇编。
打开文档
open -a "Hopper Disassembler" /path/to/Binary
小型二进制文件无需对话框即可导入。大型框架需要几分钟;请轮询,而不要休眠等待:
until mcporter call hopper.list_documents --output json 2>/dev/null | grep -qi "appkit"; do sleep 10; done
首次打开时出现的任何对话框都应通过 Accessibility 按下按钮来关闭,切勿模拟点击——点击会移动 Peter 的实体指针:
osascript -e 'tell application "System Events" to tell process "Hopper Disassembler" to perform action "AXPress" of (button 1 of window 1)'
Apple 框架
Apple 框架位于 dyld 共享缓存中,而不在磁盘上。有两种方式:
- 优先使用 Peter 预先导出的文件,位于
~/Library/CloudStorage/Dropbox/Hopper/——其中有.hop文档和 AppKit、AccessibilityKit 等框架的.m伪代码转储。对.m使用 grep 往往比任何 MCP 往返都快(AppKit.m有 244 MB)。 将这些文件用于版本相关工作前,请检查其来源。 这些是快照;截至 2026-08,它们早于 macOS 26.6 和 27.0,其类/方法清单与这两个实时运行环境都不同。适合了解结构,但不适合可靠地比较操作系统版本差异。 - 使用
/usr/lib/dsc_extractor.bundle提取最新内容(macOS 自带;会提取所有 dylib,数据量达数 GB,速度较慢)。
查询工作流
- 从要解释的本地源码路径或运行时符号入手。
- 找到符号,然后一次检查一个小目标:
mcporter call hopper.search_procedures --args '{"document":"AppKit","pattern":"addCursorRect"}' --output json
mcporter call hopper.procedure_pseudo_code --args '{"document":"AppKit","procedure":"0x185475b2c"}' --output json
procedure 接受符号名称或十六进制地址。其他实用工具:list_documents、current_document、set_current_document、list_segments、list_procedures、list_strings、search_strings、procedure_info、procedure_address、current_procedure。
- 概述相关控制流;不要粘贴大段反编译内容。
- 在编辑应用代码前,使用 LLDB、日志或复现来验证假设。
与运行时证据配合
反汇编会告诉你值被写入哪个存储位置;只有运行时才能告诉你它是否确实写入了。先阅读伪代码,了解 API 实际写入了哪个 ivar/集合,然后在运行时通过 class_copyIvarList + object_getIvar + perform 读取那个确切的存储位置。对错误的(旧版)路径进行插桩是最典型的时间陷阱:在现代 AppKit 中,-[NSWindow _addCursorRect:cursor:forView:] 已是死代码,光标矩形存储在 _NSTrackingAreaAKViewHelper 的 cursorAreas 集合中。
在得出“回归”结论之前,务必在 OS 版本不同的第二台机器上运行同一个探测。几个空操作探测在已知正常和已知故障的 OS 上看起来都一样;对照运行才能告诉你探测测量到的其实是什么也没有。关于设备群,请参阅 $remote-mac;关于光标测量工具,请参阅 codexbar-ui-verification-quirks 记忆。
故障处理
- 使用
timeout包装 Hopper 调用;模态窗口或导入操作可能导致传输卡住。 - 导入期间不要并发发送 Hopper MCP 请求。
Connection closed通常意味着 Hopper 未运行或正显示模态窗口。通过 System Events 检查窗口,然后重试。Document not found.几乎总是意味着缺少参数(见上文的--args),而不是文档损坏。- 如果 mcporter 卡住,优先重启其守护进程,而不是大范围终止进程:
mcporter daemon stop && mcporter daemon start