多次Printf()是否使用用同一栈帧的参数?
如题,问题出自于格式化字符串漏洞,(教师展示的源码)显示printf函数,“调用第一次打印正常数字,第二次打印时不指定变量 (printf("%d%d")),会将上一次压入的值和栈中下一个值打印出”。其实我怀疑他是不是讲错了。
引申:
格式化字符串漏洞成因:程序将格式化字符串的输入权交给用户,printf函数并不知道参数个数,它的内部有个指针,用来索检格式化字符串。对于特定类型%,就去取相应参数的值,直到索检到格式化字符串结束。所以没有参数,代码也会将format string 后面的内存当做参数以16进制输出。这样就会造成内存泄露。
1.先来看调用printf函数以后会不会清除参数
如上程序,我用execl画到0040104B地址的堆栈(add esp 8处)
可以看到如果执行add esp,8先前的参数也会被堆栈清除,第二次打印会使用同一函数栈帧,但是参数已经清除,格式化字符串漏洞的打印上一次的参数不成立
2.矛盾
自己编写程序,发现教师的结果没有讲错
拿去OD反汇编,第一次打印函数的确平衡了堆栈,清除了参数
Leave的作用相当==mov esp,ebp和pop ebp
那么到这就可以下结论了:printf()函数被调用多次,它的栈在每次调用完后都会被清除,多次调用打印上一次变量的值应该与printf()函数自身有关。
3.不一样的结果
但是但是,在经过一个小时的测试后
如图VC++中的结果,明确了函数调用完堆栈会清除参数,问题不在printf函数本身,而在于编译器怎样去编译执行这个程序
由于2中是用codeblock编写的,两个编译器出现不同的结果,由结论知:call调用同一函数,结束后会清除参数,所以多次Printf()不会使用用同一栈帧的参数。
[Sign]做不出ctf题的时候很痛苦,你只能眼睁睁看着其他人领先你