格式化串漏洞

作者: 0x110 分类: security 发布时间: 2012-04-06 17:06

printf的缺陷:

#include "stdio.h"
int main(int argc, char* argv[])
{
int a=11,b=22;
printf("a=%d,b=%d\n",a,b);
printf("a=%d,b=%d\n");
return 0;
}

第二次调试没有引起编译错误,程序正常,只是数据异常。api的参数入栈方式是_stdcall,参数按照从右到左的顺序入栈。

printf(“a=%d,b=%d\n”,a,b);的堆栈排列方式

栈顶---"a=%d,b=%d\n"

栈-----变量1(a)(11)

栈底---变量2(b)(22)

第二次调用printf函数,堆栈排序

栈顶---"a=%d,b=%d\n"

栈----"a=%d,b=%d\n"

栈-----变量1(a)(11)

栈底---变量2(b)(22)

虽然调用时没给出“输出数据列表”,但系统仍然按照“格式控制符”所指明的方式输出了栈中紧随其后的两个DWORD。现在应该明白输出“a=4223024,b=11”的原因了,

4223024的十六进制形式为0x407030,是指向格式控制符“a=%d,b=%d\n”的指针:11是残留下来的变量a的值

printf读取内存数据:

#include "stdio.h"

int main(int argc, char* argv[])

{

printf(argv[1]);

return 0;

}

输入普通字符串(如“test”)时,得到简单反馈。但是输入格式控制符时,printf就会打印出栈中不该有的数据。

例如,输入“%p,%p,%p……”,实际上读出了栈中的数据

printf向内存写数据

只允许读取数据还不算很糟糕,配合上修改数据就有可能造成进程劫持和shellcode植入了。

在格式化控制符中,有一种鲜为人知的控制符%n,这个控制符用于把当前输出的所有数据的长度写回一个变量中去。

#include "stdio.h"int main(int argc, char* argv[])

{

int len_print=0;

printf("before write:length=%d\n",len_print);

printf("failwest:%d%n\n",len_print,&len_print);

printf("after write:length=%d\n",len_print);

return 0;

}

第二次printf调用使用了%n控制符,它会将最终输出的字符串长度写入变量len_print中。“failwest:0”长度为10,所以这次调用len_print将被修改为10.

转载保留版权:SZBUFFER-《格式化串漏洞》
本文链接地址:http://blog.16lo.cn/archives/161.html

如果觉得我的文章对您有用,请随意赞赏。您的支持将鼓励我继续创作!

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据