S.l.e!ep.¢%

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

PE 文件格式 (1)

Posted on 2009-09-12 04:55 S.l.e!ep.¢% 阅读(2165) 评论(1)  编辑 收藏 引用 所属分类: PE
 
PE 文件格式
 
PE. Portable Executable, 可移植的可执行文件, 是 MS WinNT, Win95, Win32中可执行的二进制文件
   a.在 Win 中,驱动也是这种格式
   b.这种文件格式由MS设计
 
1. DOS 头是这样的一个结构(也叫 'MZ' 头), 总共是 64 bytes
    typedef struct _IMAGE_DOS_HEADER
   {      
        WORD   e_magic;        // 必需为 4D 5A     'MZ'   IMAGE_DOS_SIGNATURE
        WORD   e_cblp;          // 文件最后页的字节数           
        WORD   e_cp;            // 文件页数
        WORD   e_crlc;          // 重定义元素个数
        WORD   e_cparhdr;     // 头部尽寸, 以段落为单位              
        WORD   e_minalloc;     // 所需的最小附加段
        WORD   e_maxalloc;    // 所需的最大附加段
        WORD   e_ss;            // 初始的SS值 (相对偏移量)
        WORD   e_sp;            // 实始的SP值 
        WORD   e_csum;        // 校验和
        WORD   e_ip;             // 初始的IP值
        WORD   e_cs;            // 初始的CS值(相对偏移量)
        WORD   e_lfarlc;         // 重分配表文件地址
        WORD   e_ovno;         // 覆盖号
        WORD   e_res[4];       // 保留字 
        WORD   e_oemid;       // OEM标识符 (相对 e_oeminfo)              
        WORD   e_oeminfo;     // OEM 信息                
        WORD   e_res2[10];    // 保留字
        LONG   e_lfanew;       //  PE头文件偏移量 , IMAGE_NT_HEADER32 结构所在的文件地址         
   }IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
   
   (1). “MZ”是MS-DOS开发者之一的马克·茨柏克沃斯基(Mark Zbikowski)的姓名首字母缩写。
   (2).  e_lfanew定位到PE文件头
 
   P:  1. 如何修改 DOS Stub
        A:   If you're compiling and linking the program yourself using MS compilers then the simplest approach would be to put in a custom DOS stub using the linkers /STUB[^] switch. Put in one which simply does nothing and returns immediately. 
       
/STUB:filename
 Remarks

where:

filename

An MS-DOS application.

The /STUB option attaches an MS-DOS stub program to a Win32 program.

A stub program is invoked if the file is executed in MS-DOS. It usually displays an appropriate message; however, any valid MS-DOS application can be a stub program.

Specify a filename for the stub program after a colon (:) on the command line. The linker checks filename and issues an error message if the file is not an executable. The program must be an .exe file; a .com file is invalid for a stub program.

If this option is not used, the linker attaches a default stub program that issues the following message:

When building a virtual device driver, filename allows the user to specify a file name that contains an IMAGE_DOS_HEADER structure (defined in WINNT.H) to be used in the VXD, rather than the default header.

To set this linker option in the Visual Studio development environment

  1. Open the project's Property Pages dialog box. For details, see Setting Visual C++ Project Properties.

  2. Click the Linker folder.

  3. Click the Command Line property page.

  4. Type the option into the Additional Options box.

To set this linker option programmatically


 
        2. DOS 下的程序 与 (Win32下的程序 / VC6编译的DOS程序), MZ头的不同?
 
   ---------------------------------------------------------------------------------

   Offset       00 01 02 03 04 05 06 07  08 09 0A 0B 0C 0D 0E 0F

   00000000  4D 5A 90 00 03 00 00 00   04 00 00 00 FF FF 00 00   MZ?..........
   00000010  B8 00 00 00 00 00 00 00   40 00 00 00 00 00 00 00   ?......@.......
   00000020  00 00 00 00 00 00 00 00   00 00 00 00 00 00 00 00   ................
   00000030  00 00 00 00 00 00 00 00   00 00 00 00 F0 00 00 00   ............?..

   ---------------------------------------------------------------------------------  
  
   第一行:
   (1). 4D 5A 对应 IMAGE_DOS_HEADER.e_magic 字段, 分别为 'MZ' 的 ASCII 码
   (2). 90 00 对应 IMAGE_DOS_HEADER.e_cblp 字段,值为 0x0090,
   (3). 03 00 对应 IMAGE_DOS_HEADER.e_cp 字段,值为 0x0003,
   (4). 00 00 对应 IMAGE_DOS_HEADER.e_crlc 字段,值为 0x0000
  
   (5). 04 00 对应 IMAGE_DOS_HEADER.e_cparhdr   0x0004;     // 头部尽寸, 以段落为单位              
   (6). 00 00 对应 IMAGE_DOS_HEADER.e_minalloc   0x0000;     // 所需的最小附加段
   (7). FF FF 对应 IMAGE_DOS_HEADER.e_maxalloc  0xFFFF;    // 所需的最大附加段
   (8). 00 00 对应 IMAGE_DOS_HEADER.e_ss;         0x0000     // 初始的SS值 (相对偏移量)
   
   第二行:
   (9) . B8 00 对应 IMAGE_DOS_HEADER.e_sp;    0x00B8         // 实始的SP值 
   (10).00 00 对应 IMAGE_DOS_HEADER.e_csum; 0x0000       // 校验和
   (11).00 00 对应 IMAGE_DOS_HEADER.e_ip;   0x00          // 初始的IP值
   (12).00 00 对应 IMAGE_DOS_HEADER.e_cs;  0x00          // 初始的CS值(相对偏移量)
   
    (13). 40 00 对应 IMAGE_DOS_HEADER.e_lfarlc;  0x0040        // 重分配表文件地址
    (14). 00 00 对应 IMAGE_DOS_HEADER.e_ovno;  0x0000       // 覆盖号
    (15). 00 00 对应 IMAGE_DOS_HEADER.e_res[4]; 0x0000      // 保留字
            00 00
            00 00
 
    第三行:
    (16). 00 00
    (17). 00 00 对应 IMAGE_DOS_HEADER.e_oemid;       // OEM标识符 (相对 e_oeminfo)  
    (18). 00 00 对应 IMAGE_DOS_HEADER.WORD   e_oeminfo;     // OEM 信息
    (16). 00 00 对应 IMAGE_DOS_HEADER.WORD   e_res2[10];    // 保留字 
           
    (17). 00 00
    (18). 00 00 
    (19). 00 00
    (20). 00 00

 

    第四行:
    (21). 00 00
    (22). 00 00 
    (23). 00 00
    (24). 00 00

 

    (25). 00 00
    (26). 00 00 
    (27). F0 00 对应 IMAGE_DOS_HEADER.LONG   e_lfanew;  这里的地址为 0x000000F0 //  PE头文件偏移量 , IMAGE_NT_HEADER32 结构所在的文件地址
    (28). 00 00

2. DOS Stub (DOS实模式残余程序)
   (1). 实模式残余程序 是一个在装载时能够被 MS-DOS运行的实际程序。
   (2). Dos Stub 只是提供了 PE 文件在DOS下面执行时,DOS会把它当作有效的执行文件而顺利执行。
         通常 Win32 的程序会在屏幕上输入"This Program cannot run in DOS mode"之类的提示语
   (3). 可以随便改变 DOS Stub, 根据自己的意图实现完整的 DOS 代码
   (4). DOS 下的EXE文件,长度不定
   (5). 在 Win32下, MZ头 跟 DOS 加载模块 用不上, 加上这两个只为兼容性问题

P:
1.  只取 MZ 头与 DOS Stub

Offset      0  1  2  3  4  5  6  7   8  9  A  B  C  D  E  F

00000000   4D 5A 90 00 03 00 00 00  04 00 00 00 FF FF 00 00   MZ?..........
00000010   B8 00 00 00 00 00 00 00  40 00 00 00 00 00 00 00   ?......@.......
00000020   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000030   00 00 00 00 00 00 00 00  00 00 00 00 00 0F 00 00   ............?..
00000040   0E 1F BA 0E 00 B4 09 CD  21 B8 01 4C CD 21 54 68   ..?.???L?Th
00000050   69 73 20 70 72 6F 67 72  61 6D 20 63 61 6E 6E 6F   is program canno
00000060   74 20 62 65 20 72 75 6E  20 69 6E 20 44 4F 53 20   t be run in DOS
00000070   6D 6F 64 65 2E 0D 0D 0A  24 00 00 00 00 00 00 00   mode....$.......
00000080   8D 44 CE 8E C9 25 A0 DD  C9 25 A0 DD C9 25 A0 DD   岲螏?犦?犦?犦
00000090   AB 3A B3 DD CD 25 A0 DD  4A 39 AE DD C8 25 A0 DD   ?齿?犦J9?犦
000000A0   A6 3A AA DD C2 25 A0 DD  A6 3A A4 DD CB 25 A0 DD   ??犦?ぽ?犦
000000B0   FF 03 A4 DD CA 25 A0 DD  C9 25 A1 DD BA 25 A0 DD   .ぽ?犦?≥?犦
000000C0   FF 03 AB DD CF 25 A0 DD  0E 23 A6 DD C8 25 A0 DD   .?犦.#?犦
000000D0   52 69 63 68 C9 25 A0 DD  00 00 00 00 00 00 00 00   Rich?犦........
000000E0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................

结果,
运行程序并没有显示 ' This program cannot be run in DOS mode ' ..........  
在纯DOS下会显示 'Errror in exe file'
难道跟 MZ 头除了e_lfanew的字段有关?........

将开头的  4D 5A 90 00 03 00 改为
                  4D 5A 00 01 01 00
之后,在纯DOS下就会显示  ' This program cannot be run in DOS mode '
在 Win 下会一闪而过, 需要先 run cmd, 再run debug, -q 退出, 再执行,就会显示 ' This program cannot be run in DOS mode '
原因暂时未知.

Feedback

# re: PE 文件格式 (1)  回复  更多评论   

2009-09-13 11:41 by 99书城
按时间爱的世界

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