我正在尝试获取隐藏在结构后面的函数地址。不幸的是,void*
基本的 C++ 转换不起作用,所以我C++ template
改用了。
1. 基本的 C++ 转换不适用于结构内的函数,为什么?void*
void * lpfunction;
lpfunction = scanf; //OK
lpfunction = MessageBoxA; //OK
我做了一个简单的结构:
struct FOO{
void PRINT(void){printf("bla bla bla");}
void SETA(int){} //nothing you can see
void SETB(int){} //nothing you can see
int GETA(void){} //nothing you can see
int GETB(void){} //nothing you can see
};
///////////////////////////////////////////
void *lpFunction = FOO::PRINT;
和编译错误:
error C2440: 'initializing' :
cannot convert from 'void (__thiscall FOO::*)(void)' to 'void *'
2. 获取函数成员地址是不可能的吗?
然后,我制作了一个模板函数,它能够将函数成员转换为地址。然后我会通过汇编来调用它。它应该是这样的:
template <class F,void (F::*Function)()>
void * GetFunctionAddress() {
union ADDRESS
{
void (F::*func)();
void * lpdata;
}address_data;
address_data.func = Function;
return address_data.lpdata; //Address found!!!
}
这是代码:
int main()
{
void * address = GetFunctionAddress<FOO,&FOO::PRINT>();
FOO number;
number.PRINT(); //Template call
void * lpdata = &number;
__asm mov ecx, lpdata //Attach "number" structure address
__asm call address //Call FOO::PRINT with assembly using __thiscall
printf("Done.\n");
system("pause");
return 0;
}
但是,我看到它非常具体。它看起来像LOCK - KEY,我必须为每组参数类型制作一个新模板。
原件(好的):
void PRINT(); //void FOO::PRINT();
稍微修改一下:
void PRINT(int); //void FOO::PRINT(int);
编译器立即使用旧模板代码显示:
//void (F::*func)();
//address_data.func = Function;
error C2440: '=' : cannot convert from
'void (__thiscall FOO::*)(int)' to 'void (__thiscall FOO::*)(void)'
为什么?它们只是地址。
69: address_data.func = Function;
00420328 mov dword ptr [ebp-4],offset @ILT+2940(FOO::PRINT) (00401b81)
...
EDIT3:我知道更好的解决方案:
void(NUMBER::*address_PRINT)(void) = FOO::PRINT;
int(NUMBER::*address_GETA)(void) = FOO::GETA;
int(NUMBER::*address_GETB)(void) = FOO::GETB;
void(NUMBER::*address_SETA)(int) = FOO::SETA;
void(NUMBER::*address_SETA)(int) = FOO::SETB;
它比模板好得多。顺便说一句,我想实现目标:
<special_definition> lpfunction;
lpfunction = FOO::PRINT; //OK
lpfunction = FOO::GETA; //OK
lpfunction = FOO::GETB; //OK
lpfunction = FOO::SETA; //OK
lpfunction = FOO::SETB; //OK
这可能吗?