缓冲区溢出还是问题吗?C++/CLI安全编码
我们在此继续使用托管扩展(CLR)。
这是一个非常简单的程序,尽管为了支持Windows GUI,它显得稍微有点长。在17至20行,有几个有意思的变量,lpszPassword是一个由16个宽字符(32字节)组成的已初始化的静态变量,紧跟其后的是userP指针及两个无符号整形:userNameLen和userPasswordLen,之后,userP在33行初始化。这些变量的地址如下:
userP的值为0x00554D30,userNameLen的值为0x00000010,userPasswordLen的值为0xffffffff。如果我们查看lpszPassword地址的起始处内存,可以非常清楚地看到这些变量的初始值(见插3)。 代码段3:
此程序中的漏洞是在118至123行中对SendDlgItemMessage的调用,EM_GETLINE消息指定了从编辑控件IDC_EDIT1获取一行文本--编辑控件在Login对话框中,并把它复制到定长缓冲区lpszPassword中。这个缓冲区只能容纳15个Unicode字符及一个结尾的null,如果输入了多于15个字符,就会发生缓冲区溢出;在此假设输入了20个字符,第17及18个字符将会覆盖掉userP,第19及20个字符将会覆盖掉userNameLen,结尾的null将会覆盖掉userPasswordLen。 假定userP与userNameLen两者都被覆盖,当userNameLen被赋给存储在userP+4(user结构内len的偏移地址)的地址时,在124行就会导致对内存的任意写入。通过把一个地址覆盖为控制权最终要传递到的地址,攻击者就能利用内存的任意写入,把控制权传给任意的代码。而在本例中,堆栈上的返回地址被覆盖了。 因为lpszGuestPassword变量是一个声明在GetPassword函数中的自动变量,我们也可以查看这个变量地址起始处的内存。假定lpszGuestPassword定位在0x002DEB9C,那么可在这个位置查看堆栈的内容。经由程序调试,可以确定0x004f3a99的返回码位于堆栈上的0x002DEBD0处(见插4)。 代码段4:
假定shellcode已被注入到程序中的0x00409028,那么接下来,攻击者可在Login对话框的密码输入栏中输入以下字符串:
在缓冲区溢出之后,数据段的内存显示见插5: 代码段5:
棕色的字节表示userP的值在何处被堆栈上的返回代码地址所覆盖(负4),绿色的字节表示userNameLen的值在何处被shellcode的地址所覆盖。当124行的内存任意写入执行之后,堆栈现在如插6所示。 代码段6:
红色表示的字节标出了堆 |
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |