前言

CTF题目中经常会给出libc的文件,首先需要做的就是确定libc的版本,对程序进行针对性的攻击。最直接的确定方法就是直接运行该libc./libc.so.6,但通常由于本机ld版本与libc版本不匹配,发生段错误。

确定完大版本号还不够,因为就算是同一版本的libc也会有较大的变动。比方说,与最开始的2.29版本相比,gnu libc库的release/2.29/master分支的tcache_perthread_struct->counts的变量类型都变了;__libc_malloc中取用tcache的判定,也由判断指针是否为空变成了判断counts是否大于0。这些细节很大程度上影响了exploit的书写。

下面以pwnable.tw re-alloc的libc为例,写一写我的经验。

确定版本号

有libc

从libc的字符串确定大版本strings libc.so.6 | grep libc-

image-20200808100344272

自编译对应版本的glibc使用其ld程序,可以使用how2heap的编译脚本使用方法。拷贝ld到libc.so.6的目录。

使用ld运行libc.so.6得到小版本号,./ld-2.29.so --library-path . ./libc.so.6

image-20200808100856947

最后,google搜索GLIBC 2.29-0ubuntu2 source就能够得到该libc版本的源码。

也可以搜索libc6-dbg GLIBC 2.29-0ubuntu获取调试符号信息。

无libc

1
$ objdump -s --section .comment /path/to/binary

通过编译器版本注释推测libc版本。

以指定libc运行程序

1
2
$ patchelf --set-interpreter ./ld-2.29.so re-alloc
$ patchelf --set-rpath '$ORIGIN/' re-alloc

patchelf可以通过apt直接安装。

修改程序ld路径和library查找路径。

$ORIGIN是个特殊的变量,ld会将它替换成程序当前目录

tips

如果动态链接发生错误,可以使用LD_DEBUG环境变量打印动态链接日志。

其变量有files, bindings, libs, versions, reloc, symbols, statistics, all, help

例如:LD_DEBUG=all ./re-alloc

reference

  1. http://shibing.github.io/2016/08/20/%E5%8A%A8%E6%80%81%E9%93%BE%E6%8E%A5%E4%B8%8Erpath/