``
mmap(NULL, len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS, -1, 0);
addr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_ANONYMOUS, -1, 0);
mprotect(addr, leng, PROT_READ | PROT_EXEC);
``
mmap(NULL, len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS, -1, 0);
addr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_ANONYMOUS, -1, 0);
mprotect(addr, leng, PROT_READ | PROT_EXEC);
当使用mmap
函数进行内存映射时,如果返回MAP_FAILED
,通常表示内存映射请求失败。MAP_FAILED
是一个宏定义,通常被定义为(void *)-1
,表示一个错误的状态。
在你的代码中,你首先尝试了一次带有PROT_EXEC
权限的mmap
调用,但随后你使用了一个不带PROT_EXEC
的mmap
调用,并且随后使用mprotect
来修改内存保护标志。这里可能有几个原因导致mmap
返回MAP_FAILED
和EINVAL
(无效参数)错误:
PROT_EXEC
)。特别是在安全敏感的系统或配置了特定安全策略的系统上,这样的请求可能会被拒绝。len
的值可能超出了系统允许的最大映射长度,或者不是页面大小的整数倍(页面大小通常是4KB、8KB、16KB等,取决于系统和硬件)。MAP_ANONYMOUS
(表示匿名映射,不需要文件描述符),但如果你不小心传入了一个无效的文件描述符,这也可能导致错误。NULL
给mmap
作为起始地址的提示,但系统可能无法找到适合映射的地址空间。mprotect
的调用:即使mmap
成功,mprotect
的调用也可能失败,特别是如果leng
(注意这里应该是len
,而不是leng
)不是一个页面大小的整数倍,或者尝试设置不允许的权限组合。为了解决这个问题,你可以:
len
的值,确保它是一个页面大小的整数倍。PROT_EXEC
权限,看看是否可以成功映射内存。errno
的值以获取更详细的错误信息。PROT_READ | PROT_WRITE
),然后逐步添加其他功能。另外,注意在你的mprotect
调用中,你使用了leng
而不是len
,这应该是一个拼写错误。确保在调用mprotect
时使用正确的变量名。
为了维护生态的纯净,防止恶意应用向匿名内存注入指令,实现任意代码执行,以绕过代码签名管控,达到变脸或攻击系统的目的,系统要限制应用内设置匿名内存为可执行的行为。
升级到beta2后,应用在申请内存或修改内存权限时,将匿名内存(MAP_ANONYMOUS)的权限设置为可执行(PROT_EXEC),相应行为会被系统拦截,具体如下: