前言

IDA Pro 是逆向工程界的瑞士军刀,但真正强大的地方不仅仅是反汇编和 F5 反编译,更在于是一个可交互的数据库。分析一个复杂的程序(如 .so 文件、.exe 等)是一个漫长且需要迭代的过程。

核心理念: 我们的目标不是一次性看懂所有代码,而是把每次的理解都记录回 IDA 的数据库 (IDB) 中。添加的注释、重命名的函数、定义的结构体越多,这个程序就越“透明”。


基础导航与视图

掌握最基本的“移动”方式是最高效的。

  • Space (空格键):在汇编图表视图(Graph View)和汇编文本视图(Text View)之间切换。图表视图更直观,文本视图适合阅读线性逻辑。
  • F5最核心的功能。查看当前函数的 C 语言伪代码。 90% 的分析时间都应该在这里。
  • **\ (反斜杠)**:在 F5 伪代码窗口中,切换回对应的汇编代码视图。再次按下可切换回来。
  • **G (Go)**:跳转到指定地址或函数名。
  • X (Xrefs):查看交叉引用。即“谁调用了这个函数?”或“谁访问了这个数据?”。在函数名、变量名、字符串上按 X 是最常用的定位手段。
  • **Esc (Escape)**:在代码中后退。
  • **Ctrl + Enter**:在代码中前进。(与 Esc 对应)
  • **Tab**:在 F5 伪代码窗口中,按下 Tab 可以在伪代码和对应的汇编代码之间快速同步跳转。

关键技巧:注释与重命名

这是最需要养成习惯的部分。一个全是 sub_XXXXv5a1 的伪代码是无法阅读的。

重命名 (Rename) - 快捷键 N

重命名是给一个“地址”赋予一个有意义的“符号名”。不支持中文,必须遵循 C 语言的命名规范(英文、数字、下划线)。

为什么不支持中文? 因为 N 修改的是**标识符 (Identifier)**,会直接影响 F5 反编译出的伪代码。v5 = Calculate_Damage(a1); 是合法的 C 代码,但 v5 = 计算伤害(a1); 不是。

  • 重命名函数:在 sub_12345 上按 N -> 输入 ParseNetworkPacket
  • 重命名变量:在 F5 窗口的 a1v10 上按 N -> 输入 this_ptrdecrypted_buffer
  • 重命名全局数据:在 dword_ABCDE 上按 N -> 输入 g_PlayerConfig

添加注释 (Commenting)

IDA 提供三种注释,用途完全不同:

  • ; (分号) - 可重复注释 (Repeatable Comment)

    • 用途:给一个地址添加注释。所有引用这个地址的地方都会显示该注释。
    • 示例
      1. 在一个关键函数 sub_12345(已重命名为 DoLoginRequest)的开头按 :,输入:“登录包加密函数”。
      2. 在程序中任何调用 DoLoginRequest 的地方(例如 BL DoLoginRequest),旁边都会自动显示“登录包加密函数”的注释。
    • 一般用来:标记函数、全局变量、重要代码块的“一句话总结”。
  • : (冒号) - 普通注释 (Regular Comment)

    • 用途:给当前行添加注释。只在当前视图(汇编或 F5)的这一行显示。

    • 示例:在 F5 伪代码中:

      1
      2
      if ( v10 > 100 ) // ; 检查玩家等级是否超过100
      return -1; // ; 返回-1表示等级错误
    • 我用来:解释单行代码的复杂逻辑或意图。

  • ; (分号) - 函数注释 (Function Comment)

    • 用途:给整个函数添加一大段注释,会显示在函数的最开头。
    • 示例:在函数 ParseNetworkPacket 上按 Shift + ;,输入:
      1
      2
      3
      4
      此函数是网络包的核心处理函数。
      - 作用:解密、解压、分发。
      - 算法:AES-128-CBC
      - 注意:参数 a2 是一个 PlayerState 结构体指针。
    • 一般用来:写函数的详细分析文档。

逆向的灵魂:数据结构

分析 C++/C 代码的核心就是还原结构体和枚举。

结构体 (Structures) - 快捷键 Shift + F9

当看到大量的 [r0, #4][r0, #8] 或者 F5 里的 *(a1 + 4)*(a1 + 8) 时,a1 几乎 100% 是一个结构体指针。

工作流:

  1. 打开结构体窗口:按 Shift + F9
  2. 创建新结构体:按 Ins (Insert) 键,输入结构体名字,例如 PlayerState
  3. 定义成员
    • 光标停在 PlayerState 上,按 D 键来定义数据成员(比如 db 字节, dw 字, dd 双字, dq 四字)。
    • 技巧:如果不知道多大,就一直按 D,IDA 会帮创建 field_0, field_4, field_8
    • 可以按 N 重命名这些 field_ 成员,例如 field_0 改为 healthfield_4 改为 mana
    • 还可以按 Y 更改成员类型,例如把 field_8 的类型 dd (4字节) 改为 char*(一个指针)。
  4. 应用结构体
    • 回到 F5 伪代码窗口。
    • 找到那个被当作指针的变量(比如 a1)。
    • Y (Set Type)。
    • 输入类型:PlayerState* (注意,是指针 *)。
  5. 见证奇迹
    • 所有 *(a1 + 4) 会自动变成 a1->mana
    • 所有 *(a1 + 8) 会自动变成 a1->name
    • 代码可读性瞬间提升 100 倍。

枚举 (Enums) - 快捷键 Shift + F10

当看到 if (v5 == 1)if (v5 == 2) 这种“魔法数字”(Magic Number) 时,们很可能是枚举值。

工作流:

  1. 打开枚举窗口:按 Shift + F10
  2. 创建新枚举:按 Ins 键,输入枚举名字,例如 LoginStatus
  3. 添加成员:在 LoginStatus 上按 N,添加成员,例如 STATUS_SUCCESS = 0STATUS_FAILED = 1STATUS_BANNED = 2
  4. 应用枚举
    • 回到 F5 伪代码或汇编。
    • 光标停在那个数字 1 上。
    • M (Enum)。
    • 选择 STATUS_FAILED
  5. 见证奇迹
    • 代码从 if (v5 == 1) 变为 if (v5 == STATUS_FAILED)

如何保存与快速定位

如何保存?

不需要“保存笔记”!

我们所做的一切——重命名、注释、结构体——都会自动保存在 .idb (32位) 或 .i64 (64位) 数据库文件中。

  • 手动保存:按 Ctrl + W 可以随时保存当前数据库状态。
  • 备份这个 .i64 文件就是所有分析心血的结晶。一定要定期备份!
  • 快照File -> Take database snapshot... 可以在做“危险”操作(如运行未知脚本)前拍个快照,以便回滚。

下次打开如何快速定位?

当分析了几天后,如何快速找到上次的进度?

  • Shift + F4 - 名称窗口 (Names Window)

    • 最快、最常用的定位方式
    • 这里列出了所有重命名过的函数、变量、地址。
    • 打开后按 J 可以快速搜索命名的函数(例如 ParseNetworkPacket)。
  • Shift + F12 - 字符串窗口 (Strings Window)

    • 如果只记得某个函数里有一条 “Login Failed” 错误信息。
    • 打开字符串窗口,找到 “Login Failed”,按 X 查看交叉引用,就能瞬间定位到使用的函数。
  • Shift + F3 - 函数窗口 (Functions Window)

    • 列出所有函数。可以按名称排序,重命名过的函数会和 sub_... 分开,便于查找。
  • Alt + M / Ctrl + M - 书签 (Bookmarks)

    • Alt + M:在当前位置添加一个书签(可以写描述)。
    • Ctrl + M:打开书签列表,快速跳转。
    • 用途:标记“这个地方我还没看懂,明天再来”或“这里是核心,要常看”。
  • View -> Open subviews -> Comments - 注释窗口

    • 列出写过的所有中文注释。
    • 可以直接搜索的注释内容,然后双击跳转。

总结:一套高效的工作流

  1. **先看 Shift + F12 (字符串)**,找一些可疑的错误信息、URL、关键字。
  2. 对可疑字符串按 X (交叉引用),找到使用的函数。
  3. 在函数中按 F5 进入伪代码。
  4. 开始分析:
    • 看到 a1v5 不顺眼 -> 按 N 重命名为 player_ptrloop_index
    • 看到 [ptr + 8] -> Shift + F9 创建结构体,回来按 Y 应用。
    • 看到 if (v10 == 3) -> Shift + F10 创建枚举,回来按 M 应用。
    • 看懂了单行逻辑 -> 按 : 写中文行注释。
    • 看懂了函数功能 -> 按 N 重命名函数 (英文),再按 ; 写详细中文功能注释。
    • 发现是关键函数 -> 按 ; 添加一个简短的中文“可重复注释”。
  5. 分析累了 -> 按 Ctrl + W 保存 IDB。
  6. 第二天打开 -> 按 Shift + F4 (名称窗口) 或 Ctrl + M (书签) 快速回到昨天的进度。

逆向是一个迭代的过程。坚持做笔记,几周后,这个程序对来说就会像自己的源码一样清晰。