只是阅读有关不同的算法反汇编用于识别二进制作为汇编指令。在不同的反汇编程序中打开一个程序,一些程序显示程序的特定部分作为代码,其他部分显示与数据相同的部分。所以我的问题是,如果反汇编程序在操作码是指令或数据之间混淆,处理器如何确切地知道如何处理该操作码?
我希望我的问题很清楚...... 提前谢谢..
答案 0 :(得分:3)
只是阅读有关不同的算法反汇编用于识别二进制作为汇编指令。
由此我假设您的意思是线性扫描与递归遍历 - 在here上有一个有趣的页面。
所以我的问题是,如果反汇编程序在操作码是指令或数据之间混淆,那么处理器如何确切知道如何处理该操作码呢?
所以,问题的关键 - 他们没有也不关心。 CPU对数据与指令一无所知。这就是为什么你可以通过替换包含操作码的字符串从缓冲区溢出执行堆栈上的输入。这可以通过标记页面不执行来解决,在这种情况下,如果指令指针(EIP / RIP)结束,那么处理器就会引发故障(基本上是在OS上呻吟)。
反汇编的挑战在于,您正在尝试计算代码的结构,并执行实际运行它的所有内容。解决这个问题的唯一方法是生成一个x86模拟器并使用它。
这被称为halting problem。
答案 1 :(得分:3)
处理器不知道要求执行的是代码还是数据。它可以是同时或两者之一。 CPU将尝试执行它给出的任何内容。
如果无法执行,它可能会生成一个事件,例如“遇到无效指令”或“指令所引用的内存不可访问”或操作系统将“分零”或“权限不足”(希望)处理。如果它知道如何(虚拟内存通常基于此机制)或让应用程序处理此事件或终止应用程序,它将解决问题。
有不同的反汇编程序。有些是“愚蠢”的反汇编程序,因为它们不会尝试对可执行文件格式产生太多或任何意义,它们只会尝试反汇编它们给出的任何内容。其他人将反汇编标记为代码的文件部分,并且它们将从入口点位置开始反汇编(每个可执行文件都有一个应由OS / CPU启动的位置)并使用各种启发式方法进行合理的反汇编。 / p>
然而,拆卸几乎不可能完美。正确反汇编的主要问题是反汇编程序不知道代码片段将执行什么操作以及它不会执行什么操作。
例如,可以编写代码,以便计算要跳转或调用的地址。反汇编程序将无法计算这样的地址,因为它不会执行,模拟或解释代码。因此,反汇编程序可能无法找出要拆卸的下一个位置。
还有一些CPU具有可变长度指令。这使得代码可以跳转到指令的中间。反汇编程序应该如何反汇编这种代码呢?
另一个恶化的做法是使用代码进行操作。代码可以在执行时动态更改。代码也可以生成更多代码。代码也可以存储为数据。你如何拆解所有这些?
因此,许多反汇编者仍然非常愚蠢,这并不令人惊讶。他们只是无法与编写各种曲目程序的程序员的智力竞争。
修改强>:
此外,由于相同的可变长度指令问题,从稍微不同的位置开始反汇编相同的代码会产生不同的指令。
示例:
在32位模式下考虑x86处理器的这个字节序列:66h,0B8h,90h,90h,90h,90h。
如果您开始在第一个字节处对其进行反汇编,您将获得:
mov ax,9090h
nop
nop
如果您开始在下一个字节进行反汇编,您将获得:
mov eax,90909090h
如果你跳过另一个字节,你会得到:
nop
nop
nop
nop