重新映射共享库

时间:2013-12-18 19:03:50

标签: linux process linker shared-libraries mmap

我有一个使用共享库的正在运行的进程。

有没有办法将共享库重新映射到另一个虚拟地址并对旧版本进行映射,将进程地址更新为新的共享对象地址并继续运行?

2 个答案:

答案 0 :(得分:1)

当进程正在运行时,如果没有准备好的话,当然不会。请记住,共享库代码是一回事,共享库中的数据结构是另一回事。库中静态定义的数据结构的指针可能出现在流程的任何位置,您无法更改它们。

现在,如果您正在尝试编写一个应该允许的 new 程序,那么它应该不会太难。对共享库没有静态依赖关系,使用dlopen()打开它并使用dlsym()获取函数。让您的进程捕获一些信号,如SIGUSR1,并在信号处理程序中(更好:在主循环中的某个安全点,检测到信号处理程序在调用时设置的标志)丢弃旧库,加载新库,并调整相应的符号。

答案 1 :(得分:0)

如果你知道共享库没有被执行(即不在某个地方的调用堆栈中),那么执行此操作相当容易。只需dlclose()库,然后再次dlopen()它。如果你需要一个库的句柄,你可以自己dlopen()然后关闭它两次。我相信这将有效,因为引用计数将达到零并且库将被取消映射(除非最初加载的库在某种程度上是特殊的)。如果你可以避免对共享库的链接时依赖(只需在ELF构造函数中调用dlopen),这肯定会有效。

如果您手动加载新库(例如,如果您希望能够选择其加载地址),则可以自行覆盖PLT条目。我写了一个工具,它做了一些非常相似的工作https://github.com/dwks/asyncsafe。如果覆盖每个PLT条目以指向分辨率函数,则会自动再次进行惰性符号加载;或者,你可以自己解决它们。

我确定您已经了解了盲目ROP学术攻击(http://www.scs.stanford.edu/~abelay/pdf/bittau:brop.pdf)。这种攻击有几种防御措施可以做你正在提出的建议,尝试搜索文献。