首页
社区
课程
招聘
[原创] 简单修复Themida加壳的VC7+去除软件自校验
发表于: 2009-8-10 09:08 8783

[原创] 简单修复Themida加壳的VC7+去除软件自校验

2009-8-10 09:08
8783

【文章标题】: 简单修复Themida加壳的VC7+去除软件自校验
【文章作者】: wuhanqi
【作者邮箱】: wuhanqi@qq.com
【下载地址】: 自己搜索下载
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
  题外话:
   其实这个VC7的程序我本来都放一边了,因为实在是找不到对比OEP的无壳程序,可是昨天Nisy 老大发给我一个蛮有意思的注册验证程序,DJ Java Decompiler 3.11,无壳的,我用OD载入后一看到Push 60就一下子想起了这个TMD加壳的VC7,遂有了此文。
  
  加壳程序是国产的。我就不透漏名称了。
  
  这就是无壳程序的OEP:
  00477F88 > $  6A 60         PUSH 60
  00477F8A   .  68 30805000   PUSH 00508030
  00477F8F   .  E8 744D0000   CALL 0047CD08
  00477F94   .  BF 94000000   MOV EDI,94
  00477F99   .  8BC7          MOV EAX,EDI
  00477F9B   .  E8 70FEFFFF   CALL 00477E10
  00477FA0   .  8965 E8       MOV DWORD PTR SS:[EBP-18],ESP
  00477FA3   .  8BF4          MOV ESI,ESP
  00477FA5   .  893E          MOV DWORD PTR DS:[ESI],EDI
  00477FA7   .  56            PUSH ESI                                 ; /pVersionInformation
  00477FA8   .  FF15 78934F00 CALL DWORD PTR DS:[<&KERNEL32.GetVersion>; \GetVersionExA
  00477FAE   .  8B4E 10       MOV ECX,DWORD PTR DS:[ESI+10]
  00477FB1   .  890D CC465400 MOV DWORD PTR DS:[5446CC],ECX
  00477FB7   .  8B46 04       MOV EAX,DWORD PTR DS:[ESI+4]
  00477FBA   .  A3 D8465400   MOV DWORD PTR DS:[5446D8],EAX
  00477FBF   .  8B56 08       MOV EDX,DWORD PTR DS:[ESI+8]
  00477FC2   .  8915 DC465400 MOV DWORD PTR DS:[5446DC],EDX
  00477FC8   .  8B76 0C       MOV ESI,DWORD PTR DS:[ESI+C]
  00477FCB   .  81E6 FF7F0000 AND ESI,7FFF
  00477FD1   .  8935 D0465400 MOV DWORD PTR DS:[5446D0],ESI
  00477FD7   .  83F9 02       CMP ECX,2
  00477FDA   .  74 0C         JE SHORT 00477FE8
  00477FDC   .  81CE 00800000 OR ESI,8000
  00477FE2   .  8935 D0465400 MOV DWORD PTR DS:[5446D0],ESI
  00477FE8   >  C1E0 08       SHL EAX,8
  00477FEB   .  03C2          ADD EAX,EDX
  00477FED   .  A3 D4465400   MOV DWORD PTR DS:[5446D4],EAX
  00477FF2   .  33F6          XOR ESI,ESI
  00477FF4   .  56            PUSH ESI                                 ; /pModule => NULL
  00477FF5   .  8B3D 5C934F00 MOV EDI,DWORD PTR DS:[<&KERNEL32.GetModu>; |kernel32.GetModuleHandleA
  00477FFB   .  FFD7          CALL EDI                                 ; \GetModuleHandleA
  00477FFD   .  66:8138 4D5A  CMP WORD PTR DS:[EAX],5A4D
  00478002   .  75 1F         JNZ SHORT 00478023
  
  
  废话不多说了,OD载入程序打开内存镜像看TMDBASE是多少,565000,用编辑工具修改一下Nooby牛的脚本,然后跑脚本...这个过程我就不多叙述了。
  脚本结束后停在OEP附近的第一个CALL中。
  00471940    68 A0F14600     push 0046F1A0
  00471945    64:A1 00000000  mov eax,dword ptr fs:[0]
  0047194B    50              push eax
  0047194C    8B4424 10       mov eax,dword ptr ss:[esp+10]
  00471950    896C24 10       mov dword ptr ss:[esp+10],ebp
  00471954    8D6C24 10       lea ebp,dword ptr ss:[esp+10]
  00471958    2BE0            sub esp,eax
  0047195A    53              push ebx
  0047195B    56              push esi
  0047195C    57              push edi
  0047195D    8B45 F8         mov eax,dword ptr ss:[ebp-8]
  00471960    8965 E8         mov dword ptr ss:[ebp-18],esp
  00471963    50              push eax
  00471964    8B45 FC         mov eax,dword ptr ss:[ebp-4]
  00471967    C745 FC FFFFFFF>mov dword ptr ss:[ebp-4],-1
  0047196E    8945 F8         mov dword ptr ss:[ebp-8],eax
  00471971    8D45 F0         lea eax,dword ptr ss:[ebp-10]
  00471974    64:A3 00000000  mov dword ptr fs:[0],eax
  0047197A    C3              retn
  
  看堆栈:
  0012FF54   007FE908  SuperRec.007FE908
  0012FF58   0049F740  SuperRec.0049F740  第②句PUSH
  0012FF5C   00000060                     第①句PUSH

  0012FF60   00400208  ASCII "   "
  0012FF64   0012FFC4
  0012FF68   00792EB8  SuperRec.00792EB8
  
  可以猜出前三句OEP为
  push 60
  push 0049f740
  call 00471940

  
  接下来走出这个call。
  007FE908    68 16EB2925     push 2529EB16
  007FE90D  ^ E9 29B9FFFF     jmp 007FA23B
  
  单步走过上面的jmp,来到:
  007FA23B    6A 00           push 0
  007FA23D    0F89 15000000   jns 007FA258
  
  打开内存镜像。在00401000段F2,然后F9,停在OEP附近第二个call处。
  00470540    3D 00100000     cmp eax,1000
  00470545    73 0E           jnb short 00470555
  00470547    F7D8            neg eax
  00470549    03C4            add eax,esp
  0047054B    83C0 04         add eax,4
  0047054E    8500            test dword ptr ds:[eax],eax
  00470550    94              xchg eax,esp
  00470551    8B00            mov eax,dword ptr ds:[eax]
  00470553    50              push eax
  00470554    C3              retn
  
  此时可以对比无壳的程序看一下代码,这是无壳的前几句:
  00477F88 > $  6A 60         PUSH 60
  00477F8A   .  68 30805000   PUSH 00508030
  00477F8F   .  E8 744D0000   CALL 0047CD08
  00477F94   .  BF 94000000   MOV EDI,94
  00477F99   .  8BC7          MOV EAX,EDI
  00477F9B   .  E8 70FEFFFF   CALL 00477E10
  00477FA0   .  8965 E8       MOV DWORD PTR SS:[EBP-18],ESP
  
  再看看我们的寄存器。
  EAX 00000094
  ECX 00020048
  EDX 00020048
  EBX 0012FF64
  ESP 0012FEDC
  EBP 0012FF5C
  ESI F63945F1
  EDI 00000094
  EIP 00470540 SuperRec.00470540
  
  的确EDI与EAX都变红而且都为94
  
  那接下来三句就是
mov edi,94
mov eax,edi
call 00470540

  
  接下来走出这个call:
  007FE91A    68 7FE9110B     push 0B11E97F
  007FE91F  ^ E9 17B9FFFF     jmp 007FA23B
  
  依旧走过这个jmp后在code段下断再F9
  此时停在这里:
  019F8947    FF33            push dword ptr ds:[ebx]                  ; kernel32.GetVersionExA
  019F8949  ^ E9 F580F5FF     jmp 01950A43
  
  看信息窗口:
  ds:[004932AC]=77AB9D76 (kernel32.GetVersionExA)
  
  这个地址很关键,我们可以对照着看无壳程序的OEP,在下一个call就是call这个函数,
  那这个call就应该这样写了:call dword ptr ds:[004932ac]
  
  又因为VC7的OEP相对固定,
  那接下来几句就是:
  MOV DWORD PTR SS:[EBP-18],ESP
  MOV ESI,ESP
  MOV DWORD PTR DS:[ESI],EDI
  PUSH ESI   
  call dword ptr ds:[004932ac]

   
  插句题外话:其实你记不住这个地址也没问题,因为GetVersionExA和GetModuleHandleA在IAT输入表里很接近.而程序下面就就有调用GetModuleHandleA,找到了GetModuleHandleA就等于找到了GetVersionExA.

  我们再继续走jmp下code段的断点。此过程我就不做记录了。
  值的注意的是走到这里的时候:
  019FD621    F3:A4           rep movs byte ptr es:[edi],byte ptr ds:[>
  019FD623    68 016D0000     push 6D01
  019FD628    890C24          mov dword ptr ss:[esp],ecx
  
  在019fd621需要是F7再F8,否则程序跑飞,前功尽弃。
  最终我们停在这里:
  0046EF05    A3 00B65100     mov dword ptr ds:[51B600],eax
  0046EF0A    8B56 08         mov edx,dword ptr ds:[esi+8]
  0046EF0D    8915 04B65100   mov dword ptr ds:[51B604],edx
  0046EF13    8B76 0C         mov esi,dword ptr ds:[esi+C]
  0046EF16    81E6 FF7F0000   and esi,7FFF
  0046EF1C    8935 F8B55100   mov dword ptr ds:[51B5F8],esi
  0046EF22    83F9 02         cmp ecx,2
  0046EF25    74 0C           je short 0046EF33
  0046EF27    81CE 00800000   or esi,8000
  0046EF2D    8935 F8B55100   mov dword ptr ds:[51B5F8],esi
  0046EF33    C1E0 08         shl eax,8
  0046EF36    03C2            add eax,edx
  0046EF38    A3 FCB55100     mov dword ptr ds:[51B5FC],eax
  0046EF3D    33F6            xor esi,esi
  0046EF3F    56              push esi
  0046EF40    8B3D A8324900   mov edi,dword ptr ds:[4932A8]            ; kernel32.GetModuleHandleA
  0046EF46    FFD7            call edi
  0046EF48    66:8138 4D5A    cmp word ptr ds:[eax],5A4D
  
  上面距离call GetVersionExA 这个函数依旧还有三句话:
  这是无壳程序的那三句话:
  00477FAE   .  8B4E 10       MOV ECX,DWORD PTR DS:[ESI+10]
  00477FB1   .  890D CC465400 MOV DWORD PTR DS:[5446CC],ECX
  00477FB7   .  8B46 04       MOV EAX,DWORD PTR DS:[ESI+4]
  00477FBA   .  A3 D8465400   MOV DWORD PTR DS:[5446D8],EAX
  
  这下有人晕了,这可怎么搞,没有地址怎么修复?
  其实很简单,我们用无壳程序的这两句地址相减,即5446d8-5446cc=c
  那我们需要的那个地址就应该是 51b600-c=51B5F4
  
  那我们加壳程序的接下来三句就应该是:
  MOV ECX,DWORD PTR DS:[ESI+10]
  MOV DWORD PTR DS:[51B5F4],ECX
  MOV EAX,DWORD PTR DS:[ESI+4]

  
  总结一下被偷的OEP就是:
  push 60
  push 0049f740
  call 00471940
  mov edi,94
  mov eax,edi
  call 00470540
  MOV DWORD PTR SS:[EBP-18],ESP
  MOV ESI,ESP
  MOV DWORD PTR DS:[ESI],EDI
  PUSH ESI   
  call dword ptr ds:[004932ac]
  MOV ECX,DWORD PTR DS:[ESI+10]
  MOV DWORD PTR DS:[51B5F4],ECX
  MOV EAX,DWORD PTR DS:[ESI+4]   

  
  这样脱好壳之后,运行程序,窗口一闪而过。
  自校验。。
  我用的是bp GetFileSize
  因为程序是窗口一闪而过,所以要在显示窗口后再返回程序。
  返回程序领空只需要F8即可来到这里:
  0042A126   > \3B7424 20     cmp esi,dword ptr ss:[esp+20]
  0042A12A   .  74 14         je short 0042A140
  0042A12C   .  8B5424 24     mov edx,dword ptr ss:[esp+24]
  0042A130   .  8B42 2C       mov eax,dword ptr ds:[edx+2C]
  0042A133   .  53            push ebx                                 ; /lParam
  0042A134   .  53            push ebx                                 ; |wParam
  0042A135   .  6A 12         push 12                                  ; |Message = WM_QUIT
  0042A137   .  50            push eax                                 ; |ThreadId
  0042A138   .  90            nop                                      ; |
  0042A139   .  E8 50DB1877   call user32.PostThreadMessageW           ; \PostThreadMessageW
  0042A13E   .  EB 15         jmp short 0042A155
  0042A140   >  57            push edi
  0042A141   .  E8 FC580500   call 0047FA42
  0042A146   .  8B8D 68AB0200 mov ecx,dword ptr ss:[ebp+2AB68]
  0042A14C   .  83C4 04       add esp,4
  0042A14F   .  C701 08000000 mov dword ptr ds:[ecx],8
  0042A155   >  8D4C24 28     lea ecx,dword ptr ss:[esp+28]
  0042A159   .  885C24 40     mov byte ptr ss:[esp+40],bl
  0042A15D   .  E8 6A700500   call 004811CC
  0042A162   .  5D            pop ebp
  
  把42a12a的74改成eb即可。
  第一次看到结束程序用PostThreadMessageW的这个函数的。。
  
--------------------------------------------------------------------------------
【经验总结】
  其实VC7的OEP真的很好修复的.不是一般的好修复.
  只不过很难找到一个门当户对的无壳程序来对比OEP修复.
  这次是我运气好,也感谢Nisy老大~呵呵.
  
--------------------------------------------------------------------------------
【版权声明】: 菜鸟一个,没啥版权..

                                                       2009年08月10日 8:59:29


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

收藏
免费 7
支持
分享
最新回复 (8)
雪    币: 330
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
有点像1.9.10。脱它很实用:http://bbs.pediy.com/showthread.php?t=93451
2009-8-11 17:20
0
雪    币: 103
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
顶了 以后好好看
2009-8-12 03:06
0
雪    币: 197
活跃值: (19)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
向大侠学习,真是牛啊
2009-8-19 10:00
0
雪    币: 39
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
慢慢学习学习~~~~~~~~
2009-8-19 13:23
0
雪    币: 97
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
不错了,好文章!
2009-8-19 19:04
0
雪    币: 152
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
NB,一直很烦这种偷OEP的壳。。。。。
2009-8-19 21:02
0
雪    币: 239
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
1.9.10哈哈
2009-10-5 23:22
0
雪    币: 203
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
如果出个视频教程就好了,现在就遇到这种壳,很迷茫啊。。。
2009-10-7 10:13
0
游客
登录 | 注册 方可回帖
返回
//