PE头打印

勿在浮沙筑高台

一、流程

1、打开文件,并判断是否打开成功
2、读取文件大小
3、申请内存,并判断是否申请成功
4、将文件读取到内存中
5、关闭文件
6、判断是否有效MZ标识
7、打印DOS
8、判断是否为PE标识
9、打印PE文件标识
10、打印标准PE
11、打印可选PE
12、释放内存

二、代码

1、打开文件,并判断是否打开成功

	//定义三个变量
	FILE	*pFile		=	NULL;			//用来接收打开的文件			
	DWORD	fileSize	=	0;				//用来接收文件大小
	LPVOID	pFileBuffer	=	NULL;			//用来接收

	
	pFile = fopen("c:/fg.exe","rb");	//打开文件
	if(!pFile)		//判断是否打开成功
	{
		printf("打开文件失败");
		return NULL;
	}

2、读取文件大小

	fseek(pFile,0,SEEK_END);		//将指针从开始的位置移动到末尾
	fileSize = ftell(pFile);		//获取数据大小

3、申请内存,并判断是否申请成功

	#include "stdlib.h"			
	//分配缓冲区(申请内存)
	pFileBuffer = malloc(fileSize);
	if(!pFileBuffer)
	{
		printf("分配空间失败");
		fclose(pFile);	//关闭文件
		return NULL;
	}

4、将文件读取到内存中

	fseek(pFile,0,SEEK_SET);	//将指针指向开始
	size_t n = fread(pFileBuffer,fileSize,1,pFile);	//将数据读取到缓冲区中
	if(!n)
	{
		printf("读取数据失败");
		free(pFileBuffer);		//释放内存
		fclose(pFile);			//关闭文件
		return NULL;
	}

5、关闭文件

fclose(pFile);	

6、判断是否有效MZ标识

	//定义几个变量
	PIMAGE_DOS_HEADER			pDosHeader		=	NULL;	//接收DOS头
	PIMAGE_NT_HEADERS			pNTHeader		=	NULL;
	PIMAGE_FILE_HEADER			pPEHeader		=	NULL;
	PIMAGE_OPTIONAL_HEADER32	pOptionHeader	=	NULL;

	if(*((PWORD)pFileBuffer)	!=	IMAGE_DOS_SIGNATURE)
	{
		printf("不是有效的MZ头");
		free(pFileBuffer);
		return;
	}

7、打印DOS

	pDosHeader	=	(PIMAGE_DOS_HEADER)pFileBuffer;		//类型转换 
	printf("MZ标志:	%x\n",pDosHeader->e_magic);
	printf("PE偏移:	%x\n",pDosHeader->e_lfanew);

8、判断是否为PE标识

	if(*((PDWORD)((DWORD)pFileBuffer + pDosHeader->e_lfanew))	!=	IMAGE_NT_SIGNATURE)
	{
		printf("不是有效的PE标志\n");
		free(pFileBuffer);
		return;
	}

9、打印PE文件标识

	pNTHeader	=	(PIMAGE_NT_HEADERS)((DWORD)pFileBuffer	+	pDosHeader->e_lfanew);	 //将指针移动到PE头开始位置,并且类型转换
	printf("*************************NT头*************************\n");
	printf("PE标识:	%x\n",pNTHeader->Signature);

10、打印标准PE

	pPEHeader	=	(PIMAGE_FILE_HEADER)(((DWORD)pNTHeader) + 4);
	printf("*************************标准PE头*************************\n");
	printf("节的数量:	%x\n",pPEHeader->NumberOfSections);
	printf("可选PE头的大小:	%x\n",pPEHeader->SizeOfOptionalHeader);

11、打印可选PE

	printf("*************************可选PE头*************************\n");
	pOptionHeader	=	(PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader	+	IMAGE_SIZEOF_FILE_HEADER);	
	printf("程序入口地址:	%x\n",pOptionHeader->AddressOfEntryPoint);
	printf("文件在内存中的入口地址:	%x\n",pOptionHeader->ImageBase);
	printf("文件对齐:	%x\n",pOptionHeader->FileAlignment);
	printf("内存对齐:	%x\n",pOptionHeader->SectionAlignment);
	printf("PE头在文件对齐后大小:	%x\n",pOptionHeader->SizeOfHeaders);
	printf("PE文件在内存对齐后大小:	%x\n",pOptionHeader->SizeOfImage);

12、释放内存

free(pFileBuffer);	

三、完整代码

#include "stdafx.h"
#include <windows.h>
#include "stdlib.h"	
#include "stdio.h"	


//读取文件
LPVOID ReadPEFile(LPSTR lpszFile)
{
	FILE	*pFile		=	NULL;		
	DWORD	fileSize	=	0;
	LPVOID	pFileBuffer	=	NULL;

	
	pFile = fopen(lpszFile,"rb");	//打开文件
	if(!pFile)
	{
		printf("打开文件失败");
		return NULL;
	}

	//读取文件大小
	fseek(pFile,0,SEEK_END);		//将指针从开始的位置移动到末尾
	fileSize = ftell(pFile);		//获取数据大小

	//分配缓冲区(申请内存)
	pFileBuffer = malloc(fileSize);
	if(!pFileBuffer)
	{
		printf("分配空间失败");
		fclose(pFile);
		return NULL;
	}

	//将文件数据读取到缓冲区
	fseek(pFile,0,SEEK_SET);	//将指针指向开始
	size_t n = fread(pFileBuffer,fileSize,1,pFile);	//将数据读取到缓冲区中
	if(!n)
	{
		printf("读取数据失败");
		free(pFileBuffer);		//释放内存
		fclose(pFile);			//关闭文件
		return NULL;
	}

	//关闭文件
	fclose(pFile);				//关闭文件
	return pFileBuffer;		//返回缓冲区的首地址
}


//*****************************************************************************************************************************
VOID PrintNTHeaders()
{

	LPVOID						pFileBuffer		=	NULL;
	PIMAGE_DOS_HEADER			pDosHeader		=	NULL;
	PIMAGE_NT_HEADERS			pNTHeader		=	NULL;
	PIMAGE_FILE_HEADER			pPEHeader		=	NULL;
	PIMAGE_OPTIONAL_HEADER32	pOptionHeader	=	NULL;

	//读取文件
	LPSTR	FILEPATH	=	"c:/fg.exe";
	pFileBuffer	=	ReadPEFile(FILEPATH);
	if(!pFileBuffer)
	{
		printf("文件读取失败");
		return;
	}

	//判断是否是有效的MZ标志
	if(*((PWORD)pFileBuffer)	!=	IMAGE_DOS_SIGNATURE)
	{
		printf("不是有效的MZ头");
		free(pFileBuffer);
		return;
	}

	pDosHeader	=	(PIMAGE_DOS_HEADER)pFileBuffer;
	//打印DOS头
	printf("MZ标志:	%x\n",pDosHeader->e_magic);
	printf("PE偏移:	%x\n",pDosHeader->e_lfanew);

	//判断 是否是PE标志
	if(*((PDWORD)((DWORD)pFileBuffer + pDosHeader->e_lfanew))	!=	IMAGE_NT_SIGNATURE)
	{
		printf("不是有效的PE标志\n");
		free(pFileBuffer);
		return;
	}

//***************************************************************************************************
	printf("*************************PE头*************************\n");
	pNTHeader	=	(PIMAGE_NT_HEADERS)((DWORD)pFileBuffer	+	pDosHeader->e_lfanew);
	printf("PE标识:	%x\n",pNTHeader->Signature);

//***************************************************************************************************
	printf("*************************标准PE头*************************\n");
	pPEHeader	=	(PIMAGE_FILE_HEADER)(((DWORD)pNTHeader) + 4);
	printf("节的数量:	%x\n",pPEHeader->NumberOfSections);
	printf("可选PE头的大小:	%x\n",pPEHeader->SizeOfOptionalHeader);

//***************************************************************************************************
	printf("*************************可选PE头*************************\n");
	pOptionHeader	=	(PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader	+	IMAGE_SIZEOF_FILE_HEADER);	
	printf("程序入口地址:	%x\n",pOptionHeader->AddressOfEntryPoint);
	printf("文件在内存中的入口地址:	%x\n",pOptionHeader->ImageBase);
	printf("文件对齐:	%x\n",pOptionHeader->FileAlignment);
	printf("内存对齐:	%x\n",pOptionHeader->SectionAlignment);
	printf("PE头在文件对齐后大小:	%x\n",pOptionHeader->SizeOfHeaders);
	printf("PE文件在内存对齐后大小:	%x\n",pOptionHeader->SizeOfImage);
	


}

int main(int argc, char* argv[])
{
	PrintNTHeaders();
	return 0;
}

四、勿在浮沙筑高台

猜你喜欢

转载自blog.csdn.net/qq_41232519/article/details/108593485
PE