首页
社区
课程
招聘
C源码级混乱的 CrackMe 调试过程
发表于: 2005-3-27 23:08 11303

C源码级混乱的 CrackMe 调试过程

2005-3-27 23:08
11303

C源码级混乱的 CrackMe 调试过程

     日期:2005年3月27日   调试人:csjwaman[DFCG]
―――――――――――――――――――――――――――――――――――――――――――

【软件名称】:C源码级混乱的 CrackMe 
【下载地址】:http://bbs.pediy.com/showthread.php?s=&threadid=12217
【调试声明】:初学Crack,只是感兴趣,没有其它目的。失误之处敬请诸位大侠赐教!
【操作系统】:winxp sp1
【调试工具】:OD
【调试过程】:

  这个CrackMe 是vcasm的,据称是“算法特别简单,不过可能源码不好跟踪”。到底是不是不好跟踪,我们来试试。
  
  用OD载入后,忽略所有异常:

00402710 >/$  55            push ebp////载入后停在这里。
00402711  |.  8BEC          mov ebp,esp
00402713  |.  6A FF         push -1
00402715      68 08344000   push 403408
0040271A      68 96284000   push 402896                            ;  SE handler installation
0040271F      64:A1 0000000>mov eax,dword ptr fs:[0]
00402725      50            push eax
00402726      64:8925 00000>mov dword ptr fs:[0],esp

F9运行,出现注册界面,输入用户名和验证码,点“注册”居然异常在:

00401647      56            db 56                                  ;  CHAR 'V'
00401648      57            db 57                                  ;  CHAR 'W'
00401649      8B            db 8B
0040164A      F9            db F9
0040164B      CC            int3////异常在这里!(把这里NOP掉是不行的,见后面分析。)
0040164C      9D            db 9D
0040164D      42            db 42                                  ;  CHAR 'B'
0040164E      48            db 48                                  ;  CHAR 'H'
0040164F      2A            db 2A                                  ;  CHAR '*'

  异常后程序自动退出。往下看看发现有不少类似的代码!看来是CREACKME发现被跟踪了。那么程序是如何发现被跟踪的呢?我们一起来分析一下吧!

  重新用OD载入后,忽略所有异常:

00402710 >/$  55            push ebp////入口处。
00402711  |.  8BEC          mov ebp,esp
00402713  |.  6A FF         push -1
00402715      68 08344000   push 403408
0040271A      68 96284000   push 402896////SE handler 到402896处F2下断,不然程序跑飞!installation
0040271F      64:A1 0000000>mov eax,dword ptr fs:[0]////看到fs:[0]就应该联想到异常。
00402725      50            push eax
00402726      64:8925 00000>mov dword ptr fs:[0],esp
0040272D  |.  83EC 68       sub esp,68
00402730  |.  53            push ebx
00402731  |.  56            push esi
00402732  |.  57            push edi

00402896   $- FF25 A4314000 jmp dword ptr ds:[4031A4]////这里下断!
0040289C   $- FF25 A8314000 jmp dword ptr ds:[4031A8]

接着F9运行程序,等出现注册界面后输入用户名“aman”和验证码"12345678",点“注册”。

好!断下了,清除断点。F7跟进:

77C03EB0 >  55              push ebp
77C03EB1    8BEC            mov ebp,esp
77C03EB3    83EC 08         sub esp,8
77C03EB6    53              push ebx
77C03EB7    56              push esi
77C03EB8    57              push edi
77C03EB9    55              push ebp
77C03EBA    FC              cld
77C03EBB    8B5D 0C         mov ebx,dword ptr ss:[ebp+C]
77C03EBE    8B45 08         mov eax,dword ptr ss:[ebp+8]
77C03EC1    F740 04 0600000>test dword ptr ds:[eax+4],6
77C03EC8    0F85 82000000   jnz 77C03F50                           ; 77C03F50
77C03ECE    8945 F8         mov dword ptr ss:[ebp-8],eax
77C03ED1    8B45 10         mov eax,dword ptr ss:[ebp+10]
77C03ED4    8945 FC         mov dword ptr ss:[ebp-4],eax
77C03ED7    8D45 F8         lea eax,dword ptr ss:[ebp-8]
77C03EDA    8943 FC         mov dword ptr ds:[ebx-4],eax
77C03EDD    8B73 0C         mov esi,dword ptr ds:[ebx+C]
77C03EE0    8B7B 08         mov edi,dword ptr ds:[ebx+8]
77C03EE3    83FE FF         cmp esi,-1
77C03EE6    74 61           je short 77C03F49                      ; 77C03F49
77C03EE8    8D0C76          lea ecx,dword ptr ds:[esi+esi*2]
77C03EEB    837C8F 04 00    cmp dword ptr ds:[edi+ecx*4+4],0
77C03EF0    74 45           je short 77C03F37                      ; 77C03F37
77C03EF2    56              push esi
77C03EF3    55              push ebp
77C03EF4    8D6B 10         lea ebp,dword ptr ds:[ebx+10]
77C03EF7    FF548F 04       call dword ptr ds:[edi+ecx*4+4] ////直接F4到这里,看看CALL的地址是哪里?
77C03EFB    5D              pop ebp
77C03EFC    5E              pop esi
77C03EFD    8B5D 0C         mov ebx,dword ptr ss:[ebp+C]
77C03F00    0BC0            or eax,eax

原来是CALL到0040284E处。好,继续F7跟进:

0040284E  |.  8B45 EC       mov eax,dword ptr ss:[ebp-14]////来到这里。
00402851  |.  8B08          mov ecx,dword ptr ds:[eax]
00402853  |.  8B09          mov ecx,dword ptr ds:[ecx]
00402855  |.  894D 88       mov dword ptr ss:[ebp-78],ecx
00402858  |.  50            push eax
00402859      51            push ecx
0040285A      E8 15000000   call 00402874 ;  <jmp.&MSVCRT._XcptFilter>////关键!
0040285F      59            pop ecx
00402860  |.  59            pop ecx
00402861  \.  C3            retn

在0040285A处用F7跟进:

0040286E   $- FF25 B0314000 jmp dword ptr ds:[4031B0]
00402874   $- FF25 7C314000 jmp dword ptr ds:[40317C]////继续F7。
0040287A   $- FF25 8C314000 jmp dword ptr ds:[40318C]

来到:

77C01269 >  55              push ebp////以下用F8走。
77C0126A    8BEC            mov ebp,esp
77C0126C    51              push ecx
77C0126D    53              push ebx
77C0126E    56              push esi
77C0126F    57              push edi
77C01270    E8 DD680000     call 77C07B52                          ; 77C07B52
77C01275    8B7D 08         mov edi,dword ptr ss:[ebp+8]
77C01278    8BF0            mov esi,eax
77C0127A    8B56 54         mov edx,dword ptr ds:[esi+54]
77C0127D    A1 94A7C277     mov eax,dword ptr ds:[77C2A794]
77C01282    8BCA            mov ecx,edx
77C01284    3939            cmp dword ptr ds:[ecx],edi
77C01286    74 0D           je short 77C01295                      ; 77C01295
77C01288    8D1C40          lea ebx,dword ptr ds:[eax+eax*2]
77C0128B    83C1 0C         add ecx,0C
77C0128E    8D1C9A          lea ebx,dword ptr ds:[edx+ebx*4]
77C01291    3BCB            cmp ecx,ebx
77C01293  ^ 72 EF           jb short 77C01284                      ; 77C01284
77C01295    8D0440          lea eax,dword ptr ds:[eax+eax*2]////F4下来。
77C01298    8D0482          lea eax,dword ptr ds:[edx+eax*4]
77C0129B    3BC8            cmp ecx,eax
77C0129D    73 04           jnb short 77C012A3                     ; 77C012A3
77C0129F    3939            cmp dword ptr ds:[ecx],edi
77C012A1    74 02           je short 77C012A5                      ; 77C012A5
77C012A3    33C9            xor ecx,ecx
77C012A5    85C9            test ecx,ecx
77C012A7    0F84 12010000   je 77C013BF ////这里跳!
77C012AD    8B59 08         mov ebx,dword ptr ds:[ecx+8]
77C012B0    85DB            test ebx,ebx
77C012B2    895D 08         mov dword ptr ss:[ebp+8],ebx
77C012B5    0F84 04010000   je 77C013BF                            ; 77C013BF
77C012BB    83FB 05         cmp ebx,5
77C012BE    75 0C           jnz short 77C012CC                     ; 77C012CC

跳到:

77C013BF    FF75 0C         push dword ptr ss:[ebp+C]////跳到这里。
77C013C2    FF15 C011BE77   call dword ptr ds:[77BE11C0] ; kernel32.UnhandledExceptionFilter
77C013C8    5F              pop edi
77C013C9    5E              pop esi
77C013CA    5B              pop ebx
77C013CB    C9              leave
77C013CC    C3              retn

跳到77C013BF后就可以发现开始调用UnhandledExceptionFilter了!!!

F7跟进:

77E730C0 >  68 00050000     push 500
77E730C5    68 F852E777     push 77E752F8
77E730CA    E8 0972FEFF     call 77E5A2D8                          ; 77E5A2D8
77E730CF    C745 E4 0400000>mov dword ptr ss:[ebp-1C],4
77E730D6    8B7D 08         mov edi,dword ptr ss:[ebp+8]
77E730D9    8B07            mov eax,dword ptr ds:[edi]
77E730DB    BB 050000C0     mov ebx,C0000005
77E730E0    33F6            xor esi,esi
77E730E2    3918            cmp dword ptr ds:[eax],ebx
77E730E4    75 09           jnz short 77E730EF                     ; 77E730EF
77E730E6    3970 14         cmp dword ptr ds:[eax+14],esi
77E730E9    0F85 77DC0000   jnz 77E80D66                           ; 77E80D66
77E730EF    8975 E0         mov dword ptr ss:[ebp-20],esi
77E730F2    56              push esi
77E730F3    6A 04           push 4
77E730F5    8D45 E0         lea eax,dword ptr ss:[ebp-20]
77E730F8    50              push eax
77E730F9    6A 07           push 7
77E730FB    E8 B9B5FEFF     call 77E5E6B9////调用GetCurrentProcess,返回hProcess。
77E73100    50              push eax
77E73101    FF15 AC10E477   call dword ptr ds:[77E410AC]////调用ntdll.ZwQueryInformationProcess。晕,调用好多次!
77E73107    85C0            test eax,eax////EAX=0则表示成功,否则失败。
77E73109    7C 09           jl short 77E73114
77E7310B    3975 E0         cmp dword ptr ss:[ebp-20],esi////[ebp-20]=-1,则表示有调试器,=0表示没调试器。
77E7310E    0F85 C5060000   jnz 77E737D9////这里不能跳,跳则表示有调试器。干脆NOP掉!
77E73114    A1 B473EB77     mov eax,dword ptr ds:[77EB73B4]
77E73119    3BC6            cmp eax,esi
77E7311B    74 15           je short 77E73132
77E7311D    57              push edi
77E7311E    FFD0            call eax////F7进入!
77E73120    83F8 01         cmp eax,1
77E73123    0F84 E9030000   je 77E73512                            ; 77E73512

把77E7310E处的跳转NOP掉后,在77E7311E处用F7跟进。进入后来到:

004012F0   . /EB 44         jmp short 00401336 ////来到这里。
004012F2   > |0F85 D6000000 jnz 004013CE                           ;  004013CE
004012F8   . |EB 2F         jmp short 00401329                     ;  00401329
004012FA     |9A            db 9A
004012FB   > |EB 02         jmp short 004012FF                     ;  004012FF
004012FD     |9A            db 9A

用F7跟踪几步就可以看到:

004014A8   > \8A0A          mov cl,byte ptr ds:[edx]
004014AA   .^ E9 3EFFFFFF   jmp 004013ED                           ;  004013ED
004014AF      3B            db 3B                                  ;  CHAR ';'
004014B0   >  8AC8          mov cl,al
004014B2   .^ E9 79FFFFFF   jmp 00401430                           ;  00401430
004014B7      3B            db 3B                                  ;  CHAR ';'
004014B8   >  803A CC       cmp byte ptr ds:[edx],0CC////edx=40164B,[edx]=CC,比较后跳!
004014BB   .^ E9 32FEFFFF   jmp 004012F2                           ;  004012F2
004014C0      3B            db 3B                                  ;  CHAR ';'
004014C1   >  80C1 11       add cl,11
004014C4   .^ E9 32FEFFFF   jmp 004012FB                           ;  004012FB
004014C9      3B            db 3B                                  ;  CHAR ';'

看看40164B处的数据:

00401649      8B            db 8B
0040164A      F9            db F9
0040164B      CC            int3
0040164C      9D            db 9D
0040164D      42            db 42                                  ;  CHAR 'B'
0040164E      48            db 48                                  ;  CHAR 'H'

跳到:

004012F2   > /0F85 D6000000 jnz 004013CE////跳到这里!
004012F8   . |EB 2F         jmp short 00401329                     ;  00401329
004012FA     |9A            db 9A
004012FB   > |EB 02         jmp short 004012FF                     ;  004012FF
004012FD     |9A            db 9A

如果40164B处不是CC,则跳,然后会来到:

004014A8   > \8A0A          mov cl,byte ptr ds:[edx]/////跳到这里。此时edx=40164B.
004014AA   .^ E9 3EFFFFFF   jmp 004013ED
004014AF      3B            db 3B

如果40164B处是CC,则不跳,然后会来到:

00401329   > \42            inc edx ////跳到这里。
0040132A   .  E9 81000000   jmp 004013B0                           ;  004013B0
0040132F      3B            db 3B                                  ;  CHAR ';'
00401330   >  E9 EF000000   jmp 00401424                           ;  00401424

经过几个跳转后也会来到:

004014A8   > \8A0A          mov cl,byte ptr ds:[edx]////来到这里。此时edx=40164C.
004014AA   .^ E9 3EFFFFFF   jmp 004013ED                           ;  004013ED
004014AF      3B            db 3B                                  ;  CHAR ';'
004014B0   >  8AC8          mov cl,al

但004012F2处跳与不跳,在004014A8处的[edx]中的值是不一样的,分别是CC和9D。而这个数据通过变换以后计算出堆栈数据,所以是不能轻易NOP掉的。

现在搜索所有命令“push 404020”。为什么搜索这个命令,因为404020处保存着“注册成功”的字符串:)
搜索到:

0040228F   .  44            inc esp
00402290   .  3BD9          cmp ebx,ecx////这里下断!
00402292   .  75 17         jnz short 004022AB                     ;  004022AB
00402294   .  6A 00         push 0
00402296   .  6A 00         push 0
00402298   .  68 20404000   push 404020////找到这里!
0040229D   .  8BCF          mov ecx,edi
0040229F   .  E8 14040000   call 004026B8                          ;  <jmp.&MFC42.#4224>
004022A4   .  5F            pop edi
004022A5   .  5E            pop esi
004022A6   .  5B            pop ebx
004022A7   .  8BE5          mov esp,ebp
004022A9   .  5D            pop ebp
004022AA   .  C3            retn

在00402290处下断后,F9运行程序会出现一个INT3异常,SHIFT+F9通过,接着OD会有好多“可疑中断点”的提示,因为程序在数据区中添加了好多CC在里面。全部点“否”。最后会断在00402290处。

断下后00402290处就是真假注册比较,ECX中保存的是验证码“12345678”倒置后的十六进制值,EBX中保存的“E9471”,换算成十进制后是“955505”。所以用户名“aman”的注册码是“505559”。


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 7
支持
分享
最新回复 (9)
雪    币: 301
活跃值: (300)
能力值: ( LV9,RANK:290 )
在线值:
发帖
回帖
粉丝
2
辛苦了,支持你
2005-3-27 23:25
0
雪    币: 98761
活跃值: (201039)
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
3
写的好!!!
2005-3-27 23:44
0
雪    币: 151
活跃值: (66)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
4
学习,感觉C蛮复杂的
2005-3-28 08:27
0
雪    币: 898
活跃值: (4039)
能力值: ( LV9,RANK:3410 )
在线值:
发帖
回帖
粉丝
5
用UnhExcFlt.DLL插件
BP MessageBoxA
中断后回去就能看到比较的地方了
2005-3-28 09:46
0
雪    币: 389
活跃值: (912)
能力值: ( LV9,RANK:770 )
在线值:
发帖
回帖
粉丝
6
现在怎么都玩异常。
2005-3-28 13:17
0
雪    币: 214
活跃值: (15)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
7
楼主:哪里可看出404020处保存着“注册成功”的字符串?是不是通过搜索字符串知道的?
2005-3-28 14:04
0
雪    币: 319
活跃值: (2459)
能力值: ( LV12,RANK:980 )
在线值:
发帖
回帖
粉丝
8
OD载入后看内存区就可以看到了:)偷懒的办法。
2005-3-28 14:51
0
雪    币: 214
活跃值: (15)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
9
最初由 csjwaman 发布
OD载入后看内存区就可以看到了:)偷懒的办法。

如果“注册成功”的字符串加密了怎么办?
2005-3-28 15:44
0
雪    币: 319
活跃值: (2459)
能力值: ( LV12,RANK:980 )
在线值:
发帖
回帖
粉丝
10
那就跟踪吧
2005-3-28 20:14
0
游客
登录 | 注册 方可回帖
返回
//