linux - 更改可执行二进制文件中的一个特定共享库

标签 linux shared-libraries reverse-engineering elf

Here写到 curlftpfs 由于最新的 libcurl3-gnutls 中的错误而非常慢。不建议降级,因为此软件包具有大量反向依赖性(可以通过 apt-cache showpkg libcurl3-gnutls:amd64apt-cache rdepends libcurl3-gnutls:amd64 验证) >).所以我决定以不同的方式降级它。我检查了存储库中的可用版本:

$ apt-cache policy libcurl3-gnutls:amd64
libcurl3-gnutls:
  Installed: 7.43.0-1ubuntu2.1
  Candidate: 7.43.0-1ubuntu2.1
  Version table:
 *** 7.43.0-1ubuntu2.1 0
        500 http://sk.archive.ubuntu.com/ubuntu/ wily-updates/main amd64 Packages
        500 http://security.ubuntu.com/ubuntu/ wily-security/main amd64 Packages
        100 /var/lib/dpkg/status
     7.43.0-1ubuntu2 0
        500 http://sk.archive.ubuntu.com/ubuntu/ wily/main amd64 Packages

然后我下载并提取了比安装版本更旧的版本:

$ apt-get install -d libcurl3-gnutls=7.43.0-1ubuntu2
$ sudo mv /var/cache/apt/archives/libcurl3-gnutls_7.43.0-1ubuntu2_amd64.deb .
$ dpkg -x libcurl3-gnutls_7.43.0-1ubuntu2_amd64.deb  extracted_deb

然后我备份了原始二进制文件并在共享库中搜索了一些通用名称:

$ cp $(which curlftpfs) .
$ ldd ./curlftpfs | grep curl
        libcurl-gnutls.so.4 => /usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.4 (0x00007fcac4443000)

$ readelf -d ./curlftpfs  | grep -i curl
 0x0000000000000001 (NEEDED)             Shared library: [libcurl-gnutls.so.4]

以下步骤只是证明链接文件完全属于 libcurl3-gnutls 包并且 curlftpfs 依赖于 libcurl3-gnutls:

$ dpkg -S /usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.4
libcurl3-gnutls:amd64: /usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.4

$ apt-cache depends curlftpfs
curlftpfs
  Depends: libc6
  Depends: libcurl3-gnutls
  Depends: libfuse2
  Depends: libglib2.0-0
  Depends: fuse
  Conflicts: curlftpfs:i386

而且提取和安装的 libcurl3-gnutls 包的内容看起来完全一样:

$ dpkg -L libcurl3-gnutls:amd64 | sort
/.
/usr
/usr/lib
/usr/lib/x86_64-linux-gnu
/usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.3
/usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.4
/usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.4.3.0
/usr/share
/usr/share/doc
/usr/share/doc/libcurl3-gnutls
/usr/share/doc/libcurl3-gnutls/changelog.Debian.gz
/usr/share/doc/libcurl3-gnutls/copyright
/usr/share/doc/libcurl3-gnutls/NEWS.Debian.gz
/usr/share/lintian
/usr/share/lintian/overrides
/usr/share/lintian/overrides/libcurl3-gnutls

$ find extracted_deb/ | sort
extracted/
extracted/usr
extracted/usr/lib
extracted/usr/lib/x86_64-linux-gnu
extracted/usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.3
extracted/usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.4
extracted/usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.4.3.0
extracted/usr/share
extracted/usr/share/doc
extracted/usr/share/doc/libcurl3-gnutls
extracted/usr/share/doc/libcurl3-gnutls/changelog.Debian.gz
extracted/usr/share/doc/libcurl3-gnutls/copyright
extracted/usr/share/doc/libcurl3-gnutls/NEWS.Debian.gz
extracted/usr/share/lintian
extracted/usr/share/lintian/overrides
extracted/usr/share/lintian/overrides/libcurl3-gnutls

我的问题是如何重写 ldd 输出中包含的路径并将其指向我提取的文件?我读过 rpathpatchelfchrpath herehere但我想这不是我的情况,因为以下命令没有返回任何有用的信息:

$ readelf -d ./curlftpfs | grep -i rpath
$
$ chrpath -l ./curlftpfs
./curlftpfs: no rpath or runpath tag found.
$
$ patchelf --print-rpath ./curlftpfs
$

所以好像没有用到rpath。我也读过 $LD_LIBRARY_PRELOAD 但我猜它会改变给定二进制文件的所有共享库的路径,而不仅仅是一个特定的(在我的例子中是 /usr/lib/x86_64-linux- gnu/libcurl-gnutls.so.4) 所以我需要拥有整个库树。 There也是建议更改加载程序的解决方案(在我的示例中 /lib64/ld-linux-x86-64.so.2 我猜):

$ patchelf --print-interpreter ./curlftpfs 
/lib64/ld-linux-x86-64.so.2
$
$ ldd ./curlftpfs | grep ld-linux
    /lib64/ld-linux-x86-64.so.2 (0x0000564966b64000)
$
$ ls -laL /lib/x86_64-linux-gnu/ld-2.21.so
-rwxr-xr-x 1 root root 154376 Mar 26  2015 /lib/x86_64-linux-gnu/ld-2.21.so

但老实说,我不明白这一点。你能帮忙吗?

最佳答案

My question is how can I rewrite the path that is contained in ldd output and point it to file that I've extracted?

您似乎想要的只是用旧版本覆盖 libcurl-gnutls.so 库的功能。正如您提供的最后一个链接中所暗示的那样,您可以使用 LD_PRELOAD 环境变量来覆盖标准库函数。

假设您手动安装(降级)的 libcurl-gnutls 版本具有动态库文件/usr/local/lib/libcurl-gnutls.so.4.4.0。 然后您可以执行以下操作: LD_PRELOAD=/usr/local/lib/libcurl-gnutls.so.4.4.0 curlftpfs [some_arguments...]

不要忘记/usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.4 和/usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.3 只是指向的符号链接(symbolic link)libcurl-gnutls 的主库文件。复制这些符号链接(symbolic link)可能不会产生预期的效果。您需要长名称的 SO 文件,例如 libcurl-gnutls.so.4.4.0 。

附加说明

您可以通过执行以下操作来测试此覆盖是否有效: LD_PRELOAD=/usr/local/lib/libcurl-gnutls.so.4.4.0 ldd $(which curlftpfs)

对于手动安装,/usr/local/lib 可能不是放置您不想干扰其他二进制文件的动态库的好地方。这是因为/etc/ld.so.conf.d/libc.conf 可能指向自动库的/usr/local/lib。 (我的 Debian 机器有)

要查看 LD_ 环境变量的定义,请查看 ld.so(8)手册页(man ld.so)。

关于linux - 更改可执行二进制文件中的一个特定共享库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35470600/

相关文章:

go - Go的selectnbrecv函数到底做什么?

c - gdb 断点在错误的行号中命中

python - 如何获取进程的内存使用百分比?

linux - Ansible - 未安装 winrm 或请求

memory - 阻止 Valgrind 检查共享库

c# - 逆向工程 asp.net web 应用程序

c - 在 GNU/Linux/C 中使用多播 (224.0.0.12) 发现 DHCP 服务器

linux - 共享对象库和 MPI

c# - 使共享库可用于多个应用程序的最佳方法是什么?

java - 需要帮助来反编译 jar 文件、编辑类并保存为 jar 文件