【逆向知識】動態調試技巧-C++代碼逆向


1、C++類代碼的特點

寄存器ECX傳參時一般用作this指針(對象地址)或是計數器。

有ecx傳參的call,是成員函數,構造函數,析構函數

能訪問成員變量的函數都會有ecx傳參

靜態函數、全局函數無ecx(this指針)

返回值

寄存器eax一般用作返回值

識別構造函數的OD反匯編代碼

特點:

(1) 代碼特點:沒有返回值、用於初始化

(2)反匯編特點:有返回值,而且是this指針

根據反匯編可以看出成員變量的順序,因為在內存數據中的排布順序是由代碼中成員變量定義順序決定的。

識別構造函數的辦法:

(1)構造函數調用時,會使用ECX用於this指針

(2)構造函數在反匯編層有返回值,是eax存放this指針

(3)構造函數用於初始化,一般內存如果是未初始化的比如CCCCCCC,經過構造函數會完成初始化。

(4)如果一個函數有對前4字節初始化為一個指針地址,那么可能是在初始化虛函數表指針。

如果一個類有虛函數,那么對象的內存數據里會有虛函數指針的定義。構造函數會初始化虛函數表指針,而類中定義多少個虛函數也只有一個虛函數表指針。

識別成員函數的OD反匯編代碼

特點:

(1)ECX傳遞this指針,調用成員函數

(2)成員函數中會訪問exc所指向的內存空間

成員函數與虛函數本身沒有什么區別,所以反匯編出來的代碼都差不多。

識別成員函數:

(1)如果找到了構造函數,那么下面調用的應該都是成員函數

(2)成員函數有this指針

(3)成員函數會訪問成員變量,即this指針指向的內存空間

識別析構函數的OD反匯編代碼

特點與識別:

(1)有ECX

(2)用於釋放資源,可能有delete,free等

(3)一般是在函數返回時,編譯器生成的調用。

全局構造與析構函數

初始化全局對象的構造函數,是在main函數之前,C運行庫初始化的代碼中_initterm函數

操作:

在return下斷點,main函數執行完畢后F11繼續執行,繼續F11return會返回到上一個調用函數。

exit(xxx) 調用析構函數

有虛函數的派生類

派生類對象的構造初始化

大致流程:

派生類的構造函數
{
      基類的構造函數(函數中會初始化虛函數表指針)

      初始化虛函數表指針

      初始化數據
}

虛函數表創建

虛函數表是在程序編譯時就生成了,而且存儲在程序的只讀區段中

程序中如果創建了多個對象,只會有一個虛函數表,共用一個虛函數表。

C++中的多態實現

	//多態的實現
	A* pObj = &obj;
	pObj->printfD();

模擬反匯編的調用流程

A* pObj = &obj;

測試代碼

#include "stdafx.h"

class A
{
public:
	A::A() {
		c = 3;
		m = 1;
		n = 2;


	};

	virtual void printA() { printf(" A::A\n "); };
	virtual void printB() { printf(" A::B\n "); };
	virtual void printC() { printf(" A::C\n "); };

	void printfD() { 
		
		printf("(%d,%d)\n",m,n);
		printf("hahahahaah");
	
	};

	A::~A() {
	
		printf(" A::~A\n ");
	
	};
protected:
private:
	int n;
	int c;
	int m;
};
int main()
{
	A obj;
	obj.printA();
	obj.printfD();
	printf(" %d\n ",sizeof(obj));
	printf(" 3333333333333333333333333\n ");
    return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM