c - 使用 mmap 将内容放入分配的内存区域
问题描述
我试图阅读文档,mmap
但我仍然很难理解如何使用它。
我想从命令行获取一个参数,然后将它分配给一个可执行的内存区域。然后我希望能够从该代码执行。
这是我到目前为止所拥有的:
int main(int argc, char const *argv[]) {
if (argc != 2) {
printf("Correct input was not provided\n");
exit(1);
}
char assembly_code[sizeof argv[1]];
const char *in_value = argv[1];
int x = sscanf(in_value, "%02hhx", assembly_code);
if (x != 1) {
printf("sscanf failed, exited\n");
exit(1);
}
void * map;
size_t ac_size = sizeof(assembly_code) / sizeof(assembly_code[0]);
map = mmap(NULL, ac_size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANONYMOUS, -1, 0);
if (map == MAP_FAILED) {
printf("Mapping failed\n");
exit(1);
}
((void (*)(void))map)();
return 0;
}
这是我得到的输出/错误:Mapping failed
我不知道我mmap
是否正确使用。如果我是,我不相信我正在正确执行它。
例如,如果这个文件使用一个参数运行,e8200000004889c64831c048ffc04889c74831d2b2040f054831c0b83c0000004831ff0f05e806000000584883c008c3ebf84869210a
它应该返回Hi!
然后终止。我真的不知道如何在地图之后获得此输出或如何“调用/执行” a mmap
.
解决方案
int x = sscanf(read, "%02hhx", assembly_code);
这仅转换单个字节。我认为没有标准库函数可以转换整个十六进制字节字符串;您必须在循环中调用,酌情增加输入缓冲区和输出缓冲区中sscanf
的指针。read
assembly_code
在您的mmap
通话中,如果您不想映射文件,则应使用标志MAP_ANONYMOUS
而不是MAP_SHARED
. 您还应该检查它的返回值(它返回MAP_FAILED
错误)并报告任何错误。此外,返回值原则上是类型void *
而不是int *
(尽管这在常见的 Unix 系统上应该没有区别)。
该mmap
调用(在修复后)将返回一个指向填充零的内存块的指针。它没有理由包含您assembly_code
的memcpy
. 或者您可以移动您的循环并将十六进制字节直接解析到使用mmap
.
您 ((void (*)(void))map)();
将控制权转移到映射地址似乎是正确的,因此一旦您正确映射和填充了块,它应该执行您的机器代码。我没有尝试反汇编您提供的十六进制字符串,以查看它是否真的会达到您的预期,但希望可以。
此外,read
这不是一个很好的变量名称,因为该名称还有一个标准库函数。您的代码将起作用,因为局部变量会隐藏全局对象,但选择另一个名称会更清楚。
哦,char assembly_code[sizeof argv[1]];
不对。仔细想想做什么sizeof
和不做什么。
推荐阅读
- python - 如何使用双 for 循环创建多个回调?
- xml - 从 XML 中选择节点返回 0 个项目
- java - 键入时使用 Java Scanner 检查输入
- uwp - Add-AppxPackage:无效数据。(0x8007000D) 打包独立可执行文件时
- php - 路径上存在的视图上出现错误 404。URL 和视图一样存在,但它不断返回错误 404
- php - Docker 图像推送但我的音量不持久
- asp.net-core - 如何获得跨度
到 Kestrel 中的 HTTP 请求标头 - android-studio - Android Studio recyclerview 没有附加适配器;跳过布局
- python - 当我尝试将 valstep 设置为 Slider 时,出现错误 AttributeError: Unknown property valstep
- jenkins-pipeline - 詹金斯管道无权从 system32 文件夹运行工具