欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

[原创]格式化字符串漏洞入门

[原创]格式化字符串漏洞入门

寒假在家的时候总结了一下格式化字符串漏洞,主要是在http://blogs.microsoft.co.il/applisec/2006/12/04/buffer-overflow-overrun-examples/上看到了利用格式化字符串漏洞改变程序执行流程的一个非常棒的例子,加上读了C++安全编码,所以就写一篇这个玩意的入门知识。在我的CSDN博客上已经发过了。

试验工具:ollydbg、VC++6.0
实验环境:windows2000虚拟机
1.%x查看栈内容



执行printf时第四个%x没有提供对应的参数,因此会显示本应该是参数所在位置的栈内容。通过更多的%x甚至可以重建大部分的栈内存。


2.%s查看指定地址内容



执行printf函数。


1,2,3是提供3个参数。利用%x步进,将%s的参数对应到77E61044,因此可以输出77E61044开始的字符串直到遇到截断符。0012FF58为format字符串起始地址,前四个字节即我们想要查看的内存地址77E61044。
3.缓冲区溢出


作为向字符数组中写入数据的格式化输出函数, sprintf()会假定存在任意长度的缓冲区。此处将字符数组user作为由用户构造的输入,其中出现了非常规字符%497d,是此次实验成功的关键。\x39\x4a\x42\x00是shellcode的起始地址,用来覆盖返回地址。\x90…\x33…\xD0…\x90为此次的弹框的shellcode。


第一次调用sprintf(buffer,“ERR Wrong command:%.400s”,user);时写入数据的目的地址为0x0012FB2C,格式化字符串为“ERR Wrong command: %.400s”,%.400s对应的参数为起始地址为0x00424A30的字符串,即用户输入的字符数组user。对地址0x00424A30数据窗口跟随后可以看见该字符数组的内容。


对地址0x0012fb2c查看ASCII数据,可见此时buffer中的字符串为:“ ERR Wrong command:%497d\x39\x4a\x42\x00”,其后的数据由于0x00而被截断。


执行sprintf(outbuf, buffer);时buffer中格式化字符串为:“ERR Wrong command:%497d\x39\x4a\x42\x00”,根据格式化字符串,sprintf()函数会读取一个参数以%497d的格式写入outbuf,由于未提供该参数,会自动将栈地址0x0012fae0中的值视为该参数,即0x12ff80(十进制1245056)。需要写入outbuf的总字符串长度为19+497=516,而outbuf长度为512,因此会导致栈溢出,使得函数返回执行sprintf()后outbuf中的内容。


outbuf起始地址为0x0012fd2c,19字节的字符串“ERR Wrong command:”后为497字节的整型数字1245056,因此从0012ff30开始为\x39\x4a\x42\x00。下图可见成功将返回地址覆写为shellcode起始地址0x00424a39。


继续执行,弹出对话框。


4.改变程序流程
通过格式化字符串漏洞精心构造输入使得下面的程序执行foo函数。你可以在buffer-overflow-overrun-examples上面找到这段代码。

[cpp] view plain copy

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功