<b>操纵Thunk让C++成员函数变回调函数</b>[VC/C++编程]
本文“<b>操纵Thunk让C++成员函数变回调函数</b>[VC/C++编程]”是由七道奇为您精心收集,来源于网络转载,文章版权归文章作者所有,本站不对其观点以及内容做任何评价,请读者自行判断,以下是其具体内容:
Windows API常常需求回调函数,而在C++开辟中面向对象当行其道,若能让C++类的成员函数成为回调函数,简直就是大善!但是C++成员函数都隐含了一个this指针用于指向当前的对象.要实现回调确切不简单.
我大约一年前就接触到Thunk技术,乃至也看过操纵Thunk实现将成员函数变成回调函数的例子.但是我实在没理解过C++汇编后的模样,很简单钻了牛角尖,看都看不懂,直接用他们的程序又不敢,毕竟出错后不好处理.前端时间无意想起Thunk技术,对未懂技术老这样悬着极大概影响自己的程序员生涯的,于是决计闭关参悟(没办法,天分差啊),终于弄懂得了.那种感受啊,就像诚信礼佛的人忽然见到如来一样,大概换了切近自己的比方:就像千年色鬼见到美女一样的高兴. 我不由得的模拟小说中的修真人士突悟大道后的感慨:本来如此!
下面的分享一下我的收获,基本上是出入门径的写给初学者的,大侠千万要止步,小弟皮薄!
略微研究了一下C++汇编后的代码,普通调用C++的成员函数之前,都是利用ECX存放器保存对象的指针,好在C++成员函数的调用约定__thiscall的参数压栈次序和仓库均衡的保护都是和回调函数的调用约定__stdcall一样,所以只需求构造汇编将对象指针保存在ECX存放器后JMP到成员函数的履行地址便可以了.先写个C++构造凑合这两条汇编码:
#pragma pack( push, 1 )
struct MemFunToStdCallThunk
{
BYTE m_mov;
DWORD m_this;
BYTE m_jmp;
DWORD m_relproc;
BOOL Init( DWORD_PTR proc, void* pThis )
{
m_mov = 0xB9;
m_this = PtrToUlong(pThis);
m_jmp = 0xe9;
m_relproc = DWORD((INT_PTR)proc - ((INT_PTR)this+sizeof(MemFunToStdCallThunk)));
::FlushInstructionCache( ::GetCurrentProcess(), this, sizeof(MemFunToStdCallThunk) );
return TRUE;
}
void* GetCodeAddress()
{
return this;
}
};
#pragma pack( pop )
这个构造相当于两条汇编语句:
mov ecx, pThis
jmp [偏移地址]
利用:
class CTestClass
{
private:
int m_nBase;
MemFunToStdCallThunk m_thunk;
void memFun( int m, int n )
{
int nSun = m_nBase + m + n;
CString str;
str.Format( _T("%d"), nSun );
AtlMessageBox( NULL, _U_STRINGorID( str ) );
}
public:
CTestClass()
{
m_nBase = 10;
}
void Test()
{
//UnionCastType:操纵结合将函数指针转换成DWORD_PTR
m_thunk.Init( UnionCastType<DWORD_PTR>(&CTestClass::memFun), this );
StdCallFun fun = (StdCallFun)m_thunk.GetCodeAddress();
ATLASSERT( fun != NULL );
fun( 1, 3 );
}
};
以上是“<b>操纵Thunk让C++成员函数变回调函数</b>[VC/C++编程]”的内容,如果你对以上该文章内容感兴趣,你可以看看七道奇为您推荐以下文章:
本文地址: | 与您的QQ/BBS好友分享! |