-2

I know this question was asked here before but it is not exactly what I need, and as much as I try to manipulate the answers from this thread I cannot get the result I'm looking for. So basically what I want to do is manipulate the virtual table in a C++ object so when calling one of the object's function it will call a different function It is only for educational purposes of course. my code is like that:

class Animal
{
private:
    int height;
    int length;
    int type;

public:
    virtual void makeNoise()
    {
    }

    virtual void sleep()
    {
    }
};

Dog inherits from Animal such as:

class Dog : public Animal
{
public:

    virtual void sleep() override
    {
        cout << "Going to sleep for Dog" << endl;
    }

    virtual void makeNoise() override
    {
        cout << "bark bark" << endl;
    }
};

Theres another class A:

class A
{
public:

    virtual void doSomething(void)
    {
        cout << "did nothing" << endl;
    }
};

The function Hack is the function I want to override A->doSomething()

void Hack()
{
   cout << "Hacked!" << endl;
}

main function:

void main()
{

   int x = 0, y = 0, z = 0;
   A* a = new A();
   Animal * dog = new Dog();

   someFunctionToManipulateVirtualTable(dog); //function get an object of type Dog but should hack into an object of type A's vtable

   a->doSomething(); //should print "Hacked!"

}

Now the question is what should I do here:

void someFunctionToManipulateVirtualTable(Animal * dog)
{ 
     //some code to manipulate main's local variable a (of type A).
}

So far, I have tried unsuccessfully , to get a's pointer through the dog reference from main, then get the virtual table pointer and override it with Hack's address, problem is , virtual table are in a read-only address location, I do manage to hack the vtable with local instances of A class, just with some pointer manipulation on the local instances..

Any lead on this will be awesome. Thanks

Community
  • 1
  • 1
Lior Naar
  • 85
  • 1
  • 9
  • 10
    Vtables are per-class, not per-instance; since the generated tables are read-only you need to build a compatible (complete) table and change each instance's vtable pointer. This is of course extremely platform-specific and undefined. (You won't ever access one object's vtable pointer through some other, unrelated, object, though.) – molbdnilo Jan 12 '16 at 20:57
  • 8
    Nice, the hardware/system is preventing that intrusive hack. –  Jan 12 '16 at 20:58
  • Thanks for the answer molbdnilo, I'm not quite sure what you mean by building a complete table and change each instance pointer? Should I read the current vtables and create new instances to overwrite the existing ones? – Lior Naar Jan 13 '16 at 07:12
  • 1
    @LiorNaar: Obviously not. Overwriting a table doesn't create a new table. – MSalters Jan 13 '16 at 10:27

1 Answers1

0

The easiest solution is to create the new vtable yourself first:

class Helper : A {
  virtual void doSomething() override { Hack(); }
}

Then create a Helper object, steal its vtable pointer, and put that vtable pointer in a.

Your solution assumes that the vtable for Dog is somehow related to the vtable of A. That's almost certainly not the case. The types are utterly unrelated.

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • There should be away to get to the vtable of a without the reference for it from a different function, I know it because the class I take is under how to create and how Compilers work so either from the heap or change it in a different way.. And what do you mean by steal it but then how can I put that pointer for a? It's in a read only area – Lior Naar Jan 13 '16 at 15:13
  • @LiorNaar: You're mixing things up. `a` is an object, and does not have a vtable. It has a **pointer to** a vtable, in normal implementations. The table is read-only, the pointer is not. Can't be, because in derived classes the vtable pointer has to change as the different constructors execute. C++ has well-defined behavior for calling a virtual function during construction, and that's NOT calling overrides from base class constructors. – MSalters Jan 13 '16 at 15:18
  • Ok now things are more clear, so you think I can just as said, steal the pointer from another A object I create in the MAGIC function and then make it point to a different vtable? Then I can just make it point to the function itself – Lior Naar Jan 13 '16 at 15:54
  • It's easiest to see if we just pretend `a->_vptr` is the pointer to the vtable. I propose you create `Helper helper` and then do `a->_vptr = helper._vptr`. Note that I nowhere use `&Hack` or put that in a vtable. I'm using the fact that `Helper::vtable` contains `&Helper::doSomething` which ends up calling `Hack` directly. Far more reliable. – MSalters Jan 13 '16 at 16:05
  • I'm sorry but your answer is not correct for this example.. im trying to "hack" the vtable by pointing the a function "Hack" that is unrealted to the classes mentioned above.. it should be independent, the way to do it, from a different function is to get the address of the function parameter that points to the same object that was created in "main" , then because we know in what order the objects were created we can find the other, "A* a" object that was created before "Dog *dog" in "main" and then change the vtable pointer there... thanks – Lior Naar Jan 15 '16 at 10:24
  • @LiorNaar: No, that's a flawed assumption. The order of creation of objects is generally unrelated to their position in memory, _especially_ when they're not the same type/size. – MSalters Jan 15 '16 at 10:41
  • In that specific case it is.. Well it doesn't matter how they were created in general but it does matter that you can get the address of Dog*dog that was created in main function to get to A*a and that is what is was looking for, now the question is how to write Hack method to that address is still ongoing.. The example I wrote was very specific so I'm looking for a very specific answer... – Lior Naar Jan 15 '16 at 23:10
  • @LiorNaar: The chief problem is that objects of different sizes are often allocated from unique pools, each of which is individually allocated by the OS. No way to find a random object o\in one pool given another random object in another pool. (Clustering same-sized objects is a perfect strategy to avoid memory fragmentation) – MSalters Jan 16 '16 at 17:43