从字节数组发出内联程序集 我在C++函数中有这些论点: unsigned char originalBytes[], int originalBytesLength

从字节数组发出内联程序集 我在C++函数中有这些论点: unsigned char originalBytes[], int originalBytesLength,c++,visual-c++,C++,Visual C++,这个循环将发出字节: for (int i = 0; i < originalBytesLength; i++) __asm _emit originalBytes[i]; 但是,我在最后一行中得到一个错误,表示操作数类型C2415不正确。有没有一种不用硬编码就能发出字节的方法 我试图做的是向函数传递一个字节数组,并让它通过内联汇编发出字节。因此,每次调用的字节可能不同。这可能与您认为的不同 首先,不能在循环中使用_asm _emit,因为它不知道它周围的代码。 这就像尝试在循环

这个循环将发出字节:

for (int i = 0; i < originalBytesLength; i++)
    __asm _emit originalBytes[i];
但是,我在最后一行中得到一个错误,表示操作数类型C2415不正确。有没有一种不用硬编码就能发出字节的方法


我试图做的是向函数传递一个字节数组,并让它通过内联汇编发出字节。因此,每次调用的字节可能不同。

这可能与您认为的不同

首先,不能在循环中使用_asm _emit,因为它不知道它周围的代码。 这就像尝试在循环中使用include,如果您愿意的话,它只会被处理一次

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

也意识到编译器并没有试图理解你刚才在二进制平均值中间倾倒的字节。如果您正在修改寄存器或编写位置相关的代码,这可能会与编译器的操作冲突,并导致可怕的错误

编辑:

我试图做的是向函数传递一个字节数组,并让它通过内联汇编发出字节。因此,每次调用的字节可能不同

你不能用asm做这件事。 实际上,在运行时没有简单的方法可以做到这一点,因为每次你发出一个字节,你就必须增加二进制。一旦二进制文件已经编译好,这就很难了

如果您有重定位信息,并且准备挂起所有线程,修复所有重定位,将不再适合的短跳转重写为长跳转,并重新修复重定位,并在循环中重新调整JMP,那么这是可能的。然后修复部分,如有必要,重新定位其他螺纹,然后继续。我听说恶意软件做了一个简化版本,但仅此而已

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

这可能与您认为的不一样

首先,不能在循环中使用_asm _emit,因为它不知道它周围的代码。 这就像尝试在循环中使用include,如果您愿意的话,它只会被处理一次

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

也意识到编译器并没有试图理解你刚才在二进制平均值中间倾倒的字节。如果您正在修改寄存器或编写位置相关的代码,这可能会与编译器的操作冲突,并导致可怕的错误

编辑:

我试图做的是向函数传递一个字节数组,并让它通过内联汇编发出字节。因此,每次调用的字节可能不同

你不能用asm做这件事。 实际上,在运行时没有简单的方法可以做到这一点,因为每次你发出一个字节,你就必须增加二进制。一旦二进制文件已经编译好,这就很难了

如果您有重定位信息,并且准备挂起所有线程,修复所有重定位,将不再适合的短跳转重写为长跳转,并重新修复重定位,并在循环中重新调整JMP,那么这是可能的。然后修复部分,如有必要,重新定位其他螺纹,然后继续。我听说恶意软件做了一个简化版本,但仅此而已

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

如果您确实想执行字节,并且直到运行时才知道它们,您可以将它们写入内存的读/执行区域,然后调用该区域的基。确保这是您想要做的,并且非常确定这些字节的来源。在非常特殊的情况下,我不建议这样做。下面是您在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;
    }
}

>在使用这样的技术时,需要考虑很多因素。您必须知道正在执行的字节来自何处。您正在执行的字节还必须是一个返回的函数,并且期望使用typedef中使用的约定调用该函数。代码还必须完全独立于位置,因为没有执行重新定位修复。通常,这样的代码最终成为应用程序中的漏洞和/或不稳定的根源,因此我敦促您考虑是否有更好的解决方案。

< P>如果您真的想执行字节,并且直到运行时才知道它们,则可以将它们写入到内存的读取/执行区域,然后打电话给那个地区的基地。确保这是您想要做的,并且非常确定这些字节的来源。在非常特殊的情况下,我不建议这样做。下面是您在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;
    }
}

在使用这样的技术时,需要考虑很多因素。您必须知道正在执行的字节来自何处。您正在执行的字节还必须是一个返回的函数,并且期望使用typedef中使用的约定调用该函数。代码还必须完全独立于位置,因为没有执行重新定位修复。通常,这样的代码最终成为应用程序中的漏洞和/或不稳定的根源,所以我敦促您考虑是否有更好的解决方案。

您想做什么?执行驻留在缓冲区中的编译字节?正如其他人所指出的,_asm和_emit不是运行时构造。它们仅在编译期间用于将操作码/字节写入已编译的二进制文件。不存在在运行时发出字节的情况。同样,您是否试图让CPU在运行时执行数组中的字节?或者您正在尝试执行其他操作?是否要执行字节?根据您的环境,在运行时执行字节可能是可能的,但这涉及一些技巧,不推荐使用。如果您只想以一种快速且非常肮脏的方式执行字节,调用void*void&originalBytes并确保x86 CPU的缓冲区0xC3末尾有返回:但请不要返回。@tux3该解决方案假定包含originalBytes的内存是可执行的。您试图做什么?执行驻留在缓冲区中的编译字节?正如其他人所指出的,_asm和_emit不是运行时构造。它们仅在编译期间用于将操作码/字节写入已编译的二进制文件。不存在在运行时发出字节的情况。同样,您是否试图让CPU在运行时执行数组中的字节?或者您正在尝试执行其他操作?是否要执行字节?根据您的环境,在运行时执行字节可能是可能的,但这涉及一些技巧,不推荐使用。如果您只想以一种快速且非常肮脏的方式执行字节,调用void*void&originalBytes并确保x86 CPU的缓冲区0xC3末尾有返回:但请不要返回。@tux3该解决方案假定包含originalBytes的内存是可执行的。