有这样一段代码段:
void fun() { } int mian() { int a=3; fun(); printf(“%d\n”,a); }如何实现fun函数,使得输出的a不等于3?
转到反汇编看这段代码:
00DF1850 push ebp
00DF1851 mov ebp,esp
00DF1853 sub esp,0CCh
这三步是在给函数分配栈空间,大小为CCH。
00DF1859 push ebx
00DF185A push esi
00DF185B push edi
这三步是在保存现场,函数调用结束后恢复。
00DF185C lea edi,[ebp-0CCh]
00DF1862 mov ecx,33h
00DF1867 mov eax,0CCCCCCCCh
00DF186C rep stos dword ptr es:[edi]
这里几步是在初始化堆栈中的数据。
rep stos dword ptr es:[edi]中,rep表示重复,
stos dword ptr es:[edi]终止条件为ecx=0,每次操作后ecx=ecx-1,
stos:把eax中的内容拷贝到目的地址,这里是edi的值自动增加(这个其实是可变的,它由标准寄存器df的方向来决定,当df=1时,每执行一次stos edi减两个或四个字节;df=0,edi加两个或四个字节)
所以 rep stos dword ptr es:[edi] 就是填充了ebp到esp中的空间。
00DF186E mov dword ptr [a],3:给变量a赋值。
00DF1875 call fun (0DF1221h) 调用函数。
Call分为几种情形:
段内: 保存当前偏移地址 push eips跳转 jump fun 段间: 保存基地址 push cs保存偏移地址 push eip跳转 jump fun
看栈顶esp的改变:
就是push与pop的操作:
Push xxx 就会执行 sub esp x
再看fun函数内:
ALT+5查看寄存器地址,ALT+6查看内存地址
编译器为32位,所以每次执行push,esp加4字节。接下来就变成数push了。
ESP = 0031F6A8
EBP = 0031F780
EAX = CCCCCCCC EBX = 7EFDE000 ECX = 00000000 EDX = 6C667018 ESI = 00000000 EDI = 0021F85C EIP = 01021885 ESP = 0021F784 EBP = 0021F85C EFL = 00000206
EAX = CCCCCCCC EBX = 7EFDE000 ECX = 00000000 EDX = 6C667018 ESI = 00000000 EDI = 0021F85C EIP = 01021760 ESP = 0021F780 EBP = 0021F85C EFL = 00000206
EAX = CCCCCCCC EBX = 7EFDE000 ECX = 00000000 EDX = 6C667018 ESI = 00000000 EDI = 0021F85C EIP = 01021769 ESP = 0021F6B1 EBP = 0021F77C EFL = 00000202
&a=0x0021F854
0102176C lea edi,[ebp-0C0h]
mov [ebp-0C0h]
所以最终的代码为(vs-32位):
void fun() { __asm { mov[esp + 01A4h], 9 } } int main() { int a = 3; fun(); printf("%d\n",a); return 0; }