?? lion-petut-c02.htm
字號(hào):
<html>
<head>
<meta http-equiv="Content-Type"
content="text/html; charset=gb_2312-80">
<meta name="GENERATOR" content="Microsoft FrontPage Express 2.0">
<title>PE教程2: 檢驗(yàn)PE文件的有效性</title>
</head>
<body bgcolor="#000066" text="#FFFFFF" link="#FFFFCC"
vlink="#FFCCCC" alink="#CCFFCC">
<h1 align="center"><font color="#FFFFCC">PE教程2: 檢驗(yàn)PE文件的有效性</font></h1>
<p><font size="2">本教程中我們將學(xué)習(xí)如何檢測(cè)給定文件是一有效</font><font
size="2" face="MS Sans Serif">PE</font><font size="2">文件。<br>
下載 </font><a href="files/PE-tut02.zip"><font size="2">范例</font></a></p>
<h3>理論<font face="Arial, Helvetica, sans-serif">:</font></h3>
<p><font size="2">如何才能校驗(yàn)指定文件是否為一有效</font><font
size="2" face="MS Sans Serif">PE</font><font size="2">文件呢</font><font
size="2" face="MS Sans Serif">? </font><font size="2">這個(gè)問(wèn)題很難回答,完全取決于想要的精準(zhǔn)程度。您可以檢驗(yàn)</font><font
size="2" face="MS Sans Serif">PE</font><font size="2">文件格式里的各個(gè)數(shù)據(jù)結(jié)構(gòu),或者僅校驗(yàn)一些關(guān)鍵數(shù)據(jù)結(jié)構(gòu)。大多數(shù)情況下,沒(méi)有必要校驗(yàn)文件里的每一個(gè)數(shù)據(jù)結(jié)構(gòu),只要一些關(guān)鍵數(shù)據(jù)結(jié)構(gòu)有效,我們就認(rèn)為是有效的</font><font
size="2" face="MS Sans Serif">PE</font><font size="2">文件了。下面我們就來(lái)實(shí)現(xiàn)前面的假設(shè)。</font></p>
<p><font size="2">我們要驗(yàn)證的重要數(shù)據(jù)結(jié)構(gòu)就是 </font><font
size="2" face="MS Sans Serif">PE header</font><font size="2">。從編程角度看,</font><font
size="2" face="MS Sans Serif">PE header </font><font size="2">實(shí)際就是一個(gè)
</font><font size="2" face="MS Sans Serif">IMAGE_NT_HEADERS </font><font
size="2">結(jié)構(gòu)。定義如下</font><font size="2"
face="MS Sans Serif">:</font></p>
<p><font size="2" face="MS Sans Serif"><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 color="#FFFFCC" size="2" face="MS Sans Serif"><b>Signature</b></font><font
size="2" face="MS Sans Serif"> </font><font size="2">一</font><font
size="2" face="MS Sans Serif">dword</font><font size="2">類型,值為</font><font
size="2" face="MS Sans Serif">50h, 45h, 00h, 00h</font><font
size="2">(</font><font size="2" face="MS Sans Serif">PE\0\0</font><font
size="2">)。</font><font size="2" face="MS Sans Serif"> </font><font
size="2">本域?yàn)?lt;/font><font size="2" face="MS Sans Serif">PE</font><font
size="2">標(biāo)記,我們可以此識(shí)別給定文件是否為有效</font><font
size="2" face="MS Sans Serif">PE</font><font size="2">文件。</font><br>
<font color="#FFFFCC" size="2" face="MS Sans Serif"><b>FileHeader
</b></font><font size="2">該結(jié)構(gòu)域包含了關(guān)于</font><font
size="2" face="MS Sans Serif">PE</font><font size="2">文件物理分布的信息,</font><font
size="2" face="MS Sans Serif"> </font><font size="2">比如節(jié)數(shù)目、文件執(zhí)行機(jī)器等。</font><font
size="2" face="MS Sans Serif"><br>
</font><font color="#FFFFCC" size="2" face="MS Sans Serif"><b>OptionalHeader</b></font><font
size="2" face="MS Sans Serif"> </font><font size="2">該結(jié)構(gòu)域包含了關(guān)于</font><font
size="2" face="MS Sans Serif">PE</font><font size="2">文件邏輯分布的信息,雖然域名有</font><font
size="2" face="MS Sans Serif">"</font><font size="2">可選</font><font
size="2" face="MS Sans Serif">"</font><font size="2">字樣,但實(shí)際上本結(jié)構(gòu)總是存在的。</font></p>
<p><font size="2">我們目的很明確。如果</font><font
color="#CCFFCC" size="2" face="MS Sans Serif"><b>IMAGE_NT_HEADERS</b></font><font
size="2">的</font><font size="2" face="MS Sans Serif">signature</font><font
size="2">域值等于</font><font size="2" face="MS Sans Serif">"PE\0\0"</font><font
size="2">,那么就是有效的</font><font size="2"
face="MS Sans Serif">PE</font><font size="2">文件。實(shí)際上,為了比較方便,</font><font
size="2" face="MS Sans Serif">Microsoft</font><font size="2">已定義了常量</font><font
color="#CCFFCC" size="2" face="MS Sans Serif"><b>IMAGE_NT_SIGNATURE</b></font><font
size="2">供我們使用。</font></p>
<p><font color="#FFCCFF" size="2" face="MS Sans Serif"><b>IMAGE_DOS_SIGNATURE
equ 5A4Dh </b></font><font size="2" face="MS Sans Serif"><b><br>
IMAGE_OS2_SIGNATURE equ 454Eh <br>
IMAGE_OS2_SIGNATURE_LE equ 454Ch <br>
IMAGE_VXD_SIGNATURE equ 454Ch <br>
</b></font><font color="#FFCCFF" size="2" face="MS Sans Serif"><b>IMAGE_NT_SIGNATURE
equ 4550h </b></font></p>
<p><font size="2">接下來(lái)的問(wèn)題是</font><font size="2"
face="MS Sans Serif">: </font><font size="2">如何定位 </font><font
size="2" face="MS Sans Serif">PE header? </font><font size="2">答案很簡(jiǎn)單</font><font
size="2" face="MS Sans Serif">: DOS MZ header </font><font
size="2">已經(jīng)包含了指向 </font><font size="2"
face="MS Sans Serif">PE header </font><font size="2">的文件偏移量。</font><font
size="2" face="MS Sans Serif">DOS MZ header </font><font size="2">又定義成結(jié)構(gòu)</font><font
color="#CCFFCC" size="2"><b> </b></font><font color="#CCFFCC"
size="2" face="MS Sans Serif"><b>IMAGE_DOS_HEADER</b></font><font
size="2" face="MS Sans Serif"> </font><font size="2">。查詢</font><font
size="2" face="MS Sans Serif">windows.inc</font><font size="2">,我們知道
</font><font color="#CCFFCC" size="2" face="MS Sans Serif"><b>IMAGE_DOS_HEADER</b></font><font
size="2" face="MS Sans Serif"> </font><font size="2">結(jié)構(gòu)的</font><font
color="#CC9900" size="2" face="MS Sans Serif"><b>e_lfanew</b></font><font
size="2">成員就是指向 </font><font size="2"
face="MS Sans Serif">PE header </font><font size="2">的文件偏移量。
</font></p>
<p><font size="2">現(xiàn)在將所有步驟總結(jié)如下</font><font
size="2" face="MS Sans Serif">:</font></p>
<ol>
<li><font size="2">首先檢驗(yàn)文件頭部第一個(gè)字的值是否等于
</font><font color="#CCFFCC" size="2"
face="MS Sans Serif"><b>IMAGE_DOS_SIGNATURE</b></font><font
color="#CCFFCC" size="2"><b>,</b></font><font size="2">是則
</font><font size="2" face="MS Sans Serif">DOS MZ header </font><font
size="2">有效。</font></li>
<li><font size="2">一旦證明文件的 </font><font
size="2" face="MS Sans Serif">DOS header </font><font
size="2">有效后,就可用</font><font size="2"
face="MS Sans Serif">e_lfanew</font><font size="2">來(lái)定位
</font><font size="2" face="MS Sans Serif">PE header </font><font
size="2">了。</font></li>
<li><font size="2">比較 </font><font size="2"
face="MS Sans Serif">PE header </font><font size="2">的第一個(gè)字的值是否等于</font><font
color="#CCFFCC" size="2"><b> </b></font><font
color="#CCFFCC" size="2" face="MS Sans Serif"><b>IMAGE_NT_HEADER</b></font><font
size="2">。如果前后兩個(gè)值都匹配,那我們就認(rèn)為該文件是一個(gè)有效的</font><font
size="2" face="MS Sans Serif">PE</font><font size="2">文件。</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>
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -