查看文章
 
[转]PE文件格式分析心得
2008-09-04 15:53
PE文件格式最近好像炒得沸沸扬扬,由于我正在做一个这样的程序,索性将自己的心得写出来与大家同享。
   PE文件头分两大部分:
1:DOS ‘MZ’ HEADER
2:IMAGE_NT_HEADERS
   其中IMAGE_NT_HEADERS中包含
PE signature
IMAGE_FILE_HEADER
IMAGE_OPTIONAL_HEADER(其中包含Data Direcotry)
   文件头后紧跟着为
Section Table (array of IMAGE_SECTION_HEADERs)
   在DELPHI的windows.pad中已经有定义的有:
TImageDosHeader;
TImageNtHeaders;
TImageSectionHeader; { size of TIm..der is $28 }
   定义变量后按住Ctrl可以察看具体的项目,这里我就不多说了,这方面的东西也很多。
   而其他的如TImageResourceDirectory等,在DELPHI中却没有定义,察看其他资料,我在这里给出他们的结构和简单说明:
   以下是我写的PEDump.exe的类型说明:

type
   PIMAGE_RESOURCE_DIRECTORY = ^TImageResourceDirectory;
   _IMAGE_RESOURCE_DIRECTORY = packed record
     Characteristics:DWORD;
     TimeDateStamp:DWORD;
     MajorVersion:WORD;
     MinorVersion:WORD;
     NumberOfNamedEntries:WORD;
     NumberOfIdEntries:WORD;
   end;
   TImageResourceDirectory = _IMAGE_RESOURCE_DIRECTORY;
   { 资源目录的格式说明 }

   PIMAGE_RESOURCE_DIRECTORY_ENTRY = ^TImageResourceDirectoryEntry;
   _IMAGE_RESOURCE_DIRECTORY_ENTRY = packed record
     Name:DWORD;          { NameOffset:31,NameIsString:1 }
//     Id:WORD;
     OffsetToData:DWORD; { OffsetToDirectory:31,DataIsDirectory:1 }
   end;
   TImageResourceDirectoryEntry = _IMAGE_RESOURCE_DIRECTORY_ENTRY;
   { 资源目录进入点的格式说明 }

   PIMAGE_RESOURCE_DIRECTORY_STRING = ^TImageResourceDirectoryString;
   _IMAGE_RESOURCE_DIRECTORY_STRING = packed record
     Length:WORD;
     NameString:CHAR;
   end;
   TImageResourceDirectoryString = _IMAGE_RESOURCE_DIRECTORY_STRING;
   { 资源目录名的格式说明 }

   PIMAGE_RESOURCE_DIR_STRING_U = ^TImageResourceDirStringU;
   _IMAGE_RESOURCE_DIR_STRING_U = packed record
     Length:WORD;
     NameString:WCHAR;
   end;
   TImageResourceDirStringU = _IMAGE_RESOURCE_DIR_STRING_U;
   { unicode形式的资源目录名的格式说明 }

   PIMAGE_RESOURCE_DATA_ENTRY = ^TImageResourceDataEntry;
   _IMAGE_RESOURCE_DATA_ENTRY = packed record
     OffsetToData:DWORD;
     Size:DWORD;
     CodePage:DWORD;
     Reserved:DWORD;
   end;
   TImageResourceDataEntry = _IMAGE_RESOURCE_DATA_ENTRY;
   { 资源目录数据进入点的格式说明 }

const
   IMAGE_RESOURCE_NAME_IS_STRING = $80000000;
   { 检测TImageResourceDirectoryEntry.Name的最高为是否设立,
     是则说明剩下的31位指向IMAGE_RESOURCE_DIR_STRING_U的偏移,
     否则说明剩下的31位为一个整数ID。 }
   IMAGE_RESOURCE_DATA_IS_DIRECTORY = $80000000;
   { 检测TImageResourceDirectoryEntry.OffsetToData的最高为是否设立,
     是则说明剩下的31位指向另一个IMAGE_RESOURCE_DIRECTORY的偏移,
     否则说明剩下的31位指向IMAGE_RESOURCE_DATA_ENTRY的偏移。 }

   { 以下是文件属性具体值常量说明 }
   { File Characteristics }
   IMAGE_FILE_RELOCS_STRIPPED            = $0001; // Relocation info stripped from file.
   IMAGE_FILE_EXECUTABLE_IMAGE           = $0002; // File is executable.
   IMAGE_FILE_LINE_NUMS_STRIPPED         = $0004; // Line nunbers stripped from file.
   IMAGE_FILE_LOCAL_SYMS_STRIPPED        = $0008; // Local symbols stripped from file.
   IMAGE_FILE_AGGRESIVE_WS_TRIM          = $0010; // Agressively trim working set
   IMAGE_FILE_LARGE_ADDRESS_AWARE        = $0020; // App can handle >2gb addresses
   IMAGE_FILE_BYTES_REVERSED_LO          = $0080; // Bytes of machine word are reversed.
   IMAGE_FILE_32BIT_MACHINE              = $0100; // 32 bit word machine.
   IMAGE_FILE_DEBUG_STRIPPED             = $0200;  
   // Debugging info stripped from file in .DBG file
   IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP    = $0400;  
   // If Image is on removable media, copy and run from the swap file.
   IMAGE_FILE_NET_RUN_FROM_SWAP          = $0800;  
   // If Image is on Net, copy and run from the swap file.
   IMAGE_FILE_SYSTEM                     = $1000; // System File.
   IMAGE_FILE_DLL                        = $2000; // File is a DLL.
   IMAGE_FILE_UP_SYSTEM_ONLY             = $4000; // File should only be run on a UP machine
   IMAGE_FILE_BYTES_REVERSED_HI          = $8000; // Bytes of machine word are reversed.

   { 以下是文件头机器属性值的具体说明 }
   { Machine }
   IMAGE_FILE_MACHINE_UNKNOWN            = $0;
   IMAGE_FILE_MACHINE_I386               = $014c; // Intel 386.
   IMAGE_FILE_MACHINE_R3000              = $0162; // MIPS little-endian, $160 big-endian
   IMAGE_FILE_MACHINE_R4000              = $0166; // MIPS little-endian
   IMAGE_FILE_MACHINE_R10000             = $0168; // MIPS little-endian
   IMAGE_FILE_MACHINE_WCEMIPSV2          = $0169; // MIPS little-endian WCE v2
   IMAGE_FILE_MACHINE_ALPHA              = $0184; // Alpha_AXP
   IMAGE_FILE_MACHINE_SH3                = $01a2; // SH3 little-endian
   IMAGE_FILE_MACHINE_SH3E               = $01a4; // SH3E little-endian
   IMAGE_FILE_MACHINE_SH4                = $01a6; // SH4 little-endian
   IMAGE_FILE_MACHINE_SH5                = $01a8; // SH5
   IMAGE_FILE_MACHINE_ARM                = $01c0; // ARM Little-Endian
   IMAGE_FILE_MACHINE_THUMB              = $01c2;
   IMAGE_FILE_MACHINE_ARM33              = $01d3;
   IMAGE_FILE_MACHINE_POWERPC            = $01F0; // IBM PowerPC Little-Endian
   IMAGE_FILE_MACHINE_IA64               = $0200; // Intel 64
   IMAGE_FILE_MACHINE_MIPS16             = $0266; // MIPS
   IMAGE_FILE_MACHINE_ALPHA64            = $0284; // ALPHA64
   IMAGE_FILE_MACHINE_MIPSFPU            = $0366; // MIPS
   IMAGE_FILE_MACHINE_MIPSFPU16          = $0466; // MIPS
//   IMAGE_FILE_MACHINE_AXP64              IMAGE_FILE_MACHINE_ALPHA64
   IMAGE_FILE_MACHINE_AMD64              = $0500; // AMD K8
   IMAGE_FILE_MACHINE_TRICORE            = $0520; // Infineon
   IMAGE_FILE_MACHINE_CEF                = $0CEF;

   { 以下是SECTION的属性值具体说明 }
   { Section characteristics }
//   IMAGE_SCN_TYPE_REG                    = $00000000; // Reserved.
//   IMAGE_SCN_TYPE_DSECT                  = $00000001; // Reserved.
//   IMAGE_SCN_TYPE_NOLOAD                 = $00000002; // Reserved.
//   IMAGE_SCN_TYPE_GROUP                  = $00000004; // Reserved.
   IMAGE_SCN_TYPE_NO_PAD                 = $00000008; // Reserved.
//   IMAGE_SCN_TYPE_COPY                   = $00000010; // Reserved.

   IMAGE_SCN_CNT_CODE                    = $00000020; // Section contains code.
   IMAGE_SCN_CNT_INITIALIZED_DATA        = $00000040; // Section contains initialized data.
   IMAGE_SCN_CNT_UNINITIALIZED_DATA      = $00000080; // Section contains uninitialized data.

   IMAGE_SCN_LNK_OTHER                   = $00000100; // Reserved.
   IMAGE_SCN_LNK_INFO                    = $00000200;  
   // Section contains comments or some other type of information.
//   IMAGE_SCN_TYPE_OVER                   = $00000400; // Reserved.
   IMAGE_SCN_LNK_REMOVE                  = $00000800;  
   // Section contents will not become part of image.
   IMAGE_SCN_LNK_COMDAT                  = $00001000; // Section contents comdat.
//                                        = $00002000; // Reserved.
//   IMAGE_SCN_MEM_PROTECTED - Obsolete    = $00004000;
   IMAGE_SCN_NO_DEFER_SPEC_EXC           = $00004000;  
   // Reset speculative exceptions handling bits in the TLB entries for this section.
   IMAGE_SCN_GPREL                       = $00008000;  
   // Section content can be accessed relative to GP
   IMAGE_SCN_MEM_FARDATA                 = $00008000;
//   IMAGE_SCN_MEM_SYSHEAP   - Obsolete     = $00010000;
   IMAGE_SCN_MEM_PURGEABLE               = $00020000;
   IMAGE_SCN_MEM_16BIT                   = $00020000;
   IMAGE_SCN_MEM_LOCKED                  = $00040000;
   IMAGE_SCN_MEM_PRELOAD                 = $00080000;

   IMAGE_SCN_ALIGN_1BYTES                = $00100000; //
   IMAGE_SCN_ALIGN_2BYTES                = $00200000; //
   IMAGE_SCN_ALIGN_4BYTES                = $00300000; //
   IMAGE_SCN_ALIGN_8BYTES                = $00400000; //
   IMAGE_SCN_ALIGN_16BYTES               = $00500000;  
   // Default alignment if no others are specified.
   IMAGE_SCN_ALIGN_32BYTES               = $00600000; //
   IMAGE_SCN_ALIGN_64BYTES               = $00700000; //
   IMAGE_SCN_ALIGN_128BYTES              = $00800000; //
   IMAGE_SCN_ALIGN_256BYTES              = $00900000; //
   IMAGE_SCN_ALIGN_512BYTES              = $00A00000; //
   IMAGE_SCN_ALIGN_1024BYTES             = $00B00000; //
   IMAGE_SCN_ALIGN_2048BYTES             = $00C00000; //
   IMAGE_SCN_ALIGN_4096BYTES             = $00D00000; //
   IMAGE_SCN_ALIGN_8192BYTES             = $00E00000; //
// Unused                                 = $00F00000;
   IMAGE_SCN_ALIGN_MASK                  = $00F00000;

   IMAGE_SCN_LNK_NRELOC_OVFL             = $01000000; // Section contains extended relocations.
   IMAGE_SCN_MEM_DISCARDABLE             = $02000000; // Section can be discarded.
   IMAGE_SCN_MEM_NOT_CACHED              = $04000000; // Section is not cachable.
   IMAGE_SCN_MEM_NOT_PAGED               = $08000000; // Section is not pageable.
   IMAGE_SCN_MEM_SHARED                  = $10000000; // Section is shareable.
   IMAGE_SCN_MEM_EXECUTE                 = $20000000; // Section is executable.
   IMAGE_SCN_MEM_READ                    = $40000000; // Section is readable.
   IMAGE_SCN_MEM_WRITE                   = $80000000; // Section is writeable.

   我写了检测是否包含此属性的函数
   function BeTrue(fg:Cardinal,Value):Boolean;
   begin
     Result:=fg and not Value=0;
   end;
   如果fg的属性值在Value中,则为True,否则为False;
   例如   BeTrue(IMAGE_FILE_RELOCS_STRIPPED,PENTHead.FileHeader.Characteristics);

   至于资源目录的读取,至少需要两重循环来定位,具体实现就要靠你的算法功力了:)

   好了,差不多了,再具体一点我也说不上了,我做了一个PEDump的程序,在我的主页DELPHI盒子
==================== http://www.delphibox.com =====================
可以下载,程序中有更详细的说明,相信能帮助想了解这方面的东西的朋友。

类别:默认分类||添加到搜藏 |分享到i贴吧|浏览(114)|评论 (0)
 
最近读者:
 
网友评论:
发表评论:
姓 名:
网址或邮箱: (选填)
内 容:
     

   
帮助中心 | 空间客服 | 投诉中心 | 空间协议
©2012 Baidu