更换可执行文件的 glibc 版本

准备学堆了, 不同版本的 glibc 对于堆的管理稍有不同 (比如高版本可能增加了一些补丁, 使得某些漏洞无法利用). 由于需要本地调试, 所以得先学一下怎么更换 glibc 版本.

https://github.com/matrix1001/glibc-all-in-one

首先得先下载对应版本的 glibc 吧. 这个工具非常方便.

对着 readme 照猫画虎就行.

技巧
download 文件中可以把清华镜像源换成 ubuntu 源.

他会把相应的 deb 包下载到 ./debs/ 下, 然后解压到 ./libs/ 文件夹下.

其中, 我们需要的是 libc.so.6ld-linux.so.2. 这两个文件是符号链接, 可以把他们复制到题目文件夹下, 便于后续工作.

https://github.com/NixOS/patchelf

可执行文件把链接器路径写死在 ELF 文件中了, 所以当指定其他 glibc 版本时, 连接器版本也需要指定, 否则会发生错误.

使用 patchelf 工具进行.

假设当前题目文件夹下有之前复制过来的 libc.so.6ld-linux.so.2, 以及题目 (ELF) pwn (建议备份一下).

乐, 这样 rizin 调试的时候输出不了堆, 原因 rizin 找 glibc 的时候文件名要有 -, 而 libc.so.6 没有, 离谱. radare2 有这个 issue, 好像已经解决了, rizin 没有看到.

既然如此, 就直接设置到 glibc-all-in-one 的 /libs 对应的文件夹下, 不复制出来了.

首先设置连接器:

1
patchelf --set-interpreter ${libcpath}/ld-xxx.so pwn

然后设置运行路径 (RUN_PATH, rpath), 也就是程序所使用的共享库路径:

1
patchelf --set-rpath ${libcpath} pwn

或者写成一行:

1
patchelf --set-interpreter ${libcpath}/ld-xxx.so --set-rpath ${libcpath} pwn

比如:

1
patchelf --set-interpreter ./glibc-all-in-one-master/libs/2.31-0ubuntu9.2_amd64/ld-2.31.so --set-rpath ./glibc-all-in-one-master/libs/2.31-0ubuntu9.2_amd64 pwn

可以用 ldd 查看连接器, file 查看共享库来检查修改成功与否.


有空写个脚本一键操作 (或者找师傅们要一个). github 上找到了两个, 效果貌似都不怎么样.