我拆一个程序时的顺序
刚开始学逆向时最常见的错误是:拿到一个文件,直接拖进调试器,然后对着满屏汇编发呆。工具没错,顺序错了。
我现在的顺序是固定的五步,前面几步根本不用调试器。
一、先看它是什么
文件头、架构、编译器、有没有加壳。这一步决定后面所有动作:32 位要开 x32dbg,64 位开 x64dbg,加壳的先脱。用 PE 工具看一眼导入表就能判断很多东西——只导入了 LoadLibrary 和 GetProcAddress 的程序,基本可以确定是加壳或者动态解析。
二、看它跟外界说什么
字符串是最便宜的情报。错误提示、注册表路径、URL、文件后缀名——这些都是作者写代码时顺手留下的路标。一个有 SOFTWARE\... 的字符串,往往直接指向它存配置的地方;一句「密码错误」附近,几乎一定有条件判断。
这一步用静态工具做,Ghidra 的字符串清单加上交叉引用就够,不用跑起来。
三、看它调用了什么
导入表里出现 CreateFileW、RegSetValueExW、WSAStartup 这类 API,说明它的行为范围。真正的价值在于:找到了「它写文件」这个动作,就等于找到了一个可以下断点的地方,比盲猜函数入口高效得多。
四、跑起来,只观察
到这一步才开调试器,而且第一轮不下断点。就看它启动了哪些子进程、读了哪些文件、连了哪些地址。很多时候光这一步就能得到答案——比如想找它把配置放在哪,直接看它打开了什么文件就行,根本不用看汇编。
五、才开始读代码
有了前面四步的坐标,读反汇编才有方向:从字符串的交叉引用倒推函数,从 API 调用点往上看判断条件,从输入框的回调往上找校验逻辑。没有坐标的读代码是碰运气,有坐标的读代码是查地图。
一点补充
这套顺序的核心是「先便宜后贵」。看文件头几乎不要时间,读汇编要几小时。所以永远先做便宜的观察,让它把搜索范围缩小,再决定把时间花在哪。
另外,静态分析能解决的事不要动态跑。动态分析会改内存、留痕迹,有时候还会触发反调试;静态看完再决定跑不跑,省事也更安全。
工具是次要的。同样的顺序用 IDA、Ghidra、甚至只用 strings 加 Process Monitor 都能走一遍。