#include "stdafx.h"
void HelloWorld() {
	printf("Hello World");
	getchar();
}
void Fun() {
	int arr[5] = {1,2,3,4,5};
	arr[6] = (int)HelloWorld;
}
int main(int argc, char* argv[]) {
	Fun();
	return 0;
}
代码并没有调用HelloWorld,但成功执行了HelloWorld

很容易看出arr[6] = (int)HelloWorld;这行代码有问题,将一个函数名强转为int型,并赋值给arr[6],而arr[6]已经超出数组大小
main()反汇编
main:
00410790   push        ebp
00410791   mov         ebp,esp
00410793   sub         esp,40h
00410796   push        ebx
00410797   push        esi
00410798   push        edi
00410799   lea         edi,[ebp-40h]
0041079C   mov         ecx,10h
004107A1   mov         eax,0CCCCCCCCh
004107A6   rep stos    dword ptr [edi]
004107A8   call        @ILT+15(Fun) (00401014)
004107AD   xor         eax,eax
004107AF   pop         edi
004107B0   pop         esi
004107B1   pop         ebx
004107B2   add         esp,40h
004107B5   cmp         ebp,esp
004107B7   call        __chkesp (00401140)
004107BC   mov         esp,ebp
004107BE   pop         ebp
004107BF   ret
call跟进
00401014   jmp         Fun (00410740)
00401019   jmp         HelloWorld (004106c0)
Fun()反汇编
Fun:
00410740   push        ebp
00410741   mov         ebp,esp
00410743   sub         esp,54h
00410746   push        ebx
00410747   push        esi
00410748   push        edi
00410749   lea         edi,[ebp-54h]
0041074C   mov         ecx,15h
00410751   mov         eax,0CCCCCCCCh
00410756   rep stos    dword ptr [edi]
00410758   mov         dword ptr [ebp-14h],1
0041075F   mov         dword ptr [ebp-10h],2
00410766   mov         dword ptr [ebp-0Ch],3
0041076D   mov         dword ptr [ebp-8],4
00410774   mov         dword ptr [ebp-4],5
0041077B   mov         dword ptr [ebp+4],offset @ILT+20(HelloWorld) (00401019)
00410782   pop         edi
00410783   pop         esi
00410784   pop         ebx
00410785   mov         esp,ebp
00410787   pop         ebp
00410788   ret
初始状态

堆栈图:

call指令执行后
将call后的下一指令004107AD地址压入栈

堆栈图:

jmp跳转后,到设置缓冲区后的状态

这里要注意[ebp+4],此时为004107AD为函数的返回地址

堆栈图:

局部变量设置
int arr[5] = {1,2,3,4,5};这行代码,编译器会划分出5个int宽度的内存空间存放,根据下标由小到大,内存地址由低到高。
要分配5个int大小的空间,所以从ebp-0x4*0x5即ebp-0x14开始分配

局部变量设置完成后的堆栈图:

执行arr[6] = (int)HelloWorld;发生了生么?
(int)HelloWorld这里的HelloWorld不是字符串,而是一个函数名,使用(int)强制转换为了内存地址,所以(int)HelloWorld的返回值为该指令的内存地址arr的大小为5,即最大下标为4,arr[6]发生数组越界,造成了缓冲区溢出,当给arr[6]赋值时,编译器直接以arr的内存地址为基础+0x4*0x6即0x18结果为0012FF30,也就相当把返回地址的值修改为函数HelloWorld的内存地址ret时,eip变为了函数HelloWorld的内存地址,导致执行了函数HelloWorldHelloWorld内存地址:00401019
004110B8   call        @ILT+20(HelloWorld) (00401019)


原文:https://www.cnblogs.com/ybit/p/15177171.html