逆向工程实战手册 第 3 课

第三课:第一次拆钟——找到那把钥匙

对应原书第 4 章《静态分析》完整工作流 + 第 5 章《动态分析》


第三天,陈师傅从柜台底下拿出一只"特别"的钟。它没有表盘,只有一堆齿轮,最中央挂着一把小小的铜锁。

"今天的功课:这把锁,钥匙是六个数字。你把它打开。"

小林翻来覆去看了看:"师傅,这……这不是钟吧?"

"是钟,也不是钟。"陈师傅说,"这是一只'会撒谎的钟'。它的齿轮都在正常转,但其中几个齿轮,是被'焊死'的——它们根本不是钟的一部分,是有人故意加进去的机关。我们的活儿,就是找出这几个'多余的齿轮',看看机关把真正的钥匙藏哪儿了。"

小林若有所思:"就像上一个程序?"

"对。上次我们用'听诊'找到了钥匙。这次它学乖了——它把钥匙藏起来了。听诊听不到,得。"

陈师傅把钟翻过来,露出齿轮背面刻着的一行小字:

ELF 64-bit LSB executable, x86-64, not stripped

"这是它的'出生证明'。"陈师傅指着小字,"写着:这是给 64 位电脑的程序,而且——没脱衣服。"

"没脱衣服?"

"意思是它的'零件标签'还在。你看——"

陈师傅敲了几个命令,屏幕上出现一长串齿轮名:

r2 -A 程序
[0x00400560]> afl
0x00400560  3   23  entry0
0x004005a6  4   99  sym.main           这是"大门"
0x004005c9  8   32  sym.check_key      这是"守卫"
0x004005e9  6   41  sym.decrypt        这是"密室"

"看到了吗?程序自己也标了名字:这个叫 main,是大门;这个叫 check_key,是守卫;这个叫 decrypt,是密室。"

"所以钥匙在守卫那儿?"

"去看看。"

[0x004005a6]> s sym.check_key
[0x004005c9]> pdf

屏幕上出现了守卫的"齿轮图"——一行行看不懂的符号。但陈师傅指着一行:

mov rsi, 0x0040052a     ; ← 这里!守卫手里攥着一样东西
call strcmp             ; ← 它要把你的输入和这个东西比一比

"看见了吗?守卫把'某个地址'的东西拿出来和你的输入比较。那个地址里放的就是钥匙。"

[0x004005c9]> psz @ 0x0040052a
19640807

小林凑近一看——六个数字:19640807

他赶紧把钟上的锁转到 19640807。"咔哒"一声,锁开了。


课程正文

刚才你看到了逆向的完整"三件套"流程:

1. 听诊(strings / file)      → 先听它说什么
2. 拆开(r2 -A / IDA / Ghidra)→ 再拆它骨头
3. 找关键点(xref / 交叉引用) → 顺着线索摸到答案

核心概念:交叉引用(xref)

程序里,任何东西都不是孤立的:字符串会被人"引用",函数会被人"调用"。交叉引用就是"谁在用它"的地图。

你想知道: 这个字符串在哪被用?
→ axt 0x4052a        (radare2 命令)
→ 找到: main 里 0x5c9 处的 strcmp 用了它
→ 顺藤摸瓜: 到那个地址看它在干什么

口诀:跟着"谁引用它",就能从'它是什么'追到'它干什么'。

三个"第一次"必会命令

file 程序              # 出生证明(类型/架构)
r2 -A 程序             # 拆开(radare2 自动分析)
afl                    # 零件清单(所有函数)

关于"比较"——程序的心跳

还记得第一课的口诀吗?程序只会比较和跳转。 刚才的守卫,本质就是在做一件事:

strcmp(你的输入, 地址里的钥匙)   ; 比较
test eax, eax                   ; 看结果
jne 走错分支                     ; 不等于就拒绝

看懂这三行,你就看懂了 80% 的"验证类程序"。不管是注册码、密码还是 flag 校验,最后都是这三板斧。

如果它把钥匙藏得更深?

钥匙可能会被"加密"(下次课讲),但思路不变:

先听(strings)
→ 再拆(看函数)
→ 找比较点(xref 到 strcmp / memcmp)
→ 在比较点停下来,看它拿什么和你的输入比
→ 那个东西,要么是钥匙,要么是算钥匙的原料

本课口诀

找比较点,看它比什么——比的那个东西,就是答案的入口。

动手做

  1. 自己写一个"输入密码"程序,编译后用 r2 -A 找到密码校验函数。
  2. 练习 axt:找一个字符串,追踪谁在用它。
  3. 想一想:如果钥匙不是明文,而是一个"加密结果",你怎么拿到真正的钥匙?(下节课)

想学更深的

见原书 第 4 章《静态分析》(完整 crackme 演示)、第 5 章《动态分析》(GDB 断点法)。