使用教程

Hopper 是一款辅助您进行可执行文件静态分析的工具。本快速入门指南将为您提供 Hopper 的全面概览及其工作原理。

概述

Hopper 是一款功能丰富的应用程序,由于篇幅限制,无法在此一一详述所有功能,但请放心,您会很快找到门道,并轻松发现它的各种精妙之处。

Hopper 界面概览

界面分为三个主要区域:

  • 左侧面板包含文件中定义的所有符号列表以及字符串列表。列表可以使用 标签文本 进行筛选。
  • 右侧面板称为检查器。它包含当前所浏览区域的上下文信息。
  • 中间部分用于显示汇编语言及其各种表示形式。

核心概念

Hopper 背后的理念是将一组字节(即您要分析的二进制文件)转换为人类可读的内容。

为此,Hopper 会尝试 为文件的每个字节关联一个类型。由于手动操作成本极高,Hopper 会在您加载文件后立即进行自动分析。

Hopper 中可使用的各种类型包括:

  • Data(数据):当 Hopper 判断某个区域表示常量时(例如 int 数组),该区域将被设置为数据类型。
  • ASCII:以 NULL 结尾的 C 字符串。
  • Code(代码):一条指令。
  • Procedure(过程):当确定某个字节属于 Hopper 成功重建的方法时,该字节将被赋予此类型。
  • Undefined(未定义):Hopper 尚未探索的区域。

加载可执行文件后,您可以通过键盘或窗口顶部的工具栏手动更改类型。

Hopper 工具栏

工具栏包含每种类型对应的按钮(D 代表 DataA 代表 ASCII 等)。这些字母也是您可以直接使用的键盘快捷键。

Data 类型有一个特殊行为:首次使用时,Hopper 会将区域转换为一个字节。再次使用,字节将被转换为 16 位整数,然后是 32 位整数,依此类推……

请随意尝试各种转换来探索可执行文件:Hopper 提供了 撤销/重做 功能。

显示模式

阅读汇编语言有一定的难度,在某些情况下也比较枯燥。为了帮助您更好地理解代码,Hopper 可以使用多种表示方式来展示代码。

其中大部分表示方式需要先构建过程(Procedure),因为过程包含了代码结构的附加信息,例如基本块和栈使用情况。

可以通过工具栏切换当前模式:

显示模式工具栏

汇编模式

第一种模式是 汇编模式。Hopper 逐行打印汇编代码。这也是大多数反汇编器所提供的基本模式。

汇编模式

第一列(蓝色数字)表示指令地址,然后是指令助记符及其操作数(或参数)。作为可选项,您可以在应用偏好设置中选择在地址和指令助记符之间显示指令编码。

在边距中,您会看到一些彩色箭头。这些箭头表示跳转指令的可能目标。例如,在上面的截图中,地址 0x100002d820x100002db4 之间的蓝色箭头表示地址 0x100002d82 处的 je 指令在条件满足时可能跳转到地址 0x100002db4。当指令跳转到更大的地址(前向跳转)时,箭头为蓝色;如果跳转到更小的地址(后向跳转),箭头为红色。

请注意,在此表示方式中,点击红色列可以在相应地址设置断点,点击蓝色列可以设置书签。

控制流图

控制流图(CFG)模式以更结构化的方式展示过程。

控制流图模式

在此表示方式中,您仍然可以修改注释和标签等内容。光标可以在基本块之间移动;只需将光标移到当前基本块的边界,然后使用键盘方向键即可跳转到最近的基本块。按上下方向键时,光标会跳转到最近的基本块,但保持同一列的位置。例如,在以下情况中,光标将如图所示进行移动:

CFG 光标跳转示意

左右方向键的行为同理。

在右侧面板(检查器)中,您会找到一个专门的模式区域。控制流图组件会显示当前过程的缩小表示,称为 minimap(缩略图)。每个方块代表一个基本块,线条表示它们之间的连接。蓝色填充的方块表示包含光标的基本块。浅灰色方块表示主视图中当前绘制的方法区域。您可以直接在此缩略图中点击来移动视口。

CFG 缩略图

图形中的节点是可以修改的。例如,当您认为某些节点紧密相关时,可以将它们进行分组。选中节点后,点击检查器中的 Group Nodes(分组节点)按钮。

CFG 节点分组

您还可以为指定节点设置自定义背景颜色,或编辑打印的文本。

伪代码

在此模式下,Hopper 会生成伪代码,该伪代码在功能上等同于原始 CPU 指令,但表现形式更接近 Objective-C 方法。

伪代码模式

这无疑是阅读您正在分析的代码的最简便方式,但请牢记,这并非魔法:有时候,构建出完美的伪代码表示是不可能的,某些部分可能会消失,因为 Hopper 错误地判断了代码不可达(也称为 死代码)。为了缓解这个问题,您可以尝试切换视图顶部相应的复选框。

十六进制模式

此模式允许您直接查看文件的字节。

十六进制模式

第一列表示文件中的偏移量,其他列分别表示各个字节。当您将光标放在某个字节上时,会注意到选区自动向左和向右扩展。这是因为 Hopper 比普通的十六进制编辑器了解更多文件信息——例如,在上面的截图中,Hopper 知道光标位于一条指令内部,因此会选中该指令的所有字节。

双击某个字节即可更改其值。在某些情况下,这可能会破坏底层结构。例如,如果光标位于某条指令中,该指令将被自动销毁,并且关联的 Hopper 类型将回退到 Undefined(未定义)状态。此外,如果该指令是某个过程的一部分,则该过程也将被销毁。不过请放心,您随时可以回滚更改,因为 Hopper 提供了撤销/重做功能。

此表示方式中的列数取决于窗口的宽度;这是默认行为,但可以在应用偏好设置中更改。例如,您可以强制 Hopper 始终显示 16 列,而不受窗口宽度的影响。

修改文件

十六进制编辑器

如前所述,Hopper 提供了一个 十六进制编辑器。该编辑器与汇编语言视图同步,并会自动高亮显示属于当前指令的字节。

十六进制编辑器

双击某个字节即可对其进行修改。如果操作有误,可以使用撤销/重做功能。

汇编器

可以通过 Modify > Assemble Instruction…(修改 > 汇编指令…)菜单从 Hopper 中调用内嵌的汇编器。

汇编器

您还可以使用 Modify > NOP Region(修改 > NOP 填充区域)菜单将当前选中的指令替换为 NOP 指令。