配色: 字号:
分享Armadillo的简单脱壳技巧
2012-06-14 | 阅:  转:  |  分享 
  
分享Armadillo的简单脱壳技巧

Armadillo壳(被称作穿山甲保护壳)是一种加密壳,用前人发明的ESP定律脱壳办法是无法完成脱壳工作的,属于界内的猛壳之一。Armadillo壳保护,通俗来讲可以这样简单的分类理解:保护系统授权等级、进程模式、程序所使用保护模式、其它设置。保护系统授权等级分为标准版、非标准版、专业版;进程模式分为:单进程、双进程;程序所使用保护模式分为:输入表乱序、策略代码衔接、Nanomites处理程序等保护模式;其它设置可以进行Key和时间等设定。经过任意组合后,就会形成强大的保护机制,形式多样,变幻莫测!这样会使很多“初生牛犊”望而怯步!下面谈一下Armadillo保护壳单、双进程的简单脱法,使之不再成为难事。

Armadillo1.xx-2.xx单进程的简单脱法1)准备工作,收集所有信息用PEiD侦壳为“Armadillo1.xx-2.xx->SiliconRealmsToolworks”,用ArmadilloFindProtectedV1.4汉化版查看保护机制,得知目标经Armadillo保护,保护系统授权等级(标准版);程序所使用保护模式为标准保护或最小保护模式;备份密钥设置为固定的备份密钥;程序压缩设置为最小/最快的压缩方式;其它保护设置为版本号3.70。这可谓是最基本的保护设置了。运行目标程序,再运行LordPE,查看得知是单进程模式,如图1所示。至此,信息收集完毕!



javascript:dcs.images.doResizes(this,0,null);border=0>图1

2)OD定位运行OD,载入目标程序czssgold.exe(在C:\ProgramFilessmswriter\彩尊圣手黄金版),停在这里。

004C9B19>/$?55pushebp载入处004C9B1A|.8BEC?movebp,esp004C9B1C|.6AFF?push-1004C9B1E|.68385A4E00?push004E5A38004C9B23|.6800954C00?push004C9500;SE处理程序安装004C9B28|.64:A10000000>moveax,dwordptrfs:[0]004C9B2E|.50pusheax004C9B2F|.64:892500000>movdwordptrfs:[0],esp004C9B36|.83EC58?subesp,58004C9B39|.53pushebx004C9B3A|.56pushesi004C9B3B|.57pushedi004C9B3C|.8965E8?movdwordptr[ebp-18],esp004C9B3F|.FF154C014E00calldwordptr[<&KERNEL32.GetVersion>;kernel32.GetVersion004C9B45|.33D2?xoredx,edx

我们一般是下BPGetModuleHandleA断点,我是用Ctrl+G,输入GetModuleHandleA,点确定后,程序在OD中会停在下面的代码处。

7C80B529>8BFFmovedi,edi;停在这里7C80B52B55?pushebp7C80B52C8BECmovebp,esp7C80B52E837D0800?cmpdwordptr[ebp+8],07C80B5327418??je?short7C80B54C;F2断点7C80B534FF7508?pushdwordptr[ebp+8]7C80B537E8682D0000call7C80E2A47C80B53C85C0testeax,eax7C80B53E7408jeshort7C80B5487C80B540FF7004pushdwordptr[eax+4]7C80B543E8F4300000callGetModuleHandleW7C80B5485Dpopebp7C80B549C20400retn4

在7C80B532处下F2断点,然后按Shift+F9,之后看堆栈。SHIFT+F9一次,堆栈结果:

0013FF34/0013FFC00013FF38|004C9BE1;返回到czssgold.<模块入口点>+0C8来自kernel32.GetModuleHandleA

Shift+F9两次,堆栈结果:

0013EC68/0013ECA00013EC6C|5D175324;返回到5D175324来自kernel32.GetModuleHandleA0013EC70|5D175370ASCII"kernel32.dll"0013EC74|5D1E3AB80013EC78|000000000013EC7C|5D1700000013EC80|7C812972;返回到kernel32.7C812972来自ntdll.RtlCreateHeap0013EC84|000010020013EC88|0013EC74

Shift+F9三次,堆栈结果:0013ED28/0013ED440013ED2C|77F45BD8;返回到SHLWAPI.77F45BD8,来自kernel32.GetModuleHandleA0013ED30|77F4501CASCII"KERNEL32.DLL"0013ED34|000000010013ED38|77F40000SHLWAPI.77F40000

Shift+F9四次,堆栈结果:0013F53C/0013F5A40013F540|004B50E3;返回到czssgold.004B50E3,来自kernel32.GetModuleHandleA0013F544|000000000013F548|0000FFFF0013F54C|00BE6C6A0013F550|00536E5Fczssgold.00536E5F0013F554|000000000013F558|00500000ASCII"PDATA000"0013F55C|004E0500ASCII""",error%d"

Shift+F9五次,堆栈结果:0013BB1C/0013ED6C0013BB20|00BFF65E;返回到00BFF65E来自kernel32.GetModuleHandleA0013BB24|00C10B58ASCII"kernel32.dll"0013BB28|00C11BB4ASCII"VirtualAlloc"

Shift+F9六次,堆栈结果:0013BB1C/0013ED6C0013BB20|00BFF67B;返回到00BFF67B,来自kernel32.GetModuleHandleA0013BB24|00C10B58ASCII"kernel32.dll"0013BB28|00C11BA8ASCII"VirtualFree"

Shift+F9七次,堆栈结果:0013B894/0013BB200013B898|00BE97CD;返回到00BE97CD来自kernel32.GetModuleHandleA0013B89C|0013B9D4ASCII"kernel32.dll"

这时,再看一下寄存器窗口,代码如下。

EAX0013B9D4ASCII"kernel32.dll"

ECX0013B9E0EDX0013B9D4ASCII"kernel32.dll"EBX00C0FFC4ESP0013B894EBP0013B894

注意,在这里,取消了7C80B532处的断点,按Alt+F9,执行到用户代码,来到如下代码处。00BE97CD8B0DA04CC100?movecx,dwordptr[C14CA0]00BE97D389040E?movdwordptr[esi+ecx],eax00BE97D6A1A04CC100moveax,dwordptr[C14CA0]00BE97DB393C06?cmpdwordptr[esi+eax],edi00BE97DE7516??jnzshort00BE97F600BE97E08D85B4FEFFFF?leaeax,dwordptr[ebp-14C]00BE97E650?pusheax00BE97E7FF15E0B0C000?calldwordptr[C0B0E0];kernel32.LoadLibraryA00BE97ED8B0DA04CC100?movecx,dwordptr[C14CA0]00BE97F389040E?movdwordptr[esi+ecx],eax00BE97F6A1A04CC100moveax,dwordptr[C14CA0]00BE97FB393C06?cmpdwordptr[esi+eax],edi00BE97FE0F84AD000000?je?00BE98B1?;传说中的魔法跳,修改成JMP00BE980433C9xorecx,ecx00BE98068B03moveax,dwordptr[ebx]00BE98083938cmpdwordptr[eax],edi00BE980A7406??je?short00BE981200BE980C41?incecx00BE980D83C00C?addeax,0C00BE9810^EBF6??jmpshort00BE980800BE98128BC1moveax,ecx

在00BE97CD处设断点,然后Shift+F9,就会停在00BE97CD处。00BE97E7处的函数kernel32.LoadLibraryA是判断返回时机的重要标志,如图2所示。在00BE97FE处,也就是传说中的魔法跳,把JE直接修改成JMP,即可。然后,取消所有断点,使用内存断点大法(当然,修改完魔法跳以后,直达OEP的方法很多),打开内存窗口,在401000处下F2断点。按Shift+F9运行,就会到达OEP(心中一定很激动吧!)。代码如下。?javascript:dcs.images.doResizes(this,0,null);border=0>



图2

0043DC0D6A60??push60?;OEP0043DC0F6840A04800push0048A0400043DC14E8BB0C0000call0043E8D40043DC19BF94000000movedi,940043DC1E8BC7moveax,edi0043DC20E8DBF0FFFFcall0043CD000043DC258965E8?movdwordptr[ebp-18],esp0043DC288BF4movesi,esp0043DC2A893Emovdwordptr[esi],edi0043DC2C56?pushesi0043DC2DFF1504944700?calldwordptr[479404];kernel32.GetVersionExA0043DC338B4E10?movecx,dwordptr[esi+10]0043DC36890D60DD4900?movdwordptr[49DD60],ecx0043DC3C8B4604?moveax,dwordptr[esi+4]0043DC3FA36CDD4900movdwordptr[49DD6C],eax0043DC448B5608?movedx,dwordptr[esi+8]0043DC47891570DD4900?movdwordptr[49DD70],edx0043DC4D8B760C?movesi,dwordptr[esi+C]0043DC5081E6FF7F0000?andesi,7FFF0043DC56893564DD4900?movdwordptr[49DD64],esi0043DC5C83F902?cmpecx,20043DC5F740C??je?short0043DC6D0043DC6181CE00800000?or?esi,8000

在0043DC0D处,就可以DUMP程序,到此OD的任务已经完成,但千万不要关闭OD。(这应该是医生对病人的病灶部位准确定位,如果定位的设备撤了,医生岂不是瞎子!刀子乱来,病人能好的了吗?呵呵……)

3)LordPe脱壳脱加密壳一般不用OD的插件,我喜欢使用LordPe工具。运行LordPe,找到脱壳的目标程序czssgold.exe,鼠标左键点击一下,这时下面的窗口就会有数据出现了,再用鼠标右键点击上面的目标程序,在弹出的菜单中,先“修正镜像大小”,然后“完整转存”就会在现有的文件夹下,转存出一个dumped.exe文件,不过这只是个半成品,到此LordPe的工作告一段落(这应该是医生对病人的手术过程)。OD没有关吧?4)ImportREC工具修复运行ImportREC,如图3所示,在“选择一个进程”栏里,找到目标进程czssgold.exe,点击一下,在OEP窗口中输入3DC0D(为啥?0043DC0D-400000的结果),点击“自动搜索IAT”,弹出窗口,点确定,点击“获得输入信息”,窗口中就会出现数据,点击“无效函数”,看看是否有无效的函数,对于无效函数,直接剪掉就可以了;然后,点击“修复抓取文件”,在弹出的选项中,当然是选择刚刚DUMP的文件,即dumped.exe了。如此就对刚才LordPe后的dumped.exe文件进行修复了,在原来的文件夹里会多出来一个dumped_.exe文件,这就是最终的成品,运行一下,OK!可以运行(这应该是术后的缝合及护理,病人恢复健康了,呵呵…),这时就可以关闭OD了。?

?



?图3

到此,这个Armadillo1.xx-2.xx单进程的脱壳工作就结束了,再用PEiD查看一下脱后的dumped_.exe文件,显示出了本来面目,原来是MicrosoftVisualC++7.0[Debug]。阶段小结:这是Armadillo保护壳最最基本的保护,内部没有进行任何项目的保护设置,所以脱起来比较容易。在脱此壳的实际操作中,最关键的在于返回时机的把握,我这里是Shift+F9七次,在你那里就不一定是七次,这要多练习才能领悟。我的领悟是当堆栈窗口出现“VirtualFree”函数,下一次就到了返回时机,然后看寄存器窗口。至于魔法跳处,仔细看下,是固定的格式啦!

Armadillo1.xx-2.xx双进程的简单脱法用工具PEiD和ArmadilloFindProtectedV1.4查看的方法是一样的,这里就省略过程了,直接进入OD中吧!代码如下。

00444974StayOn_P.<>/$55pushebp//进入OD后暂停在这里00444975|.8BECmovebp,esp00444977|.6AFFpush-100444979|.6800E64400pushStayOn_P.0044E6000044497E|.6894444400pushStayOn_P.00444494;SE句柄安装00444983|.64:A100000000moveax,dwordptrfs:[0]

因为是双进程(如何知道?你先独立运行目标程序后,打开你的Windows任务管理器,在进程项目中就知道了!有2个同名的程序),所以我使用了OD中插件的脚本功能。选OD的菜单“插件”,在弹出的菜单中选“OdbgScript->运行脚本->转单进程脚本.OSC”,脚本运行过程中一路“确定”后,程序就会停在如下代码处。

7C80EC1Bkernel32.O>8BFFmovedi,edi//到这里后下F2断点7C80EC1D55pushebp7C80EC1E8BECmovebp,esp7C80EC2051pushecx7C80EC2151pushecx7C80EC22837D1000?cmpdwordptrss:[ebp+10],07C80EC2656pushesi7C80EC270F8477747.net00300jekernel32.7C843CA77C80EC2D64:A118000000moveax,dwordptrfs:[18]

此时观察堆栈里的数据,代码如下。

0012F5B80043F85D/CALL到OpenMutexA来自StayOn_P.0043F8570012F5BC001F0001|Access=1F00010012F5C000000000|Inheritable=FALSE0012F5C40012FBF8\MutexName="150::DAA99D8E17"

先在7C80EC1B处下F2断点。看堆栈,这个“150::DAA99D8E17”就是我们要首先找到的数据,不同的电脑,数据肯定是不一样的,记下这里的“0012FBF8”,下面有用的!然后,用快捷键“Ctrl+G”,填入“401000”,点击“确定”,便来到了00401000处。这里的代码是空白啊!这就对了!鼠标在401000处点一下,然后按住Shift键,用鼠标在下面(多选几行)点一下,一片蓝色;用记事本把我给的二进制代码输进来,“609C68F8FB120033C05050E82FDB407C9D61E904DC407C”,先复制一下,在OD的蓝色区域,点击右键,在弹出的菜单中选“二进制->二进制粘贴”,就会出现如图4所示的界面。要特别注意啦!在00401002处的“PUSH12FBF8”和你记下的一样吗?不一样吗?当然要改成你那里的啊!然后鼠标右键在401000处点击一下,在弹出来的菜单项中,选“此处为新EIP”,弹出提示选“是”,然后“Shift+F9”运行,就会跳到7C80EC1B处,然后再Ctrl+G转到401000处,撤消所有修改后,取消断点;接下来,找魔法跳的方法是一样的,Ctrl+G,输入函数GetModuleHandleA,转到如下代码。?

??



图4

7C80B529>8BFFmovedi,edi7C80B52B55pushebp7C80B52C8BECmovebp,esp7C80B52E837D0800cmpdwordptr[ebp+8],07C80B5327418jeshort7C80B54C;下F2断点7C80B534FF7508?pushdwordptr[ebp+8]7C80B537E8682D0000call7C80E2A47C80B53C85C0testeax,eax7C80B53E7408jeshort7C80B5487C80B540FF7004?pushdwordptr[eax+4]7C80B543E8F4300000callGetModuleHandleW7C80B5485Dpopebp7C80B549C20400?retn4

在7C80B532处下F2断点;然后Shift+F9,注意看堆栈中的变化。Shift+F9一次的堆栈:

0012ED6877F45BD8/CALL到GetModuleHandleA来自77F45BD20012ED6C77F4501C\pModule="KERNEL32.DLL"0012ED7000000001

Shift+F9二次,注意看堆栈中的变化:

0012E55C5D175394/CALL到GetModuleHandleA来自5D17538E0012E5605D1753E0\pModule="kernel32.dll"0012E5645D1E2B38

Shift+F9三次,注意看堆栈中的变化:

0012F5700043EDD9/CALL到GetModuleHandleA来自StayOn_P.0043EDD30012F57400000000\pModule=NULL0012F5780044B50CASCII"RegisterServiceProcess"

Shift+F9四次,注意看堆栈中的变化:

0012E210003D5DC8/CALL到GetModuleHandleA来自003D5DC20012E214003EA7F8\pModule="kernel32.dll"0012E218003EB09CASCII"InvalidKey"

Shift+F9五次,注意看堆栈中的变化:

0012E210003D5DC8/CALL到GetModuleHandleA来自003D5DC20012E214003EA7EC\pModule="user32.dll"0012E218003EB09CASCII"InvalidKey"

Shift+F9六次,注意看堆栈中的变化:

0012E24C003DF6BD/CALL到GetModuleHandleA来自003DF6B70012E25000AF1480\pModule="WSOCK32.dll"0012E2540047F738StayOn_P.0047F738

Shift+F9七次,注意看堆栈中的变化:

0012E230003D622B/CALL到GetModuleHandleA来自003D62250012E23400000000\pModule=NULL//到这里就可以返回了0012E23800000073

到这时,取消断点,执行返回,快捷键是ALT+F9,来到如下代码处。

003D622B8B4D08movecx,dwordptrss:[ebp+8];WSOCK32.#1139//来到这里003D622E3BC8cmpecx,eax003D62307507jnzshort003D6239003D6232B898A33E00moveax,3EA398003D6237EB30jmpshort003D6269003D6239393DC8A73E00cmpdwordptrds:[3EA7C8],edi

003D623FB8C8A73E00moveax,3EA7C8003D6244740Cjeshort003D6252//魔法跳,改jmp!003D62463B4808cmpecx,dwordptrds:[eax+8]003D6249741Bjeshort003D6266

在003D622B处下F2断点,然后Shift+F9,就会断在003D622B处,再取消断点,把003D6244处的JE改为JMP(魔法跳),按Ctrl+G转到GetCurrentThreadId,来到如下代码。

7C80973764:A118000000moveax,dwordptrfs:[18]7C80973D8B4024moveax,dwordptr[eax+24]7C809740C3retn

在7C809737处下F2断点,Shift+F9运行,取消断点,F8单步向下走,找OEP。

00AC0B586A00push000AC0B5A33481C?xorecx,dwordptr[eax+1C]00AC0B5D03F9addedi,ecx00AC0B5FE85EE3FFFFcall00ABEEC200AC0B6450pusheax00AC0B65FFD7callediStayOn_P.0040DED200AC0B678BF8movedi,eax00AC0B698BC7moveax,edi……

当F8走到00AC0B65处时,在注释栏出现了OEP处的代码0040DED2;这时用F7跟进,就来到了OEP位置0040DED2处。用LordPe脱壳和修复的方法和单进程相同,就不重复了。下面简单说一下善后工作。脱壳后的程序,有时用PEiD查看还会显示成Armadillo1.xx-2.xx。这时,就用PETools工具手工处理一下,一般要先用Brain识别脱壳后的载入点(OEP),识别一下是VC、VB,还是Delphi。确定后,打开PETools,选“工具->PE编辑器”,然后选择脱壳后的程序,点“可选头”,见图5所示,把主连接器版本的数据改为“06,”副连接器版本的数据改为“00”。这样,脱壳后的程序用PEiD再看,就是VC了,哈哈!这里的数据应该填入多少?完全取决于Brain对OEP的识别。?





??图5

心得体会:对于脱Armadillo的保护壳,首先要清楚它的保护机制才能对症下药。利用脚本也好,手工进行也罢,都要想法躲避它的加密部分,找到魔法跳后,离OEP就不远了。当然,前面说过,它的保护机制是变幻多样的,但万变不离其宗,目的就是隐藏真正的OEP,实际操作中返回时机的把握,就要靠自己在练习中领悟啦!好了,以上介绍了关于Armadillo保护壳单、双进程的简单脱法,人是活的,方法是多样的,而程序是死的。我会在今后,把不断学习领悟到的简单方法,分享给大家的。



献花(0)
+1
(本文系红人会首藏)