PE 信息打印

#include<windows.h>
#include<stdio.h>
#define FILEPATH "C:\\Documents and Settings\\Administrator\\桌面\\PE练习素材\\练习素材\\NOTEPAD.EXE"
LPVOID ReadPEFile(LPSTR lpszFile);
VOID PrintNTHeaders();
int main(){
PrintNTHeaders();
return 0;
}
LPVOID ReadPEFile(LPSTR lpszFile)
{
FILE *pFile = NULL;
DWORD fileSize = 0;
LPVOID pFileBuffer = NULL;
//打开文件
pFile = fopen(lpszFile, "rb");
if(!pFile)
{
printf(" 无法打开 EXE 文件! ");
return NULL;
}
//从0开始读取文件大小,偏移量为SEEK_END,也就是到文件末尾
fseek(pFile, 0, SEEK_END);
fileSize = ftell(pFile);
//重新设置到开头,因为后面还需要用到读取
fseek(pFile, 0, SEEK_SET);
//分配缓冲区,malloc返回值是一个指针缓冲区的指针
pFileBuffer = malloc(fileSize);
if(!pFileBuffer)
{
printf(" 分配空间失败! ");
fclose(pFile);
return NULL;
}
//将文件数据读取到缓冲区
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;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
//读取文件
pFileBuffer = ReadPEFile(FILEPATH);
if(!pFileBuffer)
{
printf("文件读取失败\n");
return ;
}
//判断是否是有效的MZ标志,也就是0x5A4D,取前四个字节
if(*((PWORD)pFileBuffer) != IMAGE_DOS_SIGNATURE)
{
printf("不是有效的MZ标志\n");
free(pFileBuffer);
return ;
}
pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
//打印DOS头
printf("********************DOS头********************\n\n");
printf("_IMAGE_DOS_HEADERMZ->e_magic MZ标志:0x%x\n",pDosHeader->e_magic);
printf("_IMAGE_DOS_HEADERMZ->e_lfanew指向PE标志:0x%x\n",pDosHeader->e_lfanew);
printf("\n");
//判断是否是有效的PE标志
if(*((PDWORD)((DWORD)pFileBuffer+pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE)
{
printf("不是有效的PE标志\n");
free(pFileBuffer);
return ;
}
//需要知道的pFileBuffer是一个指向PE文件的首地址的指针
pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer+pDosHeader->e_lfanew);
//打印NT头
printf("********************NT头********************\n\n");
printf("_IMAGE_NT_HEADERS->Signature文件PE标识:0x%x\n",pNTHeader->Signature);
printf("\n");
//打印标准PE头
pPEHeader = (PIMAGE_FILE_HEADER)(((DWORD)pNTHeader) + 4);
int NumberOfSections = pPEHeader->NumberOfSections;
printf("********************PE头********************\n\n");
printf("_IMAGE_FILE_HEADER->Machine支持的CPU:0x%x\n",pPEHeader->Machine);
printf("_IMAGE_FILE_HEADER->NumberOfSections节的数量:0x%x\n",pPEHeader->NumberOfSections);
printf("_IMAGE_FILE_HEADER->SizeOfOptionalHeader可选PE头的大小:0x%x\n",pPEHeader->SizeOfOptionalHeader);
printf("\n");
//可选PE头
pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader+IMAGE_SIZEOF_FILE_HEADER);
printf("********************OPTIOIN_PE头********************\n\n");
printf("_IMAGE_OPTIONAL_HEADER->Magic分辨系统位数:0x%x\n",pOptionHeader->Magic);
printf("_IMAGE_OPTIONAL_HEADER->AddressOfEntryPoint程序入口:0x%x\n",pOptionHeader->AddressOfEntryPoint);
printf("_IMAGE_OPTIONAL_HEADER->ImageBase内存镜像基址:0x%x\n",pOptionHeader->ImageBase);
printf("_IMAGE_OPTIONAL_HEADER->SectionAlignment内存对齐大小:0x%x\n",pOptionHeader->SectionAlignment);
printf("_IMAGE_OPTIONAL_HEADER->FileAlignment文件对齐大小:0x%x\n",pOptionHeader->FileAlignment);
printf("_IMAGE_OPTIONAL_HEADER->SizeOfImage内存中PE的大小(SectionAlignment整数倍):0x%x\n",pOptionHeader->SizeOfImage);
printf("_IMAGE_OPTIONAL_HEADER->SizeOfHeaders头+节表按照文件对齐的大小:0x%x\n",pOptionHeader->SizeOfImage);
printf("_IMAGE_OPTIONAL_HEADER->NumberOfRvaAndSizes目录项数目:0x%x\n",pOptionHeader->NumberOfRvaAndSizes);
printf("\n");
//节表
printf("********************节表********************\n\n");
pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + IMAGE_SIZEOF_NT_OPTIONAL_HEADER);
for(int i=1;i<=NumberOfSections;i++){
char SectionName[9] ={0};
strcpy(SectionName,(char *)pSectionHeader->Name);
printf("_IMAGE_SECTION_HEADER->Name:%s\n",SectionName);
printf("_IMAGE_SECTION_HEADER->VirtualSize:0x%x\n",pSectionHeader->Misc);
printf("_IMAGE_SECTION_HEADER->VirtualAddress:0x%x\n",pSectionHeader->VirtualAddress);
printf("_IMAGE_SECTION_HEADER->SizeOfRawData:0x%x\n",pSectionHeader->SizeOfRawData);
printf("_IMAGE_SECTION_HEADER->PointerToRawData:0x%x\n",pSectionHeader->PointerToRawData);
printf("_IMAGE_SECTION_HEADER->Characteristics:0x%x\n",pSectionHeader->Characteristics);
pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pSectionHeader +IMAGE_SIZEOF_SECTION_HEADER);
printf("\n");
}
//释放内存
free(pFileBuffer);
}

posted @   zpchcbd  阅读(290)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
点击右上角即可分享
微信分享提示