多次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()不会使用用同一栈帧的参数。

posted @ 2020-09-26 12:19  ch0bits  阅读(286)  评论(0编辑  收藏  举报