Windows下执行一个函数,会把指向正在运行的指令的地址压入堆栈,也就是寄存器EIP的值。当函数执行完毕,会让该数据出栈,以便程序继续原路运行。
如果这个函数有8个CHAR的局部变量,也压入堆栈。堆栈是从内存高地址向低地址分配的,如果这8个CHAR是放置用户输入的数据,并且如果没有检查长度的话,可能会覆盖掉高地址的记录EIP的值,如果这个值是一个非法地址,当函数返回时,Windows就会跳出致命错误的对话框,说某某地址不可读等等。
但是如果我们精心构造一个有效的地址,让Windows以为这就是它先前压入栈的EIP的值,而这个地址有是指向我们要获得系统权限的ShellCode,那会怎样呢?
假设我们这样构造用户输入:
[8个任意CHAR]+[替代EIP的地址]+[SHELLCODE]
这些都会被写入栈中,并且替代的EIP地址覆盖掉原来的地址。
如果我们能想办法让[替代EIP的地址]的指令变是指向[SHELLCODE]就完美了。
我们发现当函数返回时,取出[替代EIP的地址]后,堆栈指针向高地址移4个字节,正好指向我们的[SHELLCODE],也就是说如果我们能找到[替代EIP的地址]是指向JMP ESP指令的,任务就完成了。
我们知道WINDOWS运行一个程序会分配给它4G虚拟内存,其中要装载很多固定基本的DLL,我们不难找到有指向JMP ESP指令的地址,通过相关工具,把这个地址写到我们的代码中就OK了。