首页
社区
课程
招聘
[求助]关于PE文件加载的疑问
发表于: 2009-3-15 12:06 3941

[求助]关于PE文件加载的疑问

2009-3-15 12:06
3941
加密与解密第三版 Page 266

紧跟着 DOS stub 的是 PE 文件(PE Header)。PE Header 是 PE 相关结构 NT 映像头
(IMAGE_NT_HEADERS)的简称,其中包含许多 PE 装载器用到的重要字段。执行体在支持 PE 文件结构的操作系统中执行时, PE 装载器将从 IMAGE_DOS_HEADER 结构中 e_lfanew 字段里找到 PE Header 的起始偏移量,加上基址得到 PE 文件头的指针。
PNTHeader = ImageBase + dosHeader->e_lfanew

我的疑问是:ImageBase 在 IMAGE_NT_HEADERS.OptionalHeader.ImageBase 中,此时还没有“读取”IMAGE_NT_HEADERS,系统怎么“知道” ImageBase 的呢?

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (8)
雪    币: 2110
活跃值: (21)
能力值: (RANK:260 )
在线值:
发帖
回帖
粉丝
2
进程创建后,PE文件被映射到进程内存空间之前,加载器已经“读取”了文件头部了。
2009-3-15 13:21
0
雪    币: 132
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
请教一下彭版主:
DOS STUB和PE之间的内容是否有什么特别的含义?
我的猜测是没有用的,但为什么连接器又填入一些数据呢,为什么不直接填入0呢?
2009-3-15 14:28
0
雪    币: 2110
活跃值: (21)
能力值: (RANK:260 )
在线值:
发帖
回帖
粉丝
4
DOS_STUB是一个完整的DOS程序。

从DOS头到PE头,这中间的部分都属于DOS_STUB。

这样,由于DOS下的MZ文件也是以EXE扩展名为特征,而PE文件的前面部分,实际上是一个合法的DOS下的MZ可执行文件。也就是说,微软实现了从DOS到WIN32的“无缝”升级。

最初这样的设计,DOS用户在看到一个EXE文件时,键入它的名字,不会出现意外的事情(要知道DOS的加载器是比较简单的,如果一个含有随机内容的EXE文件被加载,可能会对系统千万严重破坏)。

而且,这样设计还带来了一个额外的好处,微软早期的软件产品充分利用了这一设计——早期的office产品,是既可以在DOS下运行,也可以在Windows下运行的。而PE文件的特殊设计,使其只有一个EXE文件,该文件在DOS下和在Windows下都可以运行。

还有,微软早期Windows产品,内核是从DOS下引导的,这样的就要求程序同时具有16位代码和32位代码,而PE文件恰好可以做到(实际上微软最初用的是叫NE的一种格式,后来才演化成现在的PE格式)。

理论上,可以是任意的DOS程序。但由于DOS已经退出历史舞台,所以DOS_STUB现成已经完全退化成一个由于向下“兼容”的需要而存在的东西了。链接器默认使用的DOS_STUB,它打印出“This program can not run in DOS”然后退出。

DOS_STUB可以通过连接器参数而改变,这样你可以利用这一特性,实现自己特殊的功能,比如一个OS的Loader等。
2009-3-15 17:08
0
雪    币: 132
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
多谢版主解答。

看个例子:

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-C0 00 00 00
00000040:  0E 1F BA 0E-00 B4 09 CD-21 B8 01 4C-CD 21 54 68  ..............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:  E3 2B 61 C1-A7 4A 0F 92-A7 4A 0F 92-A7 4A 0F 92
00000090:  29 55 1C 92-80 4A 0F 92-5B 6A 1D 92-A6 4A 0F 92
000000A0:  60 4C 09 92-A6 4A 0F 92-52 69 63 68-A7 4A 0F 92
000000B0:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00
000000C0:  50 45 00 00-4C 01 04 00-B4 52 BC 49-00 00 00 00  PE..............
000000D0:  00 00 00 00-E0 00 0F 01-0B 01 05 0C-00 0A 00 00
000000E0:  00 1E 00 00-00 00 00 00-00 10 00 00-00 10 00 00
000000F0:  00 20 00 00-00 00 40 00-00 10 00 00-00 02 00 00

  ╔════════[ MZ-header ]═════════╗
  ║ Signature               4D5A ║
  ║ Bytes on last page      0090 ║
  ║ Pages in file           0003 ║
  ║ Relocations             0000 ║
  ║ Paragraphs in header    0004 ║
  ║ Minimum memory          0000 ║
  ║ Maximum memory          FFFF ║
  ║ SS:SP              0000:00B8 ║
  ║ Checksum                0000 ║
  ║ CS:IP              0000:0000 ║
  ║ Relocation table adress 0040 ║
  ║ Overlay number          0000 ║
  ║ Overlay length      00002770 ║
  ║ NewExe offset       000000C0 ║
  ║ >Entry point        00000040 ║
  ╚══════════════════════════════╝

CS:0000--->0E 1F BA 0E-00 B4 09 CD-21 B8 01 4C-CD 21 54 68  ..............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:  E3 2B 61 C1-A7 4A 0F 92-A7 4A 0F 92-A7 4A 0F 92
00000090:  29 55 1C 92-80 4A 0F 92-5B 6A 1D 92-A6 4A 0F 92
000000A0:  60 4C 09 92-A6 4A 0F 92-52 69 63 68-A7 4A 0F 92
000000B0:  00 00 00 00-00 00 00 00-00<---SS:00B8

我的理解:

下面这段是有用的(有效代码):
CS:0000 -> 0E 1F BA 0E-00 B4 09 CD-21 B8 01 4C-CD 21 54 68  ..............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:  E3 2B 61 C1-A7 4A 0F 92-A7 4A 0F 92-A7 4A 0F 92
00000090:  29 55 1C 92-80 4A 0F 92-5B 6A 1D 92-A6 4A 0F 92
000000A0:  60 4C 09 92-A6 4A 0F 92-52 69 63 68-A7 4A 0F 92
000000B0:  00 00 00 00-00 00 00 00-00<---SS:00B8

可以改为:
00000080:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00
00000090:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00
000000A0:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00
000000B0:  00 00 00 00-00 00 00 00-00<---SS:00B8

也不会影响该程序在DOS/WINDOWS下运行。

那么,
00000080:  E3 2B 61 C1-A7 4A 0F 92-A7 4A 0F 92-A7 4A 0F 92
00000090:  29 55 1C 92-80 4A 0F 92-5B 6A 1D 92-A6 4A 0F 92
000000A0:  60 4C 09 92-A6 4A 0F 92-52 69 63 68-A7 4A 0F 92
这段代码到底有没有用呢?
难道是随机填入的?
2009-3-15 19:17
0
雪    币: 2110
活跃值: (21)
能力值: (RANK:260 )
在线值:
发帖
回帖
粉丝
6
修改这些字节,对程序在Windows下的运行没有影响,但是对DOS下的运行有没有影响我就不知道了。

我的x64系统不支持对16位程序的兼容,所以没法验证。

反正我也不打算对DOS做深入研究,这个问题不必考虑。

至于你问的那些数据是不是随机填充的,我也不知道,想知道可以去问一下微软的设计师。
2009-3-16 00:02
0
雪    币: 132
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
哦,谢谢!谢谢!
2009-3-16 16:30
0
雪    币: 132
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
DOS STUB和PEHEAD之间的数据分析
==============================

建立一个简单的test.asm:

.386
.model flat, stdcall
option casemap:none
.data
.code
start:
mov eax,eax
ret
end start

编译:
\masm32\bin\ml /c /coff test.asm

连接:
Link.exe /SUBSYSTEM:WINDOWS test.obj

运行OLLYDBG,单独跟踪调试:
Link.exe /SUBSYSTEM:WINDOWS test.obj

;; LINK.EXE VERSION: 5.12.8078.0

;; EBP=n

0043FD52  |.  896C24 10     MOV DWORD PTR SS:[ESP+10],EBP
0043FD56  |>  8D5424 28     LEA EDX,DWORD PTR SS:[ESP+28]
0043FD5A  |.  52            PUSH EDX
0043FD5B  |.  E8 90FAFCFF   CALL link.0040F7F0
0043FD60  |.  8BB7 E0010000 MOV ESI,DWORD PTR DS:[EDI+1E0]  ;; ESI = 80
0043FD66  |.  33C9          XOR ECX,ECX
0043FD68  |.  85F6          TEST ESI,ESI
0043FD6A  |.  8BFE          MOV EDI,ESI
0043FD6C  |.  76 1C         JBE SHORT link.0043FD8A
0043FD6E  |.  8B4424 14     MOV EAX,DWORD PTR SS:[ESP+14]
0043FD72  |.  8BA8 DC010000 MOV EBP,DWORD PTR DS:[EAX+1DC]

;; ESI = 80
;; EDI = 884F3421 checksum of the 80 bytes

00406EB4  4D 5A 90 00 03 00 00 00 04 00 00 00 FF FF 00 00  MZ..............
00406EC4  B8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00  ................
00406ED4  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00406EE4  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00406EF4  0E 1F BA 0E 00 B4 09 CD 21 B8 01 4C CD 21 54 68  ..............Th
00406F04  69 73 20 70 72 6F 67 72 61 6D 20 63 61 6E 6E 6F  is program canno
00406F14  74 20 62 65 20 72 75 6E 20 69 6E 20 44 4F 53 20  t be run in DOS
00406F24  6D 6F 64 65 2E 0D 0D 0A 24 00 00 00 00 00 00 00  mode....$.......

0043FD78  |>  33D2          /XOR EDX,EDX
0043FD7A  |.  8A1429        |MOV DL,BYTE PTR DS:[ECX+EBP]
0043FD7D  |.  D3C2          |ROL EDX,CL
0043FD7F  |.  03FA          |ADD EDI,EDX
0043FD81  |.  41            |INC ECX
0043FD82  |.  3BCE          |CMP ECX,ESI
0043FD84  |.^ 72 F2         \JB SHORT link.0043FD78

;; EDI = 884F3421

0043FD86  |.  8B6C24 10     MOV EBP,DWORD PTR SS:[ESP+10]
0043FD8A  |>  85DB          TEST EBX,EBX
0043FD8C  |.  8BC3          MOV EAX,EBX
0043FD8E  |.  74 10         JE SHORT link.0043FDA0

;; EAX = 0039D438
0039D438  00 00 00 00 FC 20 12 00 01 00 00 00 AB AB AB AB  ................

0043FD90  |>  8B50 04       /MOV EDX,DWORD PTR DS:[EAX+4]
0043FD93  |.  8B48 08       |MOV ECX,DWORD PTR DS:[EAX+8]
0043FD96  |.  8B00          |MOV EAX,DWORD PTR DS:[EAX]
0043FD98  |.  D3C2          |ROL EDX,CL
0043FD9A  |.  03FA          |ADD EDI,EDX
0043FD9C  |.  85C0          |TEST EAX,EAX
0043FD9E  |.^ 75 F0         \JNZ SHORT link.0043FD90

;; EDI = 88737619

0043FDA0  |>  8BC7          MOV EAX,EDI
0043FDA2  |.  33D2          XOR EDX,EDX
0043FDA4  |.  C1E8 05       SHR EAX,5
0043FDA7  |.  B9 03000000   MOV ECX,3
0043FDAC  |.  F7F1          DIV ECX
0043FDAE  |.  03D5          ADD EDX,EBP
0043FDB0  |.  8D2CD5 200000>LEA EBP,DWORD PTR DS:[EDX*8+20]
0043FDB7  |.  55            PUSH EBP
0043FDB8  |.  E8 A3130100   CALL link.00451160

;; call calloc(n*8+20)

00451160  /$  8B4424 04     MOV EAX,DWORD PTR SS:[ESP+4]
00451164  |.  56            PUSH ESI
00451165  |.  50            PUSH EAX                                 ; /size
00451166  |.  6A 01         PUSH 1                                   ; |nitems = 1
00451168  |.  FF15 4C124000 CALL DWORD PTR DS:[<&MSVCRT.calloc>]     ; \calloc
0045116E  |.  8BF0          MOV ESI,EAX
00451170  |.  83C4 08       ADD ESP,8
00451173  |.  85F6          TEST ESI,ESI
00451175  |.  75 05         JNZ SHORT link.0045117C
00451177  |.  E8 6405FEFF   CALL link.004316E0
0045117C  |>  8BC6          MOV EAX,ESI
0045117E  |.  5E            POP ESI
0045117F  \.  C2 0400       RETN 4

;; EAX = 0039D460
0039D460  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0039D470  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0039D480  00 00 00 00 00 00 00 00 AB AB AB AB AB AB AB AB  ........

0043FDBD  |.  8B5424 3C     MOV EDX,DWORD PTR SS:[ESP+3C]
0043FDC1  |.  8BF0          MOV ESI,EAX
0043FDC3  |.  8932          MOV DWORD PTR DS:[EDX],ESI
0043FDC5  |.  A1 A0934600   MOV EAX,DWORD PTR DS:[4693A0]  ;; const [004693A0] = F93BF822
0043FDCA  |.  33C7          XOR EAX,EDI
0043FDCC  |.  897E 04       MOV DWORD PTR DS:[ESI+4],EDI   ;; PE[80][04]=EDI
0043FDCF  |.  35 669955AA   XOR EAX,AA559966
0043FDD4  |.  8906          MOV DWORD PTR DS:[ESI],EAX     ;; PE[80][00]=????
0043FDD6  |.  83C6 08       ADD ESI,8
0043FDD9  |.  8BC3          MOV EAX,EBX
0043FDDB  |.  893E          MOV DWORD PTR DS:[ESI],EDI     ;; PE[80][08]=EDI
0043FDDD  |.  897E 04       MOV DWORD PTR DS:[ESI+4],EDI   ;; PE[80][0C]=EDI
0043FDE0  |.  83C6 08       ADD ESI,8
0043FDE3  |.  85DB          TEST EBX,EBX
0043FDE5  |.  74 24         JE SHORT link.0043FE0B
0043FDE7  |>  8B48 04       /MOV ECX,DWORD PTR DS:[EAX+4]
0043FDEA  |.  50            |PUSH EAX                                ; /block
0043FDEB  |.  33CF          |XOR ECX,EDI                             ; |
0043FDED  |.  890E          |MOV DWORD PTR DS:[ESI],ECX              ; |  ;; PE[80][10+(n-1)*8+0]=????
0043FDEF  |.  8B50 08       |MOV EDX,DWORD PTR DS:[EAX+8]            ; |
0043FDF2  |.  33D7          |XOR EDX,EDI                             ; |
0043FDF4  |.  8956 04       |MOV DWORD PTR DS:[ESI+4],EDX            ; |  ;; PE[80][10+(n-1)*8+4]=????
0043FDF7  |.  8B18          |MOV EBX,DWORD PTR DS:[EAX]              ; |
0043FDF9  |.  83C6 08       |ADD ESI,8                               ; |
0043FDFC  |.  FF15 48124000 |CALL DWORD PTR DS:[<&MSVCRT.free>]      ; \free
0043FE02  |.  83C4 04       |ADD ESP,4
0043FE05  |.  8BC3          |MOV EAX,EBX
0043FE07  |.  85DB          |TEST EBX,EBX
0043FE09  |.^ 75 DC         \JNZ SHORT link.0043FDE7
0043FE0B  |>  A1 A4934600   MOV EAX,DWORD PTR DS:[4693A4]  ;; const [004693A4] = C236F034
0043FE10  |.  897E 04       MOV DWORD PTR DS:[ESI+4],EDI   ;; PE[80][10+n*8+4] = EDI
0043FE13  |.  35 669955AA   XOR EAX,AA559966
0043FE18  |.  8906          MOV DWORD PTR DS:[ESI],EAX     ;; PE[80][10+n*8+0] = C236F034 XOR AA559966 = 68636952 ("Rich")
0043FE1A  |.  8BC5          MOV EAX,EBP
0043FE1C  |.  5E            POP ESI
0043FE1D  |.  5D            POP EBP
0043FE1C  |.  5E            POP ESI
0043FE1D  |.  5D            POP EBP
0043FE1E  |.  5B            POP EBX
0043FE1F  |.  5F            POP EDI
0043FE20  |.  83C4 28       ADD ESP,28
0043FE23  |.  C2 0400       RETN 4

;; PE[80][00] --- PE[80][10+n*8+7]
;; TOTAL 18+n*8 bytes
;; if add 8 dup(0), TOTAL 20+n*8 bytes

有个简单的规律:第2,3,4及最后1个DWORD是相同的(都等于EDI),倒数第2个DWORD是Rich Signature("Rich") 。

找到另外一篇文章:Microsoft's Rich Signature (undocumented)

http://www.ntcore.com/Files/richsign.htm
2009-3-18 11:36
0
雪    币: 132
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
在网上找到一篇文章:
https://wasm.ru/forum/viewtopic.php?id=7056

里面有这段代码:
       mov     eax, const1       ; 0F93BF822h
        xor     eax, edi          ; edi==...Rich
        mov     [esi+4], edi
        xor     eax, 0AA559966h
        mov     [esi], eax

只是这篇文章我实在看不懂,如有朋友能看懂俄语,希望能翻译一下更好。
2009-3-19 08:28
0
游客
登录 | 注册 方可回帖
返回
//