是否可以反向解码x86-64指令?

时间:2018-09-20 00:12:09

标签: assembly x86 x86-64 disassembly machine-code

我想知道是否可以反向解码x86-64指令?

我需要一个运行时反汇编程序。用户可以指向内存中的随机位置,然后应该能够向上滚动并查看在指定地址之前出现了哪些指令。

我想通过反向解码来做到这一点。

2 个答案:

答案 0 :(得分:8)

x86指令的基本格式如下

x86 instruction format

现代CPU可以支持VEX和EVEX前缀。在x86-64中,开头可能还会有REX前缀

从格式上可以很容易地看出指令不是回文,而且您从头也看不懂。


关于确定任意地址属于哪条指令,不幸的是,由于x86指令不是self-synchronizable且(通常)未对齐,因此也无法执行。您必须确切地知道一条指令的开头,否则该指令将被不同地解码。

您甚至可以提供实际包含数据的地址,而CPU /反汇编程序仅将其解码为代码,因为没人知道这些字节的实际含义。跳转到指令中间通常用于代码混淆。过去该技术还被用于节省代码大小,因为一个字节可以重复使用,并且根据其所属的指令而具有不同的含义

话虽如此,由于函数和循环通常对齐16或32个字节,并且NOP填充

,因此在很多情况下猜测是可能的

答案 1 :(得分:7)

x86指令流不是自同步的,只能被明确地向前解码。您需要知道有效的解码起点。立即数的最后一个字节可以是0x90,它解码为nop,或者通常4个字节的立即数或位移可以具有有效指令的字节序列,或者其他可能与之重叠的字节ModRM / SIB字节看起来像操作码。

如果您在没有故意混淆的代码中向前解码,则通常会与“正确的”指令边界重新同步,因此您可以尝试将指令边界记为已知的好点,并检查解码是否正确从倒退的候选起始地址开始,在您的已知优点处具有指令边界。

IDK,如果您能更聪明地找到更多的已知优缺点,那么其他候选人也必须同意。

请务必以红色或灰色或其他某种方式突出显示用户的向后解码指令,以使他们知道不能保证该指令的可靠性。


另一种替代方法是要求使用函数符号(外部函数或带有调试信息的任何函数)。

除非您位于知道起始地址的函数中,否则GDB不允许您向上滚动(在layout reg模式下)。然后,我猜它是从函数的起始地址开始解码的,因此当它到达适合窗口的部分时,便知道了指令边界。

如果要向后退,则必须disas 0x12345, +16从那里开始解码。然后您可以向下滚动,但是如果您错误地插入了insn边界,则会产生垃圾。