博客网 >

编写exploit(一)
作者:分类:默认分类标签:

      昨天简单的写下了攻击者最为常用的入侵手段,今天,我打算从编写exploit开始,踏上我们的入侵之旅。在开始编写exploit之前,有几个基本的东西需要事先学习。

      首先是最起码的C/C++编程,当然,也需要懂得最起码的程序在内存中的结构,比如堆栈等,我们以windows平台下的vc++为例(最为常见的平台构架),然后就是懂得winsock编程。如果你对socket还不太熟悉的话,可以去看看微软出版的那些关于winsock开发的书籍,还有就是参考msdn(基本上对于api的讲解都是e文的)......当然,如果你对汇编和os都很熟悉的话,是很容易开始你的exploit programming之旅的。
      p.s. 如果你是高手(比如说你对汇编和os都很精通),就不要往下看了,很基础的文章,真的很基础:-P
      首先介绍一下最基本的一些概念。第一个就是bug,直译为“漏洞”,指任何软件或者硬件在设计或者在实现上存在的缺陷,并且,这些缺陷在一定条件下可以导致信息泄露等极大的危害。然后说一下exploit,也就是“攻击代码”,指那些执行后可以“展示”出bug的代码。当然,在官方网站上只会提供对bug的描述和修复方法,而不会提供exploit(不过在黑客网站上可以很容易的搜索到,嘿嘿......)。bug就是我们编写exploit的基础。目前最为常见的bug当属缓冲区溢出漏洞(详见我的第一篇web log)和sql注入漏洞,很多蠕虫都是依靠缓冲区溢出的bug进行工作的,这也是我最喜欢的一种bug,嘿嘿......
    好了,有了这个基础知识,再加上你对c/c++编程的理解,我们就可以开始学习编写exploit了。
    首先学习如何在本地利用缓冲区溢出。
    p.s. win xp sp2提供了较好的缓冲区溢出保护机制,因此在这种平台下利用缓冲区溢出是比较困难的。而本文的平台是xp sp2+vc7(当然,xp的各种补丁也是打满了的,所以这个系统应该是“安全”的了,至少在很多人眼里是),所以构造缓冲区溢出的方式显得有些与众不同:-)
    看看下面这段代码:

#include
#include
using namespace std;

void bug(char* buf)
{
 char buffer[10];
 cout << "addr of stack buffer:\t\t" << &buffer << endl;
 strcpy(buffer, buf);
 cout << "stack buffer:" << endl;
 for (int i=0; i<10; i++)
  cout << buffer[i] << '\t';
 cout << endl;
}

void hacked()
{
 cout << "Ouch, I've been hacked!" << endl;
}

void main()
{
 char* buffer;
 buffer="012345678";
 cout << "addr of function main:\t\t" << main << endl;
 cout << "addr of function bug:\t\t" << bug << endl;
 cout << "addr of function hacked:\t" << hacked << endl;
 bug(buffer);
 cin.get();
}

      显然,这段代码是有问题的,那就是程序没有对缓冲区的大小进行检测,而是直接使用了不安全的C++库函数strcpy。这段程序在编译后能够顺利执行,并输出各函数的地址,以及缓冲区的地址和其中的内容。现在,让我们给这段程序做一个小小的改动,就是将bug函数中的输出循环改为100次,编译执行一下,结果如下图所示:

      注意,在图中显示的函数和堆栈地址在不同系统中可能不一样。最关键的是看看堆栈段中的内容。看看你发现了什么,大写字母A!或许你会说,这个A没什么不寻常的,后面还有l和E...再看看函数的地址,有没有看到41(十六进制数)?!A的ASCII码正是十六进制的41!是巧合吗?NO!如果你仍然认为是巧合,请看看程序堆栈的分配先!
      现在,我们已经成功的定位了函数bug的返回地址,如果我们可以修改这个返回地址,就可以执行内存中的任意程序了!聪明的你首先或许会想到直接修改main函数中对buffer的赋值,OK,我们试一下,将字符串"012345678"改为"01234567890123456789",再编译,执行......
      这时,可爱的xp sp2弹出了一个对话框:

      我们发现,堆栈溢出,但是函数bug显然被执行。那么,我们将堆栈溢出进行下去,再覆盖接下来的几个字节,也就是说,我们修改函数的返回地址,并将其改为函数hacked的地址(关于如何获取希望执行的函数的地址,我将在以后的文章中详细讨论)。编译,执行,在vc7的调试环境下成功的执行了函数hacked(尽管编译环境会告诉你该程序发生了未处理的异常,读取时发生访问冲突等等废话,但毕竟,程序已经被执行了!!!)!如下图:

      好!在cmd下运行,sp2的缓冲区保护机制开始工作了,弹出对话框:

      晕阿,难道我们先前的打算都落空了吗?有没有办法制造这个缓冲区溢出呢??答案是肯定的:有!(如果没有,我干嘛写这篇文章呢?)不过这个方法显得有些古怪,修改函数bug,在函数结束前加入语句"buffer[21]=0xAC;"和"buffer[20]=0xE9;"。这两个位置就是函数的返回地址,而修改的值就是函数hacked的地址!compile,run it!好!函数hacked被执行了:

      很好,我们现在已经成功的构造了一个缓冲区溢出。不过,这里仍然有两个问题需要思考和改进:首先,怎样才能容易的修改函数的返回地址?第二,怎样获得需要执行的函数在内存中的地址?在接下来的日子里,我们将就这个问题做进一步的讨论。顺便说一句,如果在早期的win下实现缓冲区溢出,只需要简单的修改buffer,并让其拷贝给buf就行了。在linux和unix的很多版本中,直接拷贝也能实现缓冲区溢出。
      好了,今天就到这里吧,休息,休息休息:-)

<< 编写exploit(二) / 基本入侵技术 >>

专题推荐

不平凡的水果世界

不平凡的水果世界

平凡的水果世界,平凡中的不平凡。 今朝看水果是水果 ,看水果还是水果 ,看水果已不是水果。这境界,谁人可比?在不平凡的水果世界里,仁者见仁,智者见智。

中国春节的那些习俗

中国春节的那些习俗

正月是农历新年的开始,人们往往将它看作是新的一年年运好坏的兆示期。所以,过年的时候“禁忌”特别多。当然,各个地方的风俗习惯不一样,过年的禁忌也是不一样的。

评论
0/200
表情 验证码:

Romeo

  • 文章总数0
  • 画报总数0
  • 画报点击数0
  • 文章点击数0
个人排行
        博文分类
        日期归档