繁体   English   中英

PAGE_EXECUTE_READWRITE 作为 VirtualAlloc 中的一个选项的存在是否意味着 W^X 仅由 DEP 在 Windows 中提供便利?

[英]Does the existence of PAGE_EXECUTE_READWRITE as an option in VirtualAlloc mean that the W^X is only facilitated in Windows by DEP?

W^X(“write xor execute”,发音为 W xor X)是操作系统和虚拟机中的一项安全功能。 这是一个 memory 保护策略,进程或内核地址空间中的每个页面都可以是可写的或可执行的,但不能两者兼而有之。

我对为什么这是一个很好的安全功能的基本观点是,系统的所有者理论上有机会在 kernel 内,或者特别是在 VirtualAlloc function 内,挂钩一些分析 ZC1C425268E68385D14ZA5074 之前允许新编写的代码执行一些安全验证在机器上执行。

我已经熟悉DEP ,但直到现在才意识到它与 Windows 中的 W^X 有关:

Windows 上的可执行空间保护称为“数据执行保护”(DEP)。 在 Windows XP 或 Server 2003 NX 下,默认情况下仅对关键 Windows 服务使用保护。 如果 x86 处理器在硬件上支持此功能,则在 Windows XP/Server 2003 中默认自动打开 NX 功能。 如果 x86 处理器不支持该功能,则不提供保护。 DEP 的早期实现没有提供地址空间布局随机化 (ASLR),这允许潜在的返回 libc 攻击,这些攻击本可以在攻击期间用于禁用 DEP。

我的印象是 W^X一般适用于 Windows ,无需配置流程。 但我只是注意到VirtualProtect允许选项PAGE_EXECUTE_READWRITE ,它被记录为:

启用对已提交页面区域的执行、只读或读/写访问。

这似乎完全违背了 W^X 的概念。 那么 W^X 不是 Windows 上的强制安全策略,除非启用 DEP?

如果您关闭 DEP,则不会强制执行 W^X。 当 DEP 打开时,W^X 由所有要求它的 memory 页面强制执行(当硬件支持它时)。 它是x86上页表中的第63位,称为NX位。

现在问题变成了,这个位是什么时候设置的?

PE header 有一个位指示是否支持 DEP/W^X ( IMAGE_DLLCHARACTERISTICS_NX_COMPAT ),如果支持,当该代码映射到 memory 时,文件中没有写入属性的代码部分将设置 NX 位。

对于在运行时动态分配的 memory,开发人员可以进行选择。 PAGE_EXECUTE_READWRITE没有故意设置 NX 位。 如果他们有旧代码可以动态更改可执行代码,同时仍然在 PE 上设置了 DEP 位,那么这很有用,因此他们的大部分代码是 W^X。

早期的 x86 CPU 不支持未经 eXec 许可的页面。 传统的 32 位 x86 页表中,只有一个用于写入权限的位,即 R/W 位。 (读取权限始终隐含在有效页面中,无论该页面是否可写)。 x86-64 也使用的页表条目的 PAE 格式添加了一个 NX 位(“no exec”),又名 XD(eXecute Disable)。

操作系统仍然必须决定哪些页面不可执行。 Windows 似乎使用 DEP 来描述将逻辑页权限实际映射到硬件页表的特性,由 CPU 强制执行。

在糟糕的过去,当每个可读页面都是可执行的时,一些程序可能会草率地告诉操作系统他们希望页面是可执行的。 尤其是那些只针对 32 位 x86 的。 这就是 Windows 通过要求可执行文件选择加入 DEP 来满足的要求,以表明它们知道并兼容没有对未明确标记为这种方式的页面的 exec 权限。


一些操作系统,尤其是 OpenBSD,真正强制执行W^X。 例如, mmap(..., PROT_WRITE | PROT_EXEC, ...)将在 OpenBSD 上返回错误。 他们的mmap(2)手册页记录了这样的 mmap 或 mprotect 系统调用将返回

[ENOTSUP] 不允许在prot参数中请求的访问。 特别是PROT_WRITE | PROT_EXEC PROT_WRITE | PROT_EXEC映射是不允许的,除非文件系统被挂载wxallowed并且进程在链接时被标记为wxneeded (有关诊断故障的方法,另请参见sysctl(2)中的kern.wxabort )。


大多数其他操作系统(包括 Linux 和 Windows)允许用户空间同时创建可写和可执行的页面。 但是,如果您不使用gcc -zexecstack类的任何选项,标准工具链和动态链接机制默认针对 W^X 合规性,这将使操作系统创建带有一些 R|W|X 页面的进程映像。

Older 32-bit x86 Linux for example used to use PLT entries (dynamic linking stubs) with jmp rel32 direct jumps, and rewrite the machine code to have the right displacement to reach wherever the shared library got loaded in memory. 但是现在,PLT 代码使用间接跳转(通过 GOT = 全局偏移表),因此可执行的 PLT 代码可以位于只读页面中。

像这样的更改已经消除了使用标准工具构建的正常进程中对 write+exec 页面的任何需求

但是在 Windows、MacOS 和 Linux 上,操作系统不强制执行W^X。 像 Windows VirtualAlloc / VirtualProtect和它们的 POSIX 等效项mmap / mprotect这样的系统调用可以正常工作。

@Ander 的回答说 DEP 不强制执行 W^X,只是让操作系统在为 .text /.data /.bss 和堆栈空间创建初始映射时尊重可执行文件中的 exec 权限设置,以及在进程启动期间的类似内容.

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM