目录
  1. 1. 0x00 什么是格式化字符串
  2. 2. 0x01 漏洞原理
    1. 2.1. 产生漏洞的原因
  3. 3. 0x02利用格式化字符串漏洞实现任意地址读
格式化字符串漏洞

0x00 什么是格式化字符串

学过c语言的都知道printf,fprintf,sprintf等这一类printf函数中经常用到”%”,后面加一个或多个字符串做说明符。
格式化字符串指的就是printf函数第一个参数,最常见的包括:

1
2
3
4
5
6
%d - 十进制 - 输出十进制整数
%s - 字符串 - 从内存中读取字符串
%x - 十六进制 - 输出十六进制数
%c - 字符 - 输出字符
%p - 指针 - 指针地址
%n - 到目前为止所写的字符数

printf有一个特殊的格式化控制符%n,和其他控制输出格式和内容的格式化字符不同的是,这个格式化字符会将已输出的字符数写入到对应参数的内存中。
我们就利用这个漏洞实现任意地址写

0x01 漏洞原理

产生漏洞的原因

就是没写格式化控制符,如

1
2
3
char str[100];
scanf("%s",str);
printf(str);

事实上,这是一种非常危险的写法。由于printf函数族的设计缺陷,当其第一个参数可被控制时,攻击者将有机会对任意内存地址进行读写操作。

一般来说,每个函数的参数个数都是固定的,被调用的函数知道应该从内存中读取多少个变量,但printf是可变参数的函数,对可变参数的函数而言,一切就变得模糊了起来。函数的调用者可以自由的指定函数参数的数量和类型,被调用者无法知道在函数调用之前到底有多少参数被压入栈帧当中。所以printf函数要求传入一个format参数用以指定到底有多少,怎么样的参数被传入其中。然后它就会忠实的按照函数的调用者传入的格式一个一个的打印出数据。由于编程者的疏忽,把格式化字符串的操纵权交给用户,就会产生后面任意地址读写的漏洞。

举个栗子,主函数如下:

程序很简单,可以多次输入方便调试,
memset函数先把buf都初始化为0,
然后read函数读取键盘操作,输入buf
最后在输出buf。

正常情况下我们输入什么都会输出什么,但是当我们输入一些特定的字符时输出出现了变化。

0x02利用格式化字符串漏洞实现任意地址读

文章作者: nocbtm
文章链接: https://nocbtm.github.io/2018/11/29/格式化字符串漏洞/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 nocbtm's Blog
打赏
  • 微信
  • 支付宝