PE文件導入表代碼解析

解析導入表就需要先認識下面這三個結構體 

//導入表結構體
typedef struct _IMAGE_IMPORT_DESCRIPTOR {
	union {
		DWORD   Characteristics;   

		//主要這個,包含指向INT的RVA
		DWORD   OriginalFirstThunk;
	};

	//時間標識
	DWORD   TimeDateStamp;  

	//與轉發有關
	DWORD   ForwarderChain;             

	//這就是DLL文件名
	DWORD   Name;

	//IAT的RVA
	DWORD   FirstThunk; 
} IMAGE_IMPORT_DESCRIPTOR, *PIMAGE_IMPORT_DESCRIPTOR;

 

//
typedef struct _IMAGE_THUNK_DATA32 {
	union {

		//轉發器有關
		DWORD ForwarderString;

		//IAT有關
		DWORD Function;

		//當前結構高位爲1是有關
		DWORD Ordinal;

		//不是上面三個的時候這個就發揮作用
		//指向輸入名稱表
		DWORD AddressOfData;
	} u1;
} IMAGE_THUNK_DATA32,*PIMAGE_THUNK_DATA32;
//輸入名稱表
typedef struct _IMAGE_IMPORT_BY_NAME {

	//導入的函數序號
	WORD    Hint;

	//導入的函數名稱
	CHAR   Name[1];
} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;

 IMAGE_IMPORT_DESCRIPTOR(導入表)僅僅是一個引導者,引導系統找到那兩個保存有真正導入信息的結構體,也就是IMAGE_THUNK_DATA和IMAGE_IMPORT_BY_NAME。

實現代碼: 


BOOL PEAnalyseSpace::PEAnalyse::ShowImport()
{
	//執行是否成功
	BOOL bRet = FALSE;

	//導入表指針
	PIMAGE_IMPORT_DESCRIPTOR pImport = NULL;

	//指針
	PIMAGE_THUNK_DATA pThunk = NULL;

	//導入名稱表指針
	PIMAGE_IMPORT_BY_NAME pName = NULL;

	//字符串指針
	PCHAR pszName = NULL;

	do 
	{
		//沒有解析
		if (m_lpBase == NULL)
		{
			break;
		}

		//沒有導入導入表,這個是不可能的
		if (m_pNt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size == NULL)
		{
			break;
		}

		//獲取導入表
		pImport = (PIMAGE_IMPORT_DESCRIPTOR)
			(RVAtoOffset(m_pNt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
				+ (DWORD)m_lpBase);

		//循環遍歷
		while (pImport->Name)
		{
			//獲取導入地址表
			pThunk = (PIMAGE_THUNK_DATA)
				(RVAtoOffset(pImport->OriginalFirstThunk) + (DWORD)m_lpBase);

			//獲取模塊名字
			pszName = (PCHAR)(RVAtoOffset(pImport->Name) + (DWORD)m_lpBase);


			cout << "Module Name Is: "
				<< pszName
				<< endl;

			//循環遍歷地址
			while (pThunk->u1.AddressOfData)
			{
				//判斷是序號導入還是名稱導入
				//序號
				if (IMAGE_SNAP_BY_ORDINAL32(pThunk->u1.AddressOfData))
				{
					cout << "Index Import -> ID: "
						<< hex
						<< (pThunk->u1.Ordinal & 0xffff)
						<< endl;
				}
				else//名稱導入
				{
					//獲取導入名稱
					pName = (PIMAGE_IMPORT_BY_NAME)
						(RVAtoOffset(pThunk->u1.AddressOfData)
							+ (DWORD)m_lpBase);
					cout << "Name Import -> ID: "
						<< hex
						<< pName->Hint
						<< "\tName: "
						<< pName->Name
						<< endl;
				}
				pThunk++;
			}
			cout << endl;
			pImport++;
		}
		bRet = TRUE;
	} while (FALSE);
	return bRet;
}

 實際效果:

Github:源代碼下載

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章