i have 3 classes (cat, housecat:cat, lion:cat). i'm trying change housecat's vtable make housecat eat meat instead of cat food.
classes use:
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; }; }; i'm trying edit classes' vtable entries vtable struct created.
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; (int = 0; < size; i++)dest[i] = src[i]; virtualprotect(set, size, old, &old); } struct vtable{ static vtable read(void * object){ vtable vt = *(vtable*)(object); int = 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); } }; i confirmed vtable[0] = eat(), decided try making change on vtable :
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; } it outputed;
-------------- before edit ---------------- base: 0031106e 0031121c homecat: 00311285 0031121c lion: 0031106e 003113f2 -------------- after edit ----------------- base: 0031106e 0031121c homecat: 0031106e 0031121c lion: 0031106e 003113f2 you can see homecat[0] changed 0x311285->0x31106e
vmt.exe+11285 - e9 b6350000 - jmp virtualmethodtable test.housecat::eat [cat food] -> vmt.exe+1106e - e9 ed450000 - jmp virtualmethodtable test.cat::eat [meat] the problem output of functions didnt change @ all.
---base---
meat2
meow!2
---lion---
meat2
roar!2
---home---
cat food2
meow!2
---end---
i'm using visual studio 2013. release/debug didnt make difference either.
did wrong in code or somekind of compiler stuff i'm missing?
i agree horrible hacky thing do... however, working i'd try changing lion/base/home variables pointers objects. right since not pointers, compiler may automatically calling correct function without using vtable (since knows type object is).
Comments
Post a Comment