c++ THUNK技术

这里想说的是:代码中的关键点为用指令jmp pFunc跳转到你想要执行的函数pFunc。

指令“jmp xxxx”占5个字节,代码中用了个一字节对齐的结构体struct Thunk 

当然也可以用 unsigned char code[5]; 说另一个关键点就是地址计算了,jmp xxxx指令用了相对跳转地址,

相对地址 = 要跳转函数的地址 - “jmp xxxx”指令的下一条指令的地址。

下面代码中的class C 只有m_thunk一个数据成员,没有虚函数和在m_thunk前没有声明别的数据成员,

因此相对地址 = pFunc - [ (int)this + sizeof(struct Thunk) ]

如上所述,若有虚函数和在m_thunk前声明了别的数据成员,则相对地址的计算要做修改。

:)本来画个表会说得比较清楚,但本人嫌麻烦,就作罢了!

/下面是所转的文章

 

实际上C++ 的THUNK技术是需要改变指令代码的,这里发一个贴说明之 


// 此程序演示 运行时 改变 指令代码   
  
//实质是 C++ 实现多态  的 THUNK 技术思想的简陋模拟 

//在VC6.0 中编译通过。 

#include <windows.h> 
#include <iostream.h> 



typedef void(*pFUN)();  //函数类型 

#pragma pack(push,1) //强制编译器,使数据按字节边界对齐。 
                     //默认情况下VC6.0是按4字节对齐,VC7.0按8字节对齐 
                     //指令本不是按双字边界对齐的,所以必须使其按字节边界对齐,否则出错 

// 下面是存储机器代码的结构 
struct Thunk //有趣的是:这个结构不储存数据,而是储存指令。一个jmp跳转指令 
  //我们将改变这个结构,然后让程序执行此代码,此结构的执行将会改变程序的执行路径 
    BYTE    m_jmp; // 储存jmp指令的操作码 
    
DWORD   m_adrr;      // 储存相对jmp指令的偏移地址(指令操作数) 
};  // 
#pragma pack(pop)//撤销数据按字节对齐,数据按双字对齐的主要目的是优化执行速度 

class 

public: 
    Thunk    m_thunk;  //产生一个 Thunk 实例 

    void Init(pFUN pFun) 
    
         
        m_thunk.m_jmp 0xe9;// 跳转指令的操作码是 0xe9 所以。。。 
        
        m_thunk.m_adrr (int)pFun ((int)this+sizeof(Thunk)); 
           // JMP跳转是相对跳转,也就是说:它是跳转到的地址是: 当前指令地址(EIP)+相对操作数 
  // 相对操作数有符号的! 
         //当指令执行到Thunk 中指令的时候,我们需要跳转到pFun,而当前EIP指为(int)this+sizeof(Thunk) 
//原因:在顺序执行指令时,EIP在执行一条指令后会自动增,这里当然增的是sizeof(Thunk) 
//又由于没有virtual指针,所以 m_thunk的地址就是this指向地址,但是执行此指令后EIP会自动加,

//所以EIP内容为(int)this+sizeof(Thunk) 
//所以 pFun=m_thunk.m_adrr+((int)this+sizeof(Thunk)),移项可得上式 


FlushInstructionCache(GetCurrentProcess(),  
                              &m_thunk, sizeof(m_thunk)); //强制刷新指令缓冲, 
                                       //目的是使指令CACHE与主存相一致 

    

 //实验的第一函数 
  void function() 
    
        

        // 初始化thunk 
         

        // 获得thunk代码地址 
        pFUN pFun (pFUN)&(m_thunk); 

        // 调用StaticFun 
        pFun(); 

       
    
   static void Fun1() 
    
        cout << "this is Fun1" << endl; 
    

     

static void Fun2()  

cout << "this is Fun2" << endl; 



}; 

int main() 

   *pC=new C; 

   pC->Init(C::Fun1); 
   pC->function(); //1 

   pC->Init(C::Fun2); 
    
   pC->function();//2 
    
   //请注意,上面调用同一个函数,第一个执行的是C::Fun1,第二个却执行的是C::Fun2 
   //这充分说明实现了多态性! 
    return 0; 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值