ff 15 和e8都是用来调用函数的机器码,看一个例子:
218 f9ebc53a 6a00 push 0
218 f9ebc53c ff1500c9ebf9 call dword ptr [APC!PspExitThread_Addr (f9ebc900)]
219 f9ebc542 a100c9ebf9 mov eax,dword ptr [APC!PspExitThread_Addr (f9ebc900)]
219 f9ebc547 50 push eax
219 f9ebc548 68f0c4ebf9 push offset APC!GetPspExitThreadAddr+0xee (f9ebc4f0)
219 f9ebc54d e872020000 call APC!DbgPrint (f9ebc7c4)
219 f9ebc552 83c408 add esp,8
220 f9ebc555 e870020000 call APC!KeGetCurrentThread (f9ebc7ca)
220 f9ebc55a 8945fc mov dword ptr [ebp-4],eax
221 f9ebc55d 8b4dfc mov ecx,dword ptr [ebp-4]
221 f9ebc560 51 push ecx
221 f9ebc561 680cc5ebf9 push offset APC!GetPspExitThreadAddr+0x10a (f9ebc50c)
221 f9ebc566 e859020000 call APC!DbgPrint (f9ebc7c4)
221 f9ebc56b 83c408 add esp,8
222 f9ebc56e 6a00 push 0
222 f9ebc570 8b5508 mov edx,dword ptr [ebp+8]
222 f9ebc573 52 push edx
222 f9ebc574 ff1508c8ebf9 call dword ptr [APC!_imp__ExFreePoolWithTag (f9ebc808)]
APC!KillThreadRoutine+0x4d [f:/dvs/apc/apc.c @ 224]:
224 f9ebc57a 8be5 mov esp,ebp
224 f9ebc57c 5d pop ebp
224 f9ebc57d c21400 ret 14h
看上面的代码得到的结果是:
ff 15 调用时后面直接跟的是函数地址,并且不需要主调函数来平衡堆栈(即不需要在主调函数中使用add esp,xxh)
e8调用时后面跟的是函数地址相对于当前地址的偏移量,并且需要主调函数来实现堆栈平衡(即需要在主调函数中添加add esp,xxh),这个xxh当然是等于调用函数前push了多少字节的参数)
但是不知道还有没有其他的区别了...
PS:
call 一个near过程,只把偏移地址压入堆栈,过程返回时用retn返回
call一个far过程,把偏移地址和段地址入栈,过程返回时用retf返回
在过程中的ret指令根据near和far的不同,分别编译成retn和 retf
retn和retf的机器码是不同的,你也可以不定义过程,直接用retn和retf