繁体   English   中英

如何在 C++ 中将机器代码作为函数运行

[英]How to run machine code as a function in c++

系统:Windows 10 编译器:MinGW 错误:分段错误

我正在尝试将机器代码作为 C++ 中的函数运行。 这是我的代码:

#include <iostream>

int main()
{
    int(*fun_ptr)(void) = ((int(*)())("\xB8\x0C\x00\x00\x00\xC3"));
    std::cout << fun_ptr();
    return 0;
}

在 ideone.com 等在线编译器中,程序成功打印 12 并退出。 在我的计算机中,我收到“分段错误”错误。 谁能帮我?

诸如"\\xB8\\x0C\\x00\\x00\\x00\\xC3"类的字符串文字是静态存储持续时间[lex.string]/15 的对象 编译器通常会将此类字符串文字对象放置在二进制文件的.rdata部分中,即放入只读、不可执行的内存中。 因此,尝试执行字符串文字的字节将导致访问冲突。 如果要执行包含在全局数组对象中的机器码字节,则必须确保将对象分配在可执行的部分中。 例如(使用 Visual C++ 以 Windows 为目标):

#include <iostream>

#pragma section("runstuff", read, execute)

__declspec(allocate("runstuff"))
const unsigned char code[] = {
    0xB8, 0x0C, 0x0, 0x0, 0x0, 0xC3
};

int main()
{
    auto fun_ptr = reinterpret_cast<int(*)()>(&code[0]);
    std::cout << fun_ptr();
    return 0;
}

请注意,像这样的东西本质上是不可移植的,并且充其量具有实现定义的行为。 如果您在构建时知道要运行什么机器代码,请考虑使用汇编器并将生成的目标文件链接到您的可执行文件。 如果要在 Windows 上动态生成机器代码,则必须分配可执行内存。 为此,要么在可执行(也可写)内存(例如,类似于我上面的示例)中创建一个足够大的数组,您可以将代码放入其中,或者动态分配可执行内存,例如使用VirtualAlloc或使用HeapAlloc设置了可执行标志的堆 您还需要了解FlushInstructionCache API...

我找到了一个方法:

#include <iostream>
#include <windows.h>

using namespace std;

int main() {
    unsigned char bytes[] = "\xB8\x0C\x00\x00\x00\xC3";

    HANDLE mem_handle = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_EXECUTE_READWRITE, 0, sizeof(bytes), NULL);
    void *mem_map = MapViewOfFile(mem_handle, FILE_MAP_ALL_ACCESS | FILE_MAP_EXECUTE, 0x0, 0x0, sizeof(bytes));

    memcpy(mem_map, bytes, sizeof(bytes));
    int result = ((int (*)(void))mem_map)();

    cout << "argument:\n" << result << '\n';

    return 0;
}

您可以使用内联汇编器来做到这一点:

#include <iostream>

int code() {
    __asm (
        ".byte 0xB8, 0x0C, 0x00, 0x00, 0x00"
    );
}

int main() {
    std::cout << code() << std::endl;
    return 0;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM