我遇到了一个正在分析的恶意软件,发现它使用某种数学运算法则来随机选择特定指令的寄存器

我不了解该操作的计算方式取决于

这是我的意思的一个例子

让我说我想为指令随机选择一个寄存器

ADD DWORD PTR DS:[0],EAX


我们知道该指令的操作码是01 05 00 00 00 00

粗体数字表示该指令的寄存器

05 == EAX
0D == ECX

为了更好地说明这一点,这里是带有所有寄存器的指令

0041580B    0105 00000000   ADD DWORD PTR DS:[0],EAX
00415811    010D 00000000   ADD DWORD PTR DS:[0],ECX
00415817    0115 00000000   ADD DWORD PTR DS:[0],EDX
0041581D    011D 00000000   ADD DWORD PTR DS:[0],EBX
00415823    0125 00000000   ADD DWORD PTR DS:[0],ESP
00415829    012D 00000000   ADD DWORD PTR DS:[0],EBP
0041582F    0135 00000000   ADD DWORD PTR DS:[0],ESI
00415835    013D 00000000   ADD DWORD PTR DS:[0],EDI


该恶意软件使用了寄存器索引从0(EAX)到7(EDI)开始

首先将数字与3进行SHLed,然后与5进行OR运算,以获取正确的寄存器操作码。那么我的问题是作者是如何得出结论的呢?

我要说SHL REG,3等于REG * 8,即最大寄存器数吗?但是为什么我们需要与05进行“或”运算呢?是因为该指令的起始操作码是05?

有人对此有更好的解释吗?或任何暗示性的词来更好地理解?

#1 楼

为了更好地理解这一点,您需要研究该问题的指令编码格式,例如x86。

x86指令如下所示

+----------------------+--------+--------+-----+--------------+-----------+
| Instruction prefixes | Opcode | ModR/M | SIB | Displacement | Immediate |
+----------------------+--------+--------+-----+--------------+-----------+
|          0-4         |   1-3  |   0-1  | 0-1 |      0-4     |    0-4    |
+----------------------+--------+--------+-----+--------------+-----------+


第二行上的数字表示相应部分的长度(以字节为单位)。对于该指令,

010D 00000000   ADD DWORD PTR DS:[0],ECX


没有指令前缀。
ADD的操作码是01(在此处检查)

指令的第二个字节,即ModR/M0D
ModR/M字节提供有关该指令的寻址信息。它指定操作数是在寄存器中还是在内存中;如果它在内存中,则字节内的字段指定要使用的寻址模式。

ModR/M字节可以分解为

+-----+------------+-----+
| Mod | Reg/Opcode | R/M |
+-----+------------+-----+
|  2  |      3     |  3  |
+-----+------------+-----+


此处第二行的数字表示相应部分的长度(以位为单位)。

Mod字段(2位)与R/M字段(3位)组合在一起,形成32个可能的值8个寄存器以及24种寻址模式。

Reg/Opcode字段(3位)指定寄存器号或其他三位操作码信息; r/m字段(3位)可以指定一个寄存器作为操作数的位置,也可以与Mod字段一起构成寻址模式编码的一部分。现在,转换ModR/M,即0D为二进制。您将得到。

+-----+------------+-----+
| Mod | Reg/Opcode | R/M |
+-----+------------+-----+
|  00 |     001    | 101 |
+-----+------------+-----+


ModR/M字段分别是00101。这表示仅位移寻址模式。请参见下表。



对于所有指令,均使用该寻址方式,因此OR设置为5(二进制101)的原因是为了设置该特定地址。位模式。

进入Reg/Opcode字段,它表示一个寄存器。
001ECX的寄存器索引。

对于第一个指令,即
0105 00000000 ADD DWORD PTR DS:[0],EAX
,该字段为000代表EAX。您可以通过将05转换为二进制来进行检查。

请参见从此处获取的下表中的更多内容。



所以基本上寄存器值是用3将其移动到正确的位置。 Reg / Opcode字段从右边起3位。最后最后4个字节是SHL。在此示例中,这表示位移为零。