系统: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并退出。在我的计算机上,我收到“细分错误”错误。谁能帮我吗?
答案 0 :(得分: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
或使用HeapAlloc
中的Heap with the executable flag set。您还需要注意FlushInstructionCache
API…
答案 1 :(得分:1)
您可以使用内联汇编器来做到这一点:
#include <iostream>
int code() {
__asm (
".byte 0xB8, 0x0C, 0x00, 0x00, 0x00"
);
}
int main() {
std::cout << code() << std::endl;
return 0;
}
答案 2 :(得分: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;
}