问题描述
我试图在另一个进程上使用MMAP进行系统调用注入,但失败了。我注意到syscall正在正确执行,因此问题应该是其他原因。我决定直接通过目标程序运行syscall,以使其更易于理解。毫不奇怪,它也不起作用,我也不知道为什么:
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/syscall.h>
#include <sys/errno.h>
int main()
{
void* addr = 0;
size_t len = sysconf(_SC_PAGE_SIZE);
int prot = PROT_EXEC | PROT_READ | PROT_WRITE;
int flags = MAP_PRIVATE | MAP_ANON;
int fd = -1;
off_t offset = 0;
void* alloc0 = mmap(addr,len,prot,flags,fd,offset); //this works
void* alloc1 = syscall(__NR_mmap,addr,offset); //this doesn't work
printf("Alloc0: %p\n",alloc0);
printf("Alloc1: %p\n",alloc1);
printf("Errno: %i\n",errno);
return 0;
}
输出:
Alloc0: 0xf7fac000
Alloc1: 0xffffffff
Errno: 14
为什么正常的mmap和具有相同参数的mmap syscall无法正常工作?
我正在运行Manjaro,并且该程序已使用GCC在32位上进行了编译。另外,当我用64位编译它时,它工作得很好,没有错误。有什么想法吗?
解决方法
32位(无论如何至少为32位x86)上的旧式__NR_mmap
系统调用没有该签名。它只接受一个指向struct mmap_arg_struct32
的指针的参数。参见https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/kernel/sys_ia32.c?id=v5.9#n214。此系统调用自90年代中期以来不推荐使用,不应使用。错误编号14为EFAULT
,反映出您的第一个参数不是指向此类结构的有效指针。
现代替换是__NR_mmap2
,它采用类似于mmap
函数的参数,除了offset
是4k单位的32位计数,而不是直接偏移量。这样可以处理最大2 ^ 44的偏移量。