格式化字符串漏洞
格式化字符串
1.控制显示的数据类型
我们可以通过代替特殊的格式字符来显示一个值或数据,比如
printf("The num is %d",date)
#即我们可以通过之前对date进行定义,从而使date代替%d而被打印出来
类似于%d,%x,%o等等之类的都是格式化字符串
2.控制显示的宽度和队列
例如:
printf("%5c",65)
#会在前面补充四个空格使得宽度为5
%n这个格式化字符串会将之%n之前的字符个数写入一个参数地址中(类似于指针的功能)
32位的程序,%n取的就是4字节指针,64位取的就是8字节指针。
*%hn 写入两个字节 %hhn 写入一个字节
漏洞的成因以及原理
编译器在进行编译的时候,参数在栈上的分配是由高到低的,低栈的内容先被printf打印出来。
我们在写程序时,printf首先会输出栈上的数据,若参数和格式化字符一一对应,那么我们便会输出我们所想要的东西;如果参数不足时,那么printf便会输出该变量地址上所存储的值或者直接将该地址输出出去。
由此便可得到:当输入的参数不足时,printf便会将栈上的数据或者地址泄露出来,即发生越界访问,从而将内存中的数据泄漏。
补充:%<正整数n>$ <数据类型>,指定占位符对应的第n个参数,例如 %8$x 就是以 x 格式读第 8 个参数的值。
你需要知道格式化字符串会在调用printf之前先压入堆栈中。所以当发现一个格式化字符串漏洞时,首先你需要找到格式化字符串距离当前位置的偏移量。
例题 [第五空间2019 决赛]PWN5
用ida打开插件后可得到该伪代码
基本思路:首先需要将0x804c044这个地址写入到偏移量之后得地址中,然后我们需要输入密码,让密码和0x8040c044这个地址上的存储的值一样即可
由此可以看出这是一个字符串漏洞,首先我们需要找到偏移量以及这个准确的地址。
首先我们需要寻找到格式化字符串距离当前位置的偏移量
所以由此可得该格式化字符串的偏移量为10
而我们最开始又知道在804c044这个地址上读入的是一个4字节的内容,所以可写出以下脚本: