gpt4 book ai didi

c++ - 所有可写和可执行的程序内存段类型

转载 作者:太空狗 更新时间:2023-10-29 12:30:14 25 4
gpt4 key购买 nike

在“C 和 C++ 中的安全编码”中,作者提到,

“W^X 策略允许一个内存段是可写的或可执行的,但不能同时是可写的或可执行的。此策略不能阻止覆盖目标,例如 atexit() 要求的那些需要在运行时可写和可执行的目标。”

我有两个问题:

  1. atexit 需要通过函数指针作为参数注册一个函数。函数指针指向的函数要么在当前程序中定义,链接器将在其中找到定义,要么运行时加载器将找到函数体。无论哪种情况,我们都会知道函数定义。然后它只需要是可执行的。那么为什么 atexit() 的内存段需要在运行时可写且可执行?

  2. 任何 C/C++ 专家都可以告诉我还有哪些其他类型的 API 具有此属性(在运行时可写和可执行)? (让我们将范围限制在 linux 上)

最佳答案

从根本上说,可以写入和执行的内存很容易被调和,并且可以更容易地导致漏洞利用,因为不需要使用 ROP 或其他花哨的方法,您可以简单地在段中的任何地方编写代码来执行和分支到它。在您的引用中,此上下文中目标的含义很可能是退出时调用的函数指针列表。根据 C API,列表本身需要是可写/可变的。这些函数指向的代码只需要是可执行的。同样,由于该列表是可变的,您可以通过插入指向您的代码的指针来修改此列表并强制程序退出以执行您的代码,从而利用程序。在这种情况下,保持所有内存段可写或可执行不会为您节省,因为这里使用了 2 个不同的段(一个可写的函数指针列表,另一个可执行的代码)。

任何在运行时动态生成代码的东西都需要可写和可执行内存段:JIT、内核、可执行解包程序等。对于其中的每一个,没有技术要求段同时拥有这两个属性。可以首先分配可写内存,复制/生成代码并调用 mprotect(),使其可执行(并删除可写属性)。我能看到的唯一可以从同时拥有这两个属性中获益的场景可能是在内存受限的环境中(例如:就地解压缩可执行文件)。

请注意,某些平台不支持在用户空间中分配可执行内存:例如 Xbox360 和 PS3 不支持 JIT。 (内核/api 支持它,但您将无法发布您的软件,Microsoft 和 Sony 将拒绝您的提交,因此该功能只能用于开发。)

关于c++ - 所有可写和可执行的程序内存段类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29721093/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com