11关于虚函数_使用IDA通过虚函数识别构造、析构、虚函数

根据虚函数与构造、析构函数的关系,使用IDA识别C++中的构造、析构、虚函数

#include "stdafx.h"

class CVirtual
{
public:
	~CVirtual()
	{
		printf("~CVirtual");
	}
	CVirtual()
	{
	}
	CVirtual(int nNumber)
	{
		m_nNumber = nNumber;
	}
	virtual int GetNumber()
	{
		return m_nNumber;
	}
	virtual void SetNumber(int nNumber)
	{
		m_nNumber = nNumber;
	}
private:
	int m_nNumber;
};


int main(int argc, char* argv[])
{
	// 获取含有虚函数表的类大小
//	int nSize = sizeof(CVirtual);
	CVirtual MyVirtual;
	CVirtual MyVirtual1(1);
// 	MyVirtual.SetNumber(argc);
// 	printf("%d\r\n", MyVirtual.GetNumber());
	return 0;
}

直接使用IDA对生成的exe进行分析,先找到main:

 

.text:00411440 ; __unwind { // _main_0_SEH
.text:00411440                 push    ebp
.text:00411441                 mov     ebp, esp
.text:00411443                 push    0FFFFFFFFh
.text:00411445                 push    offset _main_0_SEH
.text:0041144A                 mov     eax, large fs:0
.text:00411450                 push    eax
.text:00411451                 sub     esp, 0ECh
.text:00411457                 push    ebx
.text:00411458                 push    esi
.text:00411459                 push    edi
.text:0041145A                 lea     edi, [ebp+var_F8]
.text:00411460                 mov     ecx, 3Bh
.text:00411465                 mov     eax, 0CCCCCCCCh
.text:0041146A                 rep stosd
.text:0041146C                 mov     eax, dword_41801C
.text:00411471                 xor     eax, ebp
.text:00411473                 push    eax
.text:00411474                 lea     eax, [ebp+var_C]
.text:00411477                 mov     large fs:0, eax
.text:0041147D                 lea     ecx, [ebp+var_18]
.text:00411480                 call    sub_4111EF      //无参构造
.text:00411485 ;   try {
.text:00411485                 mov     [ebp+var_4], 0
.text:0041148C                 push    1
.text:0041148E                 lea     ecx, [ebp+var_28]
.text:00411491                 call    sub_411087      //带1个参数构造
.text:00411496                 mov     [ebp+var_F4], 0
.text:004114A0                 lea     ecx, [ebp+var_28]
.text:004114A3                 call    sub_4111AE      //析构
.text:004114A3 ;   } // starts at 411485
.text:004114A8                 mov     [ebp+var_4], 0FFFFFFFFh
.text:004114AF                 lea     ecx, [ebp+var_18]
.text:004114B2                 call    sub_4111AE      //析构
.text:004114B7                 mov     eax, [ebp+var_F4]
.text:004114BD                 push    edx
.text:004114BE                 mov     ecx, ebp
.text:004114C0                 push    eax
.text:004114C1                 lea     edx, dword_4114F0
.text:004114C7                 call    j_@_RTC_CheckStackVars@8 ; _RTC_CheckStackVars(x,x)
.text:004114CC                 pop     eax
call    sub_4111AE调用2次很有可能是生成2个对象,析构的时候调用同1个析构函数,
call    sub_4111EF和call    sub_411087 
传入的参数是ecx,但是传入的this指针不一样,很有可能生成了2个对象,所以传入的指针不一样。
并且由于构造函数可以重载,有参和无参构造。

先进入构造函数里面查看:
.text:004115D0 var_CC          = byte ptr -0CCh
.text:004115D0 var_8           = dword ptr -8
.text:004115D0
.text:004115D0                 push    ebp
.text:004115D1                 mov     ebp, esp
.text:004115D3                 sub     esp, 0CCh
.text:004115D9                 push    ebx
.text:004115DA                 push    esi
.text:004115DB                 push    edi
.text:004115DC                 push    ecx
.text:004115DD                 lea     edi, [ebp+var_CC]
.text:004115E3                 mov     ecx, 33h
.text:004115E8                 mov     eax, 0CCCCCCCCh
.text:004115ED                 rep stosd
.text:004115EF                 pop     ecx
.text:004115F0                 mov     [ebp+var_8], ecx
.text:004115F3                 mov     eax, [ebp+var_8]
.text:004115F6                 mov     dword ptr [eax], offset ??_7CVirtual@@6B@ ; const CVirtual::`vftable'
.text:004115FC                 mov     eax, [ebp+var_8]
.text:004115FF                 pop     edi
.text:00411600                 pop     esi
.text:00411601                 pop     ebx
.text:00411602                 mov     esp, ebp
.text:00411604                 pop     ebp
.text:00411605                 retn
.text:00411605 sub_4115D0      endp

  在IDA中 ??_7CVirtual@@6B@ 右键“xref  to”和"“xref  from"

 “xref  to”指的是读取这个数据的位置

  

  通过这种方法,可以找到所有的构造和析构函数,因为在构造和析构函数里面会对虚表进行重写(初始化和还原)

    “xref  from”指的是该地址来自哪里

通过这种方法,可以找到所有的虚函数。

 

posted @ 2023-09-08 17:25  一日学一日功  阅读(814)  评论(0)    收藏  举报