?? pe-tut1.html
字號:
<html>
<head>
<title>Iczelion's PE Tutorial 1: Overview of PE File Format</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body bgcolor="#000066" text="#FFFFFF" link="#FFFFCC" vlink="#FFCCCC" alink="#CCFFCC">
<h1 align="center"><font face="Arial, Helvetica, sans-serif" color="#FFFFCC">Tutorial
1: Overview of PE file format</font></h1>
<p><font face="MS Sans Serif" size="-1">This is the complete rewrite of the old
PE tutorial no1 which I considered the worst tutorial I have ever written. So
I decided to replace it with this new one.</font></p>
<p><font face="MS Sans Serif" size="-1">PE stands for Portable Executable. It's
the native file format of Win32. Its specification is derived somewhat from
the Unix Coff (common object file format). The meaning of "portable executable"
is that the file format is universal across win32 platform: the PE loader of
every win32 platform recognizes and uses this file format even when Windows
is running on CPU platforms other than Intel. It doesn't mean your PE executables
would be able to port to other CPU platforms without change. Every win32 executable
(except VxDs and 16-bit Dlls) uses PE file format. Even NT's kernel mode drivers
use PE file format. Thus studying the PE file format gives you valuable insights
into the structure of Windows.</font></p>
<p><font face="MS Sans Serif" size="-1">Let's jump into the general outline of
PE file format without further ado.</font></p>
<table border="1" cellspacing="2" cellpadding="2" align="center">
<tr bgcolor="#0033CC">
<td>
<div align="center"><b><font face="MS Sans Serif" size="-1">DOS MZ header</font></b></div>
</td>
</tr>
<tr bgcolor="#990000">
<td height="28">
<div align="center"><b><font face="MS Sans Serif" size="-1">DOS stub</font></b></div>
</td>
</tr>
<tr bgcolor="#006600">
<td height="36">
<div align="center"><b><font face="MS Sans Serif" size="-1">PE header</font></b></div>
</td>
</tr>
<tr bgcolor="#333399">
<td>
<div align="center"><b><font face="MS Sans Serif" size="-1">Section table</font></b></div>
</td>
</tr>
<tr bgcolor="#660066">
<td height="52">
<div align="center"><b><font face="MS Sans Serif" size="-1">Section 1</font></b></div>
</td>
</tr>
<tr bgcolor="#660066">
<td height="55">
<div align="center"><b><font face="MS Sans Serif" size="-1">Section 2</font></b></div>
</td>
</tr>
<tr bgcolor="#660066">
<td height="53">
<div align="center"><b><font face="MS Sans Serif" size="-1">Section ...</font></b></div>
</td>
</tr>
<tr bgcolor="#660066">
<td height="50">
<div align="center"><b><font face="MS Sans Serif" size="-1">Section n</font></b></div>
</td>
</tr>
</table>
<p><font face="MS Sans Serif" size="-1">The above picture is the general layout
of a PE file. All PE files (even 32-bit DLLs) must start with a simple DOS MZ
header. We usually aren't interested in this structure much. It's provided in
the case when the program is run from DOS, so DOS can recognize it as a valid
executable and can thus run the DOS stub which is stored next to the MZ header.
The DOS stub is actually a valid EXE that is executed in case the operating
system doesn't know about PE file format. It can simply display a string like
"This program requires Windows" or it can be a full-blown DOS program
depending on the intent of the programmer. We are also not very interested in
DOS stub: it's usually provided by the assembler/compiler. In most case, it
simply uses int 21h, service 9 to print a string saying "This program cannot
run in DOS mode". </font></p>
<p><font face="MS Sans Serif" size="-1">After the DOS stub comes<font color="#FFFFCC"><b>
the PE header</b></font>. The PE header is a general term for the PE-related
structure named<font color="#FFFFCC"><b> IMAGE_NT_HEADERS</b></font>. This structure
contains many essential fields that are used by the PE loader. We will be quite
familiar with it as you know more about PE file format. In the case the program
is executed in the operating system that knows about PE file format, the PE
loader can find the starting offset of the PE header from the DOS MZ header.
Thus it can skip the DOS stub and go directly to the PE header which is the
real file header. </font></p>
<p><font face="MS Sans Serif" size="-1">The real content of the PE file is divided
into blocks called <font color="#FFFFCC"><b>sections</b></font>. A section is
nothing more than a block of data with common attributes such as code/data,
read/write etc. You can think of a PE file as a logical disk. The PE header
is the boot sector and the sections are files in the disk. The files can have
different attributes such as read-only, system, hidden, archive and so on.<font color="#66FF00"><b>
I want to make it clear from this point onwards that the grouping of data into
a section is done on the common attribute basis: not on logical basis.</b></font>
It doesn't matter how the code/data are used , if the data/code in the PE file
have the same attribute, they can be lumped together in a section. You should
not think of a section as "data", "code" or some other logical
concepts: sections can contain both code and data provided that they have the
same attribute. If you have a block of data that you want to be read-only, you
can put that data in the section that is marked as read-only. When the PE loader
maps the sections into memory, it examines the attributes of the sections and
gives the memory block occupied by the sections the indicated attributes.</font></p>
<p><font face="MS Sans Serif" size="-1">If we view the PE file format as a logical
disk, the PE header as the boot sector and the sections as files, we still don't
have enough information to find out where the files reside on the disk, ie.
we haven't discussed the directory equivalent of the PE file format. Immediately
following the PE header is <font color="#FFFFCC"> <b>the section table </b></font>which
is an array of structures. Each structure contains the information about each
section in the PE file such as its attribute, the file offset, virtual offset.
If there are 5 sections in the PE file, there will be exactly 5 members in this
structure array. We can then view the section table as the root directory of
the logical disk. Each member of the array is equvalent to the each directory
entry in the root directory.</font></p>
<p><font face="MS Sans Serif" size="-1">That's all about the physical layout of
the PE file format. I'll summarize the major steps in loading a PE file into
memory below:</font></p>
<ol>
<li><font face="MS Sans Serif" size="-1">When the PE file is run, the PE loader
examines the DOS MZ header for the offset of the PE header. If found, it skips
to the PE header.</font></li>
<li><font face="MS Sans Serif" size="-1">The PE loader checks if the PE header
is valid. If so, it goes to the end of the PE header.</font></li>
<li><font face="MS Sans Serif" size="-1">Immediately following the PE header
is the section table. The PE header reads information about the sections and
maps those sections into memory using file mapping. It also gives each section
the attributes as specified in the section table.</font></li>
<li><font face="MS Sans Serif" size="-1">After the PE file is mapped into memory,
the PE loader concerns itself with the logical parts of the PE file, such
as the import table.</font></li>
</ol>
<p><font face="MS Sans Serif" size="-1">The above steps are oversimplification
and are based on my own observation. There may be some inaccuracies but it should
give you the clear picture of the process.</font></p>
<p><font face="MS Sans Serif" size="-1">You should download <b><a href="files/pe1.zip" style="text-decoration:none">LUEVELSMEYER's
description about PE file format.</a></b> It's very detailed and you should
keep it as a reference.</font></p>
<hr>
<p align="center"><b><font face="MS Sans Serif" size="-1">[<a href="http://win32asm.cjb.net">Iczelion's
Win32 Assembly Homepage</a>]</font></b></p>
<p> </p>
</body>
</html>
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -