读取PE头信息

主要是根据PE结构, 使用文件读取的方式,依次读取PE信息:


#include "stdio.h"
#include "windows.h"

/*
typedef struct _IMAE_DOS_HEADER {       //DOS .EXE header                                    位置  
    WORD e_magic;                       //Magic number;                                      0x00  
    WORD e_cblp;                        //Bytes on last page of file                         0x02  
    WORD e_cp;                          //Pages in file                                      0x04  
    WORD e_crlc;                        //Relocations                                        0x06  
    WORD e_cparhdr;                     //Size of header in paragraphs                       0x08  
    WORD e_minalloc;                    //Minimum extra paragraphs needed                    0x0A  
    WORD e_maxalloc;                    //Maximum extra paragraphs needed                    0x0C  
    WORD e_ss;                          //Initial (relative) SS value                        0x0E  
    WORD e_sp;                          //Initial SP value                                   0x10  
    WORD e_csum;                        //Checksum                                           0x12  
    WORD e_ip;                          //Initial IP value                                   0x14  
    WORD e_cs;                          //Initial (relative) CS value                        0x16  
    WORD e_lfarlc;                      //File address of relocation table                   0x18  
    WORD e_ovno;                        //Overlay number                                     0x1A  
    WORD e_res[4];                      //Reserved words                                     0x1C  
    WORD e_oemid;                       //OEM identifier (for e_oeminfo)                     0x24  
    WORD e_oeminfo;                     //OEM information; e_oemid specific                  0x26   
    WORD e_res2[10];                    //Reserved words                                     0x28  
    LONG e_lfanew;                      //File address of new exe header                     0x3C  
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;  
*/


LPVOID ReadPEFile(LPSTR lpszFile)
{
	FILE *pFile = NULL;
	DWORD fileSize = 0;
	LPVOID pFileBuffer = NULL;
	
	//打开文件
	pFile = fopen(lpszFile,"rb");
	
	if(!pFile)
	{
		printf("无法打开文件EXE文件");
		return NULL;
	}
	
	fseek(pFile,0,SEEK_END);
	fileSize = ftell(pFile);
	fseek(pFile,0,SEEK_SET);
	
	//分配缓冲区
	pFileBuffer = malloc(fileSize);
	if(!pFileBuffer)
	{
		printf("分配空间失败!\n");
		fclose(pFile);
		return NULL;
	}
	
	//文件读取
	
	size_t n = fread(pFileBuffer,fileSize,1,pFile);
	
	if(!n)
	{
		printf("读取数据失败\n");
		free(pFileBuffer);
		fclose(pFile);
		return NULL;
	}
	
	//关闭文件
	fclose(pFile);
	return pFileBuffer;
	
}


VOID PrintNTHeaders(LPSTR lpszFile)
{
	LPVOID pFileBuffer = NULL;
	PIMAGE_DOS_HEADER pDosHeader = NULL;
	PIMAGE_NT_HEADERS pNTHeader = NULL;
	PIMAGE_FILE_HEADER pPEHeader = NULL;
	PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
	PIMAGE_SECTION_HEADER pSectionHeader = NULL;
	
	pFileBuffer= ReadPEFile(lpszFile);
	if(!pFileBuffer)
	{
		printf("文件读取失败\n");
		return;
	}
	
	//MZ标志
	if(*((PWORD)pFileBuffer)!=IMAGE_DOS_SIGNATURE)
	{
		printf("不是有效的MZ标志\n");
		free(pFileBuffer);
		return;
	}
	
	pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
	
	//打印DOS头
	printf("------------DOS头------------\n");
	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;
	}

	pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer+pDosHeader->e_lfanew);

	//打印NT头
	printf("------------NT头------------\n");
	printf("Signature: %x\n",pNTHeader->Signature);
	pPEHeader = (PIMAGE_FILE_HEADER)(((DWORD)pNTHeader)+4);
	printf("------------标准PE头--------\n");
	printf("Machine: %x\n",pPEHeader->Machine);
	printf("节的数量: %x\n",pPEHeader->NumberOfSections);
	printf("SizeOfOptionHeaders: %x\n",pPEHeader->SizeOfOptionalHeader);

	//可选择PE头
	pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader+IMAGE_SIZEOF_FILE_HEADER);
	printf("------------OPTION_PE头--------\n");
	printf("Machine: %x \n",pOptionHeader->Magic);
	printf("OEP: %x \n",pOptionHeader->AddressOfEntryPoint);
	printf("ImageBase: %x \n",pOptionHeader->ImageBase);
	printf("SectionAlignment: %x \n",pOptionHeader->SectionAlignment);
	printf("FileAlignment: %x \n",pOptionHeader->FileAlignment);
	printf("SizeOfImage: %x \n",pOptionHeader->SizeOfImage);
	printf("SizeOfHeaders: %x \n",pOptionHeader->SizeOfHeaders);

	//释放内存
	free(pFileBuffer);

}

void main()
{
	LPSTR pStr = "C://msg.exe";

	PrintNTHeaders(pStr);


	return;
}

原文链接: 读取PE头信息 版权所有,转载时请注明出处,违者必究。
注明出处格式:流沙团 ( https://gyarmy.com/post-298.html )

发表评论

0则评论给“读取PE头信息”