非栈上格式化字符串利用

发布于 2023-04-04  246 次阅读


泄露地址的方式还是一样的,但不能像栈上一样直接利用格式化字符串改数据。

思路就是因为目标地址不在栈上,也无法直接在栈上写入该地址,那么就找一个与目标地址相似的栈上的地址,改写该栈上地址即可。

技巧:

但是改ret地址中的libc_start_main为onegadget有局限性,有时候要要考虑是否满足条件,才能打通;第二个将printf的got表改为onegadget也是有局限性,但是改为system,然后传参binsh就是可以通杀的。

例题一:Playfmt

main函数:

只初始化了一个输出,没有初始化输入。

程序的逻辑,一个read将数据读入到bss段上0xc8个字节。然后比较是否为quit,若为quit则break然后返回result;如果不写quit的话,则可以触发一个格式化字符串的漏洞。 虽然该格式化字符串漏洞不在栈上,但泄露地址还是一样的。

方法一:

将printf的got表改为system,然后传参binsh,触发漏洞然后getshell。

将printf 的got表里的真实地址改为system的真实地址,然后输入binsh,就会触发漏洞。

gdb调试:

在printf出下断点:

查看栈中情况找偏移:

然后libc start main 减去libc基址即得偏移为0x18647,然后exp中泄露地址的减去偏移则为基址。

system,onegadget地址同理也可得到:部分exp如下

得到system地址后接下来把printf got表地址给改为system地址:

我们知道printf got表地址为:0x8054a010

system地址为:

然后在栈中找相似printf地址的地址:

第一个替身

但是这个只有一个依托的指针,后续写不进去,要找依托指针为3个的,比如ebp处的,那么先改0xff9a6c88指向0xff9a6c7c,

修改成功

依托指针变为3个。然后再改0xff9a6c7c指向的指针0x8048584为printfgot表0x804a010

修改成功。

然后再将0x804a010指向的printf真实地址改为system地址

最终一步一步成功改写printf地址为system地址,最后发送/bin/sh即可。

但是exp中要找两个替身,第一个改print低位2字节,第二个替身改高位1字节 。

方法二:

将返回地址中的__libc_start_main改为onegadget

先泄露地址,方法一样

先通过ebp把链给链起来,将0xffd27e88指向的0xffd27e98改为0xffd27eac


穿过云层我试着努力向你奔跑