勿在浮沙筑高台
一、流程
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;
}