【问题标题】:Use mmap to put content into an allocated memory region使用 mmap 将内容放入分配的内存区域
【发布时间】:2020-07-12 07:21:48
【问题描述】:

我试图阅读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! 然后终止。我真的不知道如何在地图之后获得此输出或如何“调用/执行”mmap

【问题讨论】:

  • 尝试过什么?你的尝试有什么问题?你从系统调用中得到什么错误(如果有的话)?
  • 另请注意,您的单个sscanf 调用将仅读取和解析argv[1] 中字符串的前两位数字。顺便说一句,您应该始终检查它是否存在,方法是检查argc。您还应该比较 x != 1 以便能够处理字符串中的无效输入。
  • 我看到了一些黑客行为......
  • @MichaelDorgan 不幸的是,这只是一个课堂作业。

标签: c mmap


【解决方案1】:
  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 做什么和不做什么。

【讨论】:

  • 我尝试根据您的建议更新我的代码。我不确定如何在这种格式的循环中使用 sscanf。你对此有什么建议吗?
  • @lex449:既然是课堂作业,我会让你考虑一下。但请关注调用sscanf(s, "%02hhx", p) 的确切作用:它解析s 指向的两个字符,并将结果字节存储在p 指向的char 中。想想sp 在循环的每次迭代中需要做什么才能做你想做的事。
猜你喜欢
  • 2011-10-22
  • 2021-12-20
  • 1970-01-01
  • 2016-06-03
  • 2023-03-30
  • 2017-07-20
  • 1970-01-01
  • 1970-01-01
  • 2018-08-21
相关资源
最近更新 更多