格式化串漏洞

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.

1. 本站所有资源来源于用户上传和网络,仅作为演示数据,如有侵权请邮件联系站长!
2. 本站文章转载,请注明出自缓冲区(SZBUFFER) - www.szbuffer.com。
缓冲区 » 格式化串漏洞

发表评论

新房二手房产系统售价¥540,不限制域名,免费更新

立即查看 了解详情