0x00 Emm。。。
今天做了个河北师范大学招新赛的题,发现好多格式化字符串的题目,以前确实做的很少,正好现在重新总结下。
0x01 格式化字符串漏洞原理
格式化字符串函数是根据格式化字符串函数来进行解析的。那么相应的要被解析的参数的个数也自然是由这个格式化字符串所控制。
在进入 printf 之后,函数首先获取第一个参数,一个一个读取其字符会遇到两种情况
- 当前字符不是 %,直接输出到相应标准输出。
- 当前字符是 %, 继续读取下一个字符
- 如果没有字符,报错
- 如果下一个字符是 %, 输出 %
- 否则根据相应的字符,获取相应的参数,对其进行解析并输出
那么假设,此时我们在编写程序时候,写成了下面的样子
1 | printf("Color %s, Number %d, Float %4.2f"); |
此时我们可以发现我们并没有提供参数,那么程序会如何运行呢?程序照样会运行,会将栈上存储格式化字符串地址上面的三个变量分别解析为
- 解析其地址对应的字符串
- 解析其内容对应的整形值
- 解析其内容对应的浮点值
0x02 格式化字符串漏洞的利用
主要利用情况有:
- 泄露栈上的数据
- 任意地址读
- 任意地址写
0x03 任意地址写模板
32位
1 | def fmt(prev, word, index): |
值得注意的是因为64位地址有\x00
会导致printf
输出被截断,所以64位的话要把要修改的地址放在后面才行
64位
1 | def fmt(prev, word, index): |
个人经验
算完偏移用aaaaaaaa%n$p试一下,会稳很多
0x04 参考
ctfwiki: https://ctf-wiki.github.io/ctf-wiki/pwn/linux/fmtstr/fmtstr_intro-zh/