mai
sargume
ts
HigherAddresses从正常时候的内存分布可以看出,内存的高端部分是函数从被调用函数返回时需要的地址,而内存低端部分则是被调用函数的两个要使用的缓冲空间:buf1和buf2。在这里解释一下,假设被调用的函数是strcpy,strcpy函数是一个字符串复制函数,有两个参数,其中buf2代表来源字符串,buf1代表目的空间,strcpy函数的目的就是要把buf2中的字符串全部复制进入buf1代表的空间。现在如果将buf2,即来源字符串弄得很长,假设是很多“A”,这个时候再去执行strcpy函数,内存中的分配空间就会出现溢出中所表现的样子。可以看到buf1中充满字符41,“41”是A的ASCII码,不但如此,紧接着buf1的内存空间也全部被覆盖成了41,最关键的一个地方“retur
address”这块内存也全部成了41。那么程序在执行完strcpy函数要返回的时候,程序获得的返回地址竟是41414141,程序不管这个地址对不对,就直接返回了,结果程序会因为这个地址非法而出错。现在看一下,因为程序的返回地址被覆盖,所以程序出错,而这个覆盖值是我们故意输入的,也就是说我们完全能够控制把什么数值覆盖到程序的返回地址上,那么如果将一段恶意代码或者要执行某个目的的代码,预先放入内存中某个地址,再将这个地址覆盖到程序的返回地址上,这样程序一旦溢出后返回,就会自动跳到代码上去,并且会执行代码,而且这一切都是由程序“正常”执行的。恶意攻击者为了能够利用栈溢出来控制软件的执行流程,一般会将溢出地址覆盖为jmpesp指令或者callesp指令所在的地址。这是因为对于程序来说,当发生栈溢出时,往往是程序中的某一个函数的返回地址被过长的数据覆盖,此时,esp寄存器指向的地址就是过长数据的后半部分。如溢出时内存分布可以看出。如果此时,esp指向的这段过长数据是一段恶意代码,那么当我们把函数的返回地址覆盖成为一个jmpesp指令或者callesp指令所在的地址时,溢出发生后,函数一返回就会跳转到jmpesp指令或者callesp指令所在地址上,CPU执行jmpesp指令或者callesp指令后,马上就会跳到esp寄存器指向的过长数据上,从而执行恶意代码,即常说的ShellCode。举个例子,如下代码:i
cludestdiohi
cludestri
ghchar
ame