PE信息獲取 記錄

#pragma once
#include <DbgHelp.h>  //ImageRvaToVa使用到

#pragma comment(lib,"Dbghelp")
#define _in
#define _out

typedef struct MAP_FILE_STRUCT
{
	HANDLE hFile;			 //文件句柄
	HANDLE hMap;			 //映射句柄
	LPVOID ImageBase;		 //文件基地址
	DWORD dwSize;			 //文件大小 
	char FileName[MAX_PATH]; //文件名
}MAP_FILE_STRUCT,*PMAP_FILE_STRUCT;

enum{
	LFILE_FROM_NOMAL=0,       //文件打開時的處理方式
	LFILE_FROM_FILE,          //從文件打開
	LFILE_FROM_MEMORY         //從內存打開
};




class LPEFile
{
public:
	LPEFile(void);
	~LPEFile(void);
private:
	BYTE m_IsOpen;                    //文件打開狀態
	MAP_FILE_STRUCT* m_pstMapFile;    //文件及PE信息結構體
public:
	//獲得文件名稱
	void GetFileName(char* FileName);  
	BOOL LoadPeFile(char* lpFile,DWORD dwGeneric);
	BOOL Free();
	MAP_FILE_STRUCT* GetInfo();    //返回文件及PE信息對應的結構體
	void SetInfo(MAP_FILE_STRUCT* pstMapFile);
	void operator=(LPEFile& lPeFile);
	BYTE* GetImage(void);
	DWORD GetImageSize(void);
	////獲得Dos頭
	PIMAGE_DOS_HEADER GetDosHeader(void);
	////獲得NT頭
	PIMAGE_NT_HEADERS GetNtHeader(void);
	PIMAGE_FILE_HEADER GetFileHeader(void);
	PIMAGE_OPTIONAL_HEADER GetOptionalHeader(void);
	PIMAGE_DATA_DIRECTORY GetDataDirectory(void);
	PIMAGE_DATA_DIRECTORY GetDataDirectory(int nIndex);
	PIMAGE_SECTION_HEADER GetFirstSection(void);
	BOOL GetFileIsPE(void);
	bool GetMachineString(WORD nValue,char* wchBuf);
	void GetSubSystemString(WORD nValue,char* wchBuf);
	PIMAGE_SECTION_HEADER GetSection(int nIndex);
	int GetSectionCount(void);
	LPVOID RvaToPtr(DWORD dwRVA);
	LPVOID GetDataDirectoryEntryToData(USHORT DirectoryEntry);
	HANDLE GetFileHandle();
	//int StrMtoW(char* chBuf, wchar_t* wchBuf);
	//int StrWtoM(wchar_t* wchBuf, char* chBuf);
};


下面是具體實現部分

#include "StdAfx.h"
#include "LPEFile.h"
#include <string.h>    //strcpy_s



//構造函數
LPEFile::LPEFile(void)
{
	m_IsOpen = LFILE_FROM_NOMAL;
	m_pstMapFile = 0;
}

//析構函數
LPEFile::~LPEFile(void)
{
	if(Free())
	{
		delete m_pstMapFile;
	}
}

void LPEFile::GetFileName(char* FileName)
{
	strcpy_s( FileName, MAX_PATH,m_pstMapFile->FileName);
}

/*/載入PE文件
參數一:指向文件名的長指針
參數二:打開後對文件的操作權限
返回值:成功或失敗*/
BOOL LPEFile::LoadPeFile(char* lpFile,DWORD dwGeneric)
{
	HANDLE hFile,hMap;  //文件句柄與映射文件句柄

	hFile = CreateFile( lpFile,  //FileName
						dwGeneric,  //打開後的權限
						FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, //其它程序文件的權限
						NULL,     //安全屬性      
						OPEN_EXISTING,  //打開方式
						0,            //文件屬性,如果系統屬性,隱藏屬性等
						0             //hTemplateFile  
					  );

	if(hFile == INVALID_HANDLE_VALUE)  //如果CreateFile失敗,則返回失敗
	{
		return FALSE;
	}
		
	//更新文件的打開狀態,這裏爲以文件方式打開
	m_IsOpen = LFILE_FROM_FILE;
	//創建文件映射
	hMap = CreateFileMapping(
		hFile,   //CreateFile返回的句柄
		0,       //安全屬性 LPSECURITY_ATTRIBUTES 
		PAGE_READONLY,  //打開映射後返回的權限,這裏爲只讀
		0,        //DWORD dwMaximumSizeHigh
		0,        //DWORD dwMaximumSizeLow
		0);       //LPCTSTR lpName

	if(hMap == 0)
	{	            //如果map失敗,則關閉文件句柄
		CloseHandle(hFile);
		return FALSE;
	}
	//文件及PE信息結構體
	m_pstMapFile = new MAP_FILE_STRUCT;

	m_pstMapFile->dwSize = GetFileSize( hFile, 0);
	m_pstMapFile->ImageBase = MapViewOfFile( hMap, FILE_MAP_READ, 0, 0, m_pstMapFile->dwSize);
	m_pstMapFile->hFile = hFile;
	strcpy_s(m_pstMapFile->FileName, lpFile);

	return TRUE;
}

BOOL LPEFile::Free()
{
	if(m_IsOpen == LFILE_FROM_FILE)
	{              //如果打開方式是以文件方式打開
		if(m_pstMapFile == NULL)  
		{
			return TRUE;
		}
		if(m_pstMapFile->hMap)
		{
			UnmapViewOfFile( m_pstMapFile->hMap);

			if(m_pstMapFile->hFile)
			{
				CloseHandle( m_pstMapFile->hFile);
				m_pstMapFile = 0;

				return TRUE;
			}
		}
	}

	return FALSE;
}

MAP_FILE_STRUCT* LPEFile::GetInfo()
{
	return m_pstMapFile;
}
//更新  PE結構信息,科用於修改PE信息
void LPEFile::SetInfo(MAP_FILE_STRUCT* pstMapFile)
{
	m_pstMapFile = pstMapFile;
}

//看看具體的MAP_FILE_STRUCT有沒有內容
BYTE* LPEFile::GetImage(void)
{
	if(m_pstMapFile == ((MAP_FILE_STRUCT*)0xCCCCCCCC) || 
		m_IsOpen == LFILE_FROM_NOMAL)
		return 0;
	return (BYTE*)m_pstMapFile->ImageBase;
}
//獲得鏡像大小
DWORD LPEFile::GetImageSize(void)
{
	if(m_pstMapFile == 0)
		return 0;

	return m_pstMapFile->dwSize;
}
//獲得DOS頭
PIMAGE_DOS_HEADER LPEFile::GetDosHeader(void)
{
	BYTE* ImageBase = GetImage();
	if(ImageBase != 0)
		return (PIMAGE_DOS_HEADER)ImageBase;

	return 0;
}
//獲得NT頭
PIMAGE_NT_HEADERS LPEFile::GetNtHeader(void)
{
	PIMAGE_DOS_HEADER pDosH = GetDosHeader();
	if(pDosH != 0)
		return (PIMAGE_NT_HEADERS)(pDosH->e_lfanew + GetImage());

	return false;
}
//獲得文件頭
PIMAGE_FILE_HEADER LPEFile::GetFileHeader(void)
{
	PIMAGE_NT_HEADERS pNtH = GetNtHeader();
	if(pNtH != NULL)
		return (PIMAGE_FILE_HEADER)&pNtH->FileHeader;

	return 0;
}
//獲得可選頭信息
PIMAGE_OPTIONAL_HEADER LPEFile::GetOptionalHeader(void)
{
	PIMAGE_NT_HEADERS pNtH = GetNtHeader();
	if(pNtH != 0)
		return (PIMAGE_OPTIONAL_HEADER)&pNtH->OptionalHeader;

	return 0;
}

PIMAGE_DATA_DIRECTORY LPEFile::GetDataDirectory(void)
{
	PIMAGE_OPTIONAL_HEADER poh = GetOptionalHeader();

	if(poh != 0)
		return (PIMAGE_DATA_DIRECTORY)&poh->DataDirectory;
	return 0;
}
//通過索引方式獲得數據目錄
PIMAGE_DATA_DIRECTORY LPEFile::GetDataDirectory(int nIndex)
{
	PIMAGE_DATA_DIRECTORY pDataDir = GetDataDirectory();
	if(pDataDir != 0)
		return (PIMAGE_DATA_DIRECTORY)&pDataDir[nIndex];
	return 0;
}
//獲得第一個節
PIMAGE_SECTION_HEADER LPEFile::GetFirstSection(void)
{
	PIMAGE_NT_HEADERS pNtH = GetNtHeader();
	if(pNtH != 0)
		return (PIMAGE_SECTION_HEADER)IMAGE_FIRST_SECTION(pNtH);
	return 0;
}
//判斷是否是PE文件
BOOL LPEFile::GetFileIsPE(void)
{
	PIMAGE_DOS_HEADER pDosHeader = GetDosHeader();

	if(pDosHeader == 0)
		return FALSE;

	if(pDosHeader->e_magic == IMAGE_DOS_SIGNATURE)
	{
		PIMAGE_NT_HEADERS pNtH = GetNtHeader();
		if(pNtH->Signature == IMAGE_NT_SIGNATURE)
			return TRUE;
	}

	return FALSE;
}

bool LPEFile::GetMachineString(WORD nValue,char* wchBuf)
{
	bool bIsSuccess = true;

	switch(nValue)
	{
	case IMAGE_FILE_MACHINE_I386:	strcpy_s( wchBuf, 50,"x86");				break;
	case IMAGE_FILE_MACHINE_IA64:	strcpy_s( wchBuf, 50,"Intel Itanium");		break;
	case IMAGE_FILE_MACHINE_AMD64:	strcpy_s( wchBuf, 50,"x64");				break;
	default:						bIsSuccess = false;							break;
	}


	return bIsSuccess;
}

void LPEFile::GetSubSystemString(WORD nValue,char* wchBuf)
{
	switch(nValue)
	{
	case IMAGE_SUBSYSTEM_UNKNOWN:			strcpy_s( wchBuf, 50,"未知的子系統");		break;
	case IMAGE_SUBSYSTEM_NATIVE:			strcpy_s( wchBuf, 50,"不需要子系統");		break;
	case IMAGE_SUBSYSTEM_WINDOWS_GUI:		strcpy_s( wchBuf, 50,"圖形界面");			break;
	case IMAGE_SUBSYSTEM_WINDOWS_CUI:		strcpy_s( wchBuf, 50,"控制檯界面");			break;
	case IMAGE_SUBSYSTEM_OS2_CUI:			strcpy_s( wchBuf, 50,"OS2控制檯界面");		break;
	case IMAGE_SUBSYSTEM_POSIX_CUI:			strcpy_s( wchBuf, 50,"POSIX控制檯界面");	break;
	case IMAGE_SUBSYSTEM_NATIVE_WINDOWS:	strcpy_s( wchBuf, 50,"不需要子系統");		break;
	case IMAGE_SUBSYSTEM_WINDOWS_CE_GUI:	strcpy_s( wchBuf, 50,"CE圖形界面");			break;
	}
}
//通過節數目獲得相應的信息
PIMAGE_SECTION_HEADER LPEFile::GetSection(int nIndex)
{
	int nCount = GetSectionCount();
	if( nIndex >= nCount || nIndex < 0)
		return 0;

	PIMAGE_SECTION_HEADER psh = GetFirstSection();

	for(int i=0; i< nCount; i++, psh++)
	{
		if( nIndex == i)
			return psh;
	}


	return 0;
}
//返回節數目
int LPEFile::GetSectionCount(void)
{
	PIMAGE_FILE_HEADER pfh = GetFileHeader();

	if(pfh != 0)
		return pfh->NumberOfSections;

	return 0;
}


LPVOID LPEFile::RvaToPtr(DWORD dwRVA)
{
	PIMAGE_NT_HEADERS pNtHead = GetNtHeader();

	return ImageRvaToVa( pNtHead, GetImage(), dwRVA, 0);
}

LPVOID LPEFile::GetDataDirectoryEntryToData(USHORT DirectoryEntry)
{
	//起始RVA
	DWORD dwDataStartRva = GetDataDirectory(DirectoryEntry)->VirtualAddress;	
	LPVOID pDirData = RvaToPtr( dwDataStartRva);

	if(pDirData != NULL)
		return pDirData;

	return 0;
}

//int LPEFile::StrMtoW(_in char* chBuf,_out wchar_t* wchBuf)
//{
//	int nSize = 0;
//	if(chBuf == 0)
//		return -1;
//	nSize = MultiByteToWideChar( CP_ACP, 0, chBuf, -1, 0, 0);
//	MultiByteToWideChar(CP_ACP, 0, chBuf, -1 , wchBuf, nSize);
//
//	return nSize;
//}
//
//int LPEFile::StrWtoM(_in wchar_t* wchBuf,_out char* chBuf)
//{
//	int nSize = 0;
//	if(wchBuf == NULL)
//	{
//		return -1;
//	}
//
//	nSize = WideCharToMultiByte(CP_ACP, 0, wchBuf, -1, 0, 0, 0, 0);
//
//	if(chBuf != NULL)
//	{
//		WideCharToMultiByte(CP_ACP, 0, wchBuf, -1, chBuf, nSize, 0, 0);
//	}
//
//	return nSize;
//}
只要編寫一個程序,來調用這些類中函數就可以了。


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