我有3个班级(Cat,HouseCat:Cat,Lion:Cat)。 我想要做的就是改变HouseCat的VTable,让HouseCat吃肉而不是猫粮。
我使用的类:
query_hash
我正在尝试通过我创建的VTable结构来编辑这些类的VTable条目。
class Cat
{
public:
int age = 2;
virtual void eat() {
cout << "Meat" << this->age << endl;
};
virtual void sound() {
cout << "Meow!" << this->age << endl;
};
};
class HouseCat : public Cat
{
public:
virtual void eat() {
cout << "Cat Food" << this->age << endl;
};
};
class Lion : public Cat
{
public:
virtual void sound() {
cout << "ROAR!" << this->age << endl;
};
};
我确认VTable [0] = eat(),所以我决定尝试对Vtable进行更改:
static void __memcpy(void * set, void * data, int size){
DWORD old;
VirtualProtect(set, size, PAGE_EXECUTE_READWRITE, &old);
char*dest = (char*)set;
char*src = (char*)data;
for (int i = 0; i < size; i++)dest[i] = src[i];
VirtualProtect(set, size, old, &old);
}
struct VTable{
static VTable read(void * object){
VTable vt = *(VTable*)(object);
int i = 0;
while ((DWORD)vt.functions[i] != 0x0)
i++;
vt.size = i;
return vt;
}
void ** functions;
int size;
void redirectFunction(int i, void * redirect){
__memcpy(&functions[i], &redirect, 4);
}
};
它结束了;
int main(int argc, char* argv[])
{
Lion lion = Lion();
Cat base = Cat();
HouseCat home = HouseCat();
VTable lionVTable = VTable::read(&lion);
VTable baseVTable = VTable::read(&base);
VTable homeVTable = VTable::read(&home);
cout << "-------------- BEFORE EDIT -----------------" << endl
<< "Base:" << endl
<< (baseVTable.functions[0]) << endl
<< (baseVTable.functions[1]) << endl
<< "HomeCat:" << endl
<< (homeVTable.functions[0]) << endl
<< (homeVTable.functions[1]) << endl
<< "Lion:" << endl
<< (lionVTable.functions[0]) << endl
<< (lionVTable.functions[1]) << endl;
homeVTable.redirectFunction(0, lionVTable.functions[0]);
cout << "-------------- AFTER EDIT -----------------" << endl
<< "Base:" << endl
<< (baseVTable.functions[0]) << endl
<< (baseVTable.functions[1]) << endl
<< "HomeCat:" << endl
<< (homeVTable.functions[0]) << endl
<< (homeVTable.functions[1]) << endl
<< "Lion:" << endl
<< (lionVTable.functions[0]) << endl
<< (lionVTable.functions[1]) << endl;
pause();
cout << "---Base---" << endl << endl;
base.eat();
base.sound();
cout << "---Lion---" << endl << endl;
lion.eat();
lion.sound();
cout << "---Home---" << endl << endl;
home.eat();
home.sound();
cout << "---End---" << endl;
pause();
return 0;
}
您可以看到HomeCat [0]已从0x311285-> 0x31106E
更改-------------- BEFORE EDIT ----------------
Base:
0031106E
0031121C
HomeCat:
00311285
0031121C
Lion:
0031106E
003113F2
-------------- AFTER EDIT -----------------
Base:
0031106E
0031121C
HomeCat:
0031106E
0031121C
Lion:
0031106E
003113F2
问题是功能的输出完全没有改变。
--- ---基
Meat2
喵!2
--- ---狮子
Meat2
怒吼!2
---首页---
Cat Food2
喵!2
--- ---完
我正在使用Visual Studio 2013.发布/调试也没有任何区别。
我在代码中做错了什么,或者是我遗漏的某些编译器东西?
答案 0 :(得分:2)
我同意这是一个可怕的hacky事情...但是,为了让它正常工作,我尝试将您的lion
/ base
/ home
变量更改为指向对象。现在因为它们不是指针,编译器可能会在不使用vtable的情况下自动调用正确的函数(因为它确切地知道对象的类型)。