WEB开发网
开发学院软件开发VC Thunk 技术的一个改进 阅读

Thunk 技术的一个改进

 2008-03-27 21:40:28 来源:WEB开发网   
核心提示: 以上面的代码为例,让我们重新考虑一下整个过程,Thunk 技术的一个改进(2),我们的目的是在调用函数foo之前将参数增加1,一般而言,另外,为了能方便的得到thunk代码模板的地址,这样做肯定是没有foo函数的源代码或者不允许修改源代码,否则直接改foo函数的代码就好了

以上面的代码为例,让我们重新考虑一下整个过程。我们的目的是在调用函数foo之前将参数增加1。一般而言,这样做肯定是没有foo函数的源代码或者不允许修改源代码,否则直接改foo函数的代码就好了,何必这么麻烦。为了调用时候的简单化,定义一个函数指针是比较合适的,否则每次调用都写汇编代码jmp或call太麻烦。这样一来,函数指针必须指向一个代码段的地址。但是这个代码段必须用机器码来构造吗,直接写汇编代码也同样可以做到。

当然,这里有一个问题。我们写汇编指令的时候,必须是一条指令一条指令的写,不能说指令写一半,然后让汇编程序去处理。上面的代码中,第一条指令inc直接写汇编语句当然没问题。但下面的jmp语句,就不能直接写。因为我们写汇编语句的时候,jmp跳转偏移量是未知的,必须编译后才知道。并且我们不能只写jmp而不写偏移量,那是通不过编译的。

这个问题可以这样解决,写jmp语句的时候,我们写一个占位的DWORD,其值设为一个特殊的值,比如0xffff(原理是这样,实际处理还要迂回一下,后面有说明)。只要在这段thunk代码中不出现这个值就好。然后执行的时候,在第一次调用之前,在thunk代码中查找该值,将其替换为计算出来的动态值。经过这样的处理,就可以彻底在thunk代码中消除机器码的直接操作。

更一般化,为了生成正确的机器码,我们用两个函数。一个用于生成机器码的模板,另一个函数用于在机器码的模板中填入需要动态计算产生的值。下面是一个例子:

void ThunkTemplate(DWORD& addr1,DWORD& addr2)//生成机器码
{
  int flag = 0;
  DWORD x1,x2;
  if(flag)
  {
     //注意,这个括号中的代码无法直接执行,因为其中可能含有无意义的占位数。
    __asm
    {
thunk_begin:
          ;//这里写thunk代码的汇编语句.
          ...
  
thunk_end:  ;
    }
  }
  __asm
  {
    mov  x1,offset thunk_begin; //取 Thunk代码段 的地址范围.
    mov  x2,offset thunk_end;
  }
  addr1 = x1;
  addr2 = x2;
}

上面的函数用于生成thunk的机器码模板,之所以称为模板,是因为其中包含了无意义的占位数,必须将这些占位数替换为有意义的值之后,才可以执行这些代码。因此,在函数中thunk代码模板放在一个if(0)语句中,就是避免调用该函数的时候执行thunk代码。另外,为了能方便的得到thunk代码模板的地址,这里采用一个函数传出thunk代码的首尾地址。

上一页  1 2 3 4  下一页

Tags:Thunk 技术 一个

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接