前言:比起ESP寻址的方式,EBP需要去理解下其中的含义,所以记录下!
个人理解:
1、EBP和ESP之间的关系
起初-1 相隔 ----> 在没进CALL之前,会先将调用CALL的参数先压入堆栈,堆栈中EBP寄存器中的地址是在ESP寄存器中的地址之下, 自己理解为相隔
中间-2 相等 ----> 进入CALL之后,EBP寄存器会先把保存的地址先压入堆栈中保存,然后再保存ESP寄存器中的地址,这里就可以理解为ESP不变,将EBP进行提升栈顶的操作
中间-3 相隔 ----> 因为调用了CALL,那么就会进行一系列的运算,那么肯定需要堆栈中的空间,那么ESP地址就会上升
中间-4 相等 ----> 当调用完了之后,当前EBP寄存器保存的就是之前的ESP的地址,现在就会返回给ESP寄存器,堆栈需要保持平衡
末尾-5 相隔 ----> 堆栈到现在还没有完全保持平衡,还需要把EBP的地址返回给EBP寄存器,然后出了CALL之后,还需要指令进行外/内平衡的操作保持真正的堆栈平衡!
汇编体现:
00401000 > 6A 01 push 0x1 ; 压入堆栈0x1
00401002 6A 02 push 0x2 ; 压入堆栈0x2
00401004 E8 3C000000 call CRACKME.00401045 ; 调用call 00401045
00401009 83C4 08 add esp,0x8 ; 恢复两个参数的堆栈数,所以+8
0040100C . 6A 00 push 0x0 ; /
0040100E . 68 F4204000 push CRACKME.004020F4 ; |
00401013 . E8 A6040000 call <jmp.&USER32.FindWindowA> ;
00401018 . 0BC0 or eax,eax
0040101A . 74 01 je short CRACKME.0040101D
0040101C . C3 retn
0040101D > C705 64204000>mov dword ptr ds:[0x402064],0x4003
00401027 . C705 68204000>mov dword ptr ds:[0x402068],CRACKME.WndP>; è
00401031 . C705 6C204000>mov dword ptr ds:[0x40206C],0x0
0040103B . C705 70204000>mov dword ptr ds:[0x402070],0x0
00401045 55 push ebp ; 保存原始ebp地址
00401046 8BEC mov ebp,esp ; 再让当前ebp中保存esp的地址
00401048 83EC 10 sub esp,0x10 ; 提升栈顶,用于保存其他要用到的东西,当前没有体现用处
0040104B 8B45 08 mov eax,dword ptr ss:[ebp+0x8] ; CRACKME.<ModuleEntryPoint>
0040104E 0345 0C add eax,dword ptr ss:[ebp+0xC]
00401051 8BE5 mov esp,ebp ; 把之前保存的ebp返回给esp
00401053 5D pop ebp ; 再把之前压入的ebp地址返回给ebp寄存器
00401054 C3 retn ; 跳出