S.l.e!ep.¢%

像打了激速一样,以四倍的速度运转,开心的工作
简单、开放、平等的公司文化;尊重个性、自由与个人价值;
posts - 1098, comments - 335, trackbacks - 0, articles - 1
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

PE文件(2)

Posted on 2009-09-13 17:05 S.l.e!ep.¢% 阅读(563) 评论(0)  编辑 收藏 引用 所属分类: PE
 
3. PE文件头 
    由 'PE' 00 00 4 bytes + PE文件头 20 bytes 组成
   
    typedef struct _IMAGE_NT_HEADERS
    {
        DWORD Signature;  //这个必需为50 45 00 (PE 00 00 )4字节  PE\0\0  
                                         //这是PE文件头的标记, 我们可以此识别给定文件是否为有效PE文件。
        //  如果IMAGE_NT_HEADERS的signature域值等于"PE\0\0",那么就是有效的PE文件
        // 实际上,为了比较方便,Microsoft已定义了常量IMAGE_NT_SIGNATURE供我们使用。

        // IMAGE_DOS_SIGNATURE      equ 5A4Dh      MZ
        // IMAGE_OS2_SIGNATURE       equ 454Eh
        // IMAGE_OS2_SIGNATURE_LE equ 454Ch
        // IMAGE_VXD_SIGNATURE      equ 454Ch
        // IMAGE_NT_SIGNATURE equ 4550h
        
        // 该结构域包含了关于PE文件逻辑分布的信息,虽然域名有"可选"字样,但实际上本结构总是存在的。

 

        IMAGE_FILE_HEADER FileHeader;  // 该结构包含了PE文件物理分布的信息,如节数目,PE文件的执行机器等
                
        IMAGE_OPTIONAL_HEADER32 OptionalHeader; 可选头结构

    } IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
 
    typedef struct _IMAGE_FILE_HEADER
    {
        WORD    Machine;                        //
INTEL 80386以上处理器必需为 4C 01 二字节
        WORD    NumberOfSections;
       // 段的个数 // P: 1. 是指哪里的 Sections ?  2. 最多可以有多少个 Sections?
        DWORD  TimeDateStamp;            // 文件的创建日期和时间
        DWORD  PointerToSymbolTable;  // 用于调试
        DWORD  NumberOfSymbols;        // 用于调试
        WORD    SizeOfOptionalHeader;   //
_IMAGE_OPTIONAL_HEADER有224字节所以为 E0 00
        WORD    Characteristics;              // 关于文件信息的标记,比如文件是EXE还是DLL?  EXE可执行文件为02 00 
 
    } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; 
 
    注:
   (1). Machine 字段表示这个PE文件被Build的目录机器种类,eg DEC(R) Alpha、MIPS R4000、Inter(R) x86
      已知的合法值: 
      IMAGE_FILE_MACHINE_I386 (0x14c)
            Intel 80386 处理器或更高
 
     0x014d
            Intel 80386 处理器或更高
 
     0x014e
            Intel 80386 处理器或更高
 
     0x0160         
             R3000 (MIPS⑧)处理器,大尾⑨
 
     IMAGE_FILE_MACHINE_R3000 (0x162)
             R3000 (MIPS)处理器,小尾
 
     IMAGE_FILE_MACHINE_R4000 (0x166)
             R4000 (MIPS)处理器,小尾
 
     IMAGE_FILE_MACHINE_R10000 (0x168)
             R10000 (MIPS)处理器,小尾
 
     IMAGE_FILE_MACHINE_ALPHA (0x184)
             DEC Alpha AXP⑩处理器
 
     IMAGE_FILE_MACHINE_POWERPC (0x1F0)
             IBM Power PC,小尾

(2). NumberOfSections 字段表示 这个PE文件有多少个段(多少个段头部和多少个段实体,每个段头部和段实体都在文件中连续排列, 所以要决定段头部和段实体在哪里结束的话,段的数目是必需的)
   
(3). 判断一个文件是否是合法的PE文件
          a. 比较 MZ 头的 e_magic 值是否为 IMAGE_DOS_SIGNATURE以验证是否是有效的DOS header
          b. 通过 MZ 头的 e_lfanew 所指向的偏移获取 PE 头
          c. 比较 PE 头的 Signature 值是否为 IMAGE_NT_SIGNATURE
          如果满足以上条件,则可以认为是一个合法的PE文件
 
(4). TimeDateStamp(32位),用来给出文件建立的时间。
         同一个文件的不同版本必须唯一,时间戳的格式没有明文规定,但似乎是按照UTC?
         (
时间“从1970年1月1日00:00:00算起的秒数值”----也就是大多数C语言编译器给time_t标志使用的格式。)
         P: 这个时间戳是用来绑定各个输入目录的?
         警告:有一些链接器往往将时间戳设为荒唐的值,而不是如前所述的time_t格式的链接时间。
 
(5). PointerToSymbolTable  符号表指针
       NumberOfSymbols        符号数
      用于调试,
P: 总是为 0x00, 即使在 VC IDE 的 Project Setting 中设置了生成调试信息,也是为 0x00 , 为什么?          
P: 1. NumberOfSections 表示 段的个数,那么 WIN32.PE 最多有多少段?
 
 (6). SizeOfOptionalHeader (16位)只是“IMAGE_OPTIONAL_HEADER(可选头)”项的大小, 
P: 只是用于验证PE文件结构的正确性?? 除了 E0 00 外是否有其它值?

(7). Characteristics (16位) 由许多标志集合组成
位1  IMAGE_FILE_EXECUTABLE_IMAGE(可执行映象文件) 表示如果文件是一个可执行文件,
也即不是目标文件或者库文件时,置1。
 如果链接器尝试创建一个可执行文件,却因为一些原因失败了,并保存映像以便下次例如增量链接时使用,此时此标志位也可能置1。 

位2  IMAGE_FILE_LINE_NUMS_STRIPPED(行数被剥离文件) 表示如果行数信息被剥除,此位置1;此位也不用于可执行文件。P:可执行文件不也有行数信息(假如PE编译时加上调试信息的话)?

位3 IMAGE_FILE_LOCAL_SYMS_STRIPPED(本地符号被剥离文件) 表示如果文件中没有关于本地符号的信息时,此位置1(此位也不用于可执行文件)。P: 同问

位4 IMAGE_FILE_AGGRESIVE_WS_TRIM(强行工作集修剪文件) 表示如果操作系统被假定为:通过将正在运行的进程(它所使用的内存数量)强行的页清除来修剪它的工作集时,此位置1。如果一进程是大部分时间处于等待,且一天中仅被唤醒一次的演示性的应用程序之类时,此位也应该被置1。P: 没看懂这句的意思。

P: 第 5,6 位跑哪去了??

位7 IMAGE_FILE_BYTES_REVERSED_LO(低字节变换文件)和 位15IMAGE_FILE_BYTES_REVERSED_HI(高字节变换文件) 表示如果一文件的字节序不是机器所预期的形式,因此它在读入前必须调换字节时,此位置1。这样做对可执行文件是不可靠的(操作系统期望可执行文件都已经被正确地按字节排整齐了)。

位8 IMAGE_FILE_32BIT_MACHINE(32位机器文件) 表示如果使用的机器被期望为32位的机器时,此位置1。现在的应用程序总将此位置1;NT5系统可能工作不同。

位9 IMAGE_FILE_DEBUG_STRIPPED(调试信息被剥离文件) 表示如果文件中没有调试信息,此位置1。此位可执行文件不用。P: (PE文件不是可以包含调试信息?)

按照其它信息([6])(这里指的是参考书目中的第[6]种----译者注),此位被称作“恒定”,并且当一个映象文件只有在被装入优先的装入地址才能运行(亦即:此文件不可重定位)时,此位置1。

位10 IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP(移动介质文件从交换文件运行) 表示如果一个应用程序不可以从可移动的介质,如软盘或CD-ROM上运行时,此位置1。在这种情况下,建议操作系统将文件复制到交换文件并从那里执行。P: 不是很懂这里的意思,'软盘或CD-ROM上运行时,此位置1。'

位11 IMAGE_FILE_NET_RUN_FROM_SWAP(网络文件从交换文件运行) 表示如果一个应用程序不可以从网络上运行时,此位置1。在这种情况下,建议操作系统将文件复制到交换文件并从那里执行。

位12 IMAGE_FILE_SYSTEM(系统文件) 表示如果文件是一个象驱动程序那样的系统文件,此位置1。此位可执行文件不用;我所见过的所有NT系统的驱动程序也不用。

位13 IMAGE_FILE_DLL(DLL文件) 表示如果文件是一个DLL文件时,此位置1。

位14 IMAGE_FILE_UP_SYSTEM_ONLY(仅但处理器系统的文件) 表示如果文件不设计运行在多处理器系统上(也就是说,因为此文件严格地依赖单一处理器的一些方式工作,所以它会发生冲突)时,此位置1。

#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES     16

typedef struct _IMAGE_OPTIONAL_HEADER

         //
         // Standard fields.
         //
         WORD   Magic;                   
// 总是 0B 01  P: 可选头的标志?意义是?
         BYTE    MajorLinkerVersion;   // 0 链接器的主版本号  // P:不同的链接器设置不同,因此不可靠?
         BYTE    MinorLinkerVersion;   // 0 链接器的小版本号
         DWORD  SizeOfCode;           // 0                        // 可执行的代码的大小 
         P: 这里的可执行代码是指整个PE文件的可执行代码段?

         DWORD  SizeOfInitializedData;     // 0                  // 已初始化数据的大小 ,数据段
         DWORD  SizeOfUninitializedData;  // 0                  // 未初始化数据的大小, BSS段 
         P: 已初始化的数据跟未初始化的数据有什么区别?它们都在数据段?

         DWORD  AddressOfEntryPoint;     //                    //  代码的入口点地址(是一个偏移量,RVA), 如 LibMain, WinMain....
         DWORD  BaseOfCode;  // 0                               //  可执行代码的偏移量, 代码基址 
         P: 不是很懂这里的意思,跟 AddressOfEntryPoint 的区别是?

         DWORD  BaseOfData;  // 0                               //  已初始化数据偏称量,数据基址  P: 同问
       
         //
         // NT additional fields.
         //
         DWORD  ImageBase;          //载入程序的RVA地址,LOADER可以改变 00 00 40 00 == 0x400000
         DWORD  SectionAlignment; //段加载后在内存的对齐方式 00 10 00 00
         DWORD  FileAlignment;      //段在文件中的对齐方式 00 20 00 00
         WORD    MajorOperatingSystemVersion;  // 0
         WORD    MinorOperatingSystemVersion;  // 0
         WORD    MajorImageVersion;                //  0
         WORD    MinorImageVersion;                //  0
         WORD    MajorSubsystemVersion; //子系统版本号如果不是4.0  对话框不能显示3D风格 04 00
         WORD    MinorSubsystemVersion; // 0
         DWORD  Win32VersionValue;       // 0
         DWORD  SizeOfImage;               // 映射到内存的代码长度
         DWORD  SizeOfHeaders; //所有文件头长度之和 00 04 00 00     (对齐后的, 包所在节?)
         DWORD  CheckSum;      // 校验和,用 0?
         WORD    Subsystem;     // 子系统 02 00 或03 00 ?
         WORD    DllCharacteristics;     // 00
         DWORD  SizeOfStackReserve;  // 00
         DWORD  SizeOfStackCommit;
         DWORD  SizeOfHeapReserve;
         DWORD  SizeOfHeapCommit;
         DWORD  LoaderFlags;             // 00
         DWORD  NumberOfRvaAndSizes; 
      
         IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
         // 16个结构,第二个结构(导入表) 
     } IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理