`
cfree
  • 浏览: 17828 次
  • 性别: Icon_minigender_1
  • 来自: 成都
最近访客 更多访客>>
社区版块
存档分类
最新评论

压缩与脱壳-PE文件格式 二

阅读更多

检验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 链上断开。
  • 大小: 14.9 KB
  • 大小: 16.4 KB
分享到:
评论

相关推荐

    PE文件的UPX脱壳算法的实现

    都会使计算机产生安全隐患或者使软件的核心技术被窃取,所以保护PE文件不被修改是一件很重要的工作,当前通常采用加壳的方法对PE文件进行保护,这其中UPX是具有代表性的压缩类外壳。 本文首先对PE文件格式进行了全面...

    红黑全能自动脱壳机——全能脱壳机

    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--...

    脱壳AspackDie

    - 询问用户是否继续解压缩不能解压缩的文件 (不知道是谁提的建议) 1.3d: (2002.3.26) --------------------- - 支持另外的一个未知的 Aspack 版本 (感谢: Proggi Killa) 1.3c: (2002.3.21) --------------------- ...

    脱壳入门初级教学(CHM格式)

    第一课 PE格式 第二课 SEH技术 第三课 认识壳 第四课 常见压缩壳与加密壳 第五课 文件类型分析 第六课 寻找OEP 第七课 Dump内存映像 第八课 重建输入表 第九课 手动确定IAT的地址与大小 第十课 DLL文件脱壳 第十一课...

    软件脱壳破解工具

    AspackDie——AsPack的脱壳利器, 这是一个小小的PE 文件解压缩器 (EXE, DLL, ...) 她可以解压缩自Aspack 2000 以后的任何Aspack 版本. 包括: - Aspack 2000 - Aspack 2001 - Aspack 2.1 - Aspack 2.11 - Aspack 2.11...

    ASPack脱壳

    这是一个小小的 PE 文件解压缩器 (EXE, DLL, ...) 她可以解压缩 自 Aspack 2000 以后的任何 Aspack 版本. 包括: - Aspack 2000 - Aspack 2001 - Aspack 2.1 - Aspack 2.11 - Aspack 2.11c/d - Aspack 2.12 - Aspack...

    rordbg辅助脱壳工具

    答:点击“打开被分析文件”,出现Windows标准的文件打开对话框,选择欲分析的文件(必须是PE格式的EXE文件), 这时,被调试程序已经加载,可以先设置断点等调试条件,如果希望研究壳的技术,可以点选“遇到异常...

    全能脱壳机

    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--...

    .Net 脱壳 反混淆神器De4dot-3.1.41592最新版

    有些模糊处理一个Win32 PE等包装.NET程序集里面的.NET反编译器无法读取该文件。 移除大多数/所有的垃圾类添加混淆。 修复了一些的peverify错误。许多混淆器是马车和创建无法验证的代码错误。 还原类型的方法的参数和...

    软件加密技术内幕 chm

    第1章 PE文件格式深入研究 1.1 PE文件格式格式纵览 1.1.1 区块(Section) 1.1.2 相对虚拟地址(Relative Virtual Addresses) 1.1.3 数据目录 1.1.4 输入函数(Importing Functions) 1.2 PE文件结构 ...

    多种脱壳软件

    现在为了适应脱壳的需要,发现原来的代码对非标准格式的PE文件的处理有些小问题, 所以代码基本都重写过了,但是基本处理步骤还是一致的,外表上看不出来 3.cooldebugger plugin(调试插件) 完全自主开发的插件,说是调试...

    软件加密技术内幕

    1.1 PE文件格式格式纵览 1.1.1 区块(Section) 1.1.2 相对虚拟地址(Relative Virtual Addresses) 1.1.3 数据目录 1.1.4 输入函数(Importing Functions) 1.2 PE文件结构 1.2.1 The MS-DOS头部 1.2.2 IMAGE...

    强大UPX加壳压缩工具(Free UPX) v1.7汉化版.rar

    UPX(the Ultimate Packer for eXecutables)是一个非常全面的可执行文件压缩软件,支持dos/exe、dos/com、dos/sys、djgpp2/coff、 watcom/le、win32/pe、rtm32/pe、tmt/adam、atari/tos、linux/i386等几乎所有平台上...

    完全掌握加密解密实战超级手册.z01

    462.1.3 PE文件格式的头结构 462.1.4 设置Optional Header可执行信息 492.1.5 Section Table结构数组 512.1.6 Import Table输入表 522.1.7 Export Table输出表 532.1.8 重定位表 542.2 简述代码分析实战 552.2.1 ...

    软件破解入门教程.txt

    PE文件格式 认识脱壳 自动脱壳 手动脱壳 脱壳高级篇 第9章 注册机和补丁制作 概念介绍 补丁制作 注册机制作工具 rufeng教程 第一章 如何成为一个Cracker 第二章 破解软件的基础 第三章 破解windows 95...

    加密解密.技术内幕.chm

    第1章 PE文件格式深入研究1.1 PE文件格式格式纵览 1.1.1 区块(Section) 1.1.2 相对虚拟地址(Relative Virtual Addresses) 1.1.3 数据目录 1.1.4 输入函数(Importing Functions)1.2 PE文件结构 1.2.1 The MS-...

    Windows应用程序捆绑核心编程光盘代码

    第2章 再谈PE文件结构 28 2.1 引言 28 2.2 PE文件格式概述 28 2.2.1 PE文件结构布局 28 2.2.2 PE文件内存映射 30 2.2.3 Big-endian和Little-endian 31 2.2.4 3种不同的地址 31 2.3 PE文件结构 32 2.3.1 MS-...

    完全掌握加密解密实战超级手册.zip02

    442.1.1 PE格式文件概述 442.1.2 检验PE格式文件 462.1.3 PE文件格式的头结构 462.1.4 设置Optional Header可执行信息 492.1.5 Section Table结构数组 512.1.6 Import Table输入表 522.1.7 Export Table输出表 532.1...

Global site tag (gtag.js) - Google Analytics