从字节数组发出内联汇编

Emit inline assembly from byte array

我在 C++ 函数中有这些参数:

unsigned char originalBytes[], int originalBytesLength

这个循环发出字节:

for (int i = 0; i < originalBytesLength; i++)
    __asm _emit originalBytes[i];

但是,我从最后一行收到一条错误消息,说 "Improper operand type (C2415)"。有没有办法在不对字节进行硬编码的情况下发出字节?

我想做的是将字节数组传递给函数,并让它使用内联汇编发出字节。因此,每次调用的字节数可能不同。

这可能与您认为的不同。

首先,您不能在循环中使用 __asm _emit,它不是围绕它的代码的 "aware"。 这就像尝试在循环中使用#include,如果你愿意的话,它只会被处理一次。

最重要的是 _asm _emit 不是您可以在运行时使用的东西,也不是变量,甚至不是 constexpr。 这只是一种在编译时将原始字节文字转储到您的应用程序中的方法。 所以确实没有一种干净的方法来做你想用 __asm _emit 做的事情。您必须在编译时逐字节发出该缓冲区或使用更方便的内联 ASM 块。 所以不,没有硬编码就无法发出字节。

另请注意,编译器不会尝试理解您刚刚转储到二进制文件中间的字节的含义。如果您正在修改寄存器,或编写位置相关的代码,这可能会与编译器正在做的事情发生冲突并导致严重的错误。

编辑:

What I'm trying to do is to pass a byte array to the function and have it emit the bytes with inline assembly. As such the bytes may differ on each call.

你不能用 __asm _emit 做到这一点。 实际上没有简单的方法可以在运行时完全做到这一点,因为每次发出一个字节时,您都必须增长二进制文件。一旦二进制文件编译完成,这真的很难。

可能如果你有重定位信息并且你准备暂停所有线程,修复所有重定位,重写不再适合的短跳转只要跳转(并在循环中重新修复重定位,并重新修复 jmps)。然后修复这些部分,必要时重新定位其他线程并恢复。我听说过恶意软件会这样做(简化版),但仅此而已。

也就是说,您可能想看一下各种 JIT 库。我知道 LLVM 和 GGC 有一个。 您不会得到完全相同的结果,但 JIT 可能是您想要的。 您将获得一个可以使用函数指针跳转到的字节数组,而不是在运行时在任意位置发出的代码。

如果你真的想执行字节,并且它们直到运行时才知道,你可以将它们写入内存的read/execute区域,然后调用该区域的基址。确定这是你想要做的,并且非常确定这些字节的来源。除了非常特殊的情况,我不建议这样做。这是 windows.

中的操作方法
typedef __cdecl void (* voidf_t)(); // make sure the calling convention is correct
void execute(LPBYTE bytes, DWORD len_bytes) {
    // bytes on the stack are NX on most modern operating systems, get some executable memory
    LPBYTE exec_region = (LPBYTE) VirtualAlloc(NULL, len_bytes, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    if(exec_region != NULL) {
        memcpy(exec_region, bytes, len_bytes);
        voidf_t fun = exec_region;
        fun(); // this will call the bytes
        VirtualFree(exec_region, 0, MEM_RELEASE);
        fun = exec_region = NULL;
    }
}

使用这种技术时需要考虑很多因素。你必须知道你正在执行的字节来自哪里。您正在执行的字节也必须是 returns 的函数,并且期望使用 typedef 中使用的约定进行调用。代码还必须完全独立于位置,因为没有执行重定位修正。通常情况下,像这样的代码最终会成为应用程序中漏洞 and/or 不稳定的根源,因此我敦促您考虑是否有更好的解决方案来解决您的问题。