首页
社区
课程
招聘
[原创]2次断点干掉加密壳EXE Stealth v2.74
发表于: 2008-5-22 13:11 11083

[原创]2次断点干掉加密壳EXE Stealth v2.74

2008-5-22 13:11
11083

OD打开附件:
00467060 > /EB 00            jmp short Project2.00467062 //这里
00467062   \EB 17            jmp short Project2.0046707B
00467064    53               push ebx
00467065    68 61726577      push 77657261
0046706A    61               popad
0046706B    72 65            jb short Project2.004670D2
0046706D    202D 20457865    and byte ptr ds:[65784520],ch
00467073    53               push ebx
00467074    74 65            je short Project2.004670DB
00467076    61               popad

ALT+M:
内存映射,项目 17
地址=00453000
大小=00002000 (8192.)
宿主=Project2 00400000
区段=DATA //在这里右键下内存访问断点
包含=data
类型=Imag 01001002
访问=R
初始访问=RWE
SHIFT+F9跑程序:
0046745F    AC               lods byte ptr ds:[esi] //这里
00467460    C0C0 C1          rol al,0C1
00467463    04 7F            add al,7F
00467465    04 15            add al,15
00467467    C0C8 14          ror al,14
0046746A    2AC1             sub al,cl
0046746C    2C 9C            sub al,9C
0046746E    C0C8 92          ror al,92
00467471    C0C0 B2          rol al,0B2
00467474    04 C5            add al,0C5
00467476    F8               clc
00467477    FEC8             dec al

ALT+M:
内存映射,项目 16
地址=00401000
大小=00052000 (335872.)
宿主=Project2 00400000
区段=CODE //下断
包含=code
类型=Imag 01001008
访问=RW  CopyOnWr
初始访问=RWE

SHIFT+F9直达OEP!!
注意:OD异常设置那里全部选上!


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 7
支持
分享
最新回复 (16)
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
很巧的方法哈。万分感谢楼主分享!~~~~
2008-5-22 16:39
0
雪    币: 209
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
这么好的贴子没人顶!!··
2008-5-22 21:35
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
大家没注意到而已~~偶来顶!~~
2008-5-22 21:55
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
学学 看看!~!
2008-5-22 22:01
0
雪    币: 317
活跃值: (93)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
6
很不错的方法,我按照你说的把你的这个程序也脱啦!!!!!
2008-5-22 22:05
0
雪    币: 190
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
脱是脱掉了,能说说为什么这么下断点吗?
要不以后还是搞不明白什么时候这么操作。
2008-5-23 02:55
0
雪    币: 722
活跃值: (123)
能力值: ( LV12,RANK:300 )
在线值:
发帖
回帖
粉丝
8
起初有点奇怪:如果这么顺利就脱壳,那还是加密壳么?!

自己单步了一下,起初也没啥感觉,不就几个SEH和IsDebuggerPresent,以及int 68这样的反调试手段么?的确比较容易地跑到了OEP:00452384

然而,对于加密壳的手脱来说,“找入口点只是第一步”,很多情况下,能不能修复文件,特别是修复IAT,才是重点。

而在这后面的步骤中,我遇到问题,回头再重新单步跟踪,才发现了一些关键。

其实,如果楼主把脱壳的步骤做完,你就会发现,有很多问题你之前根本就没有看到,而这些将可能使你前面的工作功亏一篑。

下面就来谈一谈这几个需要注意的问题,按楼主这种跑法是没有办法直接解决的。

1. 镜像大小错误——LordPE与ImportREC等工具读取错误

当你要用LordPE将文件完整转存的时候,你就看到该文件的模块属性显示:
镜像基址:00400000,镜像大小:00001000
这样dump下来的文件,也只有4KB(0x1000字节)这么大。

当用ImportREC修复IAT,IATAutoSearch之后,Get Imports,也会出现内存不可读取的错误提示

实际上,镜像文件真正大小是00069000,是壳程序从PEB结构顺藤摸瓜,改变了这个值。

相关代码:

00467286    64:FF35 3000000>push    dword ptr fs:[30]                ; PTR _PEB
0046728D    58              pop     eax
0046728E    85C0            test    eax, eax
00467290    78 0F           js      short 004672A1
00467292    8B40 0C         mov     eax, dword ptr [eax+C]           ; LDR_DATA
00467295    8B40 0C         mov     eax, dword ptr [eax+C]
00467298    C740 20 0010000>mov     dword ptr [eax+20], 1000         ; 把模块大小改为0x1000

这就是壳程序做的事情,故意将模块大小改变,使得LordPE和ImportREC等工具在dump的时候出错了。

解决方法:
当然可以将00467298处nop掉。不过后面有类似自校验的东西(虽然在脱壳完之前,似乎校验得不是很严密),以防万一,在这一句时,数据窗口跟随内存地址,我这里是00251F00,未改之前的DWORD值是00069000。单步过这一句后,数据窗口可以看到此处已被改了。这时就应该顺手把它改回来。

2. HOOK-API方式对IAT加密——ImportREC修复IAT比较麻烦

解决了上面的问题之后,再跑到OEP,LordPE能够正确dump镜像文件,ImportREC能够IAT AutoSearch了,但是Get Imports后,你会看到一大堆不可用的IAT项目,几乎只有kernel32.dll和comctl32.dll的项目可用。

显然,IAT被壳程序用HOOK-API方式加密了,这是加密壳的典型特点。

解决方法:

可以试着用ImportREC的Trace功能,Level1到Level3都试一试。
不过我觉得这种方法比较碰运气,如果加密得深了,Trace的时候会CPU占用高(我的本本很破受不了),还不一定Trace得到。

对付HOOK-API比较好的方法,是找到壳填充IAT后进行加密的代码,设法跳过这些代码,使得IAT不被加密,从而使ImportREC能够直接得到原始的IAT,直接修复。

相关代码位置:

edx为IAT中的地址,eax为相应API函数地址,在此之前已经被填入edx指向的位置中;ebx为相应dll的基址

0046763A    F785 AF2F4000 2>test    dword ptr [ebp+402FAF], 20
00467644    74 45           je      short 0046768B
00467646    83BD BB2F4000 0>cmp     dword ptr [ebp+402FBB], 0
0046764D    74 14           je      short 00467663
0046764F    81FB 00000070   cmp     ebx, 70000000
00467655    72 08           jb      short 0046765F
00467657    81FB FFFFFF77   cmp     ebx, 77FFFFFF
0046765D    76 0E           jbe     short 0046766D                   ; 跳入进行HOOK-API
0046765F    EB 2A           jmp     short 0046768B
00467661    EB 0A           jmp     short 0046766D
00467663    81FB 00000080   cmp     ebx, 80000000
00467669    73 02           jnb     short 0046766D
0046766B    EB 1E           jmp     short 0046768B
0046766D    57              push    edi
0046766E    56              push    esi
0046766F    8DBD E5344000   lea     edi, dword ptr [ebp+4034E5]
00467675    8B77 04         mov     esi, dword ptr [edi+4]
00467678    8932            mov     dword ptr [edx], esi
0046767A    2BC6            sub     eax, esi
0046767C    83E8 05         sub     eax, 5
0046767F    C606 E9         mov     byte ptr [esi], 0E9
00467682    8946 01         mov     dword ptr [esi+1], eax
00467685    8347 04 05      add     dword ptr [edi+4], 5
00467689    5E              pop     esi
0046768A    5F              pop     edi
0046768B    83C1 04         add     ecx, 4
0046768E    83C2 04         add     edx, 4
00467691    8339 00         cmp     dword ptr [ecx], 0
00467694  ^ 0F85 34FFFFFF   jnz     004675CE                         ; 取下一个API
0046769A    83C6 0C         add     esi, 0C
0046769D    837E 04 00      cmp     dword ptr [esi+4], 0
004676A1  ^ 0F85 B4FEFFFF   jnz     0046755B                         ; 取下一个DLL
004676A7    33C0            xor     eax, eax

从以下判断代码:

0046764F    81FB 00000070   cmp     ebx, 70000000
00467655    72 08           jb      short 0046765F
00467657    81FB FFFFFF77   cmp     ebx, 77FFFFFF
0046765D    76 0E           jbe     short 0046766D                   ; 跳入进行HOOK-API

对于所有基址在0x70000000-0x77FFFFFF的dll,壳将与之相关的IAT项全部用HOOK-API方式加密,加密方法是生成一条jmp代码,jmp的目标是真正的API函数地址,而将原IAT中的API函数地址替换为jmp代码的地址。

只要设法改变这个判断流程,使之不跳进0046766D,而直接跳到0046768B,就可以使IAT不被加密,保留原始的IAT。

这里有好几个判断,所以改的方法应该就不止一种。

比如将以下代码:

00467644    74 45           je      short 0046768B

改为绝对跳转:

00467644   /EB 45           jmp     short 0046768B

之后在004676A7处F4,就跑完了填充IAT的代码了,而且得到的是原始未加密的IAT。

3. 最佳时机

脱壳不一定非要跑到OEP才可以dump。完成了上面这个部分,这时应该就已经是脱壳的最佳时机了。因为我们已经在之前的几次“不成功的脱壳”中知道OEP的位置了,而这时程序的区段已经解密完成,原始完整的IAT又已经得到。

如果不在这里dump,而是坚持跑到OEP,后面又有检测IsDebuggerPresent,SEH结构化异常处理,以及类似自校验和SMC的东西,实际上只是一系列反调试的拦路虎,对脱壳结果并没有什么影响。

所以直接在这里用LordPE完整转存,再用ImportREC修复IAT,填入OEP偏移00052384,IAT AutoSearch,再Get Imports。这时的IAT就完好无损了,直接fix dump,完成。

附件中Project2_u1.exe为LordPE转存下来的文件,Project2_u1_.exe则为ImportREC修复后的程序。
上传的附件:
2008-5-23 05:03
0
雪    币: 722
活跃值: (123)
能力值: ( LV12,RANK:300 )
在线值:
发帖
回帖
粉丝
9
楼主用的是内存镜像法。这种方法依据的是壳的流程原理:
一般压缩壳的流程,是先解密区块数据,再填充IAT,然后可能再处理一下重定位,最后跳到OEP

第一次对DATA段下断点,断下的时候,正是在壳代码在修改该段数据的时候

第二次在CODE段下断点,则是抓住最后跳到OEP的这个动作。因为对于Delphi程序来说,其OEP正是在CODE中,所以当程序最后用一个跨段的大跳,跳入位于CODE段的OEP的时候,就正好被断下。

内存镜像法对于压缩壳来说,是比较快速的脱壳方法,因为它尽量少地干预壳的流程,任由壳程序一直跑到OEP,而在到达OEP的那一瞬间,再把它抓住。

然而,这样运用有一个前提,就是壳不需要我们干预就可以自己跑到OEP,然后让我们舒舒服服地dump出来。对于压缩壳来说,这个前提一般成立,而对于加密壳来说,则一般不成立。

就如我前面所说,楼主的方法,虽然是跑到了OEP,然而在真正将程序dump下来并修复的时候,却发现了问题。

对于其他一些情况,壳的反调试功能甚至根本不会让程序跑到OEP,当检测到自身被调试或自校验失败的时候,就直接终止程序。

为了解决以上的问题,在脱壳时就必须要干预和改变壳的流程,这时就必须认真细致地一步一步调试,突破一个又一个暗藏的陷阱,单步跟踪的能力就变得更为重要。
2008-5-23 05:30
0
雪    币: 209
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
小聪说的不错!值得学习!!
2008-5-23 13:09
0
雪    币: 125
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
小聪说的很不错,楼主有点太急了,并不是走到OEP,DUMP下就万事大吉。
2008-5-23 15:14
0
雪    币: 203
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
是呀,遇到dump时 转存的文件只有4KB , 这个要多努力了
2009-4-29 22:24
0
雪    币: 212
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
初学,还有很多看不懂,给自己加油,大家一起努力。谢谢了。
2009-4-30 19:32
0
雪    币: 205
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
好强, 有楼主的方法, 也有高手的指正, 值得菜鸟位学习, 收藏了, 谢谢!
2009-5-1 18:19
0
雪    币: 423
活跃值: (11)
能力值: ( LV9,RANK:230 )
在线值:
发帖
回帖
粉丝
15
三人论,必有我需。

学到了一些东西。。。
2009-5-2 20:48
0
雪    币: 203
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
都是高手啊,我望尘莫及
2009-5-3 08:57
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
很不错的思路。。。
  值得学习
2009-5-3 09:03
0
游客
登录 | 注册 方可回帖
返回
//