mcpField
H
hopper-debugger

hopper-debugger

github.com/steipete开发7.4k92 次安装1 周前更新
代码仓库

关于 hopper-debugger

hopper-debugger 是使用 Hopper 反汇编器分析二进制文件并排查问题的开发技能,面向结合源码和运行时证据进行调试的开发者。它通过 mcporter 调用 Hopper 内置 MCP 服务,并提供查询、验证和故障处理流程。

主要功能

  1. 01查询反汇编文档
  2. 02搜索过程与字符串
  3. 03查看伪代码和过程信息
  4. 04结合 LLDB 与运行时证据验证
  5. 05排查 MCP 调用问题

适用场景

  1. 01检查二进制中的符号实现
  2. 02调查 macOS 框架行为
  3. 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 共享缓存中,而不在磁盘上。有两种方式:

  1. 优先使用 Peter 预先导出的文件,位于 ~/Library/CloudStorage/Dropbox/Hopper/——其中有 .hop 文档和 AppKit、AccessibilityKit 等框架的 .m 伪代码转储。对 .m 使用 grep 往往比任何 MCP 往返都快(AppKit.m 有 244 MB)。 将这些文件用于版本相关工作前,请检查其来源。 这些是快照;截至 2026-08,它们早于 macOS 26.6 和 27.0,其类/方法清单与这两个实时运行环境都不同。适合了解结构,但不适合可靠地比较操作系统版本差异。
  2. 使用 /usr/lib/dsc_extractor.bundle 提取最新内容(macOS 自带;会提取所有 dylib,数据量达数 GB,速度较慢)。

查询工作流

  1. 从要解释的本地源码路径或运行时符号入手。
  2. 找到符号,然后一次检查一个小目标:
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。

  1. 概述相关控制流;不要粘贴大段反编译内容。
  2. 在编辑应用代码前,使用 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

评论

支持 Markdown