For a long time did not write the article, I have been doing a C + + development, I have always believed that, as a C + + programmer, if you can learn the assembly and reverse analysis, then it is very helpful for us to understand C/s, because all the mysteries of the program are hidden in the assembly, Many problems we can not see from the surface of the end is why, as long as the use of reverse tool analysis, will soon be able to know why. We all know that the virtual function table is placed in the front of the class object, but many people do not know what the first item of the virtual function table is stored, and below I use IDA to analyze the virtual function Call of C + +, from the assembly point of view to understand the virtual function. This article is only suitable for readers with the basis of reverse analysis, if there is no reverse analysis basis, please bypass directly. The following C + + code is available:
classtest{ Public: Test () {printf ("test::test\n"); } Virtual~Test () {printf ("Virtual ~test () \ n"); } Virtual voidProinter () =0; Virtual voidPointF () =0;};classTestA: Publictest{ Public: TestA () {printf ("testa::testa\n"); } Virtual~TestA () {printf ("testa::testa\n"); } Virtual voidProinter () {printf ("Derive Class testa::pointer\n"); } Virtual voidpointf () {printf ("Derive Class TestA::P ointf\n"); }};int_tmain (intARGC, _tchar*argv[]) {TestA*ptest=NewTestA; PTest-pointf (); PTest-Prointer (); DeletepTest; return 0;}
Open the exe file with Ida and display it in flowchart mode:
Run to the place where new is called:
One layer after another, we will find that the inside of new is actually called malloc for memory allocation, and Msvcr100d_malloc is the malloc function:
Go down and find the following command:
text:00c3149f call j_??2@[email Protected]_0;operator New(UINT). TEXT:00C314A4 Add ESP,4. TEXT:00C314A7 mov [EBP+ This], EAX.TEXT:00C314AD mov [EBP+var_4],0. TEXT:00C314B4 CMP [EBP+ This],0. TEXT:00C314BB JZ ShortLOC_C314D0.TEXT:00C314BD mov ecx, [EBP+ This] ; This. TEXT:00C314C3 Call J_[email protected]@[email protected]; Testa::testa (void). TEXT:00C314C8 mov [EBP+VAR_10C], eax; The return value of new is assigned to [epb+var_10c].text:00c314ce jmp ShortLoc_c314da; eax= This. text:00c314d0;---------------------------------------------------------------------------. text:00c314d0.text:00c314d0 loc_c314d0:; CODE XREF: _wmain+5bj.text:00c314d0 mov [EBP+VAR_10C],0. Text:00c314da.text:00c314da Loc_c314da:; CODE XREF: _wmain+6EJ.TEXT:00C314DA mov eax, [EBP+VAR_10C]; eax= This. TEXT:00C314E0 mov [EBP+VAR_104], eax; [ebp+var_104]= This. TEXT:00C314E6 mov [EBP+var_4], 0ffffffffh.text:00c314ed mov ecx, [EBP+VAR_104]; ecx= This. TEXT:00C314F3 mov [EBP+ptest], ecx; [ebp+ptest]= This. TEXT:00C314F6 mov eax, [EBP+ptest]; eax= This. TEXT:00C314F9 mov edx, [EAX].TEXT:00C314FB mov esi, ESP.TEXT:00C314FD mov ecx, [EBP+ptest].text:00c31500 mov eax, [edx+8] ; eax= This+8. text:00c31503 call eax;The code at +8
Follow in and find the following command:
text:00c31820 push ebp.text:00c31821 mov ebp, esp.text:00c31823 Sub ESP, 0cch.text:00c31829 push Ebx.tex t:00c3182a push esi.text:00c3182b push edi.text:00c3182c push ecx.text:00c3182d Lea EDI, [EBP+var_cc].text:00c31833 mov ecx, 33h.text:00c31838 mov eax, 0cccccccch.text:00c3183d rep stosd.text:00c3183f pop ecx.text:00c31840 mov [EBP+ This], ecx.text:00c31843 mov esi, esp.text:00c31845 push offset aderiveclasst_0; "Derive Class TestA::P ointf\n". text:00c3184a call ds:__imp__printf.text:00c31850 add ESP,4. text:00c31853 cmp esi, esp.text:00c31855 call j___rtc_checkesp.text:00c3185a pop edi.text:00c3185b pop esi.text:00c3185c Pop ebx.text:00c3185d add ESP, 0cch.text:00c31863 CMP EBP, esp.text:00c31865 call J___rt C_CHECKESP.TEXT:00C3186A mov esp, ebp.text:00c3186c pop ebp.text:00c3186d retn.text:00c3186d[Email protected]@ @UAEXXZ ENDP
This is ptest->pointf (); Call the assembly code and continue down:
Called the [edx+4] is actually the this+4 place code, followed, the code is as follows:
. text:00c517b0 push EBP.TEXT:00C517B1 mov ebp, esp.text:00c517b3 Sub ESP, 0CCH.TEXT:00C517B9 push Ebx.te XT:00C517BA push ESI.TEXT:00C517BB push EDI.TEXT:00C517BC push ECX.TEXT:00C517BD Lea EDI, [EBP+VAR_CC].TEXT:00C517C3 mov ecx, 33H.TEXT:00C517C8 mov eax, 0CCCCCCCCH.TEXT:00C517CD rep STOSD.TEXT:00C517CF pop ECX.TEXT:00C517D0 mov [EBP+ This], ecx.text:00c517d3 mov esi, esp.text:00c517d5 push offset aderiveclasstes; "Derive Class testa::pointer\n". Text:00c517da call DS:__IMP__PRINTF.TEXT:00C517E0 add ESP,4. Text:00c517e3 cmp esi, esp.text:00c517e5 call j___rtc_checkesp.text:00c517ea pop edi.text:00c517eb pop ESI.TEXT:00C517EC Pop ebx.text:00c517ed add ESP, 0CCH.TEXT:00C517F3 CMP EBP, Esp.text:00c517f5 call J___rt C_CHECKESP.TEXT:00C517FA mov esp, ebp.text:00c517fc pop ebp.text:00c517fd retn.text:00c517fd[Email protected]@ @UAEXXZ ENDP
The above is actually called ptest->prointer (), the assembly code, continue to execute:
Here is the command called this, followed by the following command:
text:011d1890 push ebp.text:011d1891 mov ebp, esp.text:011d1893 Sub ESP, 0cch.text:011d1899 push Ebx.tex t:011d189a push esi.text:011d189b push edi.text:011d189c push ecx.text:011d189d Lea EDI, [EBP+VAR_CC].TEXT:011D18A3 mov ecx, 33h.text:011d18a8 mov eax, 0CCCCCCCCH.TEXT:011D18AD rep STOSD.TEXT:011D18AF pop ECX.TEXT:011D18B0 mov [EBP+ This], ECX.TEXT:011D18B3 mov ecx, [EBP+ This] ; This. Text:011d18b6 Call J_[email protected]@[email protected]; Testa::~testa (void). TEXT:011D18BB mov eax, [EBP+arg_0].text:011d18be and EAX,1. TEXT:011D18C1 JZ ShortLOC_11D18CF.TEXT:011D18C3 mov eax, [EBP+ This].text:011d18c6 push eax; void*. Text:011d18c7 Call J_??3@[email Protected]_0;operator Delete(void*). text:011d18cc Add ESP,4
Here is where the destructor calls, in summary, we can conclude that new is finally called malloc for memory allocation, in the virtual function table, the virtual destructor is placed in the front. Of course, this is just the simplest kind of inheritance system, and some places are not written in detail, we can do their own code with IDA to reverse analysis, explore the mystery, the above is just some of my understanding, if there are unreasonable places to welcome everyone to correct, hope to work together with you to learn, and common progress.
Understanding C + + virtual function tables from a reverse perspective