C/C++ 获取PE文件的各种信息

首先感谢cyxvc老哥,他的代码可读性超高,精简有用以理解,我找这方面的资料好久了,这篇文章对我帮助很大。

参考代码:

#include "stdafx.h"
#include <Windows.h>
 
extern void DirectoryString(DWORD dwIndex);
 
int _tmain(int argc, _TCHAR* argv[])
{
	//获取文件句柄
	HANDLE hFile = CreateFile(
		_T("D:\PE.exe"),
		GENERIC_READ,
		0,
		NULL,
		OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	//获取文件大小
	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 头 信 息 ==================nn");
	printf("入 口 点:t%08Xt", pOptionalHeader->AddressOfEntryPoint);
	printf("子 系 统:t%04Xn", pOptionalHeader->Subsystem);
	printf("镜像基址:t%08Xt", pOptionalHeader->ImageBase);
	printf("区段数目:t%04Xn", pFileHeader->NumberOfSections);
	printf("镜像大小:t%08Xt", pOptionalHeader->SizeOfImage);
	printf("日期时间标志:t%08Xn", pFileHeader->TimeDateStamp);
	printf("代码基址:t%08Xt", pOptionalHeader->BaseOfCode);
	printf("部首大小:t%08Xn", pOptionalHeader->SizeOfHeaders);
	printf("数据基址:t%08Xt", pOptionalHeader->BaseOfData);
	printf("特 征 值:t%04Xn", pFileHeader->Characteristics);
	printf("块 对 齐:t%08Xt", pOptionalHeader->SectionAlignment);
	printf("校 验 和:t%08Xn", pOptionalHeader->CheckSum);
	printf("文件块对齐:t%08Xt", pOptionalHeader->FileAlignment);
	printf("可选头部大小:t%04Xn", pFileHeader->SizeOfOptionalHeader);
	printf("标 志 字:t%04Xtt", pOptionalHeader->Magic);
	printf("RVA数及大小:t%08Xnn", pOptionalHeader->NumberOfRvaAndSizes);
 
	printf("======================= 目 录 表 =======================n");
	//获取目录表头指针
	PIMAGE_DATA_DIRECTORY pDataDirectory = pOptionalHeader->DataDirectory;
	printf("tt  RAVtt  大小n");
	for (DWORD i = 0; i < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; i++)
	{
		DirectoryString(i);
		printf("%08Xt%08Xn",
			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  %08Xn",
			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("输出表:tt");
		break;
	case 1:printf("输入表:tt");
		break;
	case 2:printf("资源:tt");
		break;
	case 3:printf("异常:tt");
		break;
	case 4:printf("安全:tt");
		break;
	case 5:printf("重定位:tt");
		break;
	case 6:printf("调试:tt");
		break;
	case 7:printf("版权:tt");
		break;
	case 8:printf("全局指针:t");
		break;
	case 9:printf("TLS表:tt");
		break;
	case 10:printf("载入配置:t");
		break;
	case 11:printf("输入范围:t");
		break;
	case 12:printf("IAT:tt");
		break;
	case 13:printf("延迟输入:t");
		break;
	case 14:printf("COM:tt");
		break;
	case 15:printf("保留:tt");
		break;
	}
}

效果图:

C/C++ 获取PE文件的各种信息

另外附上我的代码。获取某指定区段的信息:

	HANDLE hFile = CreateFile(_T("C:\Windows\SysNative\ntoskrnl.exe"), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if (hFile == INVALID_HANDLE_VALUE) {
		cout << "CreateFile failed:" << GetLastError() << endl;
		return false;
	}
	DWORD dwFileSize = GetFileSize(hFile, NULL);
	CHAR* pFileBuf = new CHAR[dwFileSize];
	DWORD ReadSize = 0;
	if (!ReadFile(hFile, pFileBuf, dwFileSize, &ReadSize, NULL)) {
		cout << "ReadFile failed:" << GetLastError() << endl;
		return false;
	}
	PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pFileBuf;
	PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)(pFileBuf + pDosHeader->e_lfanew);
	PIMAGE_FILE_HEADER		pFileHeader = &(pNtHeader->FileHeader);
	PIMAGE_OPTIONAL_HEADER	pOptionalHeader = &(pNtHeader->OptionalHeader);
	PIMAGE_SECTION_HEADER pSectionHeader = IMAGE_FIRST_SECTION(pNtHeader);
	DWORD dwSectionNum = pFileHeader->NumberOfSections;
	int page_vaddr = 0, page_roff = 0;
	for (DWORD i = 0; i < dwSectionNum; i++, pSectionHeader++) {
		string s_name;
		for (DWORD j = 0; j < IMAGE_SIZEOF_SHORT_NAME; j++) {
			if (pSectionHeader->Name[j]) {
				s_name += pSectionHeader->Name[j];
			}
		}
		if (s_name == "PAGE") {
			page_vaddr = pSectionHeader->VirtualAddress;
			page_roff = pSectionHeader->PointerToRawData;
			break;
		}
	}
	if (page_vaddr == 0 || page_roff == 0) { cout << "没有找到 PAGE 区段" << endl; return false; }

原文链接: https://www.cnblogs.com/LyShark/p/15019702.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

    C/C++ 获取PE文件的各种信息

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/212328

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月13日 上午1:12
下一篇 2023年2月13日 上午1:12

相关推荐