2013-12-18 120 views
0

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

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

+1

如果给mmap()提供了正确的选项,你也许可以映射这个库的一个新副本,但它只是文件的映射,而不是解释和分割成文本/数据等等。像加载器或'dlopen()'这样的节会给。 'dlopen()'可能会让你回到现有的副本。取消映射现有的副本很可能是不可能的,因为如果允许的话,它可能会对进程造成致命的影响...... – twalberg

回答

1

肯定不是在进程运行时,如果它没有准备好这样做。请记住,共享库代码是一回事,共享库内的数据结构是另一回事。指向库中静态定义的数据结构的指针可能只存在于您的进程中的任何位置,而您无法更改它们。

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

+0

我想要做以下操作,让父母取消映射并重新映射库,然后再分叉孩子,孩子将要使用重新映射的库,我如何解决所有符号,以便孩子能够正确运行?我应该为每个符号调用dlsym吗? –

0

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

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

我确定你知道Blind ROP学术攻击(http://www.scs.stanford.edu/~abelay/pdf/bittau:brop.pdf)。这种攻击有几种防御措施可以满足你的要求,试着搜索文献。