遍歷PE文件基本信息

遍歷導入表和導出表見另一篇文章

 運行效果如下:

 

代碼如下,獲取的是主要信息:

#include <stdio.h>
#include <windows.h>
#pragma warning(disable : 4996)

IMAGE_DOS_HEADER DosHeader;		
PIMAGE_DOS_HEADER pDosHeader;
IMAGE_NT_HEADERS NtHeader;
PIMAGE_NT_HEADERS pNtHeader;
IMAGE_FILE_HEADER FileHeader;
PIMAGE_FILE_HEADER pFileHeader;
IMAGE_OPTIONAL_HEADER OptionHeader;
PIMAGE_OPTIONAL_HEADER pOptionHeader;
PIMAGE_DATA_DIRECTORY pDataDirectory;
IMAGE_SECTION_HEADER SectionHeader;
char * filepath = "atl.dll";				// 寫死
long e_lfanew;

DWORD RvaToRaw(PIMAGE_NT_HEADERS pNtHeader, DWORD Rva){

	PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)IMAGE_FIRST_SECTION(pNtHeader);
	for (int i = 0; i < pNtHeader->FileHeader.NumberOfSections; i++){
		DWORD SectionBeginRva = pSectionHeader[i].VirtualAddress;
		DWORD SectionEndRva = pSectionHeader[i].VirtualAddress + pSectionHeader[i].SizeOfRawData;
		if (Rva >= SectionBeginRva && Rva <= SectionEndRva){
			DWORD Temp = Rva - SectionBeginRva;
			DWORD Rwa = Temp + pSectionHeader[i].PointerToRawData;
			return Rwa;
		}
	}
}

void main(int argc, char * agrv[]){

	HANDLE hFile = CreateFileA(filepath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL);
	HANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, NULL);
	PVOID pbFile = MapViewOfFile(hMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0);
	if (hFile == INVALID_HANDLE_VALUE || hMapping == NULL || pbFile == NULL){
		printf("\n>>> 文件不存在\n");
		if (hFile != INVALID_HANDLE_VALUE){
			CloseHandle(hFile);
		}
		if (hMapping != NULL){
			CloseHandle(hMapping);
		}
		if (pbFile != NULL){
			UnmapViewOfFile(pbFile);
		}
	}

	// 獲取DOS頭信息
	puts("=================DOS_HEADER======================");
	pDosHeader = (PIMAGE_DOS_HEADER)pbFile;
	printf("e_magic(MZ頭):			%X	", pDosHeader->e_magic);
	char arry_dosheader_e_magic[sizeof(pDosHeader->e_magic)];		// 申請一塊MZ頭字段大小的空間,將MZ頭複製到該內存
	memcpy(arry_dosheader_e_magic, &pDosHeader->e_magic, sizeof(pDosHeader->e_magic));
	for (int i = 0; i < sizeof(pDosHeader->e_magic) && arry_dosheader_e_magic[i] != '\0'; i++){
		printf("%c", arry_dosheader_e_magic[i]);
	}
	printf("\ne_lfanew(NT頭位置):		%X\n", pDosHeader->e_lfanew);
	pNtHeader = (PIMAGE_NT_HEADERS)((DWORD)pbFile + pDosHeader->e_lfanew);
	
	// NT頭
	puts("\n=================NT_HEADER=======================");
	printf("Signature(PE標誌):		%X	", pNtHeader->Signature);
	char arry_nt_Signature[sizeof(pNtHeader->Signature)];
	memcpy(arry_nt_Signature, &pNtHeader->Signature, sizeof(pNtHeader->Signature));
	for (int i = 0; i < sizeof(pNtHeader->Signature) && arry_nt_Signature[i] != '\0'; i++){
		printf("%c", arry_nt_Signature[i]);
	}

	// 文件頭
	puts("\n\n==========================NT_FILE_HEADER=========================");
	printf("NumberOfSections(節區數):		%X\n", pNtHeader->FileHeader.NumberOfSections);
	printf("TimeDateStamp(文件編譯時間):		%X\n", pNtHeader->FileHeader.TimeDateStamp);
	printf("SizeOfOptionalHeader(可選頭大小):	%X\n", pNtHeader->FileHeader.SizeOfOptionalHeader);
	printf("Characteristics(文件類型特徵值):	%X\n", pNtHeader->FileHeader.Characteristics);

	// 可選頭
	puts("\n====================NT_OPTIONAL_HEADER(RVA)======================");
	printf("AddressOfEntryPoint(程序執行入口點):		%X\n", pNtHeader->OptionalHeader.AddressOfEntryPoint);
	printf("BaseOfCode(代碼節地址):				%X\n", pNtHeader->OptionalHeader.BaseOfCode);
	printf("BaseOfData(數據節地址):				%X\n", pNtHeader->OptionalHeader.BaseOfData);
	printf("ImageBase(文件在內存中的基址):			%X\n", pNtHeader->OptionalHeader.ImageBase);
	printf("SectionAlignment(文件在內存中的節區對齊大小):	%X\n", pNtHeader->OptionalHeader.SectionAlignment);
	printf("FileAlignment(文件在磁盤中的節區對齊大小):	%X\n", pNtHeader->OptionalHeader.FileAlignment);
	printf("SizeOfImage(文件加載到內存中的大小):		%X\n", pNtHeader->OptionalHeader.SizeOfImage);
	printf("SizeOfHeaders(DOS頭+NT頭+節區表):		%X\n", pNtHeader->OptionalHeader.SizeOfHeaders);
	printf("NumberOfRvaAndSizes(數據目錄表的個數-bug):	%X\n", pNtHeader->OptionalHeader.NumberOfRvaAndSizes);

	/*打印數據目錄表*/
	puts("\n=================PE IMAGE_DATA_DIRECTORY HEADER==================");
	pDataDirectory = pNtHeader->OptionalHeader.DataDirectory;
	printf("Table Name\t\tVirtualAddress\t\tSize\n\n");
	printf("Export Table\t\t%08X\t\t%08X\n", pDataDirectory[0].VirtualAddress, pDataDirectory[0].Size);
	printf("Import Table\t\t%08X\t\t%08X\n", pDataDirectory[1].VirtualAddress, pDataDirectory[1].Size);
	printf("Resources Table\t\t%08X\t\t%08X\n", pDataDirectory[2].VirtualAddress, pDataDirectory[2].Size);
	printf("Exception Table\t\t%08X\t\t%08X\n", pDataDirectory[3].VirtualAddress, pDataDirectory[3].Size);
	printf("Security Table\t\t%08X\t\t%08X\n", pDataDirectory[4].VirtualAddress, pDataDirectory[4].Size);
	printf("Base relocation Table\t%08X\t\t%08X\n", pDataDirectory[5].VirtualAddress, pDataDirectory[5].Size);
	printf("Debug Table\t\t%08X\t\t%08X\n", pDataDirectory[6].VirtualAddress, pDataDirectory[6].Size);
	printf("Copyrught Table\t\t%08X\t\t%08X\n", pDataDirectory[7].VirtualAddress, pDataDirectory[7].Size);
	printf("Global Ptr Table\t%08X\t\t%08X\n", pDataDirectory[8].VirtualAddress, pDataDirectory[8].Size);
	printf("TLS Table\t\t%08X\t\t%08X\n", pDataDirectory[9].VirtualAddress, pDataDirectory[9].Size);
	printf("Load config Table\t%08X\t\t%08X\n", pDataDirectory[10].VirtualAddress, pDataDirectory[10].Size);
	printf("Bound Import Table\t%08X\t\t%08X\n", pDataDirectory[11].VirtualAddress, pDataDirectory[11].Size);
	printf("IAT Table\t\t%08X\t\t%08X\n", pDataDirectory[12].VirtualAddress, pDataDirectory[12].Size);
	printf("Delay Import Table\t%08X\t\t%08X\n", pDataDirectory[13].VirtualAddress, pDataDirectory[13].Size);
	printf("COM descriptor Table\t%08X\t\t%08X\n", pDataDirectory[14].VirtualAddress, pDataDirectory[14].Size);
	printf("Retention Table\t\t%08X\t\t%08X\n", pDataDirectory[15].VirtualAddress, pDataDirectory[15].Size);

	/* 打印SECTION頭 */
	PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)IMAGE_FIRST_SECTION(pNtHeader);
	puts("\n=========================SECTION HEADER==========================");
	for (int count = 0; count < pNtHeader->FileHeader.NumberOfSections; count++){

		// 打印節區標誌
		printf("\n----------------");
		char arry_section_text[sizeof(pSectionHeader->Name)];
		memcpy(arry_section_text, &pSectionHeader->Name, sizeof(pSectionHeader->Name));
		for (int i = 0; i < sizeof(pSectionHeader->Name) && arry_section_text[i] != '\0'; i++){
			printf("%c", arry_section_text[i]);
		}
		printf("----------------\n");
		printf("Name\t\t\t");
		for (int i = 0; i < sizeof(pSectionHeader->Name) && arry_section_text[i] != '\0'; i++){
			printf("%c", arry_section_text[i]);
		}
		printf("\nVirtualSize\t\t%08X\n", pSectionHeader->Misc.VirtualSize);
		printf("VirtualAddress\t\t%08X\n", pSectionHeader->VirtualAddress);
		printf("SizeOfRawData\t\t%08X\n", pSectionHeader->SizeOfRawData);
		printf("PointerToRawData\t%08X\n", pSectionHeader->PointerToRawData);
		//printf("PointerToRelocation\t%08X\n", pSectionHeader->PointerToRelocations);
		//printf("PointerToLinenumbers\t%08X\n", pSectionHeader->PointerToLinenumbers);
		//printf("NumberOfRelocations\t%04X\n", pSectionHeader->NumberOfRelocations);
		//printf("NumberOfLinenumbers\t%04X\n", pSectionHeader->NumberOfLinenumbers);
		printf("Characteristics\t\t%08X\n", pSectionHeader->Characteristics);
		pSectionHeader++;
	}

	system("pause");
}

 

版本二:

#include <stdio.h>
#include <Windows.h>
#include <tchar.h>
#pragma warning(disable : 4996)
extern void DirectoryString(DWORD dwIndex);
char path[MAX_PATH];																		// 文件路徑

int _tmain(int argc, _TCHAR* argv[])
{
	// 選擇Virus文件
	OPENFILENAMEA ofn;
	memset(path, 0, MAX_PATH);
	memset(&ofn, 0, sizeof(ofn));
	ofn.lStructSize = sizeof(ofn);
	ofn.lpstrFile = path;																	// path
	ofn.nMaxFile = MAX_PATH;
	ofn.lpstrFilter = "*.exe\0*.exe\0";
	ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
	if (!GetOpenFileName(&ofn)) {															// 如果打開文件錯誤
		MessageBox(NULL, "Open file failed!", NULL, MB_OK);
		exit(0);																			// 退出所有進程
	}
	// 獲取文件句柄,映射到內存
	HANDLE hFile = CreateFileA(path, GENERIC_ALL, 3u, NULL, OPEN_EXISTING, 0x80u, 0);		// path,第一個3u表示共享讀寫

	// 獲取文件大小
	DWORD dwFileSize = GetFileSize(hFile, NULL);
	CHAR *pFileBuf = new CHAR[dwFileSize];
	
	// 將文件讀取到內存
	DWORD ReadSize = 0;
	ReadFile(hFile, pFileBuf, dwFileSize, &ReadSize, NULL);

	// 判斷是否爲PE文件
	PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pFileBuf;
	if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
	{
		// 不是PE
		printf("不是PE文件\n");
		system("pause");
		return 0;
	}

	PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)(pFileBuf + pDosHeader->e_lfanew);
	if (pNtHeader->Signature != IMAGE_NT_SIGNATURE)
	{
		// 不是PE文件
		printf("不是PE文件\n");
		system("pause");
		return 0;
	}

	// 獲取基本PE頭信息
	// 獲取信息所用到的兩個結構體指針	(這兩個結構體都屬於NT頭)
	PIMAGE_FILE_HEADER		pFileHeader = &(pNtHeader->FileHeader);
	PIMAGE_OPTIONAL_HEADER	pOptionalHeader = &(pNtHeader->OptionalHeader);
	// 輸出PE頭信息
	printf("================== 基 本 P E 頭 信 息 ==================\n\n");
	printf("入 口 點:\t%08X\t", pOptionalHeader->AddressOfEntryPoint);
	printf("子 系 統:\t%04X\n", pOptionalHeader->Subsystem);
	printf("鏡像基址:\t%08X\t", pOptionalHeader->ImageBase);
	printf("區段數目:\t%04X\n", pFileHeader->NumberOfSections);
	printf("鏡像大小:\t%08X\t", pOptionalHeader->SizeOfImage);
	printf("日期時間標誌:\t%08X\n", pFileHeader->TimeDateStamp);
	printf("代碼基址:\t%08X\t", pOptionalHeader->BaseOfCode);
	printf("部首大小:\t%08X\n", pOptionalHeader->SizeOfHeaders);
	printf("數據基址:\t%08X\t", pOptionalHeader->BaseOfData);
	printf("特 徵 值:\t%04X\n", pFileHeader->Characteristics);
	printf("塊 對 齊:\t%08X\t", pOptionalHeader->SectionAlignment);
	printf("校 驗 和:\t%08X\n", pOptionalHeader->CheckSum);
	printf("文件塊對齊:\t%08X\t", pOptionalHeader->FileAlignment);
	printf("可選頭部大小:\t%04X\n", pFileHeader->SizeOfOptionalHeader);
	printf("標 志 字:\t%04X\t\t", pOptionalHeader->Magic);
	printf("RVA數及大小:\t%08X\n\n", pOptionalHeader->NumberOfRvaAndSizes);

	printf("======================= 目 錄 表 =======================\n");
	
	// 獲取目錄表頭指針,數據目錄表個數宏定義默認爲16
	PIMAGE_DATA_DIRECTORY pDataDirectory = pOptionalHeader->DataDirectory;
	printf("\t\t  RAV\t\t  大小\n");
	for (DWORD i = 0; i < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; i++)			
	{
		DirectoryString(i);
		printf("%08X\t%08X\n",
			pDataDirectory[i].VirtualAddress, pDataDirectory[i].Size);
	}

	printf("======================= 區 段 表 =======================\n");
	
	// 獲取區段表頭指針
	PIMAGE_SECTION_HEADER pSectionHeader = IMAGE_FIRST_SECTION(pNtHeader);
	printf("名稱      VOffset   VSize     ROffset   RSize     標誌\n");
	
	// 獲取區段個數
	DWORD dwSectionNum = pFileHeader->NumberOfSections;
	
	// 根據區段個數遍歷區段信息
	for (DWORD i = 0; i < dwSectionNum; i++, pSectionHeader++)
	{
		for (DWORD j = 0; j < IMAGE_SIZEOF_SHORT_NAME; j++)
		{
			printf("%c", pSectionHeader->Name[j]);
		}
		printf("  %08X  %08X  %08X  %08X  %08X\n",
			pSectionHeader->VirtualAddress,
			pSectionHeader->Misc.VirtualSize,
			pSectionHeader->PointerToRawData,
			pSectionHeader->SizeOfRawData,
			pSectionHeader->Characteristics);
	}
	printf("\n");

	system("pause");
	return 0;
}

void DirectoryString(DWORD dwIndex)
{
	switch (dwIndex)
	{
	case 0:printf("輸出表:\t\t");
		break;
	case 1:printf("輸入表:\t\t");
		break;
	case 2:printf("資源:\t\t");
		break;
	case 3:printf("異常:\t\t");
		break;
	case 4:printf("安全:\t\t");
		break;
	case 5:printf("重定位:\t\t");
		break;
	case 6:printf("調試:\t\t");
		break;
	case 7:printf("版權:\t\t");
		break;
	case 8:printf("全局指針:\t");
		break;
	case 9:printf("TLS表:\t\t");
		break;
	case 10:printf("載入配置:\t");
		break;
	case 11:printf("輸入範圍:\t");
		break;
	case 12:printf("IAT:\t\t");
		break;
	case 13:printf("延遲輸入:\t");
		break;
	case 14:printf("COM:\t\t");
		break;
	case 15:printf("保留:\t\t");
		break;
	}
}

 

效果:

 

 

發佈了66 篇原創文章 · 獲贊 30 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章