Wednesday, April 30, 2008

VIRTUAL REALITY

Virtual functions are a key feature of C++. Via dynamic binding( Late Binding ), they provide a powerful mechanism to change the semantics of a function at run time. To support the virtual function mechanism, different schema's have been adopted. I shall discuss the method used by Microsoft Visual C++ compiler (Model proposed by Martin O' Riordan).
Whenever a class declares a virtual function or is derived directly or indirectly from a class which declares a virtual function, the complier adds an extra hidden member variable which points to the virtual table. A virtual table is nothing but an array of pointers to the virtual functions. The entries in the virtual table are changed at run time to point to the correct function.Consider the following class :
    class Base
    {
    public :
    Base() { }
    ~Base() { }
    virtual void VirtualFunc() { cout << "Base::VirtualFunc()" << endl ; }

    };

    Base defines a trivial virtual function VirtualFunc(). Let us derive a new class 'Derived' from 'Base'.

      class Derived : public Base
      {
      public :
      Derived() { }
      ~CDerived() { }
      void VirtualFunc() { cout << "Derived::VirtualFunc()" << endl ; }

      };

As you can see, Derived has overriden VirtualFunc(). When we create an instance of Derived, typical object layout is shown below :

0064FDE0 84 30 41 00 E8 FD 64 „0A.èýd
0064FDE7 00 54 30 41 00 28 FE .T0A.(þ
0064FDEE 64 00 CF 10 40 00 01 d.Ï.@..
0064FDF5 00 00 00 38 FE 64 00 ...8þd.
0064FDFC D9 27 40 00 01 00 00 Ù'@....
0064FE03 00 48 02 76 00 98 02 .H.v.˜.
0064FE0A 76 00 68 F1 59 81 48 v.hñY.H

The first four bytes are pointer to the virtual table. The virtual table itself contains pointers to the virtual functions of the object. In our case, it is a pointer to VirtualFunc().

Memory layout of the virtual table is :

00413084 32 10 40 00 FF FF FF 2.@.ÿÿÿ
0041308B FF DE 2D 40 00 EB 2D ÿÞ-@.ë-
00413092 40 00 00 00 00 00 FF @.....ÿ
00413099 FF FF FF 00 00 00 00 ÿÿÿ....

The first four bytes are pointer to VirtualFunc().

With this information, we can tweak an object and make it do weird things !! (just for fun)
Let us change the virtual table pointer and point it to our own table !!!.

    ////////////////////////////////////////// Modify.cpp ///////////////////////////////////////////////////
    #include "iostream.h"
    #include "memory.h"

    //Pointer to a function returning void
    typedef void (*PFN)();

    typedef struct
    {
    PFN Fn;
    } VTable;

    //The function which will replace VirtualFunc
    void ModifyFunc() { cout << " Modified the vitual table !!!" << endl ; }

    int main()
    {
    Derived DerivedObj;

    Base *pBase = &DerivedObj;

    //Create our own virtual table
    VTable MyOwnTable;

    //Point Fn to ModifyFunc
    MyOwnTable.Fn = ModifyFunc;

    //Holder for pointer to virtual table
    VTable *pVTable = &MyOwnTable;

    //Modify the virtual table pointer by changing the first 4 bytes (assuming a long holds a pointer)
    memcpy(&DerivedObj, &pVTable , sizeof(long));

    //Call the virtual function
    pBase->VirtualFunc();

    //Strange !! ModifyFunc() is called ... enjoy playing :)
    return 0;
    }

A similar though slightly complex technique is used for multiple inheritance and virtual inheritance. Might as well write about them sometime....

No comments: