内容提要:一、定制自己的WIN2000 SERVER: 1.版本的选择:Win2000有各种语言的版本,对于我们来说,可以选择英文版或简体中文版,我强烈建议:在语言不成为障碍的情况下,请一定使用英文版。要知道,微软的产品是以Bu …… |
在main函数中,局部变量x的初值首先被赋为0,然后调用与x毫无关系的function函数,最后将x的值改为1并打印出来。结果是多少呢,如果我告诉你是0你相信吗?闲话少说,还是赶快来看看函数function都动了哪些手脚吧。这里的function函数与图5中的function相比只是多了一个指针变量ret以及两条对ret进行操作的语句,就是它们使得main函数最后打印的结果变成了0。对照图7可知,地址buffer + 20处保存的正是函数function的返回地址,第7行的语句将函数function的返回地址加了10。这样会达到什么效果呢?看一下main函数对应的汇编程序就一目了然了。
|
图9 example2.c中main函数对应的汇编程序
地址为0x804833f的call指令会将0x8048344压入堆栈作为函数function的返回地址,而图8中第7行语句的作用就是将0x8048344加10从而变成了0x804834e。这么一改当函数function返回时地址为0x8048347的mov指令就被跳过了,而这条mov指令的作用正是用来将x的值改为1。既然x的值没有改变,我们打印看到的结果就必然是其初值0了。
当然,图8所示只是一个示例性的程序,通过修改保存在堆栈帧中的函数的返回地址,我们改变了程序正常的控制流。图8中程序的运行结果可能会使很多读者感到新奇,但是如果函数的返回地址被修改为指向一段精心安排好的恶意代码,那时你又会做何感想呢?缓冲区溢出攻击正是利用了在某些体系结构下函数的返回地址被保存在程序员可见的堆栈中这一缺陷,修改函数的返回地址,使得一段精心安排好的恶意代码在函数返回时得以执行,从而达到危害系统安全的目的。
说到缓冲区溢出就不能不提shellcode,shellcode读者已经在图1中见过了,其作用就是生成一个shell。下面我们就来一步步看一下这段令人眼花缭乱的程序是如何得来的。首先要说明一下,Linux下的系统调用都是通过int $0x80中断实现的。在调用int $0x80之前,eax中保存了系统调用号,而系统调用的参数则保存在其它寄存器中。图10所示是直接利用系统调用实现的Hello World程序。
|
图