这次还是一道format string bug的题目,不过稍微麻烦了一点,程序中没有后门可以直接利用了,因此要靠自己想办法执行system("/bin/sh")
缓冲区有限制,没有buffer overflow的可能,checksec的结果也表示程序无法使用shellcode方法,好在还是没有开启内存随机化。
gdb调试,程序和上一个基本相同。
aaaa%p%p%p%p%p,发现第五个%p输出了我们输入的内容,因此01234,偏移为4的参数就是我们的工具。
我目前的思路是,leak几个函数,确定libc的版本,然后找一个函数的真实地址算出system的真实地址,然后hijack puts 的got
可是我还是太天真了,printf函数只能利用一次!,我需要通过printf来leak函数的真实地址,也需要printf来修改got表,如果只能利用这一次的话,那这个方法可能是失败的。
以下代码是我用来获取alarm函数的真实地址的:
from pwn import *
io=process('./fsb')
elf=ELF('./fsb')
alarm_got=elf.got['alarm']
#这个值其实也可以用objdump工具来获得/且随便leak哪个函数都可以
#我不用puts是因为我的putsGOT值中有’\x00‘也就是c语言的字符串结束符
#如果用了在echo返回的时候我就读不到足够的信息了....
io.sendline(p32(alarm_got)+'|%4$s|lalalalala')
recvuntil('|')
alarm_addr=u32(recvuntil('|')[0:4])
#对偏移为4的参数,看作字符串指针进行寻址,就可以通过alarm_got找到动态加载的真实addr了
以下是我确定libc的方式:
gdb调试程序
b*main
可以在main函数的第一行停住,这个时候可以观察堆栈的顶部,就是main的返回地址,指向的就是__libc_start_main_ret,此时获取了第一个信息
alarm函数的真实地址同样也是这个libc的信息,
将这两个信息输入到一些libc的数据库中,就可以通过偏移分析出原始的libc的版本了
学长给我推荐了一个github上的库:
https://github.com/niklasb/libc-database
看上去很好用,结果我不知道为啥我用不了!!!我$./get一直都是fail的,所以我找了别的库(github可太棒了~)
https://github.com/lieanu/LibcSearcher
好吧这个库有点大,是直接一起把libc放在里面了好像,我是5kb的速度,下到自闭都没下完555555
最后我找到了一个web的libc库,nice!!!!
https://libc.blukat.me
输入以上找到的两个信息,就可以找到对应的libc了!
确定了这个libc 之后,就是想办法改变程序的control flow了
printf漏洞只有一次!,怎么办呢?
我的第一反应是能否将获取函数的真实地址 和 hijackGOT在同一步内完成,也就是说发送一个超级payload…理论上应该是可行的吧?
具体行为:
coming soon~
不过我想到了一个更好的办法!!!!
我利用printf漏洞所拥有的是:
1.“任意读”;2.“任意写”
拥有这两个能力意味着我可以对这个程序做任何事!
我竟然会因为printf漏洞只能用一次而困扰,实在太蠢了
这就好像,面对神龙你可以任意许一个愿望,那这个愿望一定是——
我要能够许无限多的愿望!!!
没错,我要利用printf漏洞改变程序的control flow,使他变成一个无限循环的程序,这样我就有无限多个printf漏洞可以用了
哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈
太简单了,太easy了,哈哈哈哈哈哈哈哈哈哈
没有内存随机化,把exit函数的调用变成main就好了:):)
yes!
>>>a few minutes later...
直接使用了上次hijackGOT的脚本,但是失败了
思路,第一次printf形成循环,
第二次leak出system的真实地址
然后用printf修改printf的got为system
然后输入“/bin/sh”?
可以getshell?应该可以吧?
之前尝试直接修改puts的got表,使其指向echo,但是由于puts的got中包含’\x00’字符,所以在构建payload时会发生困难
gets函数在获取字符串时遇到’\x00’就会停止,之后的payload就会失效
从前一个字节开始写,不适用\x00
这个思路是正确的,成功在本地getshell了
可是为什么,没办法用remote连接getshell呢?
懵逼了
后续:
这里要纠正一个巨大的错误,主要原因是我对elf文件还不够了解。
动态链接的elf文件,所依赖的libc是由系统决定的。同一个文件在不同系统下的libc是不同的,因此leak的对象不应该在本地,而是应该直接leak远程的那个端口,所以综上应该准备两个程序(如果写在一起可能会很麻烦…)1.利用漏洞leak系统的libc;2.exp