遍历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;
	}
}

 

效果:

 

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值