1.搭建题目:socat tcp-listen:10001,fork exec:./pingme,reuseaddr &
2.题目不给文件,只有地址和端口,可能是BROP也可能是格式化字符串盲打。连接上先尝试格式化字符串盲打,输入多个%p.%p.%p,可以看到泄露出了数据,那么就应该是格式化字符串盲打。
3.首先利用爆破找到我们输入的参数偏移:
1 | #注释头 |
偏移为7,验证一下:
4.利用格式化字符串漏洞将二进制文件dump下来:
1 | #注释头 |
(1)由于是格式化字符串打印,会打印到字符串结尾”\x00”,但是不会打印出”\x00”,所以需要补上”\x00”。
(2)这里的%9$s.AAA中偏移为9,是因为打印的是p32(start_addr)处的内容,前面有%9$s.AAA共八个字节,两个地址单位,所以偏移7+2=9。并且填充AAA也是为了满足地址对齐,同时作为特征点来获取程序传回来的数据。将地址放在后面也是为了防止地址中的”\x00”造成截断。
(3)dump的内容只需要有0x1000这么大就行,一个内存页即可。
(4)没有开启PIE时,32位程序从0x8048000开始。
▲搭建题目时,dump出来的内容可能会有点改变,没办法gdb调试,应该是libc版本或者ASLR的问题,不过不影响,IDA静态分析就好。
5.之后就是常规的格式化字符串漏洞利用了,借助dump下来的文件,找到printf的got表地址,利用格式化字符串打印printf函数真实地址。之后通过DynELF或者LibcSearch来获取system函数在libc中的偏移,利用泄露的printf函数真实地址,得到Libc加载的基地址,再计算得到system函数的真实地址。最后再利用格式化字符串漏洞将system函数真实地址写到printf的got表处,劫持got表。最后再输入binsh字符串即可劫持printf(“/bin/sh”)为system(“/bin/sh”)。
(1)泄露printf函数真实地址:
1 | #注释头 |
(2)计算或者DynELF得到system函数真实地址system_addr。
(3)利用格式化字符串漏洞进行attack
1 | payload = fmtstr_payload(7, {printf_got:system_addr}) |
参考资料: