通用 Thunk

http://tech.ddvip.com   2008年05月25日    社区交流

内容摘要:这篇文章提出了一种基于Thunk技术,让一个成员函数成为一个回调函数的通用方法。文章主要讨论原理,同时也提供了一份实现和示例。

  执行完这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)

来源:vckbase    作者:OwnWaterloo    责编:豆豆技术应用

正在加载评论...