【问题标题】:Is there a way to load a Linux shared library into a specific memory location?有没有办法将 Linux 共享库加载到特定的内存位置?
【发布时间】:2014-09-18 18:29:17
【问题描述】:

我有一个 Linux 应用程序,它在运行时加载非常小的(一些小功能)共享库。由于各种重要原因™,我需要将共享库加载到某个虚拟内存范围中。但是,dlopen() 没有提供任何方法(我可以看到)告诉它或提示它将加载的内容放在哪里。

有没有办法告诉dlopen() 应该把它加载的库放在哪里?

dlopen() 是否有其他替代方案可以提供该功能?

【问题讨论】:

  • 我不这么认为,如果有的话,将对用户模式应用程序产生巨大的安全影响。假设有这样一个函数,你将如何调用库中特定内存位置的函数?
  • 你应该解释你想要这个的原因。真正的动机和总体目标是什么?看起来像XY problem。而且我没有看到任何替代方案(除了自己重新实现 dlopen )。顺便说一句,在 Linux 上,您可以在同一个进程中打开数十万个共享对象。
  • @ElliottFrisch “巨大的安全隐患”是什么(假设设计是理智的,检查了调用者尚未使用地址空间)? mmap 允许调用者指定所需的地址,这不会造成任何灾难。 Windows 允许共享库指定自己的首选基地址(不保证),而不会产生“大量安全隐患”(Windows 偏好在每个进程中将所有 DLL 加载到相同地址,但这样操作系统可以保存内存,而不是因为 DLL 可以有首选的图像库)。
  • 如果攻击者可以覆盖你的记忆,他们就已经赢了。在特定地址加载库不会产生任何重大影响。是的,它使事情变得一点更容易,但我不会称之为“大规模”。我会为允许内存覆盖的问题保留该标签。
  • 好吧,如果真正的问题是,例如隐藏现有库或覆盖现有函数 - 除了在现有代码之上加载库之外,还有其他方法可以做到这一点。

标签: c linux elf dlopen


【解决方案1】:

如果您愿意修改库,我认为预链接程序实际上可能会演示一种方法来执行此操作。目标是修改库,使其具有首选地址。预链接的目的是为了提高性能,但我怀疑它可以修改为适用于您的用例。 请注意,您永远无法保证在一般情况下会发生这种情况,但在受控情况下,您可以保证它会发生。 当然,检查 prelink 将使您了解 elf 所涉及的部分,并对是否可能做出更明智的决定。 http://en.wikipedia.org/wiki/Prelink# 或者查看 http://packages.qa.debian.org/prelink 获取 Debian 中的源代码。

【讨论】:

    【解决方案2】:

    您需要指定您要解决的实际问题。

    出于各种重要原因™

    我只能解释此声明,因为这是向您提出的要求,而您对此无能为力(即争议)。
    所以关于你的问题:
    加载地址已指定,因此您无法通过此库更改它。实际上你需要阅读PIC
    我认为做你想做的唯一方法是“破解”库并修改文本段。
    看看这个specify-preferred-load-address

    老实说,您应该在此处说明您要解决的问题是什么,这样您就可以得到答案以从各个方面为您提供帮助。 IE。这样您就可以有另一种选择作为解决方案

    【讨论】:

      【解决方案3】:

      你不能这样做,并且最近的 Linux 系统上的dlopen(甚至任何mmap 没有 MAP_FIXED)受ASLR的约束。

      因此,您的方法将失败,即使您成功地在某个固定地址执行 dlopen 的等效操作,除非您在系统范围内禁用 ASLR

      特别是同一程序的两个“相同”运行执行相同的dlopen-s 将进入(即让dlopen-ed 共享库进入)可能不同的地址。

      另外,在 Linux 上,您可以dlopen 大量(至少几十万)共享对象。以我的manydl.c 为例

      正如我评论的那样,您的问题看起来像 XY problem。你应该解释你想要这个的原因。真正的动机和总体目标是什么?

      您可以通过处理 ELF 共享对象文件自己重新实现修改后的 dlopen,并自己进行重定位。您还需要专门编译和链接您的共享对象。

      如果函数简单且小(并且如果您接受相对于dlopen-ing 使用gcc -fPIC -O2 -shared -Wall 编译的小型共享库的性能略有下降),您可以考虑使用一些JIT compilation 库,例如libjit , GNU lighting, asmjit, LLVM, ... 在某个固定地址生成机器码(或者只是生成调用或跳转到真正的共享库函数)

      顺便说一句,您可能会使用 musl-libc 并适应您的奇怪需求(它包括一个 dlopen 函数,您可以根据自己的需要移植)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-11-26
        • 2017-05-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-09
        • 2017-12-08
        相关资源
        最近更新 更多