【问题标题】:Insert an undefined instruction in X86 code to be detected by Intel PIN在 X86 代码中插入一条未定义的指令以供 Intel PIN 检测
【发布时间】:2016-04-15 03:02:10
【问题描述】:

我正在使用基于 PIN 的模拟器来测试一些新的架构修改。我需要使用我的模拟器测试带有两个操作数(一个寄存器和一个内存位置)的“新”指令。

由于使用 GCC 机器描述仅添加一条指令很乏味,因此使用 NOP 或未定义指令似乎是合乎逻辑的。 PIN 可以很容易地使用INS_IsNop 检测 NOP 指令,但它会干扰自然添加到代码中的 NOP,它也没有操作数或单个内存操作数。

剩下的唯一选择是使用未定义的指令。未定义的指令永远不会干扰代码的其余部分,并且可以通过 PIN 使用INS_IsInvalid 检测到。

问题是我不知道如何使用 GCC 内联汇编添加未定义的指令(带有操作数)。我该怎么做?

【问题讨论】:

  • 从您的问题来看,您的问题是在 gcc 中发出未定义的指令。从您的评论看来,另一个问题是解码指令。您是否还有其他问题?

标签: gcc assembly x86 inline-assembly intel-pin


【解决方案1】:

尝试使用通常不适用于指令的前缀。例如

rep add eax, [rsi + rax*4 - 15]

会组装得很好。一些指令集扩展就是这样完成的。例如lzcnt 被编码为rep bsf,因此它在旧 CPU 上以bsf 执行,而不是生成非法指令异常。 (根据 x86 ISA 的要求,不适用的前缀将被忽略。)

这将让您利用汇编器对指令操作数进行编码的能力,正如 David Wohlferd 在他的回答中指出的那样,如果您使用 ud2,这将是一个问题。

【讨论】:

    【解决方案2】:

    所以事实证明 x86 有一个明确的“未知指令”(参见this)。 gcc 可以通过简单地使用:

    asm("ud2");
    

    至于带有操作数的未定义指令,我不确定这意味着什么。一旦你有一个未定义的操作码,额外的字节都是未定义的。

    但也许你可以通过以下方式得到你想要的:

    asm(".byte 0x0f, 0x0b");
    

    【讨论】:

    • 该指令仅对 GCC 未定义,对我而言,它代表了我的新指令。假设我的新指令是添加 ADD OP1,OP2。我会使用 PIN 提取操作数,然后插入对 INS_Delete() 的调用,这样指令就不会引发异常。
    • 如果目标是生成 GCC 不理解的 asm 操作码,那么您就很不走运了。 GCC 不解释操作码。将任何内容放入 asm 中,gcc 只会输出它。如果目标是输出汇编器不理解的操作码,那么您可以使用 asm("xxx 1,2") 并且汇编器将拒绝它。如果目标是输出 CPU 不理解的操作码,那么您可以使用“已知”的无效操作码 (ud2)。像asm(".byte 0x0f, 0x0b, 0x90, 0x90") 这样的东西怎么样。这应该会生成(看起来像)一个不会自然出现的 4 字节指令。
    • 你能解释一下为什么0x0f, 0x0b 很特别吗?它们是 x86 中的无效操作码,因此使用它们会导致非法指令吗?
    • @umopapisdn 查看 ud2 的 docs
    猜你喜欢
    • 2022-07-01
    • 2019-05-16
    • 2012-12-01
    • 2017-02-24
    • 2019-11-11
    • 2020-01-04
    • 2019-03-12
    • 2013-03-06
    • 2023-01-04
    相关资源
    最近更新 更多