首页
社区
课程
招聘
[原创]yoda's Protector 1.03.3主程序简单分析
发表于: 2009-4-23 22:55 8914

[原创]yoda's Protector 1.03.3主程序简单分析

2009-4-23 22:55
8914

【文章标题】: yoda's Protector 1.03.3主程序简单分析
【文章作者】: frozenrain
【作者邮箱】: frozenrain86@163.com
【软件名称】: yoda's Protector 1.03.3
【下载地址】: 自己搜索下载
【保护方式】: yoda's Protector 1.03.3
【编写语言】: VC
【使用工具】: OD,LORDPE IMPORTREC
【操作平台】: WIN XP
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
  最近看坛子里有人问这个壳,所以拿来看看,当作一次学习过程吧,高手飘过。
  OD载入,F7单步跟踪
  0043E795    33C0            xor     eax, eax
  0043E797    64:FF30         push    dword ptr fs:[eax]
  0043E79A    64:8920         mov     dword ptr fs:[eax], esp
  0043E79D    4B              dec     ebx
  0043E79E    CC              int3
  第一次异常看堆栈 在SE句柄上下断就过去了
  0043E783    33C0            xor     eax, eax
  0043E785    64:FF30         push    dword ptr fs:[eax]
  0043E788    64:8920         mov     dword ptr fs:[eax], esp
  0043E78B    CC              int3
  
  同样的方法,跳过了几个int3后,F7走到这里
  0043E74B    60              pushad
  0043E74C    E8 00000000     call    0043E751
  0043E751    5D              pop     ebp
  0043E752    81ED 07E24000   sub     ebp, 0040E207                    ; 入口地址
  0043E758    8BD5            mov     edx, ebp
  
  花指令太多了,可能有贴出来的有点乱
  下面是解码部分。
  0043E808   /EB 01           jmp     short 0043E80B
  0043E80A   |C2 EB01         retn    1EB
  0043E80D    E8 C0C8822A     call    2AC6B0D2
  0043E812    C1EB 01         shr     ebx, 1
  0043E815    E8 EB01C2C0     call    C105EA05
  0043E81A    C8 973467       enter   3497, 67
  0043E81E    EB 01           jmp     short 0043E821
  0043E820    E8 F8F802C1     call    C146E11D
  0043E825    34 0C           xor     al, 0C
  0043E827    F9              stc
  0043E828    EB 01           jmp     short 0043E82B
  0043E82A    C2 EB01         retn    1EB
  0043E82D  - E9 EB01C22C     jmp     2D05EA1D
  0043E832    D1EB            shr     ebx, 1
  0043E834    01E9            add     ecx, ebp
  0043E836    02C1            add     al, cl
  0043E838    C0C0 41         rol     al, 41
  0043E83B    EB 01           jmp     short 0043E83E
  0043E83D    E8 04552AC1     call    C16E3D46
  0043E842    2C 53           sub     al, 53
  0043E844    F8              clc
  0043E845    D9D0            fnop
  0043E847    90              nop
  0043E848    AA              stos    byte ptr es:[edi]
  0043E849  ^ E2 9C           loopd   short 0043E7E7
  见到CALL,除去系统API外,一般F7跟进,否则可能跑飞。
  到了这里
  0043F3BB    CC              int3
  0043F3BC    8BEF            mov     ebp, edi
  0043F3BE    33DB            xor     ebx, ebx
  还是SHE ,SE句柄上下断
  到这里,这就是SHE处理程序
  00440CAC    55              push    ebp
  00440CAD    8BEC            mov     ebp, esp
  00440CAF    57              push    edi
  00440CB0    36:8B45 10      mov     eax, dword ptr [ebp+10]
  00440CB4    3E:8BB8 9C00000>mov     edi, dword ptr [eax+9C]
  00440CBB    8BD7            mov     edx, edi
  00440CBD    81C2 4C0B4100   add     edx, 00410B4C
  00440CC3    3E:FF32         push    dword ptr [edx]
  00440CC6    3E:8F80 B800000>pop     dword ptr [eax+B8]       修改EIP
  00440CCD    3E:89B8 B400000>mov     dword ptr [eax+B4], edi
  00440CD4    3E:C780 B000000>mov     dword ptr [eax+B0], 4
  00440CDF    B8 00000000     mov     eax, 0
  00440CE4    5F              pop     edi
  00440CE5    C9              leave
  上面EAX指向线程上下文,B0,B4,B8是偏移。具体多少查资料
  PE头变形了,引入表只有两个函数,下面是程序解出了大部分API用于后面的解码
  0043F477    8B85 E0074100   mov     eax, dword ptr [ebp+4107E0]
  0043F47D    0340 3C         add     eax, dword ptr [eax+3C]
  0043F480    05 80000000     add     eax, 80                          ; 引入表
  0043F485    8B08            mov     ecx, dword ptr [eax]
  0043F487    038D E0074100   add     ecx, dword ptr [ebp+4107E0]
  0043F48D    83C1 10         add     ecx, 10
  0043F490    8B01            mov     eax, dword ptr [ecx]
  0043F492    0385 E0074100   add     eax, dword ptr [ebp+4107E0]
  
  这里是读取开机到现在的时间,后面用的着。
  0043E937    E8 03FDFFFF     call    0043E63F   ; jmp 到 kernel32.GetTickCount
  0043E93C    8985 68084100   mov     dword ptr [ebp+410868], eax   保存地址可记下来
  0043E942    E8 03000000     call    0043E94A
  0043E947    EB 01           jmp     short 0043E94A
  
  获取操作系统版本,用XP实践的其他版本没尝试。
  0043F412    E8 2EF2FFFF     call    0043E645  ; jmp 到 kernel32.GetVersion
  0043F417    A9 00000080     test    eax, 80000000
  0043F41C    74 20           je      short 0043F43E
  0043F41E    3C 04           cmp     al, 4
  0043F420    75 0C           jnz     short 0043F42E
  0043F422    C785 F4074100 0>mov     dword ptr [ebp+4107F4], 2
  0043F42C    EB 40           jmp     short 0043F46E
  0043F42E    3C 03           cmp     al, 3
  
  继续往下走
  0043E990    E8 68FCFFFF     call    0043E5FD  ; jmp 到 kernel32.GetPriorityClass
  0043E995    8985 0C084100   mov     dword ptr [ebp+41080C], eax
  0043E99B    58              pop     eax
  0043E99C    68 80000000     push    80
  0043E9A1    50              push    eax
  0043E9A2    E8 50FCFFFF     call    0043E5F7   ; jmp 到 kernel32.SetPriorityClass
  0043E9A7    F785 F4074100 0>test    dword ptr [ebp+4107F4], 8
  0043E9B1    75 07           jnz     short 0043E9BA
  0043E9B3    6A 01           push    1
  0043E9B5    E8 BBFCFFFF     call    0043E675    ; jmp 到 User32.BlockInput
  BlockInput这个函数用于阻止键盘输入,可NOP掉,用CTRL+ALT+DEL比较方便
  
  再往下走就有很多反调试的东西了,基本上涵盖了看雪那基本书上介绍的那几种方法。IsDebugPresent函数,CreateFile检测SOFTICE,ToolHelp32快照函数检测父进程,还有BlockInput.用海风大侠插件就不用怕了。
  下面有个anti-dump的代码
  0043ED82    64:FF35 3000000>push    dword ptr fs:[30]
  0043ED89    58              pop     eax                     PEB
  0043ED8A    85C0            test    eax, eax
  0043ED8C    78 0F           js      short 0043ED9D
  0043ED8E    8B40 0C         mov     eax, dword ptr [eax+C]     LDR
  0043ED91    8B40 0C         mov     eax, dword ptr [eax+C]     InLoadOderModule-
  0043ED94    C740 20 0020000>mov     dword ptr [eax+20], 2000  
  SizeOfImage改为2000,如果后面DUMP失败,则可以将这里NOP掉。
  
  继续往下走,校验的地方,参考其他文章。
  0043EF3E    02C1            add     al, cl
  0043EF40    EB 01           jmp     short 0043EF43
  0043EF42  - E9 2AC1EB01     jmp     022FB071
  0043EF47    C2 D9D0         retn    0D0D9
  0043EF4A    C0C0 8B         rol     al, 8B
  0043EF4D    F9              stc
  0043EF4E    02C1            add     al, cl
  0043EF50    C0C8 58         ror     al, 58
  0043EF53    AA              stos    byte ptr es:[edi]
  0043EF54  ^ E2 CC           loopd   short 0043EF22
  0043EF56    C3              retn
  上面是解码部分,有花,估计贴出来的有些部分代码改变了
  继续下面是区块表的处理。
  0043F199    8BF7            mov     esi, edi
  0043F19B    81C6 F8000000   add     esi, 0F8
  0043F1A1    8D9D 600B4100   lea     ebx, dword ptr [ebp+410B60]
  0043F1A7    33D2            xor     edx, edx
  0043F1A9    52              push    edx
  0043F1AA    51              push    ecx
  0043F1AB    50              push    eax
  0043F1AC    56              push    esi
  0043F1AD    57              push    edi
  0043F1AE    8BFE            mov     edi, esi
  0043F1B0    8BF3            mov     esi, ebx
  0043F1B2    B9 08000000     mov     ecx, 8
  0043F1B7    AC              lods    byte ptr [esi]
  0043F1B8    AA              stos    byte ptr es:[edi]
  0043F1B9  ^ E2 FC           loopd   short 0043F1B7
  0043F1BB    5F              pop     edi
  0043F1BC    5E              pop     esi
  0043F1BD    58              pop     eax
  0043F1BE    59              pop     ecx
  0043F1BF    5A              pop     edx
  0043F1C0    83C3 08         add     ebx, 8
  0043F1C3    83C6 28         add     esi, 28
  0043F1C6    42              inc     edx
  0043F1C7    66:3E:3B57 06   cmp     dx, word ptr [edi+6]
  0043F1CC  ^ 75 DB           jnz     short 0043F1A9
  0043F1CE    C3              retn
  
  继续往下走,到了IAT处理部分。外壳保存引入表格式的信息为 Name,FirstThunk,OrignalFirstThunK,ESI指向Name,后面偏移分别为4,8.
  ESI指向->Name
  0044046C    3E:837E 04 00   cmp     dword ptr [esi+4], 0       FirstThunk
  00440471    0F84 19030000   je      00440790
  00440477    3E:8B1E         mov     ebx, dword ptr [esi]      Name
  0044047A    039D E0074100   add     ebx, dword ptr [ebp+4107E0]
  00440480    8BC3            mov     eax, ebx
  00440482    E8 08000000     call    0044048F           解码出DLL名字
  00440487    8D85 14014100   lea     eax, dword ptr [ebp+410114]
  0044048D    50              push    eax
  0044048E    C3              retn
  
  0044065E    53              push    ebx
  0044065F    BA 21DF4000     mov     edx, 0040DF21  ; ASCII CC,"烫烫"
  00440664    FF5415 00       call    dword ptr [ebp+edx] ; kernel32.LoadLibraryA
  00440668    85C0            test    eax, eax
  0044066A    0F84 23010000   je      00440793
  00440670    52              push    edx
  00440671    50              push    eax
  00440672    F785 500B4100 0>test    dword ptr [ebp+410B50], 4
  0044067C    74 0E           je      short 0044068C
  0044067E    8D85 42014100   lea     eax, dword ptr [ebp+410142]
  00440684    50              push    eax
  00440685    8BC3            mov     eax, ebx
  00440687    E9 12060000     jmp     00440C9E
  
  下面是将字符串清空
  00440CA0    3E:C600 00      mov     byte ptr [eax], 0   这里要NOP掉
  00440CA4    40              inc     eax
  00440CA5    3E:8038 00      cmp     byte ptr [eax], 0
  00440CA9  ^ 75 F5           jnz     short 00440CA0
  00440CAB    C3              retn
  
  0044068C    5B              pop     ebx
  0044068D    5A              pop     edx
  0044068E    3E:8B4E 08      mov     ecx, dword ptr [esi+8]  OringnalFirstThunk
  00440692    0BC9            or      ecx, ecx
  00440694    75 04           jnz     short 0044069A
  
  004406D0    52              push    edx
  004406D1    51              push    ecx
  004406D2    50              push    eax
  004406D3    53              push    ebx
  004406D4    BA 25DF4000     mov     edx, 0040DF25   ; ASCII CC,"烫烫烫"
  004406D9    FF5415 00    call    dword ptr [ebp+edx]  ; kernel32.GetProcAddress
  004406DD    0BC0          or      eax, eax
  004406DF    75 07           jnz     short 004406E8
  
  00440706    61              popad
  00440707    5A             pop     edx                           
  00440708    8902            mov     dword ptr [edx], eax          ; 写入内存
  0044070A    EB 1C           jmp     short 00440728
  
  下面是对不同的DLL库做不同的处理,他里面的OPENGL32.DLL,GLU32.DLL不处理。
  00440728    51              push    ecx        ; yP.00432984
  00440729    F785 500B4100 2>test    dword ptr [ebp+410B50], 20
  00440733    74 47           je      short 0044077C
  00440735    83BD 580B4100 0>cmp     dword ptr [ebp+410B58], 0
  0044073C    74 14           je      short 00440752
  0044073E    81FB 00000070   cmp     ebx, 70000000
  00440744    72 08           jb      short 0044074E  
  00440746    81FB FFFFFF77   cmp     ebx, 77FFFFFF
  0044074C    76 0E           jbe     short 0044075C
  0044074E    EB 2C           jmp     short 0044077C      不处理
  00440750    EB 0A           jmp     short 0044075C
  00440752    81FB 00000080   cmp     ebx, 80000000
  00440758    73 02           jnb     short 0044075C
  0044075A    EB 20           jmp     short 0044077C
  0044075C    57              push    edi
  0044075D    56              push    esi
  0044075E    8DBD 7B0C4100   lea     edi, dword ptr [ebp+410C7B]
  00440764    3E:8B77 04      mov     esi, dword ptr [edi+4]
  00440768    8932            mov     dword ptr [edx], esi     这里要NOP掉
  0044076A    2BC6            sub     eax, esi
  0044076C    83E8 05         sub     eax, 5
  0044076F    C606 E9         mov     byte ptr [esi], 0E9      构造跳转表
  00440772    8946 01         mov     dword ptr [esi+1], eax
  00440775    3E:8347 04 05   add     dword ptr [edi+4], 5
  0044077A    5E              pop     esi
  0044077B    5F              pop     edi
  0044077C    59              pop     ecx
  0044077D    83C1 04         add     ecx, 4
  00440780    83C2 04         add     edx, 4
  00440783  ^ E9 22FFFFFF     jmp     004406AA
  00440788    83C6 0C         add     esi, 0C
  0044078B  ^ E9 DCFCFFFF     jmp     0044046C
  上面程序在动态申请的空间构造了以个跳转表,然后将檫掉程序里的IAT。所以NOP掉那两句就可以用IMPORTREC得到完整的IAT,保存后面使用。
  
  IAT完了后,继续往下走
  00440890    E8 AADDFFFF     call    0043E63F    ; jmp 到 kernel32.GetTickCount
  00440895    8B8D 68084100   mov     ecx, dword ptr [ebp+410868]
  0044089B    2BC1            sub     eax, ecx
  0044089D    3D E02E0000     cmp     eax, 2EE0
  004408A2    78 08           js      short 004408AC  这里要跳,不跳就挂
  004408A4    EB 01           jmp     short 004408A7
  004408A6    2C 61           sub     al, 61
  004408A8  ^ EB E5           jmp     short 0044088F
  
  GetTickCount来和上次获取的时间进行比较,改标志位跳过。
  下面又到了继续解码的地方,F4跳过去
  004408FE    AA              stos    byte ptr es:[edi]
  004408FF  ^ E2 CC           loopd   short 004408CD
  00440901    8D85 C3034100   lea     eax, dword ptr [ebp+4103C3]
  00440907    50              push    eax
  00440908    C3              retn
  
  下面有个异常,看堆栈跳过去
  00440C8D    50              push    eax
  00440C8E    33C0            xor     eax, eax
  00440C90    64:FF30         push    dword ptr fs:[eax]
  00440C93    64:8920         mov     dword ptr fs:[eax], esp
  00440C96    EB 01           jmp     short 00440C99
  00440C98    C3              retn
  00440C99    0000            add     byte ptr [eax], al
  到了异常处理处
  00440A2C    55              push    ebp
  00440A2D    8BEC            mov     ebp, esp
  00440A2F    57              push    edi
  00440A30    36:8B45 10      mov     eax, dword ptr [ebp+10]
  00440A34    3E:8BB8 C400000>mov     edi, dword ptr [eax+C4]
  00440A3B    3E:FF37         push    dword ptr [edi]
  00440A3E    33FF            xor     edi, edi
  00440A40    64:8F07         pop     dword ptr fs:[edi]
  00440A43    3E:8380 C400000>add     dword ptr [eax+C4], 8
  00440A4B    3E:8BB8 A400000>mov     edi, dword ptr [eax+A4]
  00440A52    C1C7 07         rol     edi, 7
  00440A55    3E:89B8 B800000>mov     dword ptr [eax+B8], edi  这里改了EIP
  00440A5C    B8 00000000     mov     eax, 0
  00440A61    5F              pop     edi
  00440A62    C9              leave
  00440A63    C3              retn
  
  在EDI地址上下段后F9过去就是OEP了
  0041B295   .  6A 60         push    60
  0041B297   .  68 D05B4000   push    00405BD0
  0041B29C   .  E8 670D0000   call    0041C008
  0041B2A1   .  BF 94000000   mov     edi, 94
  0041B2A6   .  8BC7          mov     eax, edi
  0041B2A8   .  E8 C3FCFFFF   call    0041AF70
  0041B2AD   .  8965 E8       mov     dword ptr [ebp-18], esp
  0041B2B0   .  8BF4          mov     esi, esp
  0041B2B2   .  893E          mov     dword ptr [esi], edi
  0041B2B4   .  56            push    esi      ; /pVersionInformation
  0041B2B5   .  FF15 48114000 call    dword ptr [401148]      ; \GetVersionExA
  
  dump后,修复下IAT可以运行。
  
  参考资料:fly大侠的yoda's Protector V1.03.2.02脱壳——yP.exe全过程分析
  http://bbs.pediy.com/showthread.php?t=13927
  
--------------------------------------------------------------------------------
【经验总结】
  学脱壳得单步走,多用F7,少用F8。
  壳比较老,没什么价值,而且前辈也写有文章。算是新手的一次练习。
  
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2009年04月23日 22:54:58


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

上传的附件:
收藏
免费 7
支持
分享
最新回复 (9)
雪    币: 231
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
lang07123  。。我顶。我顶。我顶蘑菇。

顶完之后还是学习了。强大啊。。
2009-4-24 09:55
0
雪    币: 209
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
ppt
3
学习下,不会脱壳
2009-4-24 10:16
0
雪    币: 232
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
支持冷雨了,写得很详细
2009-4-24 10:53
0
雪    币: 697
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
不错,写得很详细,学习下
2009-4-24 11:21
0
雪    币: 167
活跃值: (1574)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
6
Good Job!
2009-4-24 12:34
0
雪    币: 239
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
不错啊,写的很好
2009-4-24 12:59
0
雪    币: 443
活跃值: (200)
能力值: ( LV9,RANK:1140 )
在线值:
发帖
回帖
粉丝
8
很厲害啊,,學習
2009-4-26 01:29
0
雪    币: 264
活跃值: (11)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
9
详细的分析 其中一些手段虽然老 但是经典..
2009-4-26 02:19
0
雪    币: 262
活跃值: (36)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
10
好贴,学习ing
2009-4-26 18:41
0
游客
登录 | 注册 方可回帖
返回
//