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

问题描述 投票:1回答:2

system: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并退出。在我的计算机中,我收到“分段错误”错误。谁能帮我?

c++ machine-code
2个回答
2
投票

"\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或使用来自HeapAllocHeap with the executable flag set。您还需要了解FlushInstructionCache API ...


0
投票

我找到了一个方法:

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

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));
cout << "argument:\n";

int result = (( int(*)(void) )mem_map)();
cout << result;
cout << '\n';

return 0;

}

© www.soinside.com 2019 - 2024. All rights reserved.