PatchELF¶
PatchELF用于修改ELF文件依赖的动态链接器和库路径,在Pwn中被用来解决动态链接库路径不匹配的问题。PatchELF最初是为了解决NixOS上的动态链接问题而开发的,是NixOS打包工具集的一部分。听起来好神奇,一个Pwn工具竟然来源于NixOS。
NixOS采用的Nix包管理器使用纯函数式编程范式来描述软件包和系统配置,确保了软件包的可重现性和隔离性。因此,NixOS上的可执行文件都被放在/nix/store目录下,这导致传统的动态链接二进制文件无法在NixOS上运行,因为它们期望库文件位于标准位置(如/lib或/usr/lib)。为了解决这个问题,PatchELF被开发出来,用于修改ELF文件的动态链接器和库路径,使其能够在NixOS上运行。
PatchELF在2023年之后就没有发布过新版本。Arch Linux用户可以通过安装patchelf-gitAUR包来获取最新的PatchELF,带有zsh补全等功能。
基本用法¶
patchelf --set-interpreter <new-interpreter> <binary> # 设置新的动态链接器路径
patchelf --set-rpath <new-rpath> <binary> # 设置新的运行时库搜索路径
patchelf --remove-rpath <binary> # 移除运行时库搜索路径
patchelf --print-interpreter <binary> # 打印当前的动态链接器路径
patchelf --print-rpath <binary> # 打印当前的运行时库搜索路径
应用实例¶
假设我们有一个ELF二进制文件pwn,我们想要修改它的动态链接器和运行时库搜索路径。先使用ldd命令查看当前的设置:
输出可能如下所示:
linux-vdso.so.1 (0x00007f65a9c43000)
libc.so.6 => /usr/lib/libc.so.6 (0x00007f65a9800000)
/lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007f65a9c45000)
题目一般会给出libc.so供参考。为了找到合适的GLIBC版本,我们可以用strings命令查看文件中的字符串来找出GLIBC版本:
输出可能如下所示:
1dc680 GNU C Library (Ubuntu GLIBC 2.35-0ubuntu3.11) stable release version 2.35.
1dc793 Compiled by GNU CC version 11.4.0.
由输出可知,该GLIBC版本为2.35-0ubuntu3.11。接下来,通过glibc-all-in-oneGitHub获取合适版本的GLIBC,并使用PatchELF修改动态链接器和运行时库搜索路径。先创建副本,再进行修改:
cp pwn pwn_patched
patchelf --set-interpreter ~/glibc-all-in-one/libs/2.35-0ubuntu3.11_amd64/ld-linux-x86-64.so.2 pwn_patched
patchelf --set-rpath ~/glibc-all-in-one/libs/2.35-0ubuntu3.11_amd64 pwn_patched
最后,再次使用ldd命令验证修改是否成功:
输出可能如下所示:
linux-vdso.so.1 (0x00007f7ac6d23000)
libc.so.6 => /home/khyan/glibc-all-in-one/libs/2.35-0ubuntu3.11_amd64/libc.so.6 (0x00007f7ac6a00000)
/home/khyan/glibc-all-in-one/libs/2.35-0ubuntu3.11_amd64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007f7ac6d25000)
这样,我们就成功地使用PatchELF修改了ELF二进制文件的动态链接器和运行时库搜索路径,使其能够在当前系统上正确运行。接下来,便可以使用./pwn_patched来运行修改后的二进制文件了。