检验PE文件的有效性
理论 :
如何才能校验指定文件是否为一有效 PE 文件呢 ? 这个问题很难回答,完全取决于想要的精准程度。您可以检验 PE 文件格式里的各个数据结构,或者仅校验一些关键数据结构。大多数情况下,没有必要校验文件里的每一个数据结构,只要一些关键数据结构有效,我们就认为是有效的 PE 文件了。下面我们就来实现前面的假设。
我们要验证的重要数据结构就是 PE header 。从编程角度看, PE header 实际就是一个 IMAGE_NT_HEADERS 结构。定义如下 :
Signature 一 dword 类型,值为 50h, 45h, 00h, 00h ( PE )。 本域为 PE 标记,我们可以此识别给定文件是否为有效 PE 文件。
FileHeader 该结构域包含了关于 PE 文件物理分布的信息, 比如节数目、文件执行机器等。
OptionalHeader 该结构域包含了关于 PE 文件逻辑分布的信息,虽然域名有 " 可选 " 字样,但实际上本结构总是存在的。
我们目的很明确。如果 IMAGE_NT_HEADERS 的 signature 域值等于 "PE" ,那么就是有效的 PE 文件。实际上,为了比较方便, Microsoft 已定义了常量 IMAGE_NT_SIGNATURE 供我们使用。
接下来的问题是 : 如何定位 PE header? 答案很简单 : DOS MZ header 已经包含了指向 PE header 的文件偏移量。 DOS MZ header 又定义成结构 IMAGE_DOS_HEADER 。查询 windows.inc ,我们知道 IMAGE_DOS_HEADER 结构的 e_lfanew 成员就是指向 PE header 的文件偏移量。
现在将所有步骤总结如下 :
首先检验文件头部第一个字的值是否等于 IMAGE_DOS_SIGNATURE , 是则 DOS MZ header 有效。 一旦证明文件的 DOS header 有效后,就可用 e_lfanew 来定位 PE header 了。 比较 PE header 的第一个字的值是否等于 IMAGE_NT_HEADER 。如果前后两个值都匹配,那我们就认为该文件是一个有效的 PE 文件。 Example:
.386 .model flat,stdcall option casemap:none include masm32includewindows.inc include masm32includekernel32.inc include masm32includecomdlg32.inc include masm32includeuser32.inc includelib masm32libuser32.lib includelib masm32libkernel32.lib includelib masm32libcomdlg32.lib SEH struct PrevLink dd ? ; the address of the previous seh structure CurrentHandler dd ? ; the address of the exception handler SafeOffset dd ? ; The offset where it's safe to continue execution PrevEsp dd ? ; the old value in esp PrevEbp dd ? ; The old value in ebp SEH ends .data AppName db "PE tutorial no.2",0 ofn OPENFILENAME <> FilterString db "Executable Files (*.exe, *.dll)",0,"*.exe;*.dll",0 db "All Files",0,"*.*",0,0 FileOpenError db "Cannot open the file for reading",0 FileOpenMappingError db "Cannot open the file for memory mapping",0 FileMappingError db "Cannot map the file into memory",0 FileValidPE db "This file is a valid PE",0 FileInValidPE db "This file is not a valid PE",0 .data? buffer db 512 dup(?) hFile dd ? hMapping dd ? pMapping dd ? ValidPE dd ? .code start proc LOCAL seh:SEH mov ofn.lStructSize,SIZEOF ofn mov ofn.lpstrFilter, OFFSET FilterString mov ofn.lpstrFile, OFFSET buffer mov ofn.nMaxFile,512 mov ofn.Flags, OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST or OFN_LONGNAMES or OFN_EXPLORER or OFN_HIDEREADONLY invoke GetOpenFileName, ADDR ofn .if eax==TRUE invoke CreateFile, addr buffer, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL .if eax!=INVALID_HANDLE_VALUE mov hFile, eax invoke CreateFileMapping, hFile, NULL, PAGE_READONLY,0,0,0 .if eax!=NULL mov hMapping, eax invoke MapViewOfFile,hMapping,FILE_MAP_READ,0,0,0 .if eax!=NULL mov pMapping,eax assume fs:nothing push fs:[0] pop seh.PrevLink mov seh.CurrentHandler,offset SEHHandler mov seh.SafeOffset,offset FinalExit lea eax,seh mov fs:[0], eax mov seh.PrevEsp,esp mov seh.PrevEbp,ebp mov edi, pMapping assume edi:ptr IMAGE_DOS_HEADER .if [edi].e_magic==IMAGE_DOS_SIGNATURE add edi, [edi].e_lfanew assume edi:ptr IMAGE_NT_HEADERS .if [edi].Signature==IMAGE_NT_SIGNATURE mov ValidPE, TRUE .else mov ValidPE, FALSE .endif .else mov ValidPE,FALSE .endif FinalExit: .if ValidPE==TRUE invoke MessageBox, 0, addr FileValidPE, addr AppName, MB_OK+MB_ICONINFORMATION .else invoke MessageBox, 0, addr FileInValidPE, addr AppName, MB_OK+MB_ICONINFORMATION .endif push seh.PrevLink pop fs:[0] invoke UnmapViewOfFile, pMapping .else invoke MessageBox, 0, addr FileMappingError, addr AppName, MB_OK+MB_ICONERROR .endif invoke CloseHandle,hMapping .else invoke MessageBox, 0, addr FileOpenMappingError, addr AppName, MB_OK+MB_ICONERROR .endif invoke CloseHandle, hFile .else invoke MessageBox, 0, addr FileOpenError, addr AppName, MB_OK+MB_ICONERROR .endif .endif invoke ExitProcess, 0 start endp SEHHandler proc uses edx pExcept:DWORD, pFrame:DWORD, pContext:DWORD, pDispatch:DWORD mov edx,pFrame assume edx:ptr SEH mov eax,pContext assume eax:ptr CONTEXT push [edx].SafeOffset pop [eax].regEip push [edx].PrevEsp pop [eax].regEsp push [edx].PrevEbp pop [eax].regEbp mov ValidPE, FALSE mov eax,ExceptionContinueExecution ret SEHHandler endp end start
分析 :
本例程打开一文件,先检验 DOS header 是否有效,有效就接着检验 PE header 的有效性, ok 就认为是有效的 PE 文件了。这里,我们还运用了结构异常处理 (SEH) ,这样就不必检查每个可能的错误 : 如果有错误出现,就认为 PE 检测失效所致,于是给出我们的报错信息。其实 Windows 内部普遍使用 SEH 来检验参数传递的有效性。若对 SEH 感兴趣的话,可阅读 Jeremy Gordon 的 文章 。
程序调用打开文件通用对话框,用户选定执行文件后,程序便打开文件并映射到内存。并在有效性检验前建立一 SEH:
assume fs:nothing push fs:[0] pop seh.PrevLink mov seh.CurrentHandler,offset SEHHandler mov seh.SafeOffset,offset FinalExit lea eax,seh mov fs:[0], eax mov seh.PrevEsp,esp mov seh.PrevEbp,ebp
一开始就假设寄存器 fs 为空( assume fs:nothing )。 记住这一步不能省却,因为 MASM 假设 fs 寄存器为 ERROR 。接下来保存 Windows 使用的旧 SEH 处理函数地址到我们自己定义的结构中,同时保存我们的 SEH 处理函数地址和异常处理时的执行恢复地址,这样一旦错误发生就能由异常处理函数安全地恢复执行了。同时还保存当前 esp 及 ebp 的值,以便我们的 SEH 处理函数将堆栈恢复到正常状态。
mov edi, pMapping assume edi:ptr IMAGE_DOS_HEADER .if [edi].e_magic==IMAGE_DOS_SIGNATURE
成功建立 SEH 后继续校验工作。置目标文件的首字节地址给 edi ,使其指向 DOS header 的首字节。为便于比较,我们告诉编译器可以假定 edi 正指向 IMAGE_DOS_HEADER 结构 ( 事实亦是如此 ) 。然后比较 DOS header 的首字是否等于字符串 "MZ" ,这里利用了 windows.inc 中定义的 IMAGE_DOS_SIGNATURE 常量。若比较成功,继续转到 PE header ,否则设 ValidPE 值为 FALSE ,意味着文件不是有效 PE 文件。
add edi, [edi].e_lfanew assume edi:ptr IMAGE_NT_HEADERS .if [edi].Signature==IMAGE_NT_SIGNATURE mov ValidPE, TRUE .else mov ValidPE, FALSE .endif
要定位到 PE header ,需要读取 DOS header 中的 e_lfanew 域值。该域含有 PE header 在文件中相对文件首部的偏移量。 edi 加上该值正好定位到 PE header 的首字节。这儿可能会出错,如果文件不是 PE 文件, e_lfanew 值就不正确,加上该值作为指针就可能导致异常。若不用 SEH ,我们必须校验 e_lfanew 值是否超出文件尺寸,这不是一个好办法。如果一切 OK ,我们就比较 PE header 的首字是否是字符串 "PE" 。这里在此用到了常量 IMAGE_NT_SIGNATURE ,相等则认为是有效的 PE 文件。
如果 e_lfanew 的值不正确导致异常,我们的 SEH 处理函数就得到执行控制权,简单恢复堆栈指针和基栈指针后,就根据 safeoffset 的值恢复执行到 FinalExit 标签处。
FinalExit: .if ValidPE==TRUE invoke MessageBox, 0, addr FileValidPE, addr AppName, MB_OK+MB_ICONINFORMATION .else invoke MessageBox, 0, addr FileInValidPE, addr AppName, MB_OK+MB_ICONINFORMATION .endif
上述代码简单明确,根据 ValidPE 的值显示相应信息。
push seh.PrevLink
pop fs:[0]
一旦 SEH 不再使用,必须从 SEH 链上断开。
发表评论
-
压缩与脱壳-PE文件格式 七
2009-04-13 11:44 695Export Table(引出表) 上一课我们已经学习了 ... -
压缩与脱壳-PE文件格式 六 续
2009-04-13 11:39 1078assume edi:ptr IMAGE_IMPORT_D ... -
压缩与脱壳-PE文件格式 六 续一
2009-04-13 11:33 978示例 : 本例程打开一 PE 文件,将所有引入函数名读入一 ... -
压缩与脱壳-PE文件格式 六
2009-04-13 11:29 898Import Table (引入表) 本课我们将学习引入表。 ... -
压缩与脱壳-PE文件格式 五
2009-04-13 11:09 924Section Table(节表) 理论 : 到本课为止, ... -
压缩与脱壳-PE文件格式 四
2009-04-13 11:05 1082Optional Header 我们已经学习了关于 DOS ... -
压缩与脱壳-PE文件格式 三
2009-04-13 11:03 914File Header (文件头) ... -
压缩与脱壳-PE文件格式 一
2009-04-13 10:48 1234PE 文件格式一览 PE 的 ... -
脱壳基础知识入门之认识壳
2009-04-13 10:35 10811.什么是壳 在一些计算 ...
相关推荐
### PE文件中脱壳技术的研究 #### 摘要与背景 随着信息技术的快速发展,软件保护成为了一个重要的议题。为了防止软件被非法复制或者逆向工程,开发人员常常采用一种称为“加壳”的技术来保护自己的软件产品。然而...
都会使计算机产生安全隐患或者使软件的核心技术被窃取,所以保护PE文件不被修改是一件很重要的工作,当前通常采用加壳的方法对PE文件进行保护,这其中UPX是具有代表性的压缩类外壳。 本文首先对PE文件格式进行了全面...
UPX是一个着名的压缩壳,主要功能是压缩PE文件(比如exe,dll等文件),有时候也可能被病毒用于免杀。壳upx是一种保护程序。 ........................ UPX是大家熟悉的EXE/Dll资源压缩工具,也称作可执行文件压缩...
PE文件格式是Windows操作系统中用于执行程序的标准格式,包括可执行文件(.exe)、动态链接库(.dll)等。PE脱壳工具能够识别并处理这些文件中的各种壳技术,例如UPX、ASPack、PECompact等。这些壳通常用于压缩程序...
UPX(UPX UnPacker eXtended)是一款广泛使用的可执行文件压缩工具,它能够将PE(Portable Executable,Windows平台上的可执行文件格式)文件进行压缩,从而减小程序的体积,提高分发效率。然而,这也为逆向工程和...
在计算机安全领域,PECompact是一款知名的可执行文件打包和压缩工具,它能够将Windows下的PE(Portable Executable)格式文件进行压缩,从而减小文件体积,提高分发效率。然而,这样的压缩过程也使得一些恶意软件...
Aspack stripper就是这样的一个工具,它的主要功能是对使用ASPack 2.12版本压缩的可执行文件进行自动脱壳。这个工具的存在,使得安全分析人员能够揭示被压缩和混淆的原始代码,从而更好地理解软件的工作原理,检查...
总结以上内容,脱壳是逆向工程的重要组成部分,需要掌握PE文件格式、SEH机制、调试工具的使用,以及对各种加密算法和保护技术的理解。只有对这些基础知识和高级技术有了充分的认识,才能在软件安全和逆向工程的道路...
对于想要深入理解脱壳技术的学习者来说,熟悉PE文件格式至关重要。 **PE文件格式简介** - **定义**:PE格式由微软开发,用于定义Windows平台上可执行文件(如.EXE、.DLL等)的结构。 - **关键特性**:PE文件包含了...
2. **脱壳机制**:脱壳工具的核心在于正确地解压UPX壳并恢复原始的未压缩PE文件。源码可能会包含解压算法,根据UPX的压缩格式进行还原。 3. **内存操作**:由于程序可能已经在内存中运行,脱壳工具可能需要在内存中...
- **静态与动态分析的兼容性**:构建一个可以在静态分析时重建有效PE文件,并在动态分析时执行的PE文件。 - **防止恶意软件检测**:确保脱壳过程不会被恶意软件检测到,避免分析过程中的干扰。 - **兼容性问题**:...
2. **代码压缩**:将原始代码进行压缩,以减少文件大小,同时增加解密和解压缩代码。 3. **反调试技术**:添加检测调试器的代码,一旦检测到调试器的存在,程序可能会立即终止运行。 4. **代码混淆**:通过修改指令...
这个过程涉及到对PE(Portable Executable)文件格式的理解,包括节区、导入表、导出表等关键结构。脱壳机通过识别和解析ASPack的特定标志和模式来实现这一目标。 在安全社区中,ASPack常被视为一种双刃剑。一方面...
2.支持文件拖拽功能 3.脱未知壳时,如果IAT加密了,请选上解密加密IAT项,进行IAT还原 下面是它能脱的壳: upx 0.5x-3.00 aspack 1.x--2.x PEcompact 0.90--1.76 PEcompact 2.06--2.79 NsPack nPack FSG 1.0--...
1. **分析PE文件结构**:首先要熟悉PE(Portable Executable)文件格式,这是Windows操作系统下的可执行文件格式。理解导入表、节区、重定位等概念是脱壳的基础。 2. **识别壳特征**:通过工具如PEview或OllyDbg,...
你可以用它来压缩或解压缩PE(Windows)、ELF(Linux)或DOS格式的可执行文件。例如,将一个.exe文件压缩,可以使用以下命令: ``` upx -q your_program.exe ``` 如果想要脱壳,只需添加`-d`参数: ``` upx -qd your...
有些模糊处理一个Win32 PE等包装.NET程序集里面的.NET反编译器无法读取该文件。 移除大多数/所有的垃圾类添加混淆。 修复了一些的peverify错误。许多混淆器是马车和创建无法验证的代码错误。 还原类型的方法的参数和...
但这需要深入理解PE文件格式和UPX壳的内部机制。 2. 自动脱壳工具:存在许多自动化工具如UPX-unpacker、PE-bear等,它们能识别并移除UPX壳,恢复原始可执行文件。例如,我们可以使用UPX-iT.EXE这个工具尝试对加壳...