SCSC注册分析
【破解作者】 winndy
【作者邮箱】 CNwinndy@hotmail.com
【使用工具】 PEID v0.93  OllyDbg v1.10 fly修改版
【破解平台】 Winxp SP2
【软件名称】 SCSC - Source Code SpellChecker V1.10
【官方网址】 HTTP://www.parasitesoft.com 
【编写语言】 VC6
【软件介绍】 SCSC - Source Code SpellChecker facilitates spelling check and correction for                 user interface 

that is exposed by your C/C++ source code. 
【破解声明】 For study ,For Fun,
【破解说明】 无壳,采用MD5算法,失误之处还望指出
【破解过程】PEID查壳,无壳,Microsoft Visual C++ 6.0编写.
            先运行Scsc,打开注册窗口,输入Name:CNwinndy,Code:1234567890
            点"OK",弹出messagebox(不一定,也许是一个form,猜测),显示警告消息为"Invalid registration code",           
            标题为"Source Code Spell Checker".
            OllyDbg载入Scsc.exe.右键,"搜索"--"所有参考字符串".
            找到这里:
            0040319D push Scsc.0045C034   ASCII "Invalid registration code"
            光标落在这一行,F2,下断点.
            再多下些断点,Command命令行输入:bpx messageboxex,打开了Intermodular calls,
            点目标,按照字母顺序排序,找到messageboxA,
            00432C32 call dword ptr ds:[<&USER32.MessageBoxA>]  USER32.MessageBoxA
            再下断点.
            Scsc是用getdlgitem还是GetWindowTextA来获得用户名和假注册码呢?
            把GetWindowTextA下断,顺便把GetWindowTextLengthA也下断点,
            往上找,call USER32.GetDlgItem处也下断点.

            然后F9运行程序,由于刚才在所有GetWindowTextA和getdlgitem处都下了断点,
            因此会有一些不必要的中断,通过观察寄存器,可以取消不必要的断点.
            进入主程序以后,打开输入注册码的窗口,输入Name:CNwinndy,Code:1234567890.
            点"OK",程序会中断在00432A7C :

00432A62   /$  55                 push ebp
00432A63   |.  8BEC               mov ebp,esp
00432A65   |.  56                 push esi
00432A66   |.  57                 push edi
00432A67   |.  8B7D 08            mov edi,dword ptr ss:[ebp+8]
00432A6A   |.  FF75 0C            push dword ptr ss:[ebp+C]
00432A6D   |.  8BCF               mov ecx,edi
00432A6F   |.  E8 A8FFFFFF        call Scsc.00432A1C
00432A74   |.  833F 00            cmp dword ptr ds:[edi],0
00432A77   |.  8BF0               mov esi,eax
00432A79   |.  74 28              je short Scsc.00432AA3
00432A7B   |.  56                 push esi                            ; /hWnd
00432A7C   |.  FF15 00964400      call dword ptr ds:[<&USER32.GetWind>; \GetWindowTextLengthA

            ;F8跳过,发现EAX=0000000A,这是注册码"1234567890"的长度.
            ;第二次进入,F8跳过,发现EAX=00000008,这是用户名"CNwinndy"的长度.

00432A82   |.  8D48 01            lea ecx,dword ptr ds:[eax+1]
00432A85   |.  51                 push ecx
00432A86   |.  8B4D 10            mov ecx,dword ptr ss:[ebp+10]
00432A89   |.  50                 push eax
00432A8A   |.  E8 A689FFFF        call Scsc.0042B435   ;F8先跳过再说,有问题再进去看
00432A8F   |.  50                 push eax                            ; |Buffer
00432A90   |.  56                 push esi                            ; |hWnd
00432A91   |.  FF15 E0944400      call dword ptr ds:[<&USER32.GetWind>; \GetWindowTextA ;F8跳过,
00432A97   |.  8B4D 10            mov ecx,dword ptr ss:[ebp+10]       ; 
 
            ;Ecx=0012FBD8    D ECX 查看内存:58 3B BC 00   再D [ECX] (或D 00BC3B58),查看:
            ;00BC3B58  31 32 33 34 35 36 37 38  12345678    ===>这里是假key
            ;00BC3B60  39 30 00                 90.
            ;第二次进入,D [ECX],
            ;00BC3BA8  43 4E 77 69 6E 6E 64 79  CNwinndy    ===>这里是用户名


00432A9A   |.  6A FF              push -1
00432A9C   |.  E8 6C89FFFF        call Scsc.0042B40D   ;F8先跳过再说,有问题再进去看
00432AA1   |.  EB 0B              jmp short Scsc.00432AAE
00432AA3   |> \8B45 10            mov eax,dword ptr ss:[ebp+10]
00432AA6   |.  FF30               push dword ptr ds:[eax]             ; /Arg2
00432AA8   |.  56                 push esi                            ; |Arg1
00432AA9   |.  E8 EEE8FFFF        call Scsc.0043139C                  ; \Scsc.0043139C
00432AAE   |>  5F                 pop edi                             ;  0012F6CC
00432AAF   |.  5E                 pop esi
00432AB0   |.  5D                 pop ebp
00432AB1   \.  C2 0C00            retn 0C


返回到:004030D7  

004030C0    .  56                 push esi
004030C1    .  8BF1               mov esi,ecx
004030C3    .  57                 push edi
004030C4    .  8B7C24 0C          mov edi,dword ptr ss:[esp+C]
004030C8    .  8D46 60            lea eax,dword ptr ds:[esi+60]
004030CB    .  50                 push eax                            ; /Arg3
004030CC    .  68 EF030000        push 3EF                            ; |Arg2 = 000003EF
004030D1    .  57                 push edi                            ; |Arg1
004030D2    .  E8 8BF90200        call Scsc.00432A62                  ; \Scsc.00432A62 ;取注册码

回到这里,再去取用户名
004030D7    .  83C6 5C            add esi,5C
004030DA    .  56                 push esi                            ; /Arg3
004030DB    .  68 F0030000        push 3F0                            ; |Arg2 = 000003F0
004030E0    .  57                 push edi                            ; |Arg1
004030E1    .  E8 7CF90200        call Scsc.00432A62                  ; \Scsc.00432A62;取用户名
004030E6    .  5F                 pop edi
004030E7    .  5E                 pop esi
004030E8    .  C2 0400            retn 4

回到这里:
004299AB    .  C745 08 01000000   mov dword ptr ss:[ebp+8],1
004299B2    .  EB 27              jmp short Scsc.004299DB

004299DB    > \8B45 E8            mov eax,dword ptr ss:[ebp-18]
004299DE    .  8B4D F4            mov ecx,dword ptr ss:[ebp-C]
004299E1    .  8987 B8000000      mov dword ptr ds:[edi+B8],eax
004299E7    .  8B45 08            mov eax,dword ptr ss:[ebp+8]
004299EA    .  5F                 pop edi
004299EB    .  5E                 pop esi
004299EC    .  64:890D 00000000   mov dword ptr fs:[0],ecx
004299F3    .  5B                 pop ebx
004299F4    .  C9                 leave
004299F5    .  C2 0400            retn 4

回到0040310A:

00403100    .  56                 push esi
00403101    .  8BF1               mov esi,ecx
00403103    .  6A 01              push 1
00403105    .  E8 4C680200        call Scsc.00429956
0040310A    .  8B46 60            mov eax,dword ptr ds:[esi+60]   ; 

;注意观察寄存器:EAX 00BC3B58 ASCII "1234567890"

0040310D    .  B9 30154600        mov ecx,Scsc.00461530
00403112    .  50                 push eax                        ;将注册码压入堆栈,下面这个Call不可跳过,需单步进入
00403113    .  68 90C14500        push Scsc.0045C190              ;  ASCII "scsc"
00403118    .  E8 03070000        call Scsc.00403820              ;  *****************,F7进入,见下面的[分析一]
0040311D    .  83F8 02            cmp eax,2                       ;  Switch (cases 0..10000)
00403120    .  77 4B              ja short Scsc.0040316D

00403122    .  74 39              je short Scsc.0040315D

00403124    .  83E8 00            sub eax,0
00403127    .  74 13              je short Scsc.0040313C

00403129    .  48                 dec eax
0040312A    .  75 4D              jnz short Scsc.00403179

0040312C    .  6A 00              push 0                          ; /Arg3 = 00000000; Case 1 of switch 0040311D
0040312E    .  6A 00              push 0                          ; |Arg2 = 00000000
00403130    .  68 48C14500        push Scsc.0045C148              ; |Arg1 = 0045C148 ASCII "Registration Code specified for 

ParasiteSoft product other then SCSC"
00403135    .  E8 2DFB0200        call Scsc.00432C67              ; \Scsc.00432C67
0040313A    .  5E                 pop esi
0040313B    .  C3                 retn

0040313C    >  8B46 5C            mov eax,dword ptr ds:[esi+5C]   ;  Case 0 of switch 0040311D
0040313F    .  B9 30154600        mov ecx,Scsc.00461530
00403144    .  50                 push eax                        ; /Arg3
00403145    .  68 1CA14500        push Scsc.0045A11C              ; |Arg2 = 0045A11C ASCII "UserName"
0040314A    .  68 28154600        push Scsc.00461528              ; |Arg1 = 00461528
0040314F    .  E8 28F80200        call Scsc.0043297C              ; \Scsc.0043297C
00403154    .  8BCE               mov ecx,esi
00403156    .  E8 633E0200        call Scsc.00426FBE
0040315B    .  5E                 pop esi
0040315C    .  C3                 retn

0040315D    >  6A 00              push 0                          ; /Arg3 = 00000000; Case 2 of switch 0040311D
0040315F    .  6A 00              push 0                          ; |Arg2 = 00000000
00403161    .  68 28C14500        push Scsc.0045C128              ; |Arg1 = 0045C128 ASCII "Indecent user name specified"
00403166    .  E8 FCFA0200        call Scsc.00432C67              ; \Scsc.00432C67
0040316B    .  5E                 pop esi
0040316C    .  C3                 retn

//查词典:Indecent:无礼的,下流的;不适当的,不合理的 
//对用户名还有限制?要重新跟,看EAX是怎么生成的.

0040316D    >  83F8 03            cmp eax,3
00403170    .  74 27              je short Scsc.00403199

00403172    .  3D 00000100        cmp eax,10000                   ;  UNICODE "=::=::\"
00403177    .  74 10              je short Scsc.00403189

00403179    >  6A 00              push 0                          ; /Arg3 = 00000000; Default case of switch 0040311D
0040317B    .  6A 00              push 0                          ; |Arg2 = 00000000
0040317D    .  68 E4C04500        push Scsc.0045C0E4              ; |Arg1 = 0045C0E4 ASCII "Internal software error. Please 

contact ParasiteSoft representative"
00403182    .  E8 E0FA0200        call Scsc.00432C67              ; \Scsc.00432C67
00403187    .  5E                 pop esi
00403188    .  C3                 retn

00403189    >  6A 00              push 0                          ; /Arg3 = 00000000; Case 10000 of switch 0040311D
0040318B    .  6A 00              push 0                          ; |Arg2 = 00000000
0040318D    .  68 50C04500        push Scsc.0045C050              ; |Arg1 = 0045C050 ASCII "This serial number is for upgrade 

license only.
Please enter your original serial number for limited license first and then apply upgrade license"
00403192    .  E8 D0FA0200        call Scsc.00432C67              ; \Scsc.00432C67
00403197    .  5E                 pop esi
00403198    .  C3                 retn
///说明:当输入ESI=1时的注册码时,会弹出此对话框.
00403199    >  6A 00              push 0                          ; /Arg3 = 00000000; Case 3 of switch 0040311D
0040319B    .  6A 00              push 0                          ; |Arg2 = 00000000
0040319D    .  68 34C04500        push Scsc.0045C034              ; |Arg1 = 0045C034 ASCII "Invalid registration code"
004031A2    .  E8 C0FA0200        call Scsc.00432C67              ; \Scsc.00432C67
004031A7    .  5E                 pop esi
004031A8    .  C3                 retn

可以注意到这段根据EAX的返回值来确定分支:
EAX=0时注册成功,调用了两个call:call Scsc.0043297C 和call Scsc.00426FBE,.

EAX为其他值(1,2,3,10000,Default case )的处理函数都相同:call Scsc.00432C67 ,弹出错误的对话框.

对于EAX=1,2,从程序分析来看,好像是不可能的(有误之处还请多指教),从该公司网站来看,
目前它只有一种产品,所以EAX=1时的报错不可能,可能是为以后扩展用的吧.
至于EX=2时的错误信息是"Indecent user name specified",可能也是为扩展所用.

###########################################################################################
[分析一]

00403820   /$  53                 push ebx
00403821   |.  55                 push ebp
00403822   |.  56                 push esi
00403823   |.  57                 push edi
00403824   |.  E8 C7FFFFFF        call Scsc.004037F0              ;F8先跳过再说,先从宏观上有个认识
           ;跳过后,EAX=FFFFFFFF,可能是个标志,如有需要,再跟进去看
           ;后来追踪EAX时回到了这个call里面,看来还是得进去看,见后面的代码[分析二]
00403829   |.  8B7C24 18          mov edi,dword ptr ss:[esp+18]   ;  我们输入的注册码
0040382D   |.  8B5C24 14          mov ebx,dword ptr ss:[esp+14]   ;  scsc,注意了,这是一个常数
00403831   |.  8BE8               mov ebp,eax                     ;  FFFFFFFF
00403833   |.  BE 0A000000        mov esi,0A                      ;注意了,这是一个常数
00403838   |>  57                 /push edi
00403839   |.  53                 |push ebx                      
0040383A   |.  56                 |push esi                       ; ESI的值为注册码的序号index 
0040383B   |.  68 FA000000        |push 0FA                       ;  注意了,这是一个常数
00403840   |.  E8 5B7E0000        |call Scsc.0040B6A0             ;  ###################
              ;山雨欲来风满楼啊,一下子压入了这么多参数,这个call当然不可放过,进入!见下面的[分析三]
00403845   |.  83C4 10            |add esp,10
00403848   |.  85C0               |test eax,eax
0040384A   |.  75 0F              |jnz short Scsc.0040385B         ;注册成功就跳
0040384C   |.  4E                 |dec esi
0040384D   |.^ 79 E9              \jns short Scsc.00403838         ;循环依次与11个注册码相比较
0040384F   |.  5F                 pop edi
00403850   |.  5E                 pop esi                          ;ESI的值为注册码的序号index
00403851   |.  5D                 pop ebp
00403852   |.  B8 03000000        mov eax,3                         ;设置注册码错误标志
00403857   |.  5B                 pop ebx
00403858   |.  C2 0800            retn 8                            ;跳去messageboxexa...记起来了吧
==================
比较完注册码之后从
00403858   |.  C2 0800            retn 8 
返回到
0040311D    .  83F8 02            cmp eax,2                                    ;  Switch (cases 0..10000)
========================
0040385B   |>  85F6               test esi,esi
0040385D   |.  7D 0C              jge short Scsc.0040386B

0040385F   |.  5F                 pop edi
00403860   |.  5E                 pop esi
00403861   |.  5D                 pop ebp
00403862   |.  B8 03000000        mov eax,3                        ;设置注册码错误标志
00403867   |.  5B                 pop ebx
00403868   |.  C2 0800            retn 8

0040386B   |>  3BF5               cmp esi,ebp
0040386D   |.  7D 09              jge short Scsc.00403878
0040386F   |.  5F                 pop edi
00403870   |.  5E                 pop esi
00403871   |.  5D                 pop ebp
00403872   |.  33C0               xor eax,eax
00403874   |.  5B                 pop ebx
00403875   |.  C2 0800            retn 8

00403878   |>  85ED               test ebp,ebp
0040387A   |.  7D 11              jge short Scsc.0040388D

0040387C   |.  83FE 01            cmp esi,1               ;若注册码对应的序号为1,则设置"upgrade license"标志
0040387F   |.  75 0C              jnz short Scsc.0040388D

00403881   |.  5F                 pop edi
00403882   |.  5E                 pop esi
00403883   |.  5D                 pop ebp
00403884   |.  B8 00000100        mov eax,10000                   ;  UNICODE "=::=::\"
/////这里设置注册码为"upgrade license"标志,确定以后的Switch分支,
00403889   |.  5B                 pop ebx
0040388A   |.  C2 0800            retn 8

0040388D   |>  57                 push edi
0040388E   |.  53                 push ebx
0040388F   |.  56                 push esi
00403890   |.  68 FA000000        push 0FA
00403895   |.  E8 E67E0000        call Scsc.0040B780

;;跟进后发现是将用户名和注册码写入注册表
;查看注册表:HKEY_CURRENT_USER\Software\ParasiteSoft\ProductData\Product011
;这个项目下面会生成"code000"-"code010"(注册码)以及"data000-data010"(用户名)的键,
;但值是二进制的,不是明码.

0040389A   |.  83C4 10            add esp,10
0040389D   |.  5F                 pop edi
0040389E   |.  5E                 pop esi
0040389F   |.  5D                 pop ebp
004038A0   |.  5B                 pop ebx
004038A1   \.  C2 0800            retn 8

###########################################################################################

[分析三]

0040B6A0   /$  81EC 00010000      sub esp,100
0040B6A6   |.  8B9424 08010000    mov edx,dword ptr ss:[esp+108]
0040B6AD   |.  B9 40000000        mov ecx,40   ;这是个计数器,为rep stos服务
0040B6B2   |.  33C0               xor eax,eax
0040B6B4   |.  57                 push edi
0040B6B5   |.  8D7C24 04          lea edi,dword ptr ss:[esp+4]
0040B6B9   |.  F3:AB              rep stos dword ptr es:[edi]  ;

0040B6BB   |.  8B8C24 10010000    mov ecx,dword ptr ss:[esp+110]      ;ECX 0045C190 ASCII "scsc"
0040B6C2   |.  8D4424 04          lea eax,dword ptr ss:[esp+4]    ;EAX=0012F5D4
0040B6C6   |.  50                 push eax
0040B6C7   |.  8B8424 0C010000    mov eax,dword ptr ss:[esp+10C]
0040B6CE   |.  51                 push ecx                        ;  scsc,Const
0040B6CF   |.  52                 push edx                        ;  00A-000,计数器
0040B6D0   |.  50                 push eax                        ;  00FA,Const
0040B6D1   |.  E8 9AFEFFFF        call Scsc.0040B570              ;这个call也要跟进,见核心call[分析四]
0040B6D6   |.  8B8C24 24010000    mov ecx,dword ptr ss:[esp+124]  ;  我们输入的码
0040B6DD   |.  8D5424 14          lea edx,dword ptr ss:[esp+14]   ;  真正的注册码
0040B6E1   |.  51                 push ecx
0040B6E2   |.  52                 push edx
0040B6E3   |.  E8 48FFFFFF        call Scsc.0040B630              ;这是干嘛用的?^_^见下面的核心[分析五].
0040B6E8   |.  83C4 18            add esp,18
0040B6EB   |.  5F                 pop edi
0040B6EC   |.  81C4 00010000      add esp,100
0040B6F2   \.  C3                 retn


###########################################################################################
核心:
[分析四]

0040B570   /$  8B4424 0C          mov eax,dword ptr ss:[esp+C]    ;  scsc
0040B574   |.  8B4C24 08          mov ecx,dword ptr ss:[esp+8]    ;  00a-000,counter
0040B578   |.  8B5424 04          mov edx,dword ptr ss:[esp+4]    ;  00FA 这是刚才压入的三个参数
0040B57C   |.  81EC 6C010000      sub esp,16C
0040B582   |.  53                 push ebx
0040B583   |.  55                 push ebp
0040B584   |.  56                 push esi
0040B585   |.  57                 push edi
0040B586   |.  50                 push eax
0040B587   |.  51                 push ecx
0040B588   |.  52                 push edx
0040B589   |.  8D8424 88000000    lea eax,dword ptr ss:[esp+88]   ;  EAX 0012F2EC ASCII "580b1cc08479915b2aeccdb9aed0af93"
0040B590   |.  68 8CCF4500        push Scsc.0045CF8C              ;  ASCII "%08X%08X%s"
0040B595   |.  50                 push eax                        ;  20."000000FA00000009scsc"的长度
0040B596   |.  E8 9D990000        call Scsc.00414F38
0040B59B   |.  8D8C24 90000000    lea ecx,dword ptr ss:[esp+90]   ;  ECX 0012F2EC ASCII "000000FA0000000Ascsc"
0040B5A2   |.  51                 push ecx                        ;  
0040B5A3   |.  E8 2A7D0100        call Scsc.004232D2 
   ;不用跟进,执行完后,EAX 0012F4BC ASCII "000000fa0000000ascsc",可以推测       
   ;  这个call的功能是把"000000FA00000009scsc"变成小写"000000fa00000009scsc"

0040B5A8   |.  83C4 18            add esp,18
0040B5AB   |.  8D4C24 10          lea ecx,dword ptr ss:[esp+10]
0040B5AF   |.  E8 EC050000        call Scsc.0040BBA0
   
;这个call是MD5::initialize,执行完后,EAX=0012F450,D EAX,
;0012F450  01 23 45 67 89 AB CD EF  #Eg壂惋 ==>很熟悉吧,不用想了,就是MD5
;0012F458  FE DC BA 98 76 54 32 10  簶vT2



0040B5B4   |.  8D7C24 7C          lea edi,dword ptr ss:[esp+7C]
0040B5B8   |.  83C9 FF            or ecx,FFFFFFFF
0040B5BB   |.  33C0               xor eax,eax
0040B5BD   |.  8D5424 7C          lea edx,dword ptr ss:[esp+7C]
0040B5C1   |.  F2:AE              repne scas byte ptr es:[edi]  ;用来测试用来Hash的MD5字符串长度
0040B5C3   |.  F7D1               not ecx
0040B5C5   |.  49                 dec ecx    ;ECX=0014,长度20,

0040B5C6   |.  51                 push ecx
0040B5C7   |.  52                 push edx

;EDX 0012F4BC ASCII "000000fa0000000ascsc"


0040B5C8   |.  8D4C24 18          lea ecx,dword ptr ss:[esp+18]
;ECX=0012F450, D ECX,
0012F450  01 23 45 67 89 AB CD EF  #Eg壂惋
0012F458  FE DC BA 98 76 54 32 10  簶vT2


0040B5CC   |.  E8 DF050000        call Scsc.0040BBB0              ;  unpdate

;进入,看到很醒目的一串:
;0045D020=Scsc.0045D020 (ASCII "MD5::update:  Can't update a finalized digest!")
;作者已经告诉我们是什么算法了

0040B5D1   |.  8D4C24 10          lea ecx,dword ptr ss:[esp+10]    ;ECX=0012F450,

0040B5D5   |.  E8 B6060000        call Scsc.0040BC90              ;  finalize

;进入,看到很醒目的一串:
;0045D050=Scsc.0045D050 (ASCII "MD5::finalize:  Already finalized this digest!")

;这个call之后,观察内存
;012F450  58 0B 1C C0 84 79 91 5B  X 绖y慬  =>MD5Hash后的值
;0012F458  2A EC CD B9 AE D0 AF 93  *焱巩携


0040B5DA   |.  8D4424 7C          lea eax,dword ptr ss:[esp+7C]
0040B5DE   |.  8D4C24 10          lea ecx,dword ptr ss:[esp+10]

;EAX 0012F4BC ASCII "000000fa0000000ascsc"
;ECX 0012F450

0040B5E2   |.  50                 push eax
0040B5E3   |.  E8 58070000        call Scsc.0040BD40              ;  get md5 ,lower case

;进入,看到很醒目的一串:
;0045D098=Scsc.0045D098 (ASCII "MD5::hex_digest:  Can't get digest if you haven't ")

;出来后:EAX 0012F4BC ASCII "580b1cc08479915b2aeccdb9aed0af93"

0040B5E8   |.  8BBC24 8C010000    mov edi,dword ptr ss:[esp+18C]
0040B5EF   |.  33C9               xor ecx,ecx
0040B5F1   |.  8BD7               mov edx,edi
0040B5F3   |.  8D7424 7C          lea esi,dword ptr ss:[esp+7C]
0040B5F7   |>  8BC6               /mov eax,esi
0040B5F9   |.  8BDA               |mov ebx,edx
0040B5FB   |.  8B28               |mov ebp,dword ptr ds:[eax]
0040B5FD   |.  892B               |mov dword ptr ds:[ebx],ebp
0040B5FF   |.  8A40 04            |mov al,byte ptr ds:[eax+4]
0040B602   |.  8843 04            |mov byte ptr ds:[ebx+4],al
0040B605   |.  8BC1               |mov eax,ecx
0040B607   |.  83E8 05            |sub eax,5
0040B60A   |.  F7D8               |neg eax
0040B60C   |.  1AC0               |sbb al,al
0040B60E   |.  83C6 05            |add esi,5
0040B611   |.  83E0 2D            |and eax,2D   ;EAX=002D, '-'的AScii码
0040B614   |.  41                 |inc ecx
0040B615   |.  8842 05            |mov byte ptr ds:[edx+5],al
0040B618   |.  83C2 06            |add edx,6
0040B61B   |.  83F9 06            |cmp ecx,6
0040B61E   |.^ 7C D7              \jl short Scsc.0040B5F7
0040B620   |.  8BC7               mov eax,edi

//上面的循环用来格式化注册码;
//ESI 0012F4DA ASCII "93"
//EDI 0012F5D4 ASCII "580b1-cc084-79915-b2aec-cdb9a-ed0af";这就是注册码了,呵呵

0040B622   |.  5F                 pop edi
0040B623   |.  5E                 pop esi
0040B624   |.  5D                 pop ebp
0040B625   |.  5B                 pop ebx
0040B626   |.  81C4 6C010000      add esp,16C
0040B62C   \.  C3                 retn

回到:0040B6D6  ,见上面的代码.


###########################################################################################
核心[分析五]
进行注册码校验的过程:

0040B630   /$  53                 push ebx                        ;  Scsc.00409DB0
0040B631   |.  8B5C24 08          mov ebx,dword ptr ss:[esp+8]
0040B635   |.  56                 push esi
0040B636   |.  57                 push edi
0040B637   |.  53                 push ebx
0040B638   |.  E8 C97D0100        call Scsc.00423406              ;
0040B63D   |.  8B7424 18          mov esi,dword ptr ss:[esp+18]
0040B641   |.  56                 push esi
0040B642   |.  E8 BF7D0100        call Scsc.00423406
0040B647   |.  8BFB               mov edi,ebx
0040B649   |.  83C9 FF            or ecx,FFFFFFFF
0040B64C   |.  33C0               xor eax,eax
0040B64E   |.  83C4 08            add esp,8
0040B651   |.  F2:AE              repne scas byte ptr es:[edi]
0040B653   |.  F7D1               not ecx
0040B655   |.  49                 dec ecx
0040B656   |.  83F9 23            cmp ecx,23                      ;验证真码的长度
0040B659   |.  74 04              je short Scsc.0040B65F
0040B65B   |.  5F                 pop edi
0040B65C   |.  5E                 pop esi
0040B65D   |.  5B                 pop ebx
0040B65E   |.  C3                 retn

0040B65F   |>  8BFE               mov edi,esi
0040B661   |.  83C9 FF            or ecx,FFFFFFFF
0040B664   |.  33C0               xor eax,eax
0040B666   |.  F2:AE              repne scas byte ptr es:[edi]
0040B668   |.  F7D1               not ecx
0040B66A   |.  49                 dec ecx
0040B66B   |.  83F9 23            cmp ecx,23                       ;;验证假码的长度
0040B66E   |.  74 06              je short Scsc.0040B676
0040B670   |>  5F                 pop edi
0040B671   |.  5E                 pop esi
0040B672   |.  33C0               xor eax,eax
0040B674   |.  5B                 pop ebx
0040B675   |.  C3                 retn

0040B676   |>  8BFB               mov edi,ebx
0040B678   |.  33C9               xor ecx,ecx
0040B67A   |.  8BC6               mov eax,esi
0040B67C   |.  2BFE               sub edi,esi
0040B67E   |>  8A1407             mov dl,byte ptr ds:[edi+eax]
0040B681   |.  8A18               mov bl,byte ptr ds:[eax]
0040B683   |.  3AD3               cmp dl,bl
0040B685   |.^ 75 E9              jnz short Scsc.0040B670 //真码和假码的奇数个字符不等就跳回去
0040B687   |.  83C1 02            add ecx,2              //每次递增为2个字符,只校验奇数位
0040B68A   |.  83C0 02            add eax,2
0040B68D   |.  83F9 23            cmp ecx,23
0040B690   |.^ 72 EC              jb short Scsc.0040B67E

0040B692   |.  5F                 pop edi
0040B693   |.  5E                 pop esi
0040B694   |.  B8 01000000        mov eax,1             
//校验成功,设置标志,在下面检验标志,决定是否需要继续校验后面的注册码
//00403804   |.  85C0               |test eax,eax


0040B699   |.  5B                 pop ebx
0040B69A   \.  C3                 retn


###########################################################################################
[分析二]

004037F0   /$  56                 push esi
004037F1   |.  BE 0A000000        mov esi,0A
004037F6   |>  56                 /push esi
004037F7   |.  68 FA000000        |push 0FA
004037FC   |.  E8 0F830000        |call Scsc.0040BB10
00403801   |.  83C4 08            |add esp,8
00403804   |.  85C0               |test eax,eax
00403806   |.  75 08              |jnz short Scsc.0040381>
00403808   |.  4E                 |dec esi
00403809   |.^ 79 EB              \jns short Scsc.004037F>
0040380B   |.  83C8 FF            or eax,FFFFFFFF
0040380E   |.  5E                 pop esi
0040380F   |.  C3                 retn
00403810   |>  8BC6               mov eax,esi             //设置标志
00403812   |.  5E                 pop esi                 ;  00BC51C8
00403813   \.  C3                 retn


返回到这里:004037DB



004037B0   /$  8B4424 04          mov eax,dword ptr ss:[e>
004037B4   |.  85C0               test eax,eax
004037B6   |.  74 1E              je short Scsc.004037D6
004037B8   |.  7E 17              jle short Scsc.004037D1
004037BA   |.  83F8 02            cmp eax,2
004037BD   |.  7F 12              jg short Scsc.004037D1
004037BF   |.  E8 2C000000        call Scsc.004037F0
004037C4   |.  33C9               xor ecx,ecx
004037C6   |.  83F8 01            cmp eax,1
004037C9   |.  0F9DC1             setge cl
004037CC   |.  8BC1               mov eax,ecx
004037CE   |.  C2 0400            retn 4
004037D1   |>  33C0               xor eax,eax
004037D3   |.  C2 0400            retn 4
004037D6   |>  E8 15000000        call Scsc.004037F0

004037DB   |.  33D2               xor edx,edx
004037DD   |.  85C0               test eax,eax     //00403810处设置了标志,这里检验
004037DF   |.  0F9DC2             setge dl
004037E2   |.  8BC2               mov eax,edx      //set flag
004037E4   \.  C2 0400            retn 4


回到这里:
00409E72    .  85C0               test eax,eax
00409E74    .  75 0E              jnz short Scsc.00409E84
跟踪下面的call,最后到了系统程序领空,不动了,
点击一下Scsc窗口后程序又一次中断在0040B6CE,
走下去,再回到这里,看来不取消断点就要转圈了.

我还想保留我设置的断点,于是重新运行程序,删除注册表中的值后,继续调试.


【破解总结】 注册码与用户名无关,即使用户名为空,也可以注册,基本注册码仅有10个,升级注册码一个,
             注册码为字符串000000fa0000000<X>scsc 的MD5串的前30个字符,每五个字符串用'-'分隔,             
             (说明<X>取值为a,9,8,7,6,5,4,3,2,0;都为小写,<X>=1时是升级密码).
              程序似乎有些BUG,升级密码不能输入,弹出的信息是"只有输入其他密码后才能输升级密码",
              但是当输入其他密码后,注册窗口消失了,怎么输入升级密码?
              由于程序进行校验的部分(见分析五)只检验注册码的奇数位,因此偶数为可以位任意字符,因而
              可以从基本注册码扩展为任意个注册码.注册码不区分大小写.

              基本注册码为:
         
              000000fa0000000ascsc--- 580b1-cc084-79915-b2aec-cdb9a-ed0af

              000000fa00000009scsc----c504e-55a67-da3c5-c8b36-6fb68-afb8b

              000000fa00000008scsc-----524bf-35c2f-41abf-006fe-a8807-ea77e

              000000fa00000007scsc-----07f3f-08424-13cc7-3adfd-73a46-05b4f

              000000fa00000006scsc----0C2CA-8A062-61C5F-1A21C-48A04-A8926

              000000fa00000005scsc-----3dc2b-29164-f7aff-16767-d6822-a5cfc

              000000fa00000004scsc-----0E581-13C66-1CA2A-CB1E3-4B384-ABDA3

              000000fa00000003scsc-----CDAF1-63AFE-6531F-4DE8C-87660-010E4

              000000fa00000002scsc----39F45-4367B-42F88-1974D-391FA-65B7C

              000000fa00000001scsc-----6CDFC-C1CE8-8AEDF-191A2-5E672-EDE20 [Upgrade licence,bug?]

              000000fa00000000scsc-----44EFB-47117-782CC-F990E-02C7C-1E94C

【Greetings】  看雪论坛,FCG论坛,DFCG论坛等

【完稿时间等】2005.04.27,天气:小雨,广州