通用 Thunk
2008-05-25 21:39:20 来源:WEB开发网执行完这2条指令后,栈是这个样子 :
…
1212
RET_ADD <- ESP
下一条被执行的指令,是在thunk 的地址处 (T_ADD)
thunk的第1字节是 “const unsigned char MOV_ECX” –被初始化为0xB9.
紧接着的4字节是 “const void *m_this”
在 thunk.Attach(&obj); 后,m_this = OBJ_ADD
这5字节组成一条合法的指令
T_ADD : MOV ECX,OBJ_ADD
thunk的第6字节是 “const unsigned char JMP” –被初始化为0xE9.
紧接着的4字节是 “const int m_memFunc”
将被 thunk.Attach(memFunc) 修改
这5字节又组成一条合法指令
T_ADD+5 : JMP offset
offset = MF_ADD - &thunk.JMP – 5 ( 由 thunk.Attach() 和SetTransferDST 设置)
所以,这条指令执行后,下一条被执行指令将在这里:
MF_ADD : …
现在,this指正已经准备好,(参数和返回地址也由fun(1212)准备好,而且 C::fun1 将会使用RET 4 返回到 RET_ADD,并正确的平衡堆栈。
所以,它成功了!
设计 StdToStd
让我们由以下3步分析:
1. 调用者如何准备参数和返回地址?
一般的说,一个使用__stdcall 的普通C函数会将参数从右向左依次压栈。我们假设它使得栈增长了 N。注意:N并不总等于参数数目×4!
CALL 指令将返回地址压栈,使得栈再增长4
参数 m <-ESP +4 +N
参数 m-1
…
参数 1 <- ESP + 4
返回地址 <- ESP
它将平衡堆栈的工作交给被调用者。(使用RET N)
更多精彩
赞助商链接