#include <stdio.h>
#include <Windows.h>
//堆栈平衡原理
//如果要返回父程序,则当我们在堆栈中进行堆栈的操作的时候,一定要保证在RET这条指令之前,ESP指向的是我们压入栈中的地址。
//当执行call dword ptr[fun1]语句, esp=esp-4, push eip到堆栈
void fun1()
{
__asm
{
mov eax, 1111h
push eax // esp=esp-4
mov eax, 3333h
pop eax //pop eax执行后esp=esp+4,堆栈平衡, 如果不pop eax, pop ebp 然后ret以后堆栈就会溢出
}
printf("22222222
");
}
/*--------------------------------------------------------------------------*/
以下是esp变化的时序代码
11: void fun1()
12: { //esp=esp-4
push ebp //esp=esp-4
mov ebp,esp
13: __asm
14: {
mov eax,1111h
push eax //esp=esp-4
mov eax,3333h
pop eax //esp=esp+4 esp减了3次 就要加3次,只要这样ret后eip才是call语句push的
//CPU只认识esp, esp是的地址是否正确需要我们自己去平衡
19: }
20: printf("22222222
");
21: }
pop ebp //esp=esp+4
ret //esp=esp+4
/*--------------------------------------------------------------------------*/
源码
void main()
{
char ps[20] = "111111111
";
char *p1 =ps;
HMODULE hmod =GetModuleHandle("msvcr90.DLL");
if (hmod)
{
PVOID pfun =GetProcAddress(hmod, "printf");
if (pfun)
{
HMODULE h = GetModuleHandle(NULL);
DWORD dd=(DWORD)h;
dd+=0x1000;//0x1000是fun1函数的偏移,dd表示fun1函数的地址
__asm
{
mov byte ptr [ps+3],0x62
push dword ptr[p1]
call pfun
//下面句话的调用,编译器会把fun1()函数编译进PE文件,去掉这句话dd就不是fun1()函数的地址了
call dword ptr[fun1]
call dd
}
}
FreeLibrary(hmod);
}
}