1. 程式人生 > 實用技巧 >c++逆向分析----返回物件

c++逆向分析----返回物件

物件使用預設解構函式

class Test
{
public:
	char	cNum1;
	int	iNum2;
	int*	pInt;
};


Test _ReturnObject()
{
	Test stLocalObject;
	stLocalObject.cNum1 = 0;
	stLocalObject.iNum2 = 1;
	
	stLocalObject.pInt  = new int;
	*stLocalObject.pInt = 0x55;
	return stLocalObject;
}


int main(int argc, char* argv[])
{
	Test stObject;
	stObject = _ReturnObject();

	return 0;
}

分析以上程式碼的反彙編程式碼,發現在沒有給出解構函式使用預設解構函式時編譯器並沒有呼叫解構函式(因為預設解構函式什麼都沒做調不呼叫都一樣)。其會將_ReturnObject()函式內的區域性物件先儲存到main函式的棧空間中,返回值eax為其首地址,接著會將儲存在此處的物件複製到另一處棧空間中,接著利用此棧空間對接收返回物件的實際物件賦值。

我們產生疑問!既然eax地址處和從eax複製的另一處棧地址處都儲存著返回物件的資料,是否兩處地址都可以認為是實際的物件。如果其實實際的物件那麼其一定會再生命週期快結束時呼叫解構函式,因為這裡編譯器將預設的解構函式呼叫去除了所以我們無法判斷,我們下面需要自己指定解構函式來分析。

物件不使用預設的解構函式

我們在上述程式碼的基礎上加上自己的解構函式,此解構函式會將物件動態申請的記憶體釋放掉。

~Test()
{
	if(pInt != NULL)
	      delete pInt;
}

我們檢視其對應的彙編程式碼,發現其在物件返回的過程中將物件儲存到eax地址後,直接將eax地址對應的物件儲存到stObject中。當然這兩處的物件也會分別呼叫解構函式。

值得注意的是我們這裡的程式碼是會報錯的,因為返回物件在_ReturnObject函式結束時就會呼叫解構函式將int* pInt對應的記憶體給撤銷了,當eax地址對應的物件在呼叫解構函式是就會報錯。