1.下面这段代码运行的结果是什么?
#include <stdio.h> #include <Windows.h> DWORD dz=0; DWORD dz1=0; void fun1() { __asm { mov eax, dz push eax ret } } void main() { HMODULE h = GetModuleHandle(NULL); dz1= dz =(DWORD)h; dz+=0x1062;//0x1062为 printf("2222 ")相对于代码段基址的偏移 dz1+=0x0; __asm { call fun1 } printf("1111 "); printf("2222 "); }
不仔细思考,运行结果为:
2222
实际运行结果:
2222
1111
2222
为什么会这样,分析下原因:
1. call fun1语句执行后: printf("1111
") 的地址压入栈.
2. fun1函数执行后: ret指令改变了eip, eip = dz, 转到main函数里面执行 printf("2222 ")
3. main函数执行ret后: 取出printf("1111 ")地址赋给了eip, 导致程序又跳到了printf("1111 ")处执行
2.把fun1函数改进下,使运行结果为:
2222
实现代码:
#include <stdio.h> #include <Windows.h> DWORD dz=0; DWORD dz1=0; void fun1() { __asm { add esp,8 //前面默认执行了push eip, push ebp, 保存main ret的地址内存就在esp+8的位置 mov eax, dz1 push eax //把printf("1111 ")的地址替换为 main 的'}' sub esp,4 //还原栈指针 mov eax, dz push eax ret } } void main() { HMODULE h = GetModuleHandle(NULL); dz1= dz =(DWORD)h; dz+=0x1077; //0x1062为 printf("2222 ")相对于代码段基址的偏移 dz1+=0x1085;//0x1085为 main函数的'}' 相对于代码段基址的偏移 __asm { call fun1 } printf("1111 "); printf("2222 "); }
这样 main函数执行ret后: eip= '}' 地方的地址, 程序结束,运行结果为:
2222