Let’s first understand the underlying implementation of polymorphism through a piece of code

class cVirtual 
{
public:  
    virtual void func0(a) {};  
    virtual void func1(a) {};
};
int main(a){  
    cVirtual cv;  
    cv.func0();
}
Copy the code

Very simple class, if there is no polymorphic function in the class object is actually 1 byte (placeholder byte), with the polymorphic function in the class object will hold the address table of the polymorphic function, so this object will be 4 bytes.

Look at disassembly.

cVirtual cv; 005719B3 lea ecx,[ebp-0Ch]; Memory Used by allocated objects 005719B6 Call 005713C5; Calling the constructorCopy the code

The CALL directive calls the constructor generated by the compiler for this class. Such a simple class must have constructors. It is used to initialize the polymorphic table. Go inside and see.

. 0057179F pop ecx ; Restore this pointer 005717A0 mov dword PTR [EBP-8],ecx; Save this pointer 005717A3 mov eAX,dword PTR [EBP-8]; Select this pointer 005717A6 mov dword PTR [eax],577BF8h; 005717AC mov EAX, Dword PTR [EBP-8]; Return the this pointer......Copy the code

I’ve cut out the extra code, and the only thing the constructor does is assign a pointer to the polymorphic table to the address of the object, which is the this pointer in this article.

As you can see from the code above, the memory of such objects should look like this:

Let’s take a look at what is saved in 0x577BF8:

Rearrange it like this, 0x005713C0, 0x005713BB, 0x0000000.

So these two valid addresses are two polymorphic functions in our code, so let’s verify that.

So, we can conclude that in the first 4 bytes of the object’s base address, the virtual table pointer points to an address table, and each address in the address table corresponds to each virtual function in the class.

In the above example, the destructor does exactly the same thing as the constructor, because the constructor already assigns values to the virtual table. Isn’t it a bit redundant in the destructor? No, reassignment in the destructor prevents reading a virtual table that is not its own virtual table. Readers can think of this problem from the perspective of inheritance.

I don’t know. Read my article on inheritance. Maybe not.

Here’s the kicker:

  • Virtual table information is linked to the binary file after compilation, so virtual table is a fixed address.
  • The sort order of the addresses of the virtual functions in the virtual table depends on the order in which the virtual functions are declared in the class.
  • When a virtual function is accessed, the address of the virtual table is retrieved according to the initial address of the object. After retrieving the virtual table element, multiple addresses are needed to complete the retrieval.
  • Access to a virtual table via indirection occurs only when a virtual function is called using a pointer or reference to an object. When a virtual function is called using an object, no look-up table access is required. (Call its own function, not polymorphic, check the virtual table will only reduce efficiency)

— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — – > find it

Finding polymorphism in assembly code requires the following considerations:

  • Class implicitly defines a data member
  • The data member is at the first address and is 4 bytes long
  • The constructor initializes this data member to the first address of an array
  • This address belongs to the data area and is a fixed address
  • Each element in this array is a function pointer
  • When these functions are called, the first argument must be the this pointer, notice the calling convention
  • Inside these functions, it is possible to use relatively indirect access to the this pointer

Virtual table initialization signature (present in construction or destructor) :

; Lea ecx,[ebP-8]; Lea ecx,[ebP-8]; Get the first address of the object call XXXXXXXXH; Mov reg,this; Mov dword PTR [eAX], XXXXXXXXH; Write 4 bytes of data to the first address of the object and check if the 4 bytes are the first address of the function address tableCopy the code

If the above code occurs, you should highly suspect that this function is a constructor or destructor.

The original link

Good job.