📄 chap8-1-1.htm.primary
字号:
2</b></font></td>
</tr>
<tr>
<td align=middle bgcolor=#660066 height=53><font face="MS Sans Serif" size="2" color="#FFFFFF"><b>Section
...</b></font></td>
</tr>
<tr>
<td align=middle bgcolor=#660066 height=50><font face="MS Sans Serif" size="2" color="#FFFFFF"><b>Section
n</b></font></td>
</tr>
</tbody>
</table>
<p><font size="2" color="#000000">上图是 </font><font face="MS Sans Serif" size="2" color="#000000">PE</font><font size="2" color="#000000">文件结构的总体层次分布。所有
</font><font face="MS Sans Serif" size="2" color="#000000">PE</font><font size="2" color="#000000">文件</font><font face="MS Sans Serif" size="2" color="#000000">(</font><font size="2" color="#000000">甚至</font><font face="MS Sans Serif" size="2" color="#000000">32</font><font size="2" color="#000000">位的
</font><font face="MS Sans Serif" size="2" color="#000000">DLLs) </font><font size="2" color="#000000">必须以一个简单的
</font><font face="MS Sans Serif" size="2" color="#000000">DOS MZ header </font><font size="2" color="#000000">开始。我们通常对此结构没有太大兴趣。有了它,一旦程序在</font><font face="MS Sans Serif" size="2" color="#000000">DOS</font><font size="2" color="#000000">下执行,</font><font face="MS Sans Serif" size="2" color="#000000">DOS</font><font size="2" color="#000000">就能识别出这是有效的执行体,然后运行紧随
</font><font face="MS Sans Serif" size="2" color="#000000">MZ header </font><font size="2" color="#000000">之后的
</font><font face="MS Sans Serif" size="2" color="#000000">DOS stub</font><font size="2" color="#000000">。</font><font face="MS Sans Serif" size="2" color="#000000">DOS
stub</font><font size="2" color="#000000">实际上是个有效的 </font><font face="MS Sans Serif" size="2" color="#000000">EXE</font><font size="2" color="#000000">,在不支持
</font><font face="MS Sans Serif" size="2" color="#000000">PE</font><font size="2" color="#000000">文件格式的操作系统中,它将简单显示一个错误提示,类似于字符串
</font><font face="MS Sans Serif" size="2" color="#000000">"This program requires
Windows" </font><font size="2" color="#000000">或者程序员可根据自己的意图实现完整的 </font><font face="MS Sans Serif" size="2" color="#000000">DOS</font><font size="2" color="#000000">代码。通常我们也不对
</font><font face="MS Sans Serif" size="2" color="#000000">DOS stub </font><font size="2" color="#000000">太感兴趣</font><font face="MS Sans Serif" size="2" color="#000000">:
</font><font size="2" color="#000000">因为大多数情况下它是由汇编器</font><font face="MS Sans Serif" size="2" color="#000000">/</font><font size="2" color="#000000">编译器自动生成。通常,它简单调用中断</font><font face="MS Sans Serif" size="2" color="#000000">21h</font><font size="2" color="#000000">服务</font><font face="MS Sans Serif" size="2" color="#000000">9</font><font size="2" color="#000000">来显示字符串</font><font face="MS Sans Serif" size="2" color="#000000">"This
program cannot run in DOS mode"</font><font size="2" color="#000000">。</font></p>
<p><font size="2" color="#000000">紧接着 </font><font face="MS Sans Serif" size="2" color="#000000">DOS
stub </font><font size="2" color="#000000">的是<b> </b></font><font color="#000000" face="MS Sans Serif" size="2"><b>PE
header</b></font><font size="2" color="#000000">。 </font><font face="MS Sans Serif" size="2" color="#000000">PE
header </font><font size="2" color="#000000">是</font><font face="MS Sans Serif" size="2" color="#000000">PE</font><font size="2" color="#000000">相关结构<b>
</b></font><font color="#000000" face="MS Sans Serif" size="2"><b>IMAGE_NT_HEADERS</b></font><font size="2" color="#000000">
的简称,其中包含了许多</font><font face="MS Sans Serif" size="2" color="#000000">PE</font><font size="2" color="#000000">装载器用到的重要域。当我们更加深入研究</font><font face="MS Sans Serif" size="2" color="#000000">PE</font><font size="2" color="#000000">文件格式后,将对这些重要域耳目能详。执行体在支持</font><font face="MS Sans Serif" size="2" color="#000000">PE</font><font size="2" color="#000000">文件结构的操作系统中执行时,</font><font face="MS Sans Serif" size="2" color="#000000">PE</font><font size="2" color="#000000">装载器将从
</font><font face="MS Sans Serif" size="2" color="#000000">DOS MZ header</font><font size="2" color="#000000">
中找到 </font><font face="MS Sans Serif" size="2" color="#000000">PE header</font><font size="2" color="#000000">
的起始偏移量。因而跳过了 </font><font face="MS Sans Serif" size="2" color="#000000">DOS
stub </font><font size="2" color="#000000">直接定位到真正的文件头 </font><font face="MS Sans Serif" size="2" color="#000000">PE
header</font><font size="2" color="#000000">。</font></p>
<p><font face="MS Sans Serif" size="2" color="#000000">PE</font><font size="2" color="#000000">文件的真正内容划分成块,称之为</font><font color="#000000" face="MS Sans Serif" size="2"><b>sections</b></font><font size="2" color="#000000">(节)。每节是一块拥有共同属性的数据,比如代码</font><font face="MS Sans Serif" size="2" color="#000000">/</font><font size="2" color="#000000">数据、读</font><font face="MS Sans Serif" size="2" color="#000000">/</font><font size="2" color="#000000">写等。我们可以把</font><font face="MS Sans Serif" size="2" color="#000000">PE</font><font size="2" color="#000000">文件想象成一逻辑磁盘,</font><font face="MS Sans Serif" size="2" color="#000000">PE
header </font><font size="2" color="#000000">是磁盘的</font><font face="MS Sans Serif" size="2" color="#000000">boot</font><font size="2" color="#000000">扇区,而</font><font face="MS Sans Serif" size="2" color="#000000">sections</font><font size="2" color="#000000">就是各种文件,每种文件自然就有不同属性如只读、系统、隐藏、文档等等。<b>
值得我们注意的是 </b></font><font color="#000000" face="MS Sans Serif" size="2"><b>----
</b></font><font color="#000000" size="2"><b>节的划分是基于各组数据的共同属性</b></font><font color="#000000" face="MS Sans Serif" size="2"><b>:
</b></font><font color="#000000" size="2"><b>而不是逻辑概念。</b>重要的不是数据</font><font face="MS Sans Serif" size="2" color="#000000">/</font><font size="2" color="#000000">代码是如何使用的,如果</font><font face="MS Sans Serif" size="2" color="#000000">PE</font><font size="2" color="#000000">文件中的数据</font><font face="MS Sans Serif" size="2" color="#000000">/</font><font size="2" color="#000000">代码拥有相同属性,它们就能被归入同一节中。不必关心节中类似于</font><font face="MS Sans Serif" size="2" color="#000000">"data",
"code"</font><font size="2" color="#000000">或其他的逻辑概念</font><font face="MS Sans Serif" size="2" color="#000000">:
</font><font size="2" color="#000000">如果数据和代码拥有相同属性,它们就可以被归入同一个节中。(译者注:节名称仅仅是个区别不同节的符号而已,类似</font><font face="MS Sans Serif" size="2" color="#000000">"data",
"code"</font><font size="2" color="#000000">的命名只为了便于识别,惟有节的属性设置决定了节的特性和功能)如果某块数据想付为只读属性,就可以将该块数据放入置为只读的节中,当</font><font face="MS Sans Serif" size="2" color="#000000">PE</font><font size="2" color="#000000">装载器映射节内容时,它会检查相关节属性并置对应内存块为指定属性。</font></p>
<p><font size="2" color="#000000">如果我们将</font><font face="MS Sans Serif" size="2" color="#000000">PE</font><font size="2" color="#000000">文件格式视为一逻辑磁盘,</font><font face="MS Sans Serif" size="2" color="#000000">PE
header</font><font size="2" color="#000000">是</font><font face="MS Sans Serif" size="2" color="#000000">boot</font><font size="2" color="#000000">扇区而</font><font face="MS Sans Serif" size="2" color="#000000">sections</font><font size="2" color="#000000">是各种文件,但我们仍缺乏足够信息来定位磁盘上的不同文件,譬如,什么是</font><font face="MS Sans Serif" size="2" color="#000000">PE</font><font size="2" color="#000000">文件格式中等价于目录的东东?别急,那就是
</font><font face="MS Sans Serif" size="2" color="#000000">PE header </font><font size="2" color="#000000">接下来的数组结构<b>
</b></font><font color="#000000" face="MS Sans Serif" size="2"><b>section table</b></font><font color="#000000" size="2"><b>(节表)。
</b>每个结构包含对应节的属性、文件偏移量、虚拟偏移量等。如果</font><font face="MS Sans Serif" size="2" color="#000000">PE</font><font size="2" color="#000000">文件里有</font><font face="MS Sans Serif" size="2" color="#000000">5</font><font size="2" color="#000000">个节,那么此结构数组内就有</font><font face="MS Sans Serif" size="2" color="#000000">5</font><font size="2" color="#000000">个成员。因此,我们便可以把节表视为逻辑磁盘中的根目录,每个数组成员等价于根目录中目录项。</font></p>
<p><font size="2" color="#000000">以上就是</font><font face="MS Sans Serif" size="2" color="#000000">PE</font><font size="2" color="#000000">文件格式的物理分布,下面将总结一下装载一</font><font face="MS Sans Serif" size="2" color="#000000">PE</font><font size="2" color="#000000">文件的主要步骤</font><font face="MS Sans Serif" size="2" color="#000000">:</font></p>
<ol>
<li><font size="2" color="#000000">当</font><font face="MS Sans Serif" size="2" color="#000000">PE</font><font size="2" color="#000000">文件被执行,</font><font face="MS Sans Serif" size="2" color="#000000">PE</font><font size="2" color="#000000">装载器检查
</font><font face="MS Sans Serif" size="2" color="#000000">DOS MZ header </font><font size="2" color="#000000">里的
</font><font face="MS Sans Serif" size="2" color="#000000">PE header </font><font size="2" color="#000000">偏移量。如果找到,则跳转到
</font><font face="MS Sans Serif" size="2" color="#000000">PE header</font><font size="2" color="#000000">。</font>
<li><font face="MS Sans Serif" size="2" color="#000000">PE</font><font size="2" color="#000000">装载器检查
</font><font face="MS Sans Serif" size="2" color="#000000">PE header </font><font size="2" color="#000000">的有效性。如果有效,就跳转到</font><font face="MS Sans Serif" size="2" color="#000000">PE
header</font><font size="2" color="#000000">的尾部。</font>
<li><font size="2" color="#000000">紧跟 </font><font face="MS Sans Serif" size="2" color="#000000">PE
header </font><font size="2" color="#000000">的是节表。</font><font face="MS Sans Serif" size="2" color="#000000">PE</font><font size="2" color="#000000">装载器读取其中的节信息,并采用文件映射方法将这些节映射到内存,同时付上节表里指定的节属性。</font>
<li><font face="MS Sans Serif" size="2" color="#000000">PE</font><font size="2" color="#000000">文件映射入内存后,</font><font face="MS Sans Serif" size="2" color="#000000">PE</font><font size="2" color="#000000">装载器将处理</font><font face="MS Sans Serif" size="2" color="#000000">PE</font><font size="2" color="#000000">文件中类似
</font><font face="MS Sans Serif" size="2" color="#000000">import table</font><font size="2" color="#000000">(引入表)逻辑部分。</font>
</li>
</ol>
<p><font size="2" color="#000000">上述步骤是基于本人观察后的简述,显然还有一些不够精确的地方,但基本明晰了执行体被处理的过程。</font></p>
<p><font size="2" color="#000000">你应该下载 </font><font color="#000000"><a
href="technology/pe1.zip"
style="TEXT-DECORATION: none"><font face="MS Sans Serif"
size=2><b>LUEVELSMEYER</b></font><font size=2><b>的《</b></font><font
face="MS Sans Serif" size=2><b>PE</b></font><font
size=2><b>文件格式》</b></font></a><font size=2><b>。</b> 该文的描述相当详细,可用作案头的参考手册。</font></font></p>
<p align=center><font size="2" color="#000000"><b>翻译:</b></font><font face="MS Sans Serif" size="2" color="#000000"><b>iamgufeng
[</b></font><font color="#000000"><a href="http://win32asm.cjb.net/" target="_blank"><font
face="MS Sans Serif" size=2><b>Iczelion's Win32 Assembly Homepage</b></font></a><font face="MS Sans Serif"
size=2><b>]</b><strong>[</strong></font><a href="http://asm.yeah.net/" target="_blank"><font
face="MS Sans Serif" size=2><strong>LuoYunBin's Win32 ASM Page</strong></font></a><font face="MS Sans Serif"
size=2><strong>]</strong></font></font> </p>
<p align="center"><a href="../Catalog.htm"><img src="../image/navtoc.gif" width="84" height="23" border="0"></a><a href="Chap8-1.htm"><img src="../image/Navprev.gif" width="80" height="23" border="0"></a><a href="Chap8-1-2.htm"><img src="../image/navnext.gif" width="83" height="23" border="0"></a></p>
<hr width=735>
<div align="center"><span class="p9"><font size="2"><span class="p9"><font size="2"><span class="p9">Copyright
© 2000-2001 <a href="http://www.pediy.com/">KanXue Studio</a> All Rights
Reserved.</span></font></span></font></span></div>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -