脱壳理论教程[看雪篇]

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

第一课PE格式
要想学脱壳,第一步就得掌握PE格式,PE是Portable Executable File Format(可移植的执行体)简写,它是目前Windows 平台上的主流可执行文件格式。

Microsoft Visual C++提供的WINNT.H里有PE数据结构的完整定义。

推荐文档:
ah007翻译的“PE文件格式”1.9版
qduwg翻译的PE文件格式
Iczelion's 的PE文件格式
PE结构各字段偏移参考
微软官方提供的PE文档(Revision 8.0 - May 16, 2006)
学习PE格式的方法是自己先准备一个十六进制工具,如HexWorkshop,WinHex,用这些工具打开一个EXE文件对照着学。

强烈推荐你用
Stud_PE v.2.2.0.5这款工具辅助学习PE格式。

PE格式学习的重点是在输入表(Import Table)这块。

Stud_PE工具界面:
PE结构图:
第二课SEH技术
结构化异常处理(Structured Exception Handling,SEH)是Windows操作系统处理程序错误或异常的技术。

SEH是Windows 操作系统的一种系统机制,与特定的程序设计语言无关。

外壳程序里大量地使用了SEH,如果不了解SEH,将会使你跟踪十分困难。

SEH in ASM 研究(一)by hume
SEH in ASM 研究(二)by hume
Structured Exception Handling
加密与解密二版菜鸟学习笔记(2) - SEH 结构化异常处理by ytcswb
由于Ollydbg对SEH处理异常灵活,因此脱壳用Ollydbg会大大提高效率。

附CONTEXT结构环境:
代码:
typedef struct _CONTEXT {
/*000*/ DWORD ContextFlags;
/*004*/ DWORD Dr0;
/*008*/ DWORD Dr1;
1. 什么是壳?
在一些计算机软件里也有一段专门负责保护软件不被非法修改或反编译的程序。

它们一般都是先于程序运行,拿到控制权,然后完成它们保护软件的任务。

由于这段程序和自然界的壳在功能上有很多相同的地方,基于命名的规则,就把这样的程序称为“壳”了。

推荐文档:
一切从“壳”开始
描述壳的示意图:
2. 壳的加载过程
这里谈的加壳工具不是WinZIP、WinRAR等数据压缩工具,而是谈压缩可执行文件EXE或DLL的工具。

加壳过的EXE文件是可执行文件,它可以同正常的EXE文件一样执行。

用户执行的实际上是外壳程序,这个外壳程序负责把用户原来的程序在内存中解压缩,并把控制权交还给解开后的真正程序,这一切工作都是在内存中运行的,整个过程对用户是透明的。

壳和病毒在某些方面比较类似,都需要比原程序代码更早的获得控制权。

壳修改了原程序的执行文件的组织结构,从而能够比原程序的代码提前获得控制权,并且不会影响原程序的正常运行。

这里简单说说一般壳的装载过程。

(参考了Ljtt以前写过的一篇文章)
1)获取壳自己所需要使用的API地址
如果用PE编辑工具查看加壳后的文件,会发现未加壳的文件和加壳后的文件的输入表不一样,加壳后的输入表一般所引入的DLL和API函数很少,甚至只有Kernel32.dll以及GetProcAddress这个API函数。

壳实际上还需要其他的API函数来完成它的工作,为了隐藏这些API,它一般只在壳的代码中用显式链接方式动态加载这些API 函数:3个脱壳相关的重要函数介绍
2)解密原程序的各个区块(Section)的数据
壳出于保护原程序代码和数据的目的,一般都会加密原程序文件的各个区块。

在程序执行时外壳将会对这些区块数据解密,以让程序能正常运行。

壳一般按区块加密的,那么在解密时也按区块解密,并且把解密的区块数据按照区块的定义放在合适的内存位置。

如果加壳时用到了压缩技术,那么在解密之前还有一道工序,当然是解压缩。

这也是一些壳的特色之一,比如说原来的程序文件未加壳时1~2M大小,加壳后反而只有几百K。

3)重定位
文件执行时将被映像到指定内存地址中,这个初始内存地址称为基地址(ImageBase)。

当然这只是程序文件中声明的,程序运行时能够保证系统一定满足其要求吗?
对于EXE的程序文件来说,Windows系统会尽量满足。

例如某EXE文件的基地址为0x400000,而运行时Windows系统提供给程序的基地址也同样是0x400000。

在这种情况下就不需要进行地址“重定位”了。

由于不需要对EXE文件进行“重定位”,所以加壳软件把原程序文件中用于保存重定位信息的区块干脆也删除了,这样使得加壳后的文件更加小巧。

有些工具提供“Wipe Reloc”的功
能,其实就是这个作用。

不过对于DLL的动态链接库文件来说,Windows系统没有办法保证每一次DLL运行时提供相同的基地址。

这样“重定位”就很重要了,此时壳中也需要提供进行“重定位”的代码,否则原程序中的代码是无法正常运行起来的。

从这点来说,加壳的DLL比加壳的EXE更难修正。

4)HOOK-API
程序文件中的输入表的作用是让Windows系统在程序运行时提供API的实际地址给程序使用。

在程序的第一行代码执行之前,Windows系统就完成了这个工作。

壳一般都修改了原程序文件的输入表,然后自己模仿Windows系统的工作来填充输入表中相关的数据。

在填充过程中,外壳就可填充HOOK-API的代码的地址,这样就可间接地获得程序的控制权。

5)跳转到程序原入口点(OEP)
从这个时候起壳就把控制权交还给原程序了,一般的壳在这里会有明显的一个“分界线”。

但现在的猛壳己没这界限了,壳里有肉,肉里有壳。

3. 压缩引擎
各类加壳软件,其压缩算法一般不是自己实现的,大多是调用其他的压缩引擎。

目前压缩引擎种类比较多,不同的压缩引擎有不同特点,如一些对图像压缩效果好,一些对数据压缩效果好。

而加壳软件选择压缩引擎有一个特点,在保证压缩比的条件下,压缩速度慢些关系不是太大,但解压速度一定要快,这样加了壳的EXE文件运行起来速度才不会受太大的影响。

例如下面几个压缩引擎就能满足这要求:
1. aPLib压缩引擎/,这个库对于低于64K的文件压缩效果较好,速度较快。

2. JCALG1压缩引擎,相对于aPlib,JCALG1对于大文件效果好些。

3. LZMA压缩引擎/zh-cn/sdk.html,LZMA 是7-Zip 程序中7z 格式的默认压缩算法,压缩率很高。

第四课常见压缩壳与加密壳
加壳软件按照其加壳目的和作用,可分为两类:一是压缩(Packers),二是保护(Protectors)。

压缩这类壳主要目的是
减小程序体积,如ASPacK、UPX和PECompact等。

另一类是保护程序,用上了各种反跟踪技术保护程序不被调试、脱壳等,其加壳后的体积大小不是其考虑的主要因素,如ASProtect、Armadillo、EXECryptor等。

随着加壳技术的发展,这两类软件之间的界线越来越模糊,很多加壳软件除具有较强的压缩性能,同时也有了较强的保护性能。

目前流行的一些壳可以参考这里:/tools/packers.htm
1.常用压缩壳介绍
1). ASPacK
主页:/
ASPack是款Win32可执行文件压缩软件,可压缩Windows 32位可执行文件(.exe)以及库文件(.dll、.ocx),文件压缩比率高达40%~70%。

2). UPX
主页:/
UPX是一个以命令行方式操作的可执行文件经典免费压缩程序,压缩算法自己实现,速度极快。

(开源)
3). PECompact
主页:/
PECompact同样也是一款能压缩可执行文件的工具(支持EXE、DLL、SCR、OCX等文件)。

相比同类软件,PECompact提供了多种压缩项目的选择,用户可以根据需要确定哪些内部资源需要压缩处理。

同时,该软件还提供了加解密的插件接口功能。

2.加密保护壳介绍
为了保护自己的软件不轻易被他人“借鉴”,有必要对软件进行一些加密保护,而这方面目前己有成熟的专业加密软件可选择。

但不要太依赖壳的保护,大多数壳是可以被攻破的,还是在自身保护上下些功夫。

加密软件比较多,但在强度与兼容性上做的好的并不多,这里向大家介绍几款常见的。

现在壳的发展一个趋势就是虚拟机保护,利用虚拟机保护后,能大大提高强度,因此建议尽可能使用此类技术保护软件。

如Themida ,WinLicense,EXECryptor等壳带有虚拟机保护功能,因此得用好其SDK。

1). ASProtect
主页:/
ASProtect是一款非常强大的Windows 32位保护工具,这4、5年来,其一直在更新进步。

其开发者是俄国人
Alexey Solodovnikov。

它拥有压缩、加密、反跟踪代码、反-反汇编代码、CRC校验和花指令等保护措施。

它使用Blowfish、Twofish、TEA等强劲的加密算法,还用RSA1024作为注册密钥生成器。

它还通过API钩子(API hooks,包括Import hooks(GPA hook)和Export hooks)与加壳的程序进行通信。

甚至用到了多态变形引擎(Polymorphic Engine)。

反Apihook代码(Anti-Apihook Code)和BPE32的多态变形引擎(BPE32的Polymorphic Engine)。

并且ASProtect为软件开发人员提供SDK,实现加密程序内外结合。

ASProtect SKE系列己采用了部分虚拟机技术,主要是在Protect Original EntryPoint与SDK上。

保护过程中建议大量里使用SDK,SDK使用请参考其帮助文档,在使用时注意SDK不要嵌套,并且同一组标签用在同一个子程序段里。

ASProtect使用相当的简单,打开被保护的EXE/DLL文件后,选上保护的选项。

再单击菜单Modes,单击Add Mode按钮,将Is this Mode Avtive 选上,最后,单击Protection标签,对软件进行保护即可。

ASProtect加壳过程中也可外挂用户自己写的DLL文件,方法是在上图中的External Options选项加上目标DLL即可。

这样,用户可以在DLL加入自己的反跟踪代码,以提高软件的反跟踪能力。

强度评介:由于ASProtect名气太大,研究它的人很多,因此很容易被脱壳,不推荐使用。

2). Armadillo加密壳
Armadillo也称穿山甲,是一款应用面较广的壳。

可以运用各种手段来保护你的软件,同时也可以为软件加上种种限制,包括时间、次数,启动画面等等!很多商用软件采用其加壳。

Armadillo对外发行时有Public,Custom两个版本。

Public是公开演示的版本,Custom是注册用户拿到的版本。

只有Custom才有完整的功能,Public版有功能限制,没什么强度,不建议采用。

强度评介:Armadillo中比较强大的保护选项是Nanomites保护(即CC保护),用的好能提高强度,其他选项没什么强度。

3). EXECryptor加密壳
EXECryptor也是一款猛壳,可能由于兼容性等原因,采用其保护的商业软件不是太多。

这款壳的特点是Anti-Debug做的比较隐蔽,另外就是采用了虚拟机保护一些关键代码。

强度评介:用好EXECryptor 虚拟机保护功能,将关键敏感代码用虚拟机保护起来,能提高强度。

EXECryptor 壳能脱的人很多,但对付其虚拟机代码的人不多。

4). Themida加密壳
Themida是Oreans的一款商业壳,官方链接:。

Themida 1.1以前版本带驱动,稳定性有些影响。

Themida 最大特点就是其虚拟机保护技术,因此在程序中擅用SDK,将关键的代码让Themida用虚拟机保护起来。

Themida最大的缺点就是生成的软件有些大。

WinLicense这款壳和Themida是同一公司的一个系列产品,WinLicense主要多了一个协议,可以设定使用时间,运行次数等功能,两者核心保护是一样的。

强度评介:用好其虚拟机保护功能,将关键敏感代码用虚拟机保护起来,能提高强度。

5). VMProtect
VMProtect是一款纯虚拟机保护软件,官方链接:www.VMProtect.ru。

它是当前最强的虚拟机保护软件,经VMProtect处理过的代码,至今还没有人公开宣称能还原。

但也有缺点,就是会影响程序速度,因此在一些对速度要求很高的场合就不适合用了。

VMProtect 1.22.3之前是免费版,可以支持EXE,DLL等文件。

更高版本需要购买,其支持驱动的保护。

现在流行的做法,先用VMProtect将你的核心代码处理一下,再选用一款兼容性好的壳保护。

(1).关键代码自己定位
VMProtect并没有提供使用说明,必须告诉VMProtect你要加密的代码具体地址,这对使用者有一定的要求,至少要懂一些跟踪技术,可以用调试器,如OllyDbg跟踪到程序需要保护的地址,然后添加地址到VMProtect。

在这以一个记事本程序为例来演示一下使用方法。

运行VMProtect后,打开NOTEPAD.EXE文件。

单击Dump标签,输入要加密的起始地址,光标来到要加密代码起始地址后,点击菜单“project/new procedure”,会出现一个新的项目,如下图。

需要处理其他地址时,请依次操作。

注意事项:
1.用VMProtect处理,请多测试,如果不稳定,请调整被保护代码的范围。

2.VMProtect对双线程支持不是太好,请同一次仅处理一个线程内的代码。

(2).用SDK标记代码
VMProtect v1.2以上支持SDK了,可以编程时插入一个标记,然后在加密时,VMProtect会认出这些标记,并在有标记的地方进行保护。

在程序源码中,用这对标签将一些核心代码包含,编译成EXE文件。

然后用VMProtect打开EXE,单击“Project”菜单下的“New procedure”或者单击工具栏中的“New procedure”按钮,在弹出的添加地址窗口中会自动将SDK定义代码的地址填上。

然后在VMProtect的“Options”窗口中设置相应的选项,最后单击工具栏中的“Compilation (F9)”按钮,便可对目标软件进行保护。

经VMProtect处理过的软件,可以继续用Asprotect, Themida等加壳软件进一步保护。

VMProtect是当前最强的虚拟机保护软件,经过VMProtect处理的软件基本是没法分析原程序思路的,关键是用好,一定要将程序关键代码进行处理。

另外,经虚拟机处理代码效率会降低,因此一些对效率要求比较高的代码就不要用VMProtect进行处理。

Delphi 中的标记模式
代码:
VC的VMProtect的宏:代码:
VMProtect使用相关文档:
VMProtect配合PESpin的SDK加密的另一方法作者:acafeel
VMProtect SDK+ASProtect SDK混合编程[代码演示] 作者:Anskya
VMProtect 与ASProtect 在VC中的SDK编程作者:glucose
3.小结
更多与壳有关的描述参考:
纵横间谁能相抗―论壳与加壳技术作者:forgot
常见加密壳官方站点
ASProtect /
ACProtect /
Armadillo
EXECryptor /
Obsidium http://www.obsidium.de/
PESpin http://pespin.w.interia.pl/
VMProtect http://www.polytech.ural.ru/
Xtreme-Protector /xprotector/
Themida/WinLicense
本站的工具栏目:/tools/packers.htm
第五课文件类型分析
拿到一个壳,第一步就是用相关工具分析一下是什么壳,然后就可心中有数地跟踪分析。

文件分析工具有PEID,FileInfo等。

1.PEiD
PEiD的GUI界面操作非常方便直观。

它的原理是利用查特征串搜索来完成识别工作的。

各种开发语言都有固定的启动代码部分,利用这点就可识别出是何种语言编编译的。

同样,不同的壳也有其特征码,利用这点就可识别是被何种壳所加密。

PEiD提供了一个扩展接口文件userdb.txt ,用户可以自定义一些特征码,这样就可识别出新的文件类型。

有些外壳程序为了欺骗PEiD等文件识别软件,会伪造启动代码部分,例如将入口代码改成与Visual C++ 6.0所编程程序入口处类似代码,即可达到欺骗目的。

所以,文件识别工具所给出的结果只是个参考,文件是否被加壳处理过,还得跟踪分析程序代码才可得知。

可参考这个文档了解如何伪装:让侦测工具把壳识别为VC++7.0的源代码。

目前Hying的壳PE-Armor伪装能力是最强的:
PEiD分析不出类型的文件就报告是“Nothing found *”,如出现这情况一般都是未知壳或新版的壳。

下面PEiD识别出这个软件是用Asprotect 1.2x加的壳。

2.FileInfo
FileInfo(简称Fi)另一款不错的文件检测工具。

Fi运行时是DOS界面,在DOS窗口中运行程序相当不便,建议采用下面的技巧:
1.用鼠标将文件拖到Fi主文件上。

2.将Fi快捷方放进Windows的SendTo文件夹里.以后要分析某文件,只需右击“发送到”功能就可打开Fi。

FileInfo升级慢,其识别库不能自定义。

而PEiD升级比较频繁,用户也可自定义特征码,因此PEiD用的比较普遍。

有时,FileInfo和PEID会报“PE Win GUI”,Win GUI就是Windows图形用户界面程序统称,表明程序可能没加壳。

但不排除也有加壳的可能性,下图是一个ExeCryptor 2.2x的壳,FileInfo报“*PE Win GUI *section* ??”,其不能识别出来。

识别信息中带了个问号,表明FI对给出的结果不是太肯定。

第六课寻找OEP
一般的压缩壳,如Aspack等都有专用的脱壳机。

而加密壳(如ASProtect,Armadillo)一般很少有脱壳机,必须手工脱壳。

手工脱壳一般情况是分三步:一是查找程序的真正入口点(OEP);二是抓取内存映像文件;三是输入表重建。

(当然现在的加密壳复杂些,要考虑更多的东西)
OEP是Original Entry Point缩写,即程序加壳前的真正的入口点。

外壳初始化的现场环境(各寄存器值)与原程序的现场环境是相同的。

加壳程序初始化时保存各寄存器的值,外壳执行完毕,会恢复各寄存器内容。

其代码形式一般如下:
PUSHFD ; 将标志寄存器入栈保存
PUSHAD ; push eax, ecx, edx, ebx, esp, ebp, esi, edi
……; 外壳代码部分
POPAD ; pop edi, esi, ebp, esp, ebx, edx, ecx, eax
POPFD ; 恢复标志寄存器
JMP OEP ;
OEP: ……; 解压后的程序原代码
为了讲述方便,本节用UPX加壳的Win98记事本来演示。

首先用PEid查看加壳前的记事本:
PEid显示Notepad.exe程序是用Microsoft Visual C++ 6.0编译的,接下来用UPX来加壳,方法是开个DOS窗口,用命令upx notepad.exe。

如下图所示:
这时再用PEid查看加壳的文件,PEid会给出如下信息:UPX 0.89.6 - 1.02 / 1.05 - 1.24 -> Markus & Laszlo
UPX的壳可以用UPX.exe自身来脱,命令是:upx -d 文件名。

一些变种的UPX壳用UPX.EXE自身脱不了,这时可以试试UPX ShellEx这款工具。

本节实例下载:notepad.upx.rar
脱壳前建议用PE工具LordPE打开目标文件查看一下区块,以尽可能地多了解一些信息,对脱壳有帮助,如下图:
1.根据跨段指令寻找OEP
推荐用Ollydbg来调试脱壳,比SoftICE和TRW2000方便多了。

运行Ollydbg,点击菜单“选项/调试设置”,将第一次暂停设在WinMain 函数上。

再用Ollydbg打开实例notepad.upx.exe就可中断在外壳的入口点处了:
上图相关代码如下:
0040E8C0 > 60 pushad //一开始Ollydbg就会中断这行,这个就是外壳的入口点,注意这个pushad指令
绝大多数加壳程序在被加密的程序中加上一个或多个段,所以依据跨段的转移指令(JMP)就可找到真正的入口点,此时就会有POPAD/POPFD指令出现。

UPX 用了一次跨段的转移指令(JMP),在跳到OEP处会看到虚拟地址的值有一个突变,此时就能确定OEP 了。

UPX壳比较简单,大家不必要跟踪去找这个跨段的转移指令,中断WinMain后,只需要在Ollydbg里往下翻屏,就会发现这个跨段转移指令:
上图相关代码如下:
0040EA0E 61 popad //注意这里的popad指令,和开始的pushad对应
0040EA0F - E9 B826FFFF jmp 004010CC //这里跳到OEP,将光标移到这,按F4执行到这行
这一句0040EA0F jmp 004010CC 就是跳到OEP的指令,执行到这,UPX外壳己将程序解压完毕,并模拟Windows加载器的将原始程序加载到内存,004010CC 就是映射到内存目标程序的入口点,此时就可抓取内存映像文件了。

2.根据堆栈平衡原理找OEP
这个堆栈平衡原理其找OEP原理这篇文档描述的比较详细:寻找真正的入口(OEP)--广义ESP定律作者:Lenus
操作方法:多数壳在运行到OEP的时候ESP=0012FFC4,这就是说程序的第一句是对0012FFC0进行写入操作,只要在0012FFC0下硬件写入断点(命令行里键入HW 12FFC0),我们就能停在OEP的第二句处。

注意:并不是所有程序加载时,ESP的值是0012FFC4,这个值是什么由操作系统决定,将SizeOfStackCOmmit改大ESP就会变,这是因为操作系统从这个页向上找一个足够大地方当作stack了(感谢forgot解释)。

你只要记住你系统加载时的ESP值,对其设断即可。

用OllyDBG重新加载实例程序notepad.upx.exe,在命令行下硬件写断点:
按F9执行程序,就会中断在OEP第二行:
此时如果将光标向上移,会发现第一句代码变乱了:
004010C7 000D 0A000055 add [5500000A], cl
004010CD 8BEC mov ebp, esp
这是因为Ollydbg将数据当汇编代码来分析了,你可以按Ctrl+ALT+向上光标键将当前显示的代码向上滚动一个字节就可看到正确的汇编代码了:
004010CC 55 push ebp
004010CD 8BEC mov ebp, esp//中断在这行
004010CF 83EC 44 sub esp, 44
004010D2 56 push esi
004010D3 FF15 E4634000 call [4063E4] ; kernel32.GetCommandLineA
中断后,别忘点击菜单“调试/硬件断点/”打开硬件断点面板,将刚才的硬件断点删除。

小知识:硬件断点的原理作者:Lenus
3.根据编译语言特点找OEP
各类语言编译的文件入口点都有一些规律,可以这利用这点来寻找入口点。

1)Delphi程序
执行程序,用LordPE(或Prodump)选dump(full)脱壳,存为dump.exe。

接着用Hex Workshop打开dump.exe,搜索文本“runtime”,搜到后,向前查找离“runtime”最近的十六进制数字“55 8B EC”,数字所在的地址就是程序的OEP。

2)Visual C程序
可以利用Visual C启动部分的几个函数GetCommandLineA(W)、GetVersion、GetModuleHandleA(W)、GetStartupInfoA(W) 等来定位程序的OEP。

常见的各类编译语言的入口汇编代码都要熟悉,因为一些加密强壳会偷OEP处的代码到壳里,一般情况各编译语言入口代码都相同,到时只需要直接引用相关程序的入口代码,这给我们恢复代码带来方便。

第七课 Dump内存映像
外壳程序解压还原后就会跳到OEP处执行,此时内存映像文件是己解压的程序。

这时就可抓取内存映像文件了(该过程称为Dump)。

当然不一定非要在程序原入口点抓取,只要能保证内存映像文件是己还原的就行了。

有关Dump技术的原理大家可以参考:浅谈脱壳中的Dump技术作者:Lenus
继续上一个实例notepad.upx.exe,到OEP后就可以Dump取内存映像文件:
004010CC 55 push ebp
004010CD 8BEC mov ebp, esp
004010CF 83EC 44 sub esp, 44
运行LordPE.EXE,点击Options,默认选项如下:
默认选上“Full dump:paste header from disk”,PE头的信息直接从磁盘文件获得。

设置好后,在LordPE的进程窗口选择notepad.upx.exe,点击右键,执行“dump full”菜单命令。

如图:
第八课重建输入表
在脱壳中输入表处理是很关键的一个环节,因此要求脱壳者对PE格式中的输入表概念非常清楚。

在磁盘文件中,PE文件的输入表结构如下图所示:
图8.1 磁盘文件中的输入表
PE文件运行时,Windows系统加载器首先搜索OriginalFirstThunk,如果存在,装载程序迭代搜索数组中的每个指针,找到每个IMAGE_IMPORT_BY_NAME结构所指向的输入函数的地址,然后用函数入口地址来替代由FirstThunk指向的 IMAGE_THUNK_DATA 数组里的元素值(即用真实的函数地址填充到IAT里)。

因当PE文件装载内存后准备执行时,上图己转换成这种情况了:
图8.2 PE文件装载内存后的输入表
此时输入表中其它部分就不重要了,程序依靠IAT提供的函数地址就可正常运行(图8.2 红圈部分)。

如果程序加壳了,那壳自己模
仿Windows装载器的工作来填充IAT中相关的数据,此时内存中就一张IAT表,输入表的其他部分是不存的(当然不是绝对的,也有不少壳,如Aspack等,内存中会出现完整的输入表结构),如图8.3所示。

图8.3 外壳加载程序后的内部IAT
输入表重建就是根据图8.3这张IAT恢复整个输入表的结构(即图8.1这个结构),ImpREC这款工具就是这个功能。

一些压缩壳,填充IAT过程中没做什么手脚,用ImpREC工具可以直接重建输入表。

而一些加密壳为了防止输入表被还原,就在IAT加密上大作文章,此时壳填充IAT里的不是实际的API地址,而是填充壳中用来HOOK-API的外壳代码的地址。

这样壳中的代码一旦完成了加载工作,在进入原程序的代码之后,仍然能够间接地获得程序的控制权。

因为程序总是需要与系统打交道,与系统交道的途径是API,而API的地址已经替换成了壳的HOOK-API的地址,那程序每一次与系统打交道,都会让壳的代码获得一次控制权,这样壳可以进行反跟踪继续保护软件,同时也可完成某些特殊的任务。

所以重建输入表的关键是获得没加密的IAT ,一般的做法是跟踪加壳程序对IAT处理过程,修改相关指令,不让外壳加密IAT。

UPX、ASPack等加壳保护的壳没加密IAT,而ASProtect、tElock等加密保护的壳都对IAT进行了加密处理。

这篇先来简单的,即UPX壳。

用OD打开上面的notepad.upx.exe实例,运行到OEP。

(实际跟踪过程中,不一定要到OEP,只要外壳处理完IAT就可)然后如下操作:
1) 运行ImportREC,在下拉列表框中选择notepad.upx.exe进程,如图:
2) 上面己得知notepad.upx.exe的OEP地址是4010CC,则在左下角OEP处填入OEP的RV A值,这里填上10CC。

点击“IAT AutoSearch”按钮,让其自动检测IAT偏移和大小,如出现下图表示ImportREC自己找到IAT的地址与大小了,即IAT地址:000062E0,大小248。

如果ImportREC没找到IAT偏移,则必须手工填入IAT偏移和大小(IAT偏移手动获得以后再讲述)。

3) 点击“Get Import”按钮,让其分析IAT结构得到基本信息,如下图所示:
4)如发现某个DLL显示"valid :NO" ,按"Show Invalids"按钮将分析所有的无效信息,在Imported Function Found栏中点击鼠标右键,选择"Trace Level1 (Disasm)",再按"Show Invalids"按钮。

如果成功,可以看到所有的DLL都为"valid:YES"字样;
5)再次刷新"Show Invalids"按钮查看结果,如仍有无效的地址,继续手动用右键的Level 2或3修复;
6)如还是出错,可以利用"Invalidate function(s)"、"Delete thunk(s)"、编辑Import表(双击函数)等功能手动修复。

7)开始修复已脱壳的程序。

选择Add new section (缺省是选上的) 来为Dump出来的文件加一个Section(虽然文件比较大,但避免了许多不必要的麻烦) 。

8)单击"Fix Dump"按钮,并选择刚在前面己Dump出来的文件。

如修复的文件名是"Dump.exe",它将创建一个"Dump_.exe",此外OEP也被修正。

经过这些步骤,这个UPX壳己成功脱掉。

此时再用PEID查一下脱壳后的程序dumped_.exe,会显示是“Microsoft Visual C++ 6.0 SPx Method 1”,如下图所示:
再用LordPE查看脱壳后的输入表:。

相关文档
最新文档