?? pe-tut2.html
字號:
<html>
<head>
<title>Iczelion's PE Tutorial 2: Detecting a Valid PE File</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
2: Detecting a Valid PE File</font></h1>
<p><font face="MS Sans Serif" size="-1">In this tutorial, we will learn how to
check if a given file is a valid PE file.<br>
Download <b><a href="files/PE-tut02.zip" style="text-decoration:none">the example</a></b>.</font></p>
<h3><font face="Arial, Helvetica, sans-serif">Theory:</font></h3>
<p><font face="MS Sans Serif" size="-1">How can you verify if a given file is
a PE file? That question is difficult to answer. That depends on the length
that you want to go to do that. You can verify every data structure defined
in the PE file format or you are satisfied with verifying only the crucial ones.
Most of the time, it's pretty pointless to verify every single structure in
the files. If the crucial structures are valid, we can assume that the file
is a valid PE. And we will use that assumption.</font></p>
<p><font face="MS Sans Serif" size="-1">The essential structure we will verify
is the PE header itself. So we need to know a little about it, programmatically.
The PE header is actually a structure called IMAGE_NT_HEADERS. It has the following
definition:</font></p>
<p><font face="MS Sans Serif" size="-1"><b>IMAGE_NT_HEADERS STRUCT <br>
Signature dd ? <br>
FileHeader IMAGE_FILE_HEADER <> <br>
OptionalHeader IMAGE_OPTIONAL_HEADER32 <> <br>
IMAGE_NT_HEADERS ENDS </b></font></p>
<p><font face="MS Sans Serif" size="-1"><b><font color="#FFFFCC">Signature</font></b>
is a dword that contains the value 50h, 45h, 00h, 00h. In more human term, it
contains the text "PE" followed by two terminating zeroes. This member
is the PE signature so we will use it in verifying if a given file is a valid
PE one.</font><br>
<font face="MS Sans Serif" size="-1"><b><font color="#FFFFCC">FileHeader </font></b>is
a structure that contains information about the physical layout of the PE file
such as the number of sections, the machine the file is targeted and so on.<br>
<font color="#FFFFCC"><b>OptionalHeader</b></font> is a structure that contains
information about the logical layout of the PE file. Despite the "Optional"
in its name, it's always present.</font></p>
<p><font face="MS Sans Serif" size="-1">Our goal is now clear. If value of the
signature member of the<font color="#CCFFCC"><b> IMAGE_NT_HEADERS</b></font>
is equal to "PE" followed by two zeroes, then the file is a valid
PE. In fact, for comparison purpose, Microsoft has defined a constant named
<font color="#CCFFCC"> <b>IMAGE_NT_SIGNATURE</b></font> which we can readily
use.</font></p>
<p><font face="MS Sans Serif" size="-1"><b><font color="#FFCCFF">IMAGE_DOS_SIGNATURE
equ 5A4Dh </font><br>
IMAGE_OS2_SIGNATURE equ 454Eh <br>
IMAGE_OS2_SIGNATURE_LE equ 454Ch <br>
IMAGE_VXD_SIGNATURE equ 454Ch <br>
<font color="#FFCCFF">IMAGE_NT_SIGNATURE equ 4550h </font></b></font></p>
<p><font face="MS Sans Serif" size="-1"> The next question: how can we know where
the PE header is? The answer is simple: the DOS MZ header contains the file
offset of the PE header. The DOS MZ header is defined as<font color="#CCFFCC"><b>
IMAGE_DOS_HEADER</b></font> structure. You can check it out in windows.inc.
The <font color="#CC9900"><b>e_lfanew</b></font> member of the <font color="#CCFFCC"><b>IMAGE_DOS_HEADER</b></font>
structure contains the file offset of the PE header. </font></p>
<p><font face="MS Sans Serif" size="-1">The steps are now as follows:</font></p>
<ol>
<li><font face="MS Sans Serif" size="-1">Verify if the given file has a valid
DOS MZ header by comparing the first word of the file with the value <font color="#CCFFCC"><b>IMAGE_DOS_SIGNATURE</b></font>.</font></li>
<li><font face="MS Sans Serif" size="-1">If the file has a valid DOS header,
use the value in e_lfanew member to find the PE header</font></li>
<li><font face="MS Sans Serif" size="-1">Comparing the first word of the PE
header with the value<font color="#CCFFCC"><b> IMAGE_NT_HEADER</b></font>.
If both values match, then we can assume that the file is a valid PE.</font></li>
</ol>
<h3><font face="Arial, Helvetica, sans-serif">Example:</font></h3>
<p><font face="Fixedsys">.386 <br>
.model flat,stdcall <br>
option casemap:none <br>
include \masm32\include\windows.inc <br>
include \masm32\include\kernel32.inc <br>
include \masm32\include\comdlg32.inc <br>
include \masm32\include\user32.inc <br>
includelib \masm32\lib\user32.lib <br>
includelib \masm32\lib\kernel32.lib <br>
includelib \masm32\lib\comdlg32.lib <br>
<br>
SEH struct <br>
PrevLink dd ? ; the address of the previous seh structure
<br>
CurrentHandler dd ? ; the address of the exception handler
<br>
SafeOffset dd ? ; The offset where it's safe to continue execution
<br>
PrevEsp dd ? ; the old value in esp <br>
PrevEbp dd ? ; The old value in ebp <br>
SEH ends<br>
<br>
.data <br>
AppName db "PE tutorial no.2",0 <br>
ofn OPENFILENAME <> <br>
FilterString db "Executable Files (*.exe, *.dll)",0,"*.exe;*.dll",0 <br>
db "All Files",0,"*.*",0,0 <br>
FileOpenError db "Cannot open the file for reading",0 <br>
FileOpenMappingError db "Cannot open the file for memory mapping",0 <br>
FileMappingError db "Cannot map the file into memory",0 <br>
FileValidPE db "This file is a valid PE",0 <br>
FileInValidPE db "This file is not a valid PE",0 <br>
<br>
.data? <br>
buffer db 512 dup(?) <br>
hFile dd ? <br>
hMapping dd ? <br>
pMapping dd ? <br>
ValidPE dd ? <br>
<br>
.code <br>
start proc <br>
LOCAL seh:SEH <br>
mov ofn.lStructSize,SIZEOF ofn <br>
mov ofn.lpstrFilter, OFFSET FilterString <br>
mov ofn.lpstrFile, OFFSET buffer <br>
mov ofn.nMaxFile,512 <br>
mov ofn.Flags, OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST or OFN_LONGNAMES or OFN_EXPLORER
or OFN_HIDEREADONLY <br>
invoke GetOpenFileName, ADDR ofn <br>
.if eax==TRUE <br>
invoke CreateFile, addr buffer, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL <br>
.if eax!=INVALID_HANDLE_VALUE <br>
mov hFile, eax <br>
invoke CreateFileMapping, hFile, NULL,
PAGE_READONLY,0,0,0 <br>
.if eax!=NULL <br>
mov hMapping, eax <br>
invoke MapViewOfFile,hMapping,FILE_MAP_READ,0,0,0
<br>
.if eax!=NULL <br>
mov
pMapping,eax <br>
assume
fs:nothing <br>
push
fs:[0] <br>
pop
seh.PrevLink <br>
mov
seh.CurrentHandler,offset SEHHandler <br>
mov
seh.SafeOffset,offset FinalExit <br>
lea
eax,seh <br>
mov
fs:[0], eax <br>
mov
seh.PrevEsp,esp <br>
mov
seh.PrevEbp,ebp <br>
mov
edi, pMapping <br>
assume
edi:ptr IMAGE_DOS_HEADER <br>
.if
[edi].e_magic==IMAGE_DOS_SIGNATURE <br>
add edi, [edi].e_lfanew <br>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -