1. 开篇:为什么人类看不懂反汇编?

也许不是所有的人不适合看反汇编总有人天赋异禀?就像传说中的“人肉逆向机”一样。

总有人天赋异禀?就像传说中的人肉逆向机一样。

反正我是做不到的啦~~我只是个普通的平凡人类。

身为人类的局限

人类短期记忆的容量大概在7个数字左右(左右范围是5到9个)这是著名的心理学家。。。。(嗯。。。他的名字超过了7个字母,所以我没记住)的研究结果。

ref:1956年George Miller论文 http://www.psychspace.com/psych/viewnews-12308

有兴趣的可以去:https://humanbenchmark.com/tests/number-memory 自己测试一下“你”是不是有独特的记忆天赋,反正我这个人经常忘掉东西。

而常用的指令集比如x86_64,哪怕把RIP/RBP/RSP/段寄存器/标志位全不算,剩下的寄存器还有10多个呢。要知道,记住一个寄存器的状态可比记一个数字难多了。

看不懂的汇编

汇编语言的设计就不是给人类看的。我举个最典型的例子,条件分支。

比如这样的代码

if (a == b && a == c) {
	//do something
} else {
	//do something
}

编译成汇编后因为标志位的比较是独立的,汇编代码可能是这样

cmp a,b
jz LABEL_1
cmp a,c
jz_LABEL_1

如果有更加复杂的条件,循环,那就更是一坨了

来捣乱的编译器与伟大的F5

看不懂汇编和寄存器数量,他们还都不是主要的麻烦,可以通过反复训练+足够多的经验弥补。

最麻烦的还是编译器的优化,最典型的就是 指令选择+指令调度+寄存器分配+窥孔优化 (这几个话题每个都值得后面单独开一张来讲)

最终变成了一团奇奇怪怪的东西(尤其是大型软件的反编译)

幸好,我们还有反编译器来缓解这种问题。感谢伟大的F5。

为什么要学习这部分知识?

人类的局限告诉我们,绝大部分人是很难直接看懂反汇编的。

而逆向工程,尤其是对复杂软件的逆向工程,逆向目的往往不是看懂代码的每一处,而是在理解一段段业务在做什么,确认输入输出。而伟大的F5按钮能够极大的加速这个过程。

“但是,如果F5坏了或者不好用了怎么办!!!??”

这在逆向工作中太常见了,我举几个大家一定遇到过的例子:

  • 花指令

  • switch跳转识别不出来

  • IDA说什么什么sp-error栈平衡错误是啥意思,咋解决

  • F5代码里充满了goto,根本看不懂

  • F5代码全是结构体偏移的指针计算,根本不想看

  • 他这个二进制是c++、go、rust写的,简直一坨

  • <省略>

那么为什么会有这些问题,能不能解决,怎么解决?应该在哪一步编写插件?应该如何编写插件完成优化?

如果理解了反编译器的内部构造,就能大概回答这些问题。

Last updated