C 从mmaped空指针读取数据
检查此代码:C 从mmaped空指针读取数据,c,linux,linux-kernel,null,mmap,C,Linux,Linux Kernel,Null,Mmap,检查此代码: #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("mma
#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);
}
发生了什么事?为什么可以将可访问的数据映射到空地址?有了这种行为,我如何使用它来利用系统
注意:程序必须在root权限下运行
注2:该行为是在
Linux XXXXXX 4.4.0-174-generic\204 Ubuntu SMP周三1月29日06:41:01 UTC 2020 x86\u 64 x86\u 64 x86\u 64 GNU/Linux
发生了什么事
mmap()
按照您的要求映射了您在地址0处指定的文件
显然,您不应该这样做(在第一个参数中提供NULL
,在第四个参数中的标志中提供MAP\u FIXED
),因为这样会打破各种期望
(MAP\u FIXED
是一个脚踏枪:如果未指定,内核将遵守地址请求,即使已经映射,也会滚动任何现有映射。只有当您使用MAP\u FIXED
时,内核才会确保映射不会与现有映射重叠,以此类推,从而避免零地址如果可能的话。)
Linux并不试图阻止用户自食其果;它假定用户知道他们想要完成什么,并且只确保特权分离等等。这就是为什么它允许您做乍一看似乎没有任何用处的事情
(库可能会映射前几页,甚至作为PROT_NONE,并安装一个SIGBUS处理程序来捕获空指针解引用,而不会使程序崩溃。因此,即使我们可能没有想到它们,也有这类东西的使用案例。相反,某些功能可能会以危险/无用/自我破坏的方式使用;内核会这样做(不是评判。)
另外请注意,正如前面对问题的评论中所提到的,您正在LP64体系结构上运行Linux,其中int
为32位,long
和指针为64位。这意味着%x
或%x
仅打印值的无符号整数表示的低32位。请使用%p
指针。对于其他类型,包括
(或者对于没有转换说明符的类型,只使用
),并使用特定宽度或最小宽度类型,如uint32\u t
或uint\u fast32\u t
。至少要记住对内存大小(如字符串长度或数组元素计数)使用size\u t
发生了什么事
通常,在0x0
处没有页面映射,因此取消对空指针的引用是SEGFULTS。但您在那里显式映射了页面,因此它不再SEGFULT
为什么可以将可访问的数据映射到空地址
你回答了自己的问题却没有意识到:
注意:程序必须在root权限下运行
vm.mmap\u min\u addr
sysctl通常通过设置为高于0的值来防止出现这种情况。但是,该sysctl不适用于以root用户身份运行的进程
有了这种行为,我如何使用它来利用系统
你不能,因为如果你能做到,那么
顺便说一句,您的代码在技术上是未定义的行为,因为即使存在某些内容,您仍然在取消对NULL的引用。事实上,对于大多数常见的libc,只有编译器对
printf
到put
的优化才能使其工作。“如果addr
为NULL,那么内核选择(页面对齐)从文档创建映射的地址(例如)。尝试printf(“映射到addr=%p\n”,(void*)addr);
而不是printf(“映射到addr=0x%X\n”,addr)
并告诉我们显示的内容。使用%X
显示指针值是UB。请发布所有代码,包括fd
的分配方式。无法使用printf(“%s\n”,NULL);
打印abcxyz
.prints。执行相同的操作。%X\n”,addr)
是未定义的行为,我猜它很可能只显示64位指针的32位部分(较高/较低?我认为较高,但不确定)。请发布一个@KamilCuk,代码实际上不调用printf
。GCC优化printf(“%s\n”,x);
到put(x)
。我看到您添加了MAP_ANONYMOUS和fd=-1。这是否意味着一个文件的行为会相同?@Silver是的。您在这个问题中询问的效果与映射是否支持文件无关。
Mapped into addr=0x0
abcxyz
abcxyz