一般状况下在C语言中咱们定义一个大小为5的数组是这样的:html
int arr[5] = {1,2,3,4,5};
1,2,3,4,5
这五个数字对应的下标是0,1,2,3,4
,当咱们想访问数组中第一个数字时,一般会使用arr[0]
的形式去访问,可是,若是咱们使用arr[5]=6
来对超过数组大小的地方进行赋值,会发生什么?
数组
编译以后,发现编译器并无报错,也没有警告,可是咱们知道,这里其实已经发生了数组越界问题。
那咱们先来看一下不进行数组越界操做的时候反汇编是什么样的:
函数
再来看一下对数组进行越界操做的时候是什么样的:
code
对比以后发如今添加了一句arr[5]=6
以后,反汇编代码这里多出一句0040104B mov word ptr [ebp],6
,也就是6被存到内存地址为[ebp]
的地方了。
参照上一篇文章,能够知道[ebp]
是存放原ebp的地址,也就是函数执行第一步的push ebp
,一个函数在开始执行前,会将下一条指令的地址压入栈中,位置是[ebp+4]
,这里咱们注意到,arr[5]
的位置是[ebp]
,那么[ebp+4]
的位置就是arr[6]
,存放在这里的值在函数结束以后会被存放到EIP中当成下一条指令的地址,执行此处的指令。
那么咱们要是在arr[6]
的位置换成另外一个函数的地址,那么在这个函数结束后不就能够自动调用另外一个函数了,因而将原来的代码改为这样:htm
#include <stdio.h> void First(); void Hello(); int main(void) { First(); return 0; } void First() { int arr[5] = {1,2,3,4,5}; arr[6] = (int)Hello; } void Hello() { printf("Hello World!"); getchar(); }
这样,根据咱们的构想,在主函数里面调用了First函数,可是在First函数结束后,会调用Hello函数:
blog
这里能够看到返回地址被改为了Hello函数的入口地址:
从上面就能够看出数组越界的危害性。内存