我有一个特定的问题,我正在尝试解决,我需要找到类的方法的位置(在内存中)。我想我已达到语法约束,因为指向方法的指针被处理为member pointer
示例:
class Foo {
public:
int targetFunction(int value) { return value + 5; }
};
DWORD findLocation() { // ignore the fact that DWORD might not equal pointer size.
int (Foo::*address)(int) = &(Foo::targetFunction); // member function pointer
void* typeHide = (void*)&address; // Remove type
DWORD targetAddress = *(DWORD*)typeHide; // Convert type from void* to DWORD* and dereference to DWORD
return targetAddress;
}
int (Foo::*address)(int) =
也可以写成 auto address =
现在,在VS2008中,它说Foo::targetFunction
的地址是“0x000F B890”但&Foo::targetFunction
是“0x000F 1762 ”
首先,成员指针使用成员指针运算符.*
和->*
正常工作。如果我将targetAddress强制转换回成员指针,它仍然有效!
其次,位置可以是一个thunk函数!
最后,如果我使用VS2008的调试器将targetFunction的值从member pointer
的地址1762更改为VS调试器报告的值B890,我的代码可以正常工作!
是否有特定于C ++的方法来获取地址值(B890)而不是成员指针值(1762)?
根据要求,这是我正在努力工作的代码:
BYTE overwriteStorage[300][2];
void NOP(void)
{
// hackish, but works for now.
}
void disableOlderVersions(DWORD _address, int index)
{
//...
_address = findLocation();
DWORD protectionStorage = 0;
VirtualProtect((void *)_address, 1+4, PAGE_WRITECOPY, &protectionStorage); // windows.h: Make Read/Write the location in code
{
BYTE *edit = (BYTE*)_address;
overwriteStorage[index][0] = *(edit+0); // store previous value to revert if needed
*(edit+0) = 0XE9; // JUMP (32-bit)
overwriteStorage[index][1] = *(edit+1); // store second value
signed int correctOffset = (signed int)NOP - (signed int)_address - 5; // calculate 0xE9 relative jump
*(signed int*)(edit+1) = correctOffset; // set jump target
}
VirtualProtect((void *)_address, 1+4, PAGE_EXECUTE, &protectionStorage);
}
如果我将findLocation
的第一行从member pointer
替换为实际的function pointer
,则效果非常好。但是,我需要读取和写入几个类方法,这个方法被奇数member pointer
打破。
另外,我有一些本地功能也没有报告正确的地址(最近)。是否有其他方法可以在不受编译器行为约束的情况下查找函数地址?
答案 0 :(得分:2)
听起来您正在尝试将成员函数调用压缩为单个函数指针。这是不可能的。
记住:
Object x;
x.a(1);
实际上是
的缩写a(&x /*this*/, 1 /*arg1, ... */); //approximation, leprechauns may be involved in actual implementations.
第一个论点至关重要,它将成为“这个”。
所以你不能做这样的事情:
class Object {
public:
void f(int);
}
typedef void (*FNPTR)(int);
Object a;
void (Object::* memberFuncPtr)(int);
void* nerfedPtr = (void*)memberFuncPtrl
FNPTR funcPtr = static_cast<FNPTR>(nerfedPtr);
funcPtr(1);
因为你已经抢夺了它的对象上下文的成员函数。
如果没有函数的地址和实例的地址,就无法调用对象成员函数。