|
1. 需要一个设备可以读出binary code
2. 需要一个软件可以进行初步的反编译,把binary code -> asm code;这里可能需要指定头文件或者它只能把asm中的特殊寄存器用地址标识。
3. 将反汇编的代码整理成良好的格式,行标号(绝对地址),指令,参数,要用tab或者空格对齐。
4. 用excel将此文件导入成表格。
5. 然后把BRANCH(长跳转),CALL行过滤出来,当然最好也把JMP, JZ, JNC之类的跳转语句也过滤出来,但是这个太多了,而且大部分跳转都不是子程序之间的跳转,所以必要性不大。
反编译的程序最大的难点不在于如何读取源程序,而是经过编译器优化和LINKER处理之后(甚至还有Shuffle处理),它的逻辑分支已经变得异常混乱,大量逻辑雷同的代码会被合并,或者以不同的形态分布在很多地方,直接追踪main和中断向量入口将很难follow。所以我们需要对反汇编文件进行一些处理。
根据BR和CALL的列表,逐一将入口标定出来,每个入口写一个注释,标记该入口的功能,这要从最简短和最频繁的代码部分入手,EXCEL有个很大的好处是可以分类汇总,先把那些被调用次数超级多的地方标清楚。标记的时候很重要的一个地方是要标记return,那些branch/jmp到其他地方的语句,都需要一个RET返回,但是在asm代码中确不容易看清楚,这样的BR/JMP行后面要用空行和注释写明这里会遇到RETURN。
这一步骤相当繁琐,而且一些较长的历程也不可能就能看清楚功能,但是不必担心,这样的情况不会太多,留在最后处理;能把那些简短的调用,分支,标清楚入口的功能,参数表,和返回行,就足够了。
6. 现在是时候从main开始了解设置了。使用datasheet和header文件,仔细核对初始化的寄存器值,初始化的内存段,在纸上记下使用的内存段和寄存器/内存值。然后在主程序进入等待中断的时候,得到一个系统状态表。
7. 然后从各个中断向量表开始,遍历程序。这时候大部分子程序的功能都可以大致猜出来了。把还没有标明功能的子程序整理成一个列表,仍然从比较短小的开始,结合硬件的datasheet,观察协议和状态,尤其是状态,最好能画出系统和外设的状态图。如果这个状态图能画完整,那这个反编译的工作也就算结束了。
8. 对于不太确定的反编译结果,最后的办法就是把程序的汇编代码写入开发软件,可以在调试窗口看到机器码,和binary code仔细核对确保无误。
9. 程序的原作者可能犯错误,编译器有时候也不是那么明智,但是这些并不太重要;反编译的目的也并非搞懂每一句是怎么产生的或者编译器如何工作的,只要逻辑能分析出来,关键参数(尤其是协议和一些设置数据)可以获得,然后根据这些东西重新编写C或者asm程序,在系统上实际调试出来即可。
EXCEL的那个步骤很重要也很枯燥,我试了一个大约反编译之后有600行汇编代码的程序,这步的整理工作就需要一天到两天的时间;但是这步能走下来,后面的事情就简单多了。 |
|