在OD中c32反汇编编,CALL 12345678 为什么对应 E8 74 20 EB 11 ??

脱壳基础知识入门
现在加解密发展己形成2个分支了,一个就是传统的算法,另一个就是加密壳。越来越多的软件采用了密码学相关算法,现在要做出一个软件注册机己不象前几年那 么容易,这就要求解密者必须要有一定的数学功底和密码学知识,而这些在短时间内是不容易掌握的。除了密码学的应用,越来越多的软件加壳了,因此要求解密者 必须掌握一些脱壳技术,这就使得壳成了解密必须迈过的一个门槛。壳发展到今天,强度越来越高了,将许多人挡在门外,使得大家望壳兴叹。另外,论坛现在两极 分化比较严重,高手讨论的脱壳技术新手看不懂,很多人想学脱壳,但看到壳这么难,只好放弃了,造成新手与高手间一个断档,为了鼓励更多新人加入脱壳的行 列,很有必要将壳有关知识总结一下。主页提供的教学确实有点过时了,己到非更新不可了。为此,整理这篇脱壳入门指导的文章,方 便脱壳新手们学习。相对于密码学算法,脱壳并不难,只要肯花时间,短期内还是比较容易取得成绩的。
&&&但是,不建议那些加解密刚入门,调试一个普通软件都费劲的朋友来脱壳。至少要等你有一定的调试技能再来学脱壳。也就是说必须掌握这篇文章所讲的东西:
第一课&PE格式
第二课&SEH技术
第三课&认识壳&
第四课&常见压缩壳与加密壳
第五课&文件类型分析
第六课&寻找OEP
第七课&Dump内存映像
第八课&重建输入表
第九课&手动确定IAT的地址与大小
第十课&DLL文件脱壳
第十一课&优化与自校验去除第一课&PE格式&
&&&要想学脱壳,第一步就得掌握PE格式,PE是Portable&Executable&File&Format(可移植的执行体)简写,它是目前Windows平台上的主流可执行文件格式。
Microsoft&Visual&C++提供的里有PE数据结构的完整定义。
推荐文档:
&&&学习PE格式的方法是自己先准备一个十六进制工具,如,,用这些工具打开一个EXE文件对照着学。强烈推荐你用这款工具辅助学习PE格式。PE格式学习的重点是在输入表(Import&Table)这块。
Stud_PE工具界面:
PE结构图:
第二课&SEH技术&
&&&结构化异常处理(Structured&Exception&Handling,SEH)是Windows操作系统处理程序错误或异常的技术。SEH是Windows操作系统的一种系统机制,与特定的程序设计语言无关。
&&&外壳程序里大量地使用了SEH,如果不了解SEH,将会使你跟踪十分困难。
由于&&对SEH处理异常灵活,因此脱壳用Ollydbg会大大提高效率。
附CONTEXT结构环境:
typedef&struct&_CONTEXT&{
/*000*/&DWORD&&&&&&&ContextF
/*004*/&DWORD&&&&&&&Dr0;
/*008*/&DWORD&&&&&&&Dr1;
/*00C*/&DWORD&&&&&&&Dr2;
/*010*/&DWORD&&&&&&&Dr3;
/*014*/&DWORD&&&&&&&Dr6;
/*018*/&DWORD&&&&&&&Dr7;
/*01C*/&FLOATING_SAVE_AREA&FloatS
/*08C*/&DWORD&&&&&&&SegGs;
/*090*/&DWORD&&&&&&&SegFs;
/*094*/&DWORD&&&&&&&SegEs;
/*098*/&DWORD&&&&&&&SegDs;
/*09C*/&DWORD&&&&&&&E
/*0A0*/&DWORD&&&&&&&E
/*0A4*/&DWORD&&&&&&&E
/*0A8*/&DWORD&&&&&&&E
/*0AC*/&DWORD&&&&&&&E
/*0B0*/&DWORD&&&&&&&E
/*0B4*/&DWORD&&&&&&&E
/*0B8*/&DWORD&&&&&&&E
/*0BC*/&DWORD&&&&&&&SegCs;
/*0C0*/&DWORD&&&&&&&EF
/*0C4*/&DWORD&&&&&&&E
/*0C8*/&DWORD&&&&&&&SegSs;
/*0CC*/&&&&&BYTE&&&&ExtendedRegisters[MAXIMUM_SUPPORTED_EXTENSION];
/*2CC*/&}&CONTEXT;
第三课&认识壳&
1.&什么是壳?&
&&&在一些计算机软件里也有一段专门负责保护软件不被非法修改或反编译的程序。它们一般都是先于程序运行,拿到控制权,然后完成它们保护软件的任务。由于这段程序和自然界的壳在功能上有很多相同的地方,基于命名的规则,就把这样的程序称为&壳&了。
推荐文档:
描述壳的示意图:
2.&壳的加载过程&
&&&&这里谈的加壳工具不是WinZIP、WinRAR等数据压缩工具,而是谈压缩可执行文件EXE或DLL的工具。加壳过的EXE文件是可执行文件,
它可以同正常的EXE文件一样执行。用户执行的实际上是外壳程序,这个外壳程序负责把用户原来的程序在内存中解压缩,并把控制权交还给解开后的真正程序,
这一切工作都是在内存中运行的,整个过程对用户是透明的。
&&&壳和病毒在某些方面比较类似,都需要比原程序代码更早的获得控制权。壳修改了原程序的执行文件的组织结构,从而能够比原程序的代码提前获得控制权,并且不会影响原程序的正常运行。
&&&这里简单说说一般壳的装载过程。(参考了Ljtt以前写过的一篇文章)
&&&1)获取壳自己所需要使用的API地址&
&&&如果用PE编辑工具查看加壳后的文件,会发现未加壳的文件和加壳后的文件的输入表不一样,加壳后的输入表一般所引入的DLL和API函数很少,甚至只有Kernel32.dll以及GetProcAddress这个API函数。&
&&&壳实际上还需要其他的API函数来完成它的工作,为了隐藏这些API,它一般只在壳的代码中用显式链接方式动态加载这些API函数:&
&&&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压缩引擎&http://www.7-zip.org/zh-cn/sdk.html,LZMA&是&7-Zip&程序中&7z&格式&的默认压缩算法,压缩率很高。第四课&常见压缩壳与加密壳&
&&&&加壳软件按照其加壳目的和作用,可分为两类:一是压缩(Packers),二是保护(Protectors)。压缩这类壳主要目的是减小程序体
积,如ASPacK、UPX和PECompact等。另一类是保护程序,用上了各种反跟踪技术保护程序不被调试、脱壳等,其加壳后的体积大小不是其考虑的
主要因素,如ASProtect、Armadillo、EXECryptor等。随着加壳技术的发展,这两类软件之间的界线越来越模糊,很多加壳软件除具
有较强的压缩性能,同时也有了较强的保护性能。
&&&&目前流行的一些壳可以参考这里:&
1.常用压缩壳介绍&&&
1).&ASPacK&&&
&&&ASPack是款Win32可执行文件压缩软件,可压缩Windows&32位可执行文件(.exe)以及库文件(.dll、.ocx),文件压缩比率高达40%~70%。
主页:http://upx.sourceforge.net/&
&&&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&中的标记模式
asm&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&db&$EB,$10,'VMProtect&begin',0&&&&&&&//标记开始处.
//想保护的程序代码
&&db&$EB,$0E,'VMProtect&end',0&&&&&&&&&//标记结束处.
VC的VMProtect的宏&:
#define&&VMBEGIN&
&__asm&&&&//标记开始处.
&&&&&&_emit&0xEB
&&&&&&_emit&0x10&&
&&&&&&_emit&0x56&&
&&&&&&_emit&0x4D&&
&&&&&&_emit&0x50&
&&&&&&_emit&0x72&
&&&&&&_emit&0x6F&
&&&&&&_emit&0x74&
&&&&&&_emit&0x65&
&&&&&&_emit&0x63&
&&&&&&_emit&0x74&
&&&&&&_emit&0x20&
&&&&&&_emit&0x62&
&&&&&&_emit&0x65&
&&&&&&_emit&0x67&
&&&&&&_emit&0x69&
&&&&&&_emit&0x6E&
&&&&&&_emit&0x00
&&&&//想保护的程序代码
&#define&&VMEND
&&&&__asm&&//标记结束处.
&&&&&&_emit&0xEB
&&&&&&_emit&0x0E&&
&&&&&&_emit&0x56&&&
&&&&&&_emit&0x4D&&&
&&&&&&_emit&0x50&
&&&&&&_emit&0x72&
&&&&&&_emit&0x6F&
&&&&&&_emit&0x74&
&&&&&&_emit&0x65&
&&&&&&_emit&0x63&
&&&&&&_emit&0x74&
&&&&&&_emit&0x20&
&&&&&&_emit&0x65&
&&&&&&_emit&0x6E&
&&&&&&_emit&0x64&
&&&&&&_emit&0x00
VMProtect使用相关文档:
&&作者:acafeel
&作者:Anskya&
&作者:glucose
更多与壳有关的描述参考:
&&&&作者:forgot
常见加密壳官方站点&
ASProtect&&&&&&&&&&&&
ACProtect&&&&&&&&&&&&
Armadillo&&&&&&&&&&&&
EXECryptor&&&&&&&&&&&
Obsidium&&&&&&&&&&&&&
PESpin&&&&&&&&&&&&&&&
VMProtect&&&&&&&&&&&&
Xtreme-Protector&&&&&
Themida/WinLicense&&
第五课&文件类型分析&
&&&拿到一个壳,第一步就是用相关工具分析一下是什么壳,然后就可心中有数地跟踪分析。文件分析工具有,等。
&&&PEiD的GUI界面操作非常方便直观。它的原理是利用查特征串搜索来完成识别工作的。各种开发语言都有固定的启动代码部分,利用这点就可识别出是
何种语言编编译的。同样,不同的壳也有其特征码,利用这点就可识别是被何种壳所加密。PEiD提供了一个扩展接口文件userdb.txt&,用户可以自
定义一些特征码,这样就可识别出新的文件类型。
&&&有些外壳程序为了欺骗PEiD等文件识别软件,会伪造启动代码部分,例如将入口代码改成与Visual&C++&6.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自身脱不了,这时可以试试这款工具。
脱壳前建议用PE工具打开目标文件查看一下区块,以尽可能地多了解一些信息,对脱壳有帮助,如下图:
1.根据跨段指令寻找OEP
推荐用Ollydbg来调试脱壳,比SoftICE和TRW2000方便多了。运行Ollydbg,点击菜单&选项/调试设置&,将第一次暂停设在WinMain函数上。再用Ollydbg打开实例notepad.upx.exe就可中断在外壳的入口点处了:
上图相关代码如下:
&&&60&pushad&//一开始Ollydbg就会中断这行,这个就是外壳的入口点,注意这个pushad指令
绝大多数加壳程序在被加密的程序中加上一个或多个段,所以依据跨段的转移指令(JMP)就可找到真正的入口点,此时就会有POPAD/POPFD指令出现。UPX&用了一次跨段的转移指令(JMP),在跳到OEP处会看到虚拟地址的值有一个突变,此时就能确定OEP了。
UPX壳比较简单,大家不必要跟踪去找这个跨段的转移指令,中断WinMain后,只需要在Ollydbg里往下翻屏,就会发现这个跨段转移指令:
上图相关代码如下:
&popad&//注意这里的popad指令,和开始的pushad对应&
0040EA0F&-&E9&B826FFFF&jmp&004010CC&//这里跳到OEP,将光标移到这,按F4执行到这行
这一句0040EA0F&jmp&004010CC&就是跳到OEP的指令,执行到这,UPX外壳己将程序解压完毕,并模拟Windows加载器的将原始程序加载到内存,004010CC&就是映射到内存目标程序的入口点,此时就可抓取内存映像文件了。
2.根据堆栈平衡原理找OEP
这个堆栈平衡原理其找OEP原理这篇文档描述的比较详细:
操作方法:多数壳在运行到OEP的时候ESP=0012FFC4,这就是说程序的第一句是对0012FFC0进行写入操作,只要在0012FFC0下硬件写入断点(命令行里键入HW&12FFC0),我们就能停在OEP的第二句处。
注意:并不是所有程序加载时,ESP的值是0012FFC4,这个值是什么由决定,将SizeOfStackCOmmit改大
ESP就会变,这是因为从这个页向上找一个足够大地方当作stack了(感谢forgot解释)。你只要记住你系统加载时的ESP值,对其设断即
用OllyDBG重新加载实例程序notepad.upx.exe,在命令行下硬件写断点:
按F9执行程序,就会中断在OEP第二行:
此时如果将光标向上移,会发现第一句代码变乱了:
&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
&56&push&esi
&FF15&E4634000&call&[4063E4]&;&kernel32.GetCommandLineA
中断后,别忘点击菜单&调试/硬件断点/&打开硬件断点面板,将刚才的硬件断点删除。
3.根据编译语言特点找OEP
各类语言编译的文件入口点都有一些规律,可以这利用这点来寻找入口点。
1)Delphi程序
执行程序,用LordPE(或Prodump)选dump(full)脱壳,存为dump.exe。接着用Hex&Workshop打开
dump.exe,搜索文本&runtime&,搜到后,向前查找离&runtime&最近的十六进制数字&55&8B&EC&,数字所在的地址就是程序
2)Visual&C程序
可以利用Visual&C启动部分的几个函数GetCommandLineA(W)、GetVersion、GetModuleHandleA(W)、GetStartupInfoA(W)&等来定位程序的OEP。
常见的各类编译语言的入口汇编代码都要熟悉,因为一些加密强壳会偷OEP处的代码到壳里,一般情况各编译语言入口代码都相同,到时只需要直接引用相关程序的入口代码,这给我们恢复代码带来方便。4.用内存断点找OEP
Author:Lenus
From:&&&&&&
E-mail:Lenus_
--------------------------------------------------
&&&发现论坛中很多兄弟在询问:什么是二次内存断点,三次内存断点。还有很多人对内存断点的原理不是很明白。其实只要懂得壳是如何解压代码的,那么就完全可以按自己的喜欢来下断。
&&&本文要解决的问题是:
&&&1.什么是内存断点?
&&&2.如何在寻找OEP时使用内存断点。
&&&3.内存断点的局限性。
2.内存断点寻找OEP的原理
&&i.首先,在OD中内存断点,硬件断点和普通断点(F2下断)是有本质区别的。硬件断点等效与SoftICE命令bpm,他的中断要用到DR0-DR7的调试寄存器,也就是说OD通过这些DR0-DR7的调试寄存器来判断是否断下。
&&&&普通断点(F2下断)等效于bpx,他是在所执行的的代码的当前地址的一个字节修改为CC(int3)。当程序运行到int3的时候就会产生一个
异常,而这个异常将交给OD处理,把这个异常的regEIP-1以后就正好停在了需要的中断的地方(这个根据系统不同会不一样),同时OD在把上面的
int3修改回原来的代码。
&&而内存断点基本上使用的是对代码使用的保护属性来实现中断。
&&内存断点分为:内存访问断点,内存写入断点。
&&我们知道,在程序运行的时候会有3种基本的状态产生:读取,写入,执行。
004AE242&&&&&A1&&&&&&&&mov&eax,dword&ptr&ds:[004AE24C]&&&&&&&&&&&&//004AE24C处的内存读取
004AE247&&&&&A3&&&&&&&&mov&dword&ptr&ds:[004AE24C],eax&&&&&&&&&&&&//004AE24C处的内存写入
004AE24C&&&&&83C0&01&&&&&&&&&&&add&eax,1&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&//004AE24C处的内存执行
&&那么我们应该如何中断在上面的几行呢?
&&1.当我们对004AE24C下内存访问断点的时候,可以中断在004AE242也可以中断在004AE247。
&&2.当我们对004AE24C下内存写入断点的时候,只能中断在004AE247。
&&3.当我们对004AE24C下内存访问断点的时候,能中断在004AE24C。
&&到这里你可能不明白了,为什么内存访问断点能中断在004AE247这一句对004AE24C的写入,而且还能中断在004AE24C的执行呢?
&&其实很简单,我们只要仔细体会一下&内存访问&这四个字的含义遍可以知道,当我们对004AE24C进行读取的时候需要&访问&他吧,当我对
004AE24C进行写入的时候也需要&访问&他吧!!当然我们要执行内存地址004AE24C的代码的时候也是还是要&访问&他的!
&&所以我们不难得出下面的结论:
&&1.内存写入中断的地方,一定是也可以用内存访问中断。
&&2.内存执行的地方,也可以用内存访问中断。
&&如果这时你认为,那么内存写入岂不是没用了。呵呵~那我要告诉你当然不是,如果你想快速的准确的定位到004AE247这一行的时候,那么他就大有作用了!
&&总结一下:内存断点不修改改原代码,不会像普通断点那样因为修改代码被程序校验而导致中断失败;对于区段的访问只是区域大了一点,其原理和上面分析的三行代码是一样的。
&&ii.如何使用内存断点来寻找OEP呢?
&&要回答这个问题首先要回答这一个问题:壳是如何解压代码的?
&&正如我们知道的,壳如果要把原来加密或压缩的代码运行起来就必须要解压和解密原来的代码。而这一个过程我们难道不能将他看做是对代码段(code段)
的写入吗?好了,解压完毕了。我们要从壳代码的区段JMP到原来的代码段的时候,难道不正是对代码段(code段)的执行吗?
&&理清了上面的关系就好办了,那么如果载入OD后,我们直接对code段下内存访问断点的时候,一定会中断在壳对code段的写入的代码的上面,就像上
面的004AE247的这一行。而如果当他把code段的代码全部解压解密完毕了以后,JMP到OEP的时候,我们是不是还可以停在OEP的代码上面呢?
而且每按下F9都会中断,因为这时code段在执行中哦!
&&相信很多人到这里已经明白了,为什么在教程中到达了某一个时候,某一行的时候。牛人们就叫我们对code段下内存访问断点了吧。
&&而如果你还要继续问我为什么一定要到那个地方才可以下断呢?我难道不可以一开始就下断吗?
&&正入我上面所说的,如果你在前面下断很可能壳对code段还没解压完毕呢,这时如果你不停的按F9,你将会看到OD的下方不断的在提示你&对
401000写入中断&&&对401002写入中断&&对401004写入中断&.......如果你不介意按F9到他把正个code段写完的话,我除了
同情你的&F9&以外,没什么其他的意见!
&&那么我们就没有别更快一点的办法了吗?
&&有的!那就是我们呼之欲出的两次内存断点办法。
&&怎么理解两次内存断点呢?
&&让我来做一个假设吧,假设我是一个壳的作者。一个EXE文件的有code段,data段,rsrc段.....依次排列在你的内存空间中,那么我会怎
么解码呢?呵呵~我比较笨一点,我会先将code段解码,然后再将data段解压,接着是rsrc段......那么聪明的你不难发现,只要你在data
断或者rsrc段下内存访问断点,那么中断的时候code段就已经解压完毕了。这时我们再对code段下内存反问断点,不就可以到达OEP了吗?
&&这里注意上面虽然下了两次内存访问断点,但是本质是不一样的,目的也是不一样的。
&&1.对data段下内存访问断点而中断是因为内存写入中断,目的是断在对对data段的解压时,这时壳要对data段写数据,但是code段已经解压完毕。
&&2.对code段下内存访问断点而中断是因为内存执行中断,目的当然就是寻找OEP了。
&&总结一下:如果我们知道壳在什么地方对code段解压完毕我们就可以使用内存断点,找到OEP。如果不知道,那么我们就依靠2次内存断点去找,如果还不行就用多次内存断点。总之明白了原理在多次的内存断点其实都一样。从这个过程中我们了解的是壳在对区段解码的顺序!
&&iii.实战
&&说了这么多,我想大家都越越欲试了吧。
&&好吧,来弄一个猛壳怎么样:
注:本节实例有些难度,不适合新手练习,新手可以跳过这个实例的学习,等找到合适的实例会补充上来的&
&&这个壳是一个hying的旧版,我们用他来实验一下我们内存断点法。
&&OD载入以后来到这里
&u&&&56&&&&&&&&&&&&&&&&&&&&push&esi&&&&&&&&&&&&&&//这里
&&&&&52&&&&&&&&&&&&&&&&&&&&push&edx
&&&&&51&&&&&&&&&&&&&&&&&&&&push&ecx
&&&&&53&&&&&&&&&&&&&&&&&&&&push&ebx
&&&&&55&&&&&&&&&&&&&&&&&&&&push&ebp
&&&&&E8&&&&&&&&&&&&call&unpackme.0040D11F
&&根据跟过一次的经验我们将先设置,除int3异常以外忽略其他异常,SHIFT+F9
&&&&64:&&&&&&&&mov&&&&&fs:[0],&esp
&&&&CC&&&&&&&&&&&&&&&&&&&&&int3
&&&&&90&&&&&&&&&&&&&&&&&&&&nop&&&&&&&&&&&&&&&&&&&&//到这里
003725BA&&&&&8BCD&&&&&&&&&&&&&&&&&&mov&ecx,ebp
&&然后再设置除&除零&异常外,忽略其他异常。SHIFT+F9
&&&&&F7F3&&&&&&&&&&&&&&&&&&div&ebx&&&&&&&&&&&&&&&&//到这里
&&&&&90&&&&&&&&&&&&&&&&&&&&nop
&&下面是很多的单步异常,太麻烦我们不管他,现在开始用内存断点的方法(记得将所有异常忽略)。
对code段下内存访问断点,希望他已经解压完毕。方法是按ALT+M键打开内存窗口,在.code段按F2设断:
SHIFT+F9执行:
0040D19D&&&&&A4&&&&&&&&&&&&&&&&&&&&movs&byte&ptr&es:[edi],byte&ptr&ds:[esi]&&&&&&&&&//还没解完呢
0040D19E&&&&&B3&02&&&&&&&&&&&&&&&&&mov&bl,2
对data段下内存&写入&断点,试试看他是不是要写data段。
&&&&&F3:A4&&&&&&&&&&&&&&&&&rep&movs&byte&ptr&es:[edi],byte&ptr&ds:[esi]&&&&&&//断到这里
&&&&&5E&&&&&&&&&&&&&&&&&&&&pop&esi
下面再对code段下内存访问断点。F9
&&&&&8907&&&&&&&&&&&&&&&&&&mov&dword&ptr&ds:[edi],eax&&&&&&&&&&&&&&&&&&&&&&&&&;&SHELL32.DragFinish&&//这里是对IAT加密
的地方了!!!
&&&&&5A&&&&&&&&&&&&&&&&&&&&pop&edx
&&&&&0FB642&FF&&&&&&&&&&&&&movzx&eax,byte&ptr&ds:[edx-1]
0037285C&&&&&03D0&&&&&&&&&&&&&&&&&&add&edx,eax
0037285E&&&&&42&&&&&&&&&&&&&&&&&&&&inc&edx
0037285F&&&&&83C7&04&&&&&&&&&&&&&&&add&edi,4
&&&&&59&&&&&&&&&&&&&&&&&&&&pop&ecx
&&&^&E2&A9&&&&&&&&&&&&&&&&&loopd&short&0037280E
&&&^&E9&63FFFFFF&&&&&&&&&&&jmp&003727CD
0037286A&&&&&8BB5&&&&&&&&&&mov&esi,dword&ptr&ss:[ebp+693]&&&&&&&&&&&&&&&&&&&&&&//到这里下断F2
现在如果再对data下访问断点已经是没用了。这时应该格外的小心。
我们现在就想既然这一段是对code解码的,那么我们就绕过他吧!
到0037286A下断F2,然后清除内存断点!!!!
F9以后停在这里,继续对code下内存访问断点。
看看左下角还在解码,哎~真是麻烦!
&&&&/EB&1D&&&&&&&&&&&&&&&&&jmp&short&
&&&&|25&FFFFFF7F&&&&&&&&&&&and&eax,7FFFFFFF
&&&&|0&&&&&&&&&add&eax,dword&ptr&ss:[ebp+683]
003728EE&&&&|2B85&8F060000&&&&&&&&&sub&eax,dword&ptr&ss:[ebp+68F]
&&&&|8BDE&&&&&&&&&&&&&&&&&&mov&ebx,esi
&&&&|2BD8&&&&&&&&&&&&&&&&&&sub&ebx,eax
&&&&|8958&FC&&&&&&&&&&&&&&&mov&dword&ptr&ds:[eax-4],ebx&&&&&&&&&&&&&&&&&&&&&//停在这里
003728FB&&&&|83C7&08&&&&&&&&&&&&&&&add&edi,8
003728FE&&&^|EB&DB&&&&&&&&&&&&&&&&&jmp&short&003728DB
&&&&\64:FF35&&&&&&&push&dword&ptr&fs:[30]&&&&&&&&&&&&&&&&&&&&&&&&&&//清除内存断点以后到这里下断,F9
又是一段解码的代码,再次使用上面的办法手动跳出去。
现在继续对code段下内存访问断点!!F9以后到达这里。
004010CC&&&&&FFD7&&&&&&&&&&&&&&&&&&call&edi&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&;&unpackme.004010CE&&&//OEP哦
004010CE&&&&&58&&&&&&&&&&&&&&&&&&&&pop&eax
004010CF&&&&&83EC&44&&&&&&&&&&&&&&&sub&esp,44
&&&&&56&&&&&&&&&&&&&&&&&&&&push&esi
&&&&&90&&&&&&&&&&&&&&&&&&&&nop
&&&&&E8&B518F7FF&&&&&&&&&&&call&0037298E
&&&&&8BF0&&&&&&&&&&&&&&&&&&mov&esi,eax
呵呵~虽然不是我们熟悉的OEP,但是地址是没错了,况且根据我们的步骤,我可以很肯定的说这是code段的第一次&执行&中断!
所以这就是OEP了。
总结一下:当我们在寻找OEP的时候,要多次对code下断&赌&一&赌&他解压完毕,如果不是就对别的段试试~如果程序跑飞了,那就没办法了,重来呗~
其实说起来要赌的是:当data段,idata段,rsrc段摆在你的面前,你会好好&珍惜&那个段,不过还好上天还会给我们从来一次的机会
(ctrl+F2&^_^),那么我们会对那个不会跑飞的段说3个字----&先断你&如果非要在上面加一个次数,我希望是&一次内存断点就好了&
&&vi.下面来讨论一下内存断点的局限性问题。
&&是不是什么壳都可以用内存中断啊?
&&不是每个都可以的,一些像UPX和ASPACK就不行。
&&为什么?
&&呵呵~follew&me!
&&我们来看看UPX的壳
首先,他的壳代码在UPX1段。
这里是他要跳到OEP的地方
0040ED4F&&&&/77&11&&&&&&&&&&&&&ja&short&NOTEPAD_.0040ED62&&&&&&&&&&&&
0040ED51&&&&|01C3&&&&&&&&&&&&&&add&ebx,eax
0040ED53&&&&|8B03&&&&&&&&&&&&&&mov&eax,dword&ptr&ds:[ebx]
0040ED55&&&&|86C4&&&&&&&&&&&&&&xchg&ah,al
0040ED57&&&&|C1C0&10&&&&&&&&&&&rol&eax,10&&&&&&&&&&&&&&&&&&&&&&&&&&&//在解码
0040ED5A&&&&|86C4&&&&&&&&&&&&&&xchg&ah,al
0040ED5C&&&&|01F0&&&&&&&&&&&&&&add&eax,esi
0040ED5E&&&&|8903&&&&&&&&&&&&&&mov&dword&ptr&ds:[ebx],eax
0040ED60&&&^|EB&E2&&&&&&&&&&&&&jmp&short&NOTEPAD_.0040ED44
0040ED62&&&&\24&0F&&&&&&&&&&&&&and&al,0F
0040ED64&&&&&C1E0&10&&&&&&&&&&&shl&eax,10
0040ED67&&&&&66:8B07&&&&&&&&&&&mov&ax,word&ptr&ds:[edi]
0040ED6A&&&&&83C7&02&&&&&&&&&&&add&edi,2
0040ED6D&&&^&EB&E2&&&&&&&&&&&&&jmp&short&NOTEPAD_.0040ED51&&&&&&&&//回跳解码
0040ED6F&&&&&61&&&&&&&&&&&&&&&&popad
0040ED70&&&-&E9&5723FFFF&&&&&&&jmp&NOTEPAD_.004010CC&&&&&&&&&&&&&//跳到OEP
我们看到他在对code段解压完毕的时候马上就JMP到OEP去了,那么我们根本就来不及使用内存断点的办法。
你可能说,我可以在
0040ED6F&&&&&61&&&&&&&&&&&&&&&&popad&//这一句下段然后使用啊
呵呵~~当然可以,不过你把花在下内存断点的时间,多按下几次F8不更好?!
也就是说当一个壳如果他在JMP&到OEP前的一行代码仍在都在对code段解压,那么我们就不能再使用这种办法了!
或者说我们没必要使用内存断点更贴切一点!
&&对于一些在OEP处有stolen&code的代码
&&我们来看看一个OEP
&u&&&55&&&&&&&&&&&&&&&&push&ebp&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&//OEP
&&&&&8BEC&&&&&&&&&&&&&&mov&ebp,esp
&&&&&83C4&F4&&&&&&&&&&&add&esp,-0C
0049E2FA&&&&&B8&BCE04900&&&&&&&mov&eax,unpack.0049E0BC
0049E2FF&&&&&E8&048CF6FF&&&&&&&call&unpack.00406F08&&&&&&&&&&&&&&&&&&&//这里调用子程序
&&&&&A1&B8FE4900&&&&&&&mov&eax,dword&ptr&ds:[49FEB8]
&&&&&50&&&&&&&&&&&&&&&&push&eax
0049E30A&&&&&6A&00&&&&&&&&&&&&&push&0
0049E30C&&&&&68&1F000F00&&&&&&&push&0F001F
&&&&&E8&E68EF6FF&&&&&&&call&&jmp.&kernel32.OpenFileMappingA&&&//API
&&&&&A3&60194A00&&&&&&&mov&dword&ptr&ds:[4A1960],eax
0049E31B&&&&&833D&&&cmp&dword&ptr&ds:[4A1960],0
这个软件在被PESPIN加壳了以后这些全被偷掉了!
也就是说,壳在模拟OEP代码的时候必然会执行
0049E2FF&&&&&E8&048CF6FF&&&&&&&call&unpack.00406F08&&//这一步
而这个地方是call向code段的。如果我们使用内存访问断点,那么就停在这个子程序的地方
00406F08&&&&&50&&&&&&&&&&&&&&&&push&eax&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&//会停在这里
00406F09&&&&&6A&00&&&&&&&&&&&&&push&0
00406F0B&&&&&E8&F8FEFFFF&&&&&&&call&&jmp.&kernel32.GetModuleHandleA&
00406F10&&&&&BA&04F14900&&&&&&&mov&edx,unpack.
00406F15&&&&&52&&&&&&&&&&&&&&&&push&edx
这里既不是处理stolen&code的地方,也不是FOEP的地方。这就会对我们的判断产生误导。
当然你可以alt+F9返回到壳处理stolen的地方,然后用内存断点,或者按几下F8到达FOEP处,但试问如果你拿到一个未知的壳的时候又怎么知道应该这么处理呢?
还有其他一些情况留给大家总结吧!
在下的砖已抛出,各位的玉不久矣。
--------------------------------------------------
&&&&&&好了说了很多,大家应该对内存断点的办法有了全面的了解,如果了解了内存断点的原理就不难明白他的使用方法,不难明白为什么有写壳不能使用内存断点的办法,其实任何的一种办法都需要经验的积累。相信如果大家在回答开篇的3个问题,已经不难了。
&&&&&&大家可以结合原理再好好的体会一下《手动脱壳进阶第八篇Skvp1.32》这篇文章。第七课&Dump内存映像&&
&&&&外壳程序解压还原后就会跳到OEP处执行,此时内存映像文件是己解压的程序。这时就可抓取内存映像文件了(该过程称为Dump)。当然不一定非要在程序原入口点抓取,只要能保证内存映像文件是己还原的就行了。
&&&&有关Dump技术的原理大家可以参考:&
&&&&继续上一个实例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&菜单命令。如图:
&&&将内存抓取的文件另存为dumped.exe,此时程序还不能运行,接下来就是重建输入表。第八课&重建输入表&&
&&&在脱壳中输入表处理是很关键的一个环节,因此要求脱壳者对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的RVA值,这里填上10CC。点击
&IAT&AutoSearch&按钮,让其自动检测IAT偏移和大小,如出现下图表示ImportREC自己找到IAT的地址与大小了,即IAT地
址:,大小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查看脱壳后的输入表:
从上图可以看出,输入表己正确修复,此时脱壳后的文件己能成功运行了。第九课&手动确定IAT的地址与大小&&
&&&&在第八课中讲到,点击ImportREC的&IAT&AutoSearch&按钮,一般情况下ImportREC可以自动识别出IAT地址与大
小。但如果不能自动识别,就必须手动确定IAT地址与大小,然后将IAT的RVA与Size填进ImportREC,点击&Get&Import&按钮就
可得到输入表。
&&&&还是用上一节实例演示,用OD打开notepad.upx.exe,来到OEP处:
&&&&随便找一个API函数调用语句,如:
&&&&FF15&E4634000&&&call&&&&[4063E4]&&&&&&&&&&;&kernel32.GetCommandLineA
&&&其中地址4063E4就是IAT中的一部分,在数据窗口下命令:D&4063E4,显示如下:
&&上图每一组数据都是指向一个API函数,如&8D&2C&81&7C&就是地址:7C812C8D,在OD里按Ctrl+G,输入7C812C8D跳到这个地址就会发现是kernel32.GetCommandLineA函数:
&&&IAT是一块连续排列的数据,因此在数据窗口向上翻屏,直到出现00数据,寻找IAT起始地址:
然后向下翻屏,寻找IAT结束地址:
为了直观些,你也可以这样让数据窗口直接显示这些API函数,以确定IAT是否正确,在数据窗口点击鼠标右键:
调整显示格式后的数据窗口:
这样就直观了,IAT中每组数据指向一个API函数,各DLL之间是以000000分开的。
因此IAT范围:0xx406524&,大小为0xxx240&
如果IAT加密了,此时IAT中的地址不是指向系统DLL中的API函数了,可能指向外壳。这就十分有必要找到外壳处理IAT的代码了,前面己说过,外壳
加载时,会模拟Windows加载器,向IAT里填充当前API函数的实际地址。所以,在IAT里设个内存写断点,就可中断到这段代码处。
重新加载notepad.upx.exe,在IAT某个地址下内存写断点,这里选择0x4062E4这个地址设内存写断点,先在数据窗口下命令:D&4062E4
然后选择一个地址,点击鼠标右键,下&内存写断点&。
此时只要有数据写入4062E4地址处,OD就会中断,按F9运行OD,会中断这里:
0040E96D&&&&&&/8A02&&&&&&&&&&mov&&&&&al,&[edx]
0040E96F&&&&.&|42&&&&&&&&&&&&inc&&&&&edx
&&&&.&|8807&&&&&&&&&&mov&&&&&[edi],&al
&&&&.&|47&&&&&&&&&&&&inc&&&&&edi
&&&&.&|49&&&&&&&&&&&&dec&&&&&ecx
&&&&.^\75&F7&&&&&&&&&jnz&&&&&short&0040E96D
这段还不是处理IAT,按F9继续执行程序,会中断这里:
&&&&&&/8A07&&&&&&&&&&mov&&&&&al,&[edi]
0040E9EB&&&&.&|47&&&&&&&&&&&&inc&&&&&edi
0040E9EC&&&&.&|08C0&&&&&&&&&&or&&&&&&al,&al
0040E9EE&&&&.^|74&DC&&&&&&&&&je&&&&&&short&0040E9CC
&&&&.&|89F9&&&&&&&&&&mov&&&&&ecx,&edi
&&&&.&|57&&&&&&&&&&&&push&&&&edi&&&&&&&&&&&&&&&&&&&&&&&&//&函数名字符串&&
&&&&.&|48&&&&&&&&&&&&dec&&&&&eax
&&&&.&&F2:AE&&&&&&&&&repne&&&scas&byte&ptr&es:[edi]
&&&&.&|55&&&&&&&&&&&&push&&&&ebp&&&&&&&&&&&&&&&&&&&&&&&&//&DLL模块句柄
&&&&.&&FF96&A4EC0000&call&&&&[esi+ECA4]&&&&&&&&&&&&&&&&&;&&kernel32.GetProcAddress
0040E9FD&&&&.&|09C0&&&&&&&&&&or&&&&&&eax,&eax
0040E9FF&&&&.&|74&07&&&&&&&&&je&&&&&&short&0040EA08
0040EA01&&&&.&|8903&&&&&&&&&&mov&&&&&[ebx],&eax&&&&&&&&&&&&&&&&//&EBX指向IAT,将取得的API地址填充进IAT
0040EA03&&&&.&|83C3&04&&&&&&&add&&&&&ebx,&4&&&&&&&&&&&&&&&&&&&&//&指向下一个地址
0040EA06&&&&.^\EB&E1&&&&&&&&&jmp&&&&&short&
0040EA08&&&&&&&FF96&A8EC0000&call&&&&[esi+ECA8]
上面这段就是UPX外壳填充IAT的全过程,感兴趣的,动态跟踪一下就明白了。这里用GetProcAddress函数获得函数地址:
FARPROC&GetProcAddress(
&&HMODULE&hModule,&&&&//&DLL模块句柄
&&LPCSTR&lpProcName&&&//&函数名
);第十课&DLL文件脱壳&&
第十一课&优化与自校验去除&&
第十二课&Armadillo壳&&
相应工具下载页面:/tools/unpacker.htm
Armadillo&find&protected:检测&Armadillo版本号及其保护类型
dilloDIE:一款脱&Armadillo&4.xx&的脱壳机
ArmaGUI:Armadillo&3.xx/4.xx&脱壳机
ArmInline:辅助处理Armadillo壳,其中Code&Splicing修复的很完美。输入表混淆修复感觉有些问题,建议手工修复。
手动脱壳教学
&(基础知识)
&(利用插件Dump取COPYMEMEII保护的程序)
&(Dump取COPYMEMEII保护的程序另一方法)
&(处理IAT乱序)
&(手工修复Code&Splicing)
&(利用ArmInline工具修复Code&Splicing)
&(Nanomites原理概念,即CC保护)
&(修复CC)
&(目前处理CC很好的一个方法)
带key脱壳:
/showthread.php?threadid=23174第十三课&ASProtect&2.x壳&&
PE_Kill出品的ASProtect自动脱壳机,功能非常的强大,能自动修复SDK,ASProtect&2.x之前的版本完全支持。
VolX这个脚本其实是一个ASProtect脱壳机了,支持Asprotect&1.32,&1.33,&,1.35,&1.4,&2.0,&2.1,&2.11,&2.2beta,&2.2,&2.3
1.Ollydbg&1.1
2.Odbgscript&1.47&或以上的版本(OD插件,一般集成OD都有)
3.Import&Reconstructor
运行Ollydbg打开目标程序,单击OD菜单&插件/Odbgscript/运行脚本&,打开VolX这个脚本:Aspr2.XX_unpacker_v1.0SC.osc
然后按着脚本提示操作就可。
脚本跑完,会在目标软件的目录生成一个de_文件名.exe,OD的记录窗口(按Alt+L)打开显示了OEP,IAT等信息,如:
&&&&&&&&&&&IAT&的地址&=&
&&&&&&&&&&&IAT&的相对地址&=&
&&&&&&&&&&&IAT&的大小&=&000000BC
00A70042&&&断点位于&00A70042
&&&&&&&&&&&OEP&的地址&=&00401D2B
&&&&&&&&&&&OEP&的相对地址&=&00001D2B
接下来,你再用Import&Reconstructor修复输入表即可,最后Fix&Dump时选中de_文件名.exe.
一般情况下,用ASProtect&unpacker&by&PE_Kill就能脱Asprotect了。如果你要手工脱壳,如下文章可参考:
&(Dump法对付stolen&OEP)
&(ASProtect&2.11的stolen与SDK修复技术&)
(ASProtect&2.22/2.23的stolen与SDK修复技术&)
附ASProtect脱壳机:
ASProtect1.2以前版本,可以用
ASProtect1.2x,可以用
ASProtect&1.3~ASProtect&2.0&,可以用
ASProtect&SKE&2.11以前版本,可以用
ASProtect&所有版本,包括&SKE&2.2/2.3&&摘自:/showthread.php?t=20366
【声明】:黑吧安全网()登载此文出于传递更多信息之目的,并不代表本站赞同其观点和对其真实性负责,仅适于网络安全技术爱好者学习研究使用,学习中请遵循国家相关法律法规。如有问题请联系我们,联系邮箱,我们会在最短的时间内进行处理。
上一篇:【】【】

我要回帖

更多关于 c32反汇编 的文章

 

随机推荐