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

use*_*459 7 x86 assembly x86-64 machine-code disassembly

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

我需要这个用于运行时解析器.用户可以指向内存中的随机位置,然后应该能够向上滚动并查看指定地址之前的指令.

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

phu*_*clv 8

x86指令的基本格式是这样的

x86指令格式

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

从格式看,很容易看出说明书不是回文,你不能从最后阅读.


关于确定任意地址属于哪个指令,遗憾的是它也不能完成,因为x86指令不是自同步的,并且(通常)不对齐.您必须确切地知道指令的开始,否则将以不同方式解码指令.

您甚至可以提供实际包含数据的地址,而CPU /反汇编程序只会将这些地址解码为代码,因为没有人知道这些字节实际意味着什么.跳到指令的中间通常用于代码混淆.该技术过去也已应用于代码大小保存,因为一个字节可以重用并具有不同的含义,具体取决于它属于哪个指令

也就是说,在许多情况下可能会猜测,因为函数和循环通常与16或32字节对齐,NOP填充在周围

  • 我不认为关于它不是回文的部分是相关的.也就是说,我不认为OP认为指令可能是回文并且回文拆卸不需要回文.作为一个简单的例子,固定长度的ISA不是回文(通常!),但可以反向拆解.你也可以有一个可变长度的ISA,虽然我不知道任何例子,但可以反向拆卸而不是回文. (3认同)
  • OP 询问是否可以_反汇编_。这涉及向后读取字节(简单!),然后反汇编。后面的部分是不可能的,因为这里的两个答案都显示,因为您不知道指令边界在哪里:但是整个回文的事情是一个红鲱鱼。例如,假设所有 x86 指令都以“0xFF”字节开头,并且由于编码规则,该字节从未出现在任何指令中的任何其他地方(特别是,您必须对排除它的立即值进行特殊编码)。然后你可以向后拆卸。 (2认同)

Pet*_*des 7

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

如果您在非故意混淆的代码中向前解码,您通常会重新与"正确"指令边界同步,因此您可能会尝试将指令边界记住为已知良好点,并检查从后向解码-step候选起始地址在您已知的好点处具有指令边界.

IDK,如果你能更聪明地找到更多已知的优点,那么候选人也必须同意.

请务必以红色或灰色或其他方式突出显示用户的向后解码指令,因此他们知道它不能保证可靠.


另一种方法是需要函数符号(外部函数或带调试信息的任何函数).

GDB不允许您向上滚动(在layout reg模式下),除非您在一个知道起始地址的函数内部.然后我猜它从函数起始地址解码,因此当它到达适合窗口的部分时,它知道指令边界.

如果你想倒退,你必须disas 0x12345, +16从那里开始解码.然后你可以向下滚动,但如果你得到insn边界错误你会得到垃圾.