【问题标题】:Resolving symbols differently in different dynamically loaded objects在不同的动态加载的对象中以不同的方式解析符号
【发布时间】:2017-01-06 20:07:27
【问题描述】:

阅读thesequestions后,我正在寻找有关如何控制符号解析顺序的更多详细信息。

在我的问题中,我有主要的可执行文件exec。 exec 动态链接到 a.so 和 c.so。 a.so 动态链接到 b.so。 b.so 调用函数foo,通常由c.so 提供,但在这种情况下也由exec 提供。 b.so 仅适用于 c.so 的 foo 实现。

情况示意图:

exec      (foo caller and provider)
   | \
a.so  |
   |  |
b.so  |   (foo caller)
   | /
c.so      (foo provider)

我只能控制a.so的编译/来源,我将a.so链接到exec和LD_PRELOAD。

我希望在exec 中调用foo 以解析为exec 的实现,并调用b.so 以解析为c.so 的实现。这种在不同对象中进行不同符号查找的事情是否可能?

【问题讨论】:

    标签: linux ld dynamic-linking dynamic-loading symbol-table


    【解决方案1】:

    不幸的是,没有办法在每个库级别调整符号分辨率,因此没有简单的方法来实现这一点。

    如果foo实际上是在主可执行文件中实现的(不仅仅是copy-relocated),那么你无能为力,因为来自主可执行文件的符号在解析过程中获得最高优先级(除非你对最终的hacky运行时没问题- 修补你不是的 GOT)。

    如果

    • foo 在 c.so 中实现
    • 你已经够绝望了

    您可以执行以下操作:

    • 在a.so中获取拦截器内部的返回地址(使用__builtin_return_address)
    • 将其与 b.so 的边界匹配(可以从/proc/self/maps 获得)
    • 根据结果,要么进行特殊处理(如果调用者在 b.so 中)或将调用转发到RTLD_NEXT

    这当然有明显的局限性,例如如果 b.so 从另一个 d.so 调用函数然后调用 foo 则将不起作用,但在许多情况下可能就足够了。是的,我已经在实践中看到了这种方法。

    【讨论】:

    • 我如何使用dlsym 做到这一点?我知道a.so 是如何使用dlsym 来引用c.so 的foo,但是有没有办法使用dlsym 让b.so 使用它?
    • 抱歉,误读了问题。我已经更新了答案,希望它现在更有帮助。
    • 感谢编辑!然而,所有的依赖关系只在图中向下(a.so 只调用b.so),这意味着__builtin_return_address 技巧将不起作用。此外,它实际上是exec 和c.so 中foo 的单独实现。有没有关于 GOT hacking 的资源(这不是我想走的路,但我想了解)?
    • “有没有关于 GOT hacking 的资源” - this one 似乎是最完整的。有些部分与您无关,但解析 ELF 和修补 GOT 似乎很通用。
    • BTW 在您的情况下是LD_PRELOAD 非常重要(例如,您使用它在应用程序中插入一些符号)?如果没有,您可以用来自LD_PRELOAD-ed 中间a_forwarder.so 的RTLD_DEEPBIND 代替dlopen。深度绑定将迫使 b.so 优先选择 a.so 中的符号。
    猜你喜欢
    • 1970-01-01
    • 2020-07-03
    • 2023-03-27
    • 2015-11-17
    • 1970-01-01
    • 2020-11-06
    • 2015-12-09
    • 2018-01-13
    • 1970-01-01
    相关资源
    最近更新 更多