首页
社区
课程
招聘
[原创]对手动脱壳进阶第八篇Skvp1.32的修正
发表于: 2010-12-30 21:15 8130

[原创]对手动脱壳进阶第八篇Skvp1.32的修正

2010-12-30 21:15
8130

新学脱壳技术不久,对脱壳感到神秘又新鲜,脱壳中学到许多有用的知识,也结交了许多好朋友。我的学习之路是从手动脱壳入门开始的,当练习到手动脱壳进阶第八篇Skvp1.32的时候遇到了前所未有的麻烦。
Skvp1.32的壳寻找入口点oep相对来说比较容易,找到oep后dump,使用importICE修复时遇到了巨大的困难。总是有两个无效指针无法修复,使用了插件也不行,想了许多方法也不行,足足折磨我两天,可谓身心憔悴。废话少说,直接开始。请大家手下留情。
用Peid测NOTEPAD.EXE的壳为SVKP 1.3x -> Pavol Cerven。
我们把Od中的选项-调试选项-异常选项卡了除了忽略在内存访问异常不打勾,其余全部打勾,请检查自己的Od设置。我的Od中存在一个硬件断点,这个断点让我吃尽苦头,所以检查设置的时候也要看一下是否存在不必要的断点。这里我就不手动跟到oep。介绍一下变通的方法。
用OD载入程序后,插件隐藏OD.确定一个入口警告,Od提示程序加壳,选不继续分析。
0040C000 >  60              pushad
0040C001    E8 00000000     call    0040C006
0040C006    5D              pop     ebp
0040C007    81ED 06000000   sub     ebp, 6
0040C00D    EB 05           jmp     short 0040C014
0040C00F    B8 06364200     mov     eax, 423606
0040C014    64:A0 23000000  mov     al, byte ptr fs:[23]
...............................................................
先F9运行看看。程序异常,是加密壳,有SEH陷阱语句。
异常1
00A00492    8900            mov     dword ptr [eax], eax
00A00494    E8 01000000     call    00A0049A
00A00499    E8 E8020000     call    00A00786
00A0049E    00CD            add     ch, cl
00A004A0    2083 04240B83   and     byte ptr [ebx+830B2404], al
00A004A6    44              inc     esp
00A004A7    24 04           and     al, 4
00A004A9    13C3            adc     eax, ebx
...............................................................
Shift+F9跳过运行。
异常2
00A00571    E8 01000000     call    00A00577
00A00576    E8 E8020000     call    00A00863
00A0057B    00CD            add     ch, cl
00A0057D    2083 04240B83   and     byte ptr [ebx+830B2404], al
00A00583    44              inc     esp
00A00584    24 04           and     al, 4
00A00586    13C3            adc     eax, ebx
...............................................................
Shift+F9跳过运行。
异常3
00A603E1    8900            mov     dword ptr [eax], eax
00A603E3    60              pushad
00A603E4    E8 03000000     call    00A603EC
00A603E9    D2EB            shr     bl, cl
00A603EB    0A58 EB         or      bl, byte ptr [eax-15]
00A603EE    0148 40         add     dword ptr [eax+40], ecx
00A603F1    EB 01           jmp     short 00A603F4
...............................................................
Shift+F9跳过运行。
异常4
00A6137F    6285 0E0B0000   bound   eax, qword ptr [ebp+B0E]
00A61385    EB 02           jmp     short 00A61389
00A61387    0FE88B D1EB02CD psubsb  mm1, qword ptr [ebx+CD02EBD1]
00A6138E    208B C2EB02CD   and     byte ptr [ebx+CD02EBC2], cl
00A61394    208B 8A4F0800   and     byte ptr [ebx+84F8A], cl
00A6139A    007C03 EB       add     byte ptr [ebx+eax-15], bh
00A6139E    0369 74         add     ebp, dword ptr [ecx+74]
00A613A1    FB              sti
00A613A2    8B89 74010000   mov     ecx, dword ptr [ecx+174]
...............................................................
Shift+F9跳过运行。
SVKP 1.32典型最后一次异常。如果继续Shift+F9程序就会运行。
00A6C028    CD 01           int     1
00A6C02A    E8 01000000     call    00A6C030
00A6C02F  - E9 83C4047C     jmp     7CAB84B7
00A6C034    03EB            add     ebp, ebx
00A6C036    039A 74FB648F   add     ebx, dword ptr [edx+8F64FB74]
00A6C03C    05 00000000     add     eax, 0
00A6C041    E8 02000000     call    00A6C048
00A6C046    CD20 83042408   vxdcall 8240483
...............................................................
观察一下堆栈信息,查看SEH的处理地址。
0013FF74   0013FF84  指向下一个 SEH 记录的指针
0013FF78   00A6046F  SE处理程序
0013FF7C   00A6000C
0013FF80   000000FF
00A6046F是异常处理完毕出口。
因为有stolen code直接使用Ctrl+G 是到不了00A6046F的。
00A6046B    C3              retn
00A6046C    E8 FFE1EB0B     call    0C91E670
00A60471    0000            add     byte ptr [eax], al
00A60473    FFCE            dec     esi
00A60475    0000            add     byte ptr [eax], al
所以我们先找到00A6046F的附近,使用Ctrl+上下键,找到00A6046F,下普通断点。Shift+F9跳过运行。
00A6046F   /EB 0B           jmp     short 00A6047C
00A60471   |0000            add     byte ptr [eax], al
00A60473   |FFCE            dec     esi
00A60475   |0000            add     byte ptr [eax], al
00A60477   |0000            add     byte ptr [eax], al
00A60479   |0000            add     byte ptr [eax], al
00A6047B   |00EB            add     bl, ch

Alt+M打开内存镜像窗口。
内存镜像
地址 大小 Owner Section Contains 类型 访问 初始访问 映射为
00400000 00001000 NOTEPAD PE header Imag R RWE
00401000 00004000 NOTEPAD code Imag R RWE
00405000 00001000 NOTEPAD data Imag R RWE
00406000 00001000 NOTEPAD Imag R RWE
00407000 00005000 NOTEPAD resources Imag R RWE
0040C000 0000E000 NOTEPAD .svkp SFX,imports, Imag R RWE
在这行,下内存断点。
0040C000 0000E000 NOTEPAD .svkp SFX,imports, Imag R RWE
F9运行。可能会出现异常,到达这里。
00A6F1E8    83C4 04         add     esp, 4
00A6F1EB    64:8F05 0000000>pop     dword ptr fs:[0]
00A6F1F2    7C 03           jl      short 00A6F1F7
00A6F1F4    EB 03           jmp     short 00A6F1F9
00A6F1F6  - E9 74FB83C4     jmp     C52AED6F
00A6F1FB    0C EB           or      al, 0EB
00A6F1FD    02CD            add     cl, ch
继续F9运行。
00AE0F51    8B89 78010000   mov     ecx, dword ptr [ecx+178]
00AE0F57    EB 02           jmp     short 00AE0F5B
00AE0F59    0F8B 8BAD3A0A   jpo     0AE8BCEA
00AE0F5F    0000            add     byte ptr [eax], al
00AE0F61    7C 03           jl      short 00AE0F66
00AE0F63    EB 03           jmp     short 00AE0F68

再Alt+M打开内存镜像窗口。确定一个入口点警告。
内存镜像00401000 00004000 NOTEPAD code Imag R RWE
呵呵,下内存断点,F9运行。
004010CC    55              push    ebp   
004010CD    8BEC            mov     ebp, esp
004010CF    83EC 44         sub     esp, 44
004010D2    56              push    esi
004010D3    FF15 E4634000   call    dword ptr [4063E4]
004010D9    8BF0            mov     esi, eax
到达oep,dump。使用importREC1.62进行修复。使用追踪级别1修复时,有三个指针无法修复。三个指针分别是0000639C、000063A0和000063E4。使用SvkpIAT插件一个都不能修复。
重新OD载入程序,一分钟到达Oep,Ctrl+G填入 40639C, 下内存访问断点。F9,程序运行,断点没有发挥作用。重新OD载入程序,一分钟到达Oep,向下翻页。
00401146    50              push    eax
00401147    56              push    esi
00401148    6A 00           push    0
0040114A    6A 00           push    0
0040114C    FF15 9C634000   call    dword ptr [40639C]
00401152    50              push    eax
00401153    E8 760F0000     call    004020CE
00401158    50              push    eax
00401159    8BF0            mov     esi, eax
0040115B    FF15 A0634000   call    dword ptr [4063A0]
...............................................................
0040114C    FF15 9C634000   call    dword ptr [40639C],在这行下普通断点。F9运行。在call指令之上有4个push,估计是一个有四个输入参数的函数。
此时,eax=0A,esi=00151F0F。
观察堆栈信息。
0013FF68   00000000
0013FF6C   00000000
0013FF70   00151F0F
0013FF74   0000000A
0013FF78   FFFFFFFF
F8路过。观察堆栈信息。
0013FF6C   00000000
0013FF70   00151F0F
0013FF74   0000000A
0013FF78   FFFFFFFF
貌似只使用了一个参数,难道是一个输入参数的函数?继续观察。Eax=400000,貌似是一个句柄。重新来过。
到达0040114C    FF15 9C634000   call    dword ptr [40639C]。
F7跟入。可是转来转去都不出来。重新来过。
到达0040114C    FF15 9C634000   call    dword ptr [40639C]。
F7跟入00401153    E8 760F0000     call    004020CE
到达00AF480F  - E9 B33E2277     jmp     USER32.GetDC
可以验证eax返回的是一个句柄。一个输入参数,又返回句柄的,极有可能就是GetmoduleHandle了。试一下吧。继续下一个。
000063A0这个在原文中已经提到,应该是ExitProcess。这里就不多介绍了。我们看一下最后一个函数000063E4。
同上所述,在4063E4的地方下内存访问断点。
004010D2    56              push    esi
004010D3    FF15 E4634000   call    dword ptr [4063E4]
貌似是只有一个输入参数的函数,esi=FFFFFFFF=-1,难道是void?F7跟入。
跟踪过程中,发现一个不熟悉的命令rdtsc,速度查一下,原来这个指令是获取CPU自启动以后的运行周期,返回的数值,高位返回到edx,低位放回到eax。这个有什么用呢?我们下面揭晓。继续跟入。不久,第二次发现rdtsc。
00AE3448    83C4 04         add     esp, 4
00AE344B    2BD3            sub     edx, ebx
00AE344D    EB 03           jmp     short 00AE3452
原来如此,程序通过rdtsc指令记录时间存储在edx和ebx中,计算edx和ebx之间的差,如果数值过大,说明有调试工具跟踪。所以需要修改ebx或edx的数值。
继续。跟到004010E2    FF15 F4644000   call    dword ptr [4064F4],F7进去后发现是
00AF4841  - E9 6A802377     jmp     USER32.CharNextA,这是对字符串的操作。之后的一段代码应该是对字符串的操作。Esi= 00151EE1。
004010E8    8BF0            mov     esi, eax
004010EA    8A00            mov     al, byte ptr [eax]
004010EC    84C0            test    al, al
004010EE    74 04           je      short 004010F4
004010F0    3C 22           cmp     al, 22
004010F2  ^ 75 ED           jnz     short 004010E1
004010F4    803E 22         cmp     byte ptr [esi], 22
004010F7    75 15           jnz     short 0040110E
004010F9    46              inc     esi
004010FA    EB 12           jmp     short 0040110E
004010FC    3C 20           cmp     al, 20
004010FE    7E 0E           jle     short 0040110E
00401100    56              push    esi
00401101    FF15 F4644000   call    dword ptr [4064F4]
00401107    8038 20         cmp     byte ptr [eax], 20
0040110A    8BF0            mov     esi, eax
0040110C  ^ 7F F2           jg      short 00401100
数据窗口跟随到00151EE1发现是程序的全路径。
00151EE1  46 3A 5C D1 D0 BE BF B9 A4 D7 F7 5C D2 D1 C6 C6  F:\研究工作\已破
00151EF1  BD E2 C8 ED BC FE 5C 73 76 6B 70 20 76 31 2E 33  解软件\svkp v1.3
00151F01  32 5C 4E 4F 54 45 50 41 44 2E 45 58 45 22 00 AB  2\NOTEPAD.EXE".
一般使用获得全路径的函数应该是GetModuleFileNameA,可是GetModuleFileNameA应该有三个输入参数,应该不是它,还有一个可能就是GetCommandLineA。
好了,三个无效指针都修复完毕,修复一下文件吧。没想到还真是对了。运气真是好。
小结:其实这个壳不是我一个人破掉的,作为一个菜鸟,没有什么经验和对windows函数的了解,想破解这个壳还是有一定难度的。记得《暗算》里有一句话说的好,我们需要技术、经验和耐心,最需要的是来自天外的一丝运气。对于我来说,crack的道路崎岖曲折又满布荆棘。祝我好运吧。


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 7
支持
分享
最新回复 (6)
雪    币: 3113
活跃值: (3669)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
可用申请精华咯哦
2010-12-30 23:10
0
雪    币: 106
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
支持,学习一下
2011-1-1 21:25
0
雪    币: 239
活跃值: (25)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
4
新年礼物呀~~
2011-1-1 21:38
0
雪    币: 87
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
真不错,新年新进步。分析的真不赖,很受启发啊。
特别是这句。“原来如此,程序通过rdtsc指令记录时间存储在edx和ebx中,计算edx和ebx之间的差,如果数值过大,说明有调试工具跟踪。所以需要修改ebx或edx的数值。”
2011-1-4 09:40
0
雪    币: 167
活跃值: (1574)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
6
Mark ~  列个目录吧 过年了我也学一下  
2011-1-5 10:27
0
雪    币: 32
活跃值: (34)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
mark 菜鸟膜拜
2011-11-23 10:33
0
游客
登录 | 注册 方可回帖
返回
//