通过pwntools中的dynelf模块实现无libc泄露
依旧先上一个简单的例子,程序存在明显的栈溢出

关闭栈保护、地址随机化编译一下
1 | gcc -m32 -fno-stack-protector -no-pie -o test test.c |
这里插一句话,发现一个很有意思的现象,即使没加栈保护参数-fno-stack-protector,攻击时也会成功,系统并未为函数检测栈溢出,在加了-fstack-protector-all参数后才实现了检测所有函数是否栈溢出,后来才知道-fno-stack-protector是默认选项…有点尴尬
看一下pwntools源码里对dynelf用法的介绍

直接上脚本

攻击流程分析:
1.leak函数通过栈溢出来泄露指定地址的数据
2.dynelf查找已加载的libc并通过leak函数dump出system函数的地址
3.通过read函数向bss段里写/bin/sh并最终执行system函数,这里因为连续两次使用栈所以记得pop第一次使用read函数的三个参数并ret
原理介绍
1 | d = DynELF(leak, elf=ELF('test')) |
在这里dynelf的作用是寻找内存中system函数的位置,我们定位到pwntools dynelf模块的源码,看看lookup函数都做了些什么
这里忽略了一些异常处理和优化代码

再转到_dynamic_load_dynelf函数

dynamic_load_dynelf通过link_map来查找已经加载的库中的信息,而link_map我们在 栈溢出ret2dlresolve 中遇到过,是指向内部数据结构的一个指针,这里Elf32_Link_Map的结构如下

接着_dynamic_load_dynelf通过leak.field函数来获取了libc.so的内存加载基址

通过_lookup函数来获取libc.so的hash表、动态符号表、字符串表基地址

最后通过hash表获取system函数地址
(具体实现部分还有几个问题没有理清,有空会回来再写详细一点)
实战练习
jarvisoj [XMAN]level4
和上例类似,就不赘述了,直接放脚本了
