引言
格式化字符串(Fromat String):在编码过程中,允许编码人员通过特殊的占位符,将相关对应的信息整合或提取的规则字符串。格式化字符串包括格式化输入和格式化输出 以printf()
为例,第一个参数就是格式化字符串:“字符串 %s, 整数 %d, 浮点数 %f”,然后printf函数会根据这个格式化字符串来解析对应的其他参数
%d /// 十进制-输出十进制整数 %s /// 字符串-从内存中读取字符串 %lx /// 十六进制-输出十六进制数 %c /// 字符-输出字符 %p /// 指针-指针地址 %n /// 到目前为止所写的字符数
漏洞原理利用
程序崩溃
针对格式化字符串漏洞,使程序崩溃是最简单的利用方法,只需要输入一串%s
即可
%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s
可能会有人问,为什么输入一串%s
就会导致程序崩溃,这是因为针对每一个%s
,printf()
都会从栈上取一个数字,把该数字视为地址,然后打印出该地址指向的内存内容,但是不可能获取的每个数字都是地址,所以数字对应的内容可能不存在,或者该地址是被保护的,这样就会使程序崩溃
tips:在Linux中,存取无效的指针会引起进程收到SIGSEGV信号,从而导致程序非正常终止并产生核心转储
泄漏内存
#include <stdio.h> int main() { char s[100]; int a = 1, b = 0x22222222, c = -1; scanf("%s", s); printf("%08x.%08x.%08x.%s\n", a, b, c, s); printf(s); return 0; }
编译一下:
gcc -m32 -fno-stack-protector -no-pie -o format1 format1.c
在printf函数上下一个断点,然后r运行,输入%08x.%08x.%08x
tips: 什么是%08x 在C语言中,格式说明符
%08x
用于printf
函数中,将一个无符号整数以8个字符的宽度格式化为十六进制数字。
查看此时的栈空间
来看一下栈上的地址 首先是第一行,这是
printf
的返回地址,然后是第二行,可以看到这后面是之前的一串%08x.%08x.%08x.$s\n
这是printf
函数的第一个参数:格式化字符串,printf函数会