逆向工程实战手册 第 5 课

第五课:让钟自己走——动态分析

对应原书第 5 章《动态分析(GDB / 调试器)》


第五天,小林到铺子时,陈师傅正对着一只走不动的钟发愁。那只钟的齿轮看起来完好无损,表面也没有裂痕。

"师傅,这只钟怎么了?"

"你上回学到,拆开看(静态分析)能找到钥匙。但这只钟不一样——它表面上什么破绽都没有。"陈师傅敲了敲钟面,"它的机关,只有走起来才会露出来。"

"那就让它走啊。"

"说得对!"陈师傅笑了,"今天教你第二件本事:让钟自己走,然后盯着它每一步踩在哪。 我们管这叫'动态分析'。"

陈师傅把钟上好发条,拨到整点前。秒针开始滴答走动。

"你看——"他指着秒针,"它走到 59 秒的时候,会偷偷'停顿'一下,然后才咔哒到整点。这个停顿,静态看永远发现不了。只有让它走,才能看见。"

"那程序呢?"

"程序也一样。很多机关,只有运行起来才暴露。我们给它'上好发条',然后一步一停地盯着它。"


课程正文

动态分析 = 运行程序,观察它的行为。和静态分析(第 2-4 课)互补:静态看结构,动态看行为。

第一件工具:让程序"自报家门"(ltrace/strace)

上回我们学的 ltrace 就能让程序"说真话"。再复习一下,这次加深:

ltrace ./程序        # 跟踪它调用了哪些库函数
strace -f -s 500 ./程序   # 跟踪系统调用(-f 跟子进程,-s 显示长参数)

记住strcmp 这类"比较函数"被调用时,两个参数一目了然——答案经常直接露出来。

第二件工具:GDB(调试器)

GDB 是"放大镜+慢动作":

gdb ./程序
(gdb) b main          # 下断点:跑到 main 就停
(gdb) r               # 运行
(gdb) s / n           # 单步(一步一步走)
(gdb) c               # 继续
(gdb) x/s $rsi        # 查看寄存器指向的字符串
(gdb) x/20gx $rsp     # 查看栈上的 20 个值
(gdb) quit

核心技巧:断在比较点(第五课的重点)

还记得第三课的三板斧吗?strcmp(你的输入, 钥匙) —— 动态分析的用法是:

1. 在 strcmp 上下断点: b strcmp
2. 运行: r
3. 程序停在比较那一刻
4. 看两个参数: x/s $rdi(你的输入)  x/s $rsi(钥匙!)
$ gdb -q ./程序
(gdb) b strcmp
(gdb) r
Breakpoint 1, strcmp ()
(gdb) x/s $rsi
0x4052a: "s3cr3t_k3y_2024"       钥匙直接出现在眼前

一行搞定(不进入交互):

gdb -q -ex "b strcmp" -ex "run" -ex "x/s \$rsi" -ex "quit" ./程序

陈师傅的比喻

"静态分析是看图纸,动态分析是看表演。图纸上画不出的毛病,一表演就露馅。最好的钟表匠,两种都看。"


本课口诀

让钟自己走,断在比较点——它自己会把钥匙递到你面前。

动手做

  1. 对一个密码验证程序,用 ltrace 和 GDB 两种方式找出钥匙,对比体验。
  2. 练习 b strcmp + x/s $rsi 三板斧,直到闭着眼能敲出来。
  3. 想一想:如果程序把钥匙藏进算法里(不是直接比较),断点还找得到吗?(下节课见)

想学更深的

见原书 第 5 章《动态分析》——有内存转储、条件断点、watchpoint、rr 反向调试等进阶玩法。