#include <stdio.h>
struct Class {
virtual void AFunction( void ) { printf("1"); }
};
struct AClass : public Class {
virtual void AFunction( void ) { printf("2"); }
};
typedef void (AClass::*FxPtr)(void);
int main( void ) {
union {
FxPtr pf;
int rf[2];
};
pf = &AClass::AFunction;
printf( "sizeof(pf)=%i\n", sizeof(pf) );
printf( "%08X\n", pf );
printf( "%08X %08X\n", rf[0], rf[1] );
/*
error: ISO C++ forbids taking the address of a bound member function
to form a pointer to member function. Say '&AClass::AFunction'
AClass a;
FxPtr qf = &a.AFunction;
printf( "sizeof(qf)=%i\n", sizeof(qf) );
*/
};
它很容易访问 vtable,但通过地址来识别函数并不那么简单。
一些选项:
1) 解析 .map 文件,加载并通过 typeid(或通过 map 中的 VMT 实例)查找类名,然后通过其名称查找函数地址。
2) 为给定对象编写一个调用给定虚方法的静态函数,查看它在 asm 中的样子,并从其代码中检索函数在 vtable 中的偏移量,然后读取地址
?adr_CFunction@Class@@SIXPAU1@@Z PROC ; Class::adr_CFunction, COMDAT
; _This$ = ecx
; 8 : static void adr_CFunction( Class* This ) { This->CFunction(); }
mov eax, DWORD PTR [ecx]
mov edx, DWORD PTR [eax+8]
jmp edx
?adr_CFunction@Class@@SIXPAU1@@Z ENDP ; Class::adr_CFunction
3) 有一些不错的选项,例如“/Gh enable _penter function call”,它允许在调用之后检索所有函数的地址,但在函数实际执行任何操作之前。然后 .map 可用于通过跟踪识别功能。