05. printf漏洞概述和调试
一.Format String介绍
在C语言中,我们常用的输出函数有pritnf、fprintf、vprintf、vfprintf、sprintf等。对于这些输出函数,Format String是其第一个参数,我们一般称为格式化字符串。
简单介绍格式化字符串如何在输出函数进行解析:
printf接受变长的参数,其第一个参数位格式化字符串,后面的参数在实际运行时将于格式化字符串中特定的子字符串对应,将格式化字符串中的特定子串解析为相应的参数值。
二.格式化字符串漏洞
我们知道printf函数在执行时,首先进行格式化字符串的解析–从栈(或寄存器)获取参数并于符号说明进行匹配,比如参数个数少于符号声明个数时,就有可能造成泄露。
三.实例程序1canary.c
先使用上节课用到的源程序看看,这里注意一个细节:printf函数里面没有参数!
老方法运行:gdb canary
直接先运行:
调试再运行:
查看main函数:disass mian
上节课我们分析的时canary保护,这次在后面加断点跳过canary保护:b *0x080484bb
执行:run
+65行,把eax - 0x1a555传入edx,其实这就是输出内容的地址
+71行,就是把输出内容的地址压栈!
+74行,要调用printf函数了,由于没有参数,所以它还是去esp+4的默认值,我们可以修改这里的数据就可以达到输出修改的内容:
先用0x80485ab里面的数据填充
修改:set *(0xffffd0e4)=0x80485ab
默认参数被修改后:
然后直接运行可以看到后面的参数被加入进来了:c
四.实例程序2pirntf1.c
编写代码:
1 |
|
提权:chmod 777 printf1.c
编译:gcc -no-pie -fstack-protector-all -m32 -o printf1 printf1.c
和第一个程序一样;运行gdb;查看main函数;
在canary后加断点;b*0x080484de
运行:run
+40行,提升堆栈空间
+43行,read()函数第三个参数0x20压栈
+45,+48行,read()函数第二个参数str的地址压栈
查看内容:x $ebp-0x1c
+49行,read()函数第一个参数0压栈
+51行,执行read()函数,由于第一个参数是0,便从command line获取数据,我们输入yyds,此时观察寄存器和堆栈:
+56行,外平栈
+59行,右提升堆栈空间,位执行print做准备,此时esp刚好指向我们输入的内容!
+62,+68行,就是printf()里面的内容压栈,之后,下一行就还是我们刚才输入的内容,紧跟其后!
+69行,执行printf输出!
此时即使没有给printf参数,但是,它还是默认输出来啦!
借用此漏洞,后面还可以实现输出canary保护的cookie值!敬请期待啊·!