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  阅读(289)  评论(0编辑  收藏  举报
编辑推荐:
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
· C++代码改造为UTF-8编码问题的总结
· DeepSeek 解答了困扰我五年的技术问题
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
阅读排行:
· DeepSeek智能编程
· 精选4款基于.NET开源、功能强大的通讯调试工具
· [翻译] 为什么 Tracebit 用 C# 开发
· 腾讯ima接入deepseek-r1,借用别人脑子用用成真了~
· DeepSeek崛起:程序员“饭碗”被抢,还是职业进化新起点?
点击右上角即可分享
微信分享提示