通用Thunk
2010-07-15 20:45:23 来源:WEB开发网核心提示:我们使用 CALL offset(dword) 跳转到Hook,这个指令会将返回地址压栈,通用Thunk(11),所以,CALL HOOK之后,3. Hook 使用 JMP DWORD PTR[EAX],这是一个绝对跳转,所以m_memFunc不能使用 SetTransferDST,堆栈如下 :…参数 m
我们使用 CALL offset(dword) 跳转到Hook,这个指令会将返回地址压栈。所以,CALL HOOK之后,堆栈如下 :
…
参数 m
参数m-1
…
参数1
调用者返回地址
Hook返回地址 <- ESP
Hook 返回地址刚好是紧接着“CALL HOOK”的指令,—— &m_memFunc
Hook 使用 __declspec( naked ) 强制编译器不生成额外指令。(兼容性:VC8支持。VC6,7不确定,g++不支持)
第1条指令POP EAX 将使堆栈减少4并且得到thunk对象的地址。
…
参数1
调用者返回地址 <- ESP
EAX : p //p=&m_method; &m_this=p+4; &oldESP=p+9; &oldRet=p+14
现在,还有3件事情值得我们注意:
1. thunk对象使用 CALL(0xE8)转移到 Hook。这是一个相对转移
2. thunk对象使用 JMP offset 跳转到调用者,offset将被Hook计算。
3. Hook 使用 JMP DWORD PTR[EAX],这是一个绝对跳转,所以m_memFunc不能使用 SetTransferDST,m_memFunc = PointerToInt32(&C::Fun); 才是正确的。
更详细实现见 ThisToCdecl.h 和 ThisToCdecl.cpp
设计 CdeclToCdecl
1、使用__cdecl 的普通C函数前面已经讨论过
2、一个使用__cdecl 的成员函数希望栈像这个样子:
…
参数 m <-ESP + 8 + N
参数m-1
…
参数1 <-ESP + 8
this <-ESP + 4
返回地址 <- ESP
更多精彩
赞助商链接