平台:winxp,
编译:VC++6.0
工具:PETool
PE结构也可以通过PETool查看,比较直观
//备注:这里用的是结构体来打印的,也可使用指针打印
void PrintPEInfo( FILE* fileAddr )
{
printf("fileAddr:%x
",fileAddr);
IMAGE_DOS_HEADER myDosHeader;
IMAGE_NT_HEADERS32 myNTHeaders32;
IMAGE_FILE_HEADER myFileHeader;
IMAGE_OPTIONAL_HEADER32 myOptionalHeader32;
//2、将指针指向DOS头
fread(&myDosHeader,sizeof(IMAGE_DOS_HEADER),1,fileAddr);
//2.1 打印 可执行文件标志 magic
printf("e_magic:%x
",myDosHeader.e_magic);
//2.2 打印 PE头文件地址
printf("e_lfanew:%x
",myDosHeader.e_lfanew);
//3、将指针指向NT头
fseek(fileAddr,myDosHeader.e_lfanew,SEEK_SET);
fread(&myNTHeaders32,sizeof(IMAGE_NT_HEADERS32),1,fileAddr);
//3.1 打印PE文件标志
printf("Signature:%x
",myNTHeaders32.Signature);
//4、将指针指向PE头
fseek(fileAddr,myDosHeader.e_lfanew+sizeof(DWORD),SEEK_SET);
fread(&myFileHeader,sizeof(IMAGE_FILE_HEADER),1,fileAddr);
//4.1 运行平台
printf("Machine:%x
",myFileHeader.Machine);
//4.2 节的数量
printf("NumberOfSections:%x
",myFileHeader.NumberOfSections);
//4.3 文件创建时的时间戳
printf("TimeDateStamp:%x
",myFileHeader.TimeDateStamp);
//4.4 文件属性
printf("Characteristics:%x
",myFileHeader.Characteristics);
//5、将指针指向PE可选头
fseek(fileAddr,myDosHeader.e_lfanew+0x18,SEEK_SET);
fread(&myOptionalHeader32,sizeof(IMAGE_OPTIONAL_HEADER32),1,fileAddr);
//5.1 标志字(幻数) 用来说明文件是ROM映像,还是普通可执行文件
printf("Magic:%x
",myOptionalHeader32.Magic);
//5.2 代码段(所有代码段)对齐后的大小
printf("SizeOfCode:%x
",myOptionalHeader32.SizeOfCode);
//5.3 已初始化数据块大小
printf("SizeOfInitializedData:%x
",myOptionalHeader32.SizeOfInitializedData);
//5.4 未初始化数据块大小
printf("SizeOfUninitializedData:%x
",myOptionalHeader32.SizeOfUninitializedData);
//5.5 RVA OEP(相对入口地址)
//addressOfEntryPoint = myOptionalHeader32.AddressOfEntryPoint;
printf("AddressOfEntryPoint:%x
",myOptionalHeader32.AddressOfEntryPoint);
//5.6 代码段的起始地址
printf("BaseOfCode:%x
",myOptionalHeader32.BaseOfCode);
//5.7 数据段的起始地址
printf("BaseOfData:%x
",myOptionalHeader32.BaseOfData);
//5.8 程序默认装入的地址(基址),相对地址需要加上这个基址才是真正的地址
printf("ImageBase:%x
",myOptionalHeader32.ImageBase);
//5.9 内存中节的对齐值
printf("SectionAlignment:%x
",myOptionalHeader32.SectionAlignment);
//5.A 文件中节的对齐值
printf("FileAlignment:%x
",myOptionalHeader32.FileAlignment);
//5.B 映像(文件装入内存中)大小
// sizeOfImage = myOptionalHeader32.SizeOfImage;
printf("SizeOfImage:%x
",myOptionalHeader32.SizeOfImage);
//5.C 首部及块表(首部+块表)的大小
printf("SizeOfHeaders:%x
",myOptionalHeader32.SizeOfHeaders);
//6、将指针指向节
IMAGE_SECTION_HEADER *pmySectionHeader = (IMAGE_SECTION_HEADER *)calloc(myFileHeader.NumberOfSections,sizeof(IMAGE_SECTION_HEADER));
fseek(fileAddr,(myDosHeader.e_lfanew+sizeof(IMAGE_NT_HEADERS)),SEEK_SET);
fread(pmySectionHeader,sizeof(IMAGE_SECTION_HEADER),myFileHeader.NumberOfSections,fileAddr);
for(int i=0; i<myFileHeader.NumberOfSections; i++, pmySectionHeader++)
{
//6.1 节的名字
printf("Name:%s
",pmySectionHeader->Name);
//6.2 未齐前 内存中的大小
printf("VirtualSize:%x
",pmySectionHeader->Misc.VirtualSize);
//6.3 文件中的偏移
printf("PointerToRawData:%x
",pmySectionHeader->PointerToRawData);
//6.4 对齐后 文件中的大小
printf("SizeOfRawData:%x
",pmySectionHeader->SizeOfRawData);
//6.5 内存中的偏移
printf("VirtualAddress:%x
",pmySectionHeader->VirtualAddress);
//6.6 节属性
printf("Characteristics:%x
",pmySectionHeader->Characteristics);
}
//7、关闭文件
fclose(fileAddr);
}