[原创]格式化字符串漏洞简介
0x01 简介
格式化字符串漏洞是一种比较常见的漏洞类型,主要是printf.sprintf和fprintf等c库中print家族的函数.先看看printf的函数声明:
int printf(const char* format,...)
这应该是所有人学习的第一个函数了,先是一个字符串指针,他指向一个format字符串,后面是个数可变的参数.在c程序中我们有很多用来格式化字符串的说明符,在这些说明符后面我们可以填充我们自己的内容.最常见的包括:
%d - 十进制 - 输出十进制整数 %s - 字符串 - 从内存中读取字符串 %x - 十六进制 - 输出十六进制数 %c - 字符 - 输出字符 %p - 指针 - 指针地址 %n - 到目前为止所写的字符数
在这众多的格式符中有一个异类需要注意,别的都是用来打印数据的,而%n可以用来把一个int型的值写到制定的地址去.printf一般我们这样使用:
char str[100];
scanf("%s",str);
printf("%s",str);
但是如果偷懒写成这样子:
char str[100];
scanf("%s",str);
printf(str)
看起来没什么问题,而且运行也很正常,但却产生了一个非常严重的漏洞.
0x02 漏洞的产生原理
正常情况下
//gcc test.c -o test -m32
#include <stdio.h>
int main()
{
printf("%d %d %d %d %s",1,2,3,0x21,"test");
return 0;
}
汇编源码主体是这样:
0x8048424 <main+25> push 0x21 0x8048426 <main+27> push 3 0x8048428 <main+29> push 2 0x804842a <main+31> push 1 0x804842c <main+33> push 0x80484d5 ? 0x8048431 <main+38> call printf@plt <0x80482e0>
运行到这里的时候栈是这样的:
00:0000│ esp 0xffffd760 —? 0x80484d5 ?— and eax, 0x64252064 /* '%d %d %d %d %s' */ 01:0004│ 0xffffd764 ?— 0x1 02:0008│ 0xffffd768 ?— 0x2 03:000c│ 0xffffd76c ?— 0x3 04:0010│ 0xffffd770 ?— 0x21 /* '!' */ 05:0014│ 0xffffd774 —? 0x80484d0 ?— je 0x8048537 /* 'test' */ 06:0018│ 0xffffd778 —? 0xffffd83c —? 0xffffd962 ?— 'HOSTNAME=013c1b5957f3'
本来函数应该按照cdecl函数调用规定从右边函数开始逐个压栈,但是printf是c语言中少有的支持可变参数的库函数.函数的调用者可以自由的指定函数参数的数量和类型,被调用者无法知道在函数调用之前到底会有多少个参数被压入栈中,所以printf函数要求传入一个format参数以指定参数的数量和类型,然后他就会忠实的按照函数的调用者传入的格式一个一个的打印函数.
注意:上传附件及图片大小不得大于30M。
⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途。
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。
复制成功
