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

3

这里写道,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的信息,可以在这里这里找到,但我想这不是我的情况,因为以下命令没有返回有用的内容:
$ 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),所以我需要整个库树。这里还提供了一些解决方案,建议更改加载器(在我的例子中是 /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

但说实话,我没有理解这个问题的要点。您能否提供帮助?
1个回答

0
我的问题是如何重写包含在ldd输出中的路径并将其指向我提取的文件?
看起来你想要的是仅覆盖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 [一些参数...]
不要忘记,/usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.4和/usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.3只是指向libcurl-gnutls主库文件的符号链接。复制这些符号链接可能没有期望的效果。你需要长命名的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)。


谢谢您的回复。我的问题是,这会更改一个特定的库吗?在这种情况下,是/usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.4。是否也有可能修改二进制文件以指向此库?谢谢。 - Wakan Tanka
这实际上会改变这个特定库,因为它将覆盖原始库提供的所有/主要函数。在这种情况下,如果curlftpfs被编译使用该库,则会覆盖 libcurl-gnutls.so.4。我怀疑是否有一种聪明的方法可以重写二进制文件的链接信息以使用不同的共享库名称,但是我目前还没有掌握这方面的知识。作为手动方法,您可以尝试使用十六进制编辑器,并将指定libcurl-gnutls.so.4的文本更改为可能的libcurl-gnutls.so.2(名称应该相同长度)。 - Craig H
老实说,如果您正在考虑修改curlftpfs二进制文件,您可能应该手动编译curlftpfs并更改相关的依赖项。 - Craig H
当然我可以,但我主要对一些逆向工程方法感兴趣。 - Wakan Tanka
好的,正如之前提到的那样,您可以使用十六进制编辑器(如Bless)重命名二进制文件中的库依赖项。我刚才尝试了ls二进制文件。只需在curlftpfs二进制文件上打开十六进制编辑器。搜索libcurl-gnutls.so.4文本。在保持原始长度的同时将文件改名为内联。如果需要更多详细信息,我可以写另一个答案。 - Craig H

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接