根据英特尔文档,如何在操作码中编写这 4 个示例 x86 汇编指令?

逆向工程 部件 x86 二进制
2021-07-08 19:17:38

好的,所以我一直在学习英特尔手册第 2卷的第 2

我对 ModR/M 字节、REX 字节、SIB 字节和一般指令编码有尽可能好的理解(只是通过阅读而没有实践或实际修补)。现在,根据我的理解,“指令”编码不同于整个“调用”编码(正如我所说的那样):即指令加上操作数。这花了我几天的时间才意识到,我仍然不确定。

所以我现在将尝试将我的知识应用于这 4 种类型的呼叫。

opcode              instruction           operand encoding
04 ib               ADD AL, imm8          I
REX + 80 /0 ib      ADD r/m8*, imm8       MI
00 /r               ADD r/m8, r8          MR
REX.W + 03 /r       ADD r64, r/m64        RM

首先介绍一下背景:

  • ib 是一个无符号字节
  • imm[digit] 是一个立即数
  • 指令中的大写字母是寄存器
  • 操作数编码字母用于引用文档中的查找表,仅此而已。
  • r/m[digit] 表示寄存器或内存字节
  • r[digit] 表示仅寄存器字节

查看“指令操作数编码”表,我看到:

operand encoding    operand 1             operand 2
RM                  ModRM:reg (r, w)      ModRM:r/m (r)
MR                  ModRM:r/m (r, w)      ModRM:reg (r)
MI                  ModRM:r/m (r, w)      imm8
I                   AL/AX/EAX/RAX         imm8
  • (r) 表示读取操作数。
  • (w) 表示写入操作数。

所以我看到那些“操作数编码”字符串,如MR. 这给了我00 /r示例说明。所以我们有两个十六进制值,00,然后是/r. 我已经重读了它的意思十几遍,但仍然不知道它是什么意思。

我对上述所有部分都考虑了很多,但总觉得少了点什么。我还不能拼凑起来应用这些知识。

所以我已经迷路了。我刚刚研究了 ModRM、reg 和 r/m 的东西,但我不知道它们在这里是什么意思。回去重读。

ModR/M 字节是寻址形式说明符字节它分为 3 个部分或“字段”。

  • 所述与所述R / M字段字段结合形成32点可能的值:八个寄存器和24种寻址模式。
  • REG /操作码字段可指定的寄存器数或操作码的信息的三个更多的比特。reg/opcode 字段的用途在主操作码中指定。
  • R / M字段可以指定一个寄存器作为操作数,或者它可以与模场来编码寻址模式结合。

我们不必在这个问题中处理 SIB 代码。

这并没有真正给我任何可操作的信息。然后在表 2-1 到 2-3 中提供了 ModR/M 字节占用的每个值的丰富表格。我不确定列和行如何排列以及它们的含义。

所以,我不知道如何将这 4 个指令示例写成操作码,即使我要为它们随机选择寄存器或内存地址。

跳到第 3.1.1.1 节,我也研究了那里的所有关键字。

  • REX.W — 表示使用影响操作数大小或指令语义的 REX 前缀。
  • /digit — 0 到 7 之间的数字表示指令的 ModR/M 字节仅使用 r/m(寄存器或内存)操作数。reg 字段包含提供指令操作码扩展的数字。
  • /r — 表示指令的 ModR/M 字节包含一个寄存器操作数和一个 r/m 操作数。

这 3 个与上述说明相关。

然后是“表 3-1。寄存器代码”,我认为它向您展示了每个寄存器的十进制/二进制值是什么,这在此等式中的某处很有用。

我需要知道的差不多就是这些本书中的其他所有内容似乎都是个别说明的详细信息,或者我还不关心的高级说明信息(如VEX)。

但是到目前为止,我已经阅读了大约 5 次这些内容,但我仍然对如何编写 1 个指令调用没有深入的了解,目的是在不使用 gcc/clang/llvm/etc 的情况下编写机器代码生成器..

我也看到了这张图片,但完全不知道如何处理它。


在此处输入图片说明


根据英特尔文档,您如何在操作码中编写这 4 个示例 x86 汇编指令?如何解释上表中的“操作数编码”值?假设我们选择了一些符合上述指令类型约束的随机寄存器或内存插槽,那么您如何使用英特尔手册将其写成十六进制代码?

  • 到目前为止,有点帮助。
  • 也是。但遗憾的是还不够。
  • 也是。
1个回答

这个答案不是你寻求的正向工程答案

但是一个逆向工程的答案

有许多实用程序和框架可以对您选择的助记符进行编码

其中之一是梯形引擎(pip install keystone-engine for python binding)

使用这些实用程序之一,我们可以对我们寻求理解
的内容进行编码并查看编码的字节,并尝试理解那些
ib/r/modrm/sib/rex/lock 理论

下面显示的是使用 keystoneadd r,imm8变体的简单编码

from keystone import *
from binascii import *
print( "REGISTER_GROUP names are based on legends,epics&lores from arachnid yarn")
print( "ACCUMULATOR_REGISTER_GROUP  = [AL,AX,EAX,RAX]")
print( "BASE_REGISTER_GROUP         = [BL,BX,EBX,RBX]")
print( "COUNT_REGISTER_GROUP        = [CL,CX,ECX,RCX]")
print( "DATA_REGISTER_GROUP         = [DL,DX,EDX,RDX]")
print( "Mnemonic Add r,imm8")

CODE_R_IMM8 = [
b"add   al  ,0xff",
b"add   bl  ,0xff",
b"add   cl  ,0xff",
b"add   dl  ,0xff",
b"add   ax  ,0xff",
b"add   bx  ,0xff",
b"add   cx  ,0xff",
b"add   dx  ,0xff",
b"add   eax ,0xff",
b"add   ebx ,0xff",
b"add   ecx ,0xff",
b"add   edx ,0xff",
b"add   rax ,0xff",
b"add   rbx ,0xff",
b"add   rcx ,0xff",
b"add   rdx ,0xff"
]

for i in range (0,len(CODE_R_IMM8),1):
    print("%40s" % CODE_R_IMM8[i],end="\t")
    print(hexlify((Ks(KS_ARCH_X86,KS_MODE_64).asm(CODE_R_IMM8[i],0x10000000,as_bytes=True))[0]))

被执行

:\>python openc.py
REGISTER_GROUP names are based on legends,epics&lores from arachnid yarn
ACCUMULATOR_REGISTER_GROUP  = [AL,AX,EAX,RAX]
BASE_REGISTER_GROUP         = [BL,BX,EBX,RBX]
COUNT_REGISTER_GROUP        = [CL,CX,ECX,RCX]
DATA_REGISTER_GROUP         = [DL,DX,EDX,RDX]
Mnemonic Add r,imm8
                      b'add   al  ,0xff'        b'04ff'
                      b'add   bl  ,0xff'        b'80c3ff'
                      b'add   cl  ,0xff'        b'80c1ff'
                      b'add   dl  ,0xff'        b'80c2ff'
                      b'add   ax  ,0xff'        b'6605ff00'
                      b'add   bx  ,0xff'        b'6681c3ff00'
                      b'add   cx  ,0xff'        b'6681c1ff00'
                      b'add   dx  ,0xff'        b'6681c2ff00'
                      b'add   eax ,0xff'        b'05ff000000'
                      b'add   ebx ,0xff'        b'81c3ff000000'
                      b'add   ecx ,0xff'        b'81c1ff000000'
                      b'add   edx ,0xff'        b'81c2ff000000'
                      b'add   rax ,0xff'        b'4805ff000000'
                      b'add   rbx ,0xff'        b'4881c3ff000000'
                      b'add   rcx ,0xff'        b'4881c1ff000000'
                      b'add   rdx ,0xff'        b'4881c2ff000000'

您还可以参考此站点以了解所选 memmonic 的编码字节中的每个字节