c - 从映射的 NULL 指针读取数据
问题描述
检查此代码:
#include <sys/mman.h>
#include <stdio.h>
#include <string.h>
int main(void) {
char *addr = mmap(NULL, 6, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED|MAP_ANONYMOUS, -1, 0);
if (addr == MAP_FAILED) {
perror("mmap");
return 1;
}
strcpy(addr, "abcxyz");
printf("Mapped into addr=0x%X\n", addr);
printf("%s\n", addr);
printf("%s\n", NULL);
}
fd
是包含字符串的文件的文件描述符abcxyz
我希望程序在访问 NULL 指针时应该收到 SIGSEGV 但具有讽刺意味的是,我得到了
Mapped into addr=0x0
abcxyz
abcxyz
发生了什么?为什么可以将可访问的数据映射到地址 NULL?有了这种行为,我如何使用它来利用系统?
注意:程序必须在root权限下运行。
注2:行为产生于
Linux XXXXXX 4.4.0-174-generic #204-Ubuntu SMP Wed Jan 29 06:41:01 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
解决方案
发生了什么?
通常,在 处没有映射页面0x0
,因此取消引用空指针段错误。但是您在那里明确映射了一个页面,因此它不再出现段错误。
为什么可以将可访问的数据映射到地址 NULL?
您在没有意识到的情况下回答了自己的问题:
注意:程序必须在root权限下运行。
sysctl 通常通过设置为高于 0的vm.mmap_min_addr
值来防止这种情况发生。但是,该 sysctl 不适用于以 root 身份运行的进程。
有了这种行为,我如何使用它来利用系统?
你不能,因为如果你能做到mmap
,那么你已经在密闭舱口的另一边了。
顺便说一句,您的代码在技术上是未定义的行为,因为即使那里有某些东西,您仍在取消引用 NULL。事实上,对于大多数常见的 libcs,只有编译器的优化printf
才能puts
使其工作。
推荐阅读
- javascript - React:多个异步状态更新
- elixir - Ecto 断言#Ecto.Association.NotLoaded
- ios - 如何使用 PHPickerViewController 仅显示有限的照片?
- verilog - 制作 alu 时出现 Verilog 错误:不是常量
- react-native - 带有 JSON 对象数组的 useState,未定义不是对象
- c# - 使用 Ionic.Zip dll,受密码保护的 zip 不会第二次询问密码 c#
- angular - 没有 ng-template 的 Angular ngx-bootstrap 模型
- blockchain - 错误 TS2307:找不到模块“fabric-shim”
- linux - Git 未在 SUSE Linux Enterprise Server 12 SP3 上安装
- php - Laravel guzzlehttp - 如何检查主机是否在线?