x86是可变的指令长度,这意味着非常难以反汇编。如果这是您的第一个反汇编程序,不建议。
说了......我采取的方法是,您必须在二进制文件中标识操作码第一个字节的字节,并将其与操作码或数据中第二个或其他字节的字节分开。一旦您知道可以从二进制文件的开始处开始并反汇编操作码。
哟如何找出其他字节的操作码?你需要遍历所有可能的执行路径,听起来像递归问题,可能并不是必须的。查看中断向量表和/或代码中的所有硬件入口点。这给你一个操作码字节的简短列表。非递归方法是在二进制文件上进行许多遍历,查看标记为操作码的每个字节,对其进行解码就足以知道它消耗了多少字节。您还需要知道它是否是无条件分支,条件分支,返回,调用等。如果它不是无条件分支或返回,则可以在该指令之后假定该字节是下一条指令的第一个字节。每当遇到某种分支或调用时,计算目标地址,将该字节添加到列表中。继续进行传球,直到你完成一个没有添加新字节的传球。你还需要确保如果说你发现一个字节是一个3字节的指令,但是它之后的字节被标记为一条指令,那么你就有问题了。诸如有条件的分支之类的东西确保它们永远不会分支。如果高级代码编译为二进制文件,但是手写汇编程序的好时代,或者想要保护其代码的人会做这样的事情,您看不到这么多。
不幸的是,如果你所拥有的是二进制,对于一个可变长度的instruciton集,你不会得到一个完美的反汇编。一些分支目的地是在运行时计算的,有时候手动编译的程序集会在返回之前修改堆栈,然后再更改接下来执行的代码,如果这是代码的唯一路径,那么您可能不会编程计算出来,除非您尽可能来模拟代码。即使使用模拟,你也不会涵盖所有的执行路径。
对于像ARM这样的固定长度的指令集(只要它是手臂而不是手臂和拇指的混合),你可以简单地从二进制的开始处开始并拆卸,直到用完字。您可能会将数据字反汇编为有效或无效或不太可能被使用的指令,但这很好。
我不会感到惊讶,如果在精灵的某个地方有什么指示二进制文件的哪些部分是可执行的,哪些部分是数据。也许甚至是你不必走数据路径,我怀疑objdump执行一个任务,就像它可能使用了elf文件中的东西。
许多地方都记载了elf文件格式。有基本的结构,供应商可以添加供应商记录的特定块类型。
很好的答案!非常感谢您抽出时间来贡献 – 2010-10-02 20:46:17