有没有一种可靠的方法来了解哪些库可以在elf二进制文件中进行dlopen()编辑?

时间:2015-12-18 17:54:24

标签: c posix gnu elf

基本上,我想获得二进制文件可能加载的库列表。

我提出的不可靠的方式似乎有效(可能存在误报):

comm -13 <(ldd elf_file | sed 's|\s*\([^ ]*\)\s.*|\1|'| sort -u) <(strings -a elf_file | egrep '^(|.*/)lib[^:/]*\.so(|\.[0-9]+)$' | sort -u)

这不可靠。但它提供了有用的信息,即使二进制文件被剥离了。

是否有可靠的方法来获取此信息而没有可能的误报?

编辑:更多背景信息。

Firefox正在使用gstreamer转换为使用ffmpeg。 我想知道libavcodec.so的哪个版本会起作用。 libxul.so使用dlopen()表示许多可选功能。 库名称是硬编码的。所以,上面的命令有帮助 在这种情况下。

我对包管理和二进制依赖关系也有一般兴趣。 我知道你可以通过readelf -d获得直接的依赖关系 与ldd的依赖关系。我想知道可选的依赖关系,因此问题。

2 个答案:

答案 0 :(得分:8)

ldd告诉您二进制文件链接的库。这些不是程序可以<{1}} 打开的那些。

dlopen的签名是

dlopen

所以你可以,仍然不可靠,在二进制文件上运行void *dlopen(const char *filename, int flag); ,但是如果库名不是静态字符串,但是在程序期间从某个地方构建或读取,这仍然可能会失败执行 - 这最后一种情况意味着你的问题的答案是&#34;没有&#34; ......不可靠。 (例如,可以从网络中读取库文件的名称,从Unix套接字中读取,或者甚至可以在运行中解压缩。一切皆有可能! - 尽管我自己也不会推荐任何这些想法。 。)

编辑:另外,正如John Bollinger所提到的,可以从配置文件中读取库名。

编辑:您也可以尝试使用其中一个strings系统调用替换{这是由Boehm垃圾收集器dlopen完成的,例如),所以它会打开库,但也会在某处记录它的名字。但是如果程序在执行期间没有打开特定的库,你仍然不会知道它。

答案 1 :(得分:3)

(我专注于Linux;我想我的大部分答案都适用于每个POSIX系统;但是在MacOSX上dlopen需要.dylib dynamic library个文件,而不是{{ 1}}共享对象)

程序甚至可以在某些临时文件.so/tmp/foo1234.c中将fork的一些C代码发送到共享库/tmp/foo1234.c中,由某些/tmp/foo1234.so命令 - 在程序运行时生成并执行 - 可能会删除gcc -O -shared -fPIC /tmp/foo1234.c -o /tmp/foo1234.so文件 - 因为它不再需要 - 和/tmp/foo1234.c dlopen(甚至可能删除{在/tmp/foo1234.so之后{1}},在同一过程中的所有内容。我/tmp/foo1234.so的{​​{3}}插件就是这样做的,GCC MELT也是如此,而Bigloo库正在做一些接近的事情。

所以一般来说,你的任务是不可能的,甚至没有意义。

  

是否有可靠的方法来获取此信息而没有可能的误报?

不,没有可靠的方法来获取此类信息而没有误报(您可以证明这等同于GCCJIT或其他halting problem)。另请参阅undecidable problem

实际上,大多数dlopen都发生在某些配置提供的插件上。在配置文件中可能没有确切命名(例如,某些gcc程序可能具有类似dlopen配置文件中名为Foo的插件的约定由{{1}提供插件)。

但是,您可能会发现一些启发式近似值。执行某些bar的大多数程序都有一些插件约定请求插件中的某些特定符号名称。您可以搜索定义这些名称的共享对象。当然,你会得到误报。

例如,Rice's theorem shell接受名为zsh的插件。 zsh modules模块显示foo.conffoo-bar.sodlopen等...函数在zsh模块中是预期的。您可以使用enables_查找提供这些文件的boot_文件(因此features_可以> / p>

(我不相信这样的方法是值得的;实际上你通常应该知道哪些插件对你的系统应用程序有用)

顺便说一句,您可以在执行某些命令时使用example来理解它正在执行的系统调用,因此它正在加载插件。您也可以使用strace(1)ltrace(1)(在某些特定流程上),或者只是使用pmap(1) 1234-使用nm -D来了解其process,因此它已经加载的插件。请参阅virtual address space

请注意,Linux上存在*.sozshcat /proc/1234/maps,但许多POSIX系统都有类似的程序。

此外,程序可以在运行时生成一些机器代码并执行它(proc(5)每次 SBCL交互时执行此操作!)。您的程序还可以使用一些REPL技术(例如,使用JITlibjitllvmasmjit或手写代码......)同样。因此,在没有strace的情况下可能会发生类似插件的行为(您可能会使用ltrace调用和GCCJIT重定位处理来模仿pmap

附录:

如果你从其打包版本安装firefox(例如Debian上的dlopen包),它的包可能会处理依赖项