⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lion-petut-c02.htm

📁 在DOS下编程因为实模式的限制
💻 HTM
📖 第 1 页 / 共 2 页
字号:
<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: 检验PE文件的有效性</title>
</head>

<body bgcolor="#000066" text="#FFFFFF" link="#FFFFCC"
vlink="#FFCCCC" alink="#CCFFCC">

<h1 align="center"><font color="#FFFFCC">PE教程2: 检验PE文件的有效性</font></h1>

<p><font size="2">本教程中我们将学习如何检测给定文件是一有效</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">如何才能校验指定文件是否为一有效</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">PE</font><font size="2">文件格式里的各个数据结构,或者仅校验一些关键数据结构。大多数情况下,没有必要校验文件里的每一个数据结构,只要一些关键数据结构有效,我们就认为是有效的</font><font
size="2" face="MS Sans Serif">PE</font><font size="2">文件了。下面我们就来实现前面的假设。</font></p>

<p><font size="2">我们要验证的重要数据结构就是 </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">实际就是一个
</font><font size="2" face="MS Sans Serif">IMAGE_NT_HEADERS </font><font
size="2">结构。定义如下</font><font size="2"
face="MS Sans Serif">:</font></p>

<p><font size="2" face="MS Sans Serif"><b>IMAGE_NT_HEADERS STRUCT
<br>
&nbsp;&nbsp;&nbsp;Signature dd ? <br>
&nbsp;&nbsp;&nbsp;FileHeader IMAGE_FILE_HEADER <> <br>
&nbsp;&nbsp;&nbsp;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">本域为</font><font size="2" face="MS Sans Serif">PE</font><font
size="2">标记,我们可以此识别给定文件是否为有效</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">该结构域包含了关于</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"><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">该结构域包含了关于</font><font
size="2" face="MS Sans Serif">PE</font><font size="2">文件逻辑分布的信息,虽然域名有</font><font
size="2" face="MS Sans Serif">&quot;</font><font size="2">可选</font><font
size="2" face="MS Sans Serif">&quot;</font><font size="2">字样,但实际上本结构总是存在的。</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">&quot;PE\0\0&quot;</font><font
size="2">,那么就是有效的</font><font size="2"
face="MS Sans Serif">PE</font><font size="2">文件。实际上,为了比较方便,</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">接下来的问题是</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">答案很简单</font><font
size="2" face="MS Sans Serif">: DOS MZ header </font><font
size="2">已经包含了指向 </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">又定义成结构</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">结构的</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">现在将所有步骤总结如下</font><font
size="2" face="MS Sans Serif">:</font></p>

<ol>
    <li><font size="2">首先检验文件头部第一个字的值是否等于
        </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">来定位
        </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">的第一个字的值是否等于</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">。如果前后两个值都匹配,那我们就认为该文件是一个有效的</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 ? &nbsp;&nbsp;&nbsp;; the address of the previous seh
structure <br>
CurrentHandler dd ?&nbsp;&nbsp;&nbsp; ; the address of the
exception handler <br>
SafeOffset dd ? &nbsp;&nbsp;&nbsp;; The offset where it's safe to
continue execution <br>
PrevEsp dd ? &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; the old value in esp
<br>
PrevEbp dd ? &nbsp;&nbsp;&nbsp;&nbsp;; The old value in ebp <br>
SEH ends<br>
<br>
.data <br>
AppName db &quot;PE tutorial no.2&quot;,0 <br>
ofn OPENFILENAME <> <br>
FilterString db &quot;Executable Files (*.exe,
*.dll)&quot;,0,&quot;*.exe;*.dll&quot;,0 <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
db &quot;All Files&quot;,0,&quot;*.*&quot;,0,0 <br>
FileOpenError db &quot;Cannot open the file for reading&quot;,0 <br>
FileOpenMappingError db &quot;Cannot open the file for memory
mapping&quot;,0 <br>
FileMappingError db &quot;Cannot map the file into memory&quot;,0
<br>
FileValidPE db &quot;This file is a valid PE&quot;,0 <br>
FileInValidPE db &quot;This file is not a valid PE&quot;,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>
&nbsp;&nbsp;&nbsp; invoke CreateFile, addr buffer, GENERIC_READ,
FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL
<br>
&nbsp;&nbsp;&nbsp; .if eax!=INVALID_HANDLE_VALUE <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov hFile, eax <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invoke CreateFileMapping,
hFile, NULL, PAGE_READONLY,0,0,0 <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .if eax!=NULL <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov
hMapping, eax <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invoke
MapViewOfFile,hMapping,FILE_MAP_READ,0,0,0 <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .if
eax!=NULL <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
mov pMapping,eax <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
assume fs:nothing <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
push fs:[0] <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
pop seh.PrevLink <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
mov seh.CurrentHandler,offset SEHHandler <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
mov seh.SafeOffset,offset FinalExit <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
lea eax,seh <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
mov fs:[0], eax <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
mov seh.PrevEsp,esp <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
mov seh.PrevEbp,ebp <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
mov edi, pMapping <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
assume edi:ptr IMAGE_DOS_HEADER <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
.if [edi].e_magic==IMAGE_DOS_SIGNATURE <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
add edi, [edi].e_lfanew <br>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -