【标题】【VC】SnapIt8.01注册算法初步分析
【作者】 forever[RCT]
【语言】 VC7.1
【保护】 无壳,注册码
【难度】 复杂
【工具】 ollydbg,ida,peid

【正文】
         分析这个程序时得到了xIkUg,Cnbragon,DarkNess0ut等人的帮助,在这里先说一声谢谢!同时感谢所有RCT小组
     里的朋友们及所有支持我的朋友们!
         
         用od载入程序,在注册窗口里输入用户名和注册码后,点击"ok"按钮,程序提示一个出错的对话框。提示你这是
     一个无效的key。
          
         确认后,就在od中发生异常了。仔细看,这不是一个消息框,所以不能下断点MessageBox。在这个时候看堆栈。
              
         仔细看返回地址,直到找到最近的那个返回程序空间的那个地址,我这里是6F43D5h。Ctrl+G,输入地址,
     来到下面:
         
         在地址6F4364h按下F2下个断点。重新输入注册码,点"ok"按钮后中断在6F4364h处。下面的分析从这里开始:

.text:006F4353                 lea     eax, [esp+1Ch]  ; 取注册码
.text:006F4357                 push    eax             ; int
.text:006F4358                 push    27EDh           ; int
.text:006F435D                 mov     ecx, esi
.text:006F435F                 mov     [esp+8+arg_10], 1
.text:006F4364                 call    CWnd::GetDlgItemTextA(int,ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>> &)
.text:006F4369                 lea     ecx, [esp+8]    ; 取用户名
.text:006F436D                 push    ecx             ; int
.text:006F436E                 push    27EEh           ; char
.text:006F4373                 mov     ecx, esi
.text:006F4375                 call    CWnd::GetDlgItemTextA(int,ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>> &)
.text:006F437A                 mov     ecx, [esi+74h]
.text:006F437D                 mov     eax, [ecx+34h]
.text:006F4380                 test    eax, eax
.text:006F4382                 jnz     short loc_6F43B7
.text:006F4384                 mov     eax, [ecx+0BCh]
.text:006F438A                 test    eax, eax
.text:006F438C                 jz      short loc_6F43B7
.text:006F438E                 call    sub_6F2260
.text:006F4393                 test    eax, eax
.text:006F4395                 jnz     short loc_6F43B7
.text:006F4397                 push    offset aReset   ; "reset"
.text:006F439C                 lea     ecx, [esp+4+arg_18]
.text:006F43A0                 call    ds:ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>::CompareNoCase(char const *)
.text:006F43A6                 test    eax, eax
.text:006F43A8                 jnz     short loc_6F43B7
.text:006F43AA                 mov     ecx, [esi+74h]
.text:006F43AD                 push    eax             ; int
.text:006F43AE                 push    1               ; int
.text:006F43B0                 call    sub_6F2A40
.text:006F43B5                 jmp     short loc_6F43D5
.text:006F43B7
.text:006F43B7 loc_6F43B7:                                                                  
.text:006F43B7                 mov     ecx, [esi+74h]
.text:006F43BA                 lea     edx, [esp+8]    ; 用户名
.text:006F43BE                 push    edx
.text:006F43BF                 lea     eax, [esp+32]   ; 注册码
.text:006F43C3                 push    eax             ; int
.text:006F43C4                 push    esi             ; int
.text:006F43C5                 call    sub_6F2660      ; 关键CALL,要跟进
.text:006F43CA                 test    al, al
.text:006F43CC                 jnz     short loc_6F43D5
.text:006F43CE                 mov     ecx, edi
.text:006F43D0                 call    CDataExchange::Fail(void)
.text:006F43D5

.text:006F2660 sub_6F2660      proc near               
.text:006F2660 arg_0           = dword ptr  4
.text:006F2660 arg_4           = dword ptr  8
.text:006F2660 arg_B0          = dword ptr  0B4h
.text:006F2660
.text:006F2660                 push    ebx
.text:006F2661                 mov     ebx, [esp+8]
.text:006F2665                 test    ebx, ebx
.text:006F2667                 push    ebp             ; uType
.text:006F2668                 push    esi             ; lpCaption
.text:006F2669                 mov     esi, ecx
.text:006F266B                 jnz     short loc_6F2687
.text:006F266D                 call    AfxGetThread(void)
.text:006F2672                 test    eax, eax
.text:006F2674                 jz      short loc_6F2681
.text:006F2676                 mov     edx, [eax]
.text:006F2678                 mov     ecx, eax
.text:006F267A                 call    dword ptr [edx+7Ch]
.text:006F267D                 mov     ebx, eax
.text:006F267F                 jmp     short loc_6F2683
.text:006F2681 loc_6F2681:                           
.text:006F2681                 xor     ebx, ebx
.text:006F2683
.text:006F2683 loc_6F2683:                             
.text:006F2683                 mov     [esp+0Ch+arg_0], ebx
.text:006F2687
.text:006F2687 loc_6F2687:                             
.text:006F2687                 mov     ebp, [esp+18h]  ; 判断用户名是否为空
.text:006F268B                 mov     ecx, ebp
.text:006F268D                 call    ds:ATL::CSimpleStringT<char,1>::IsEmpty(void)
.text:006F2693                 test    al, al
.text:006F2695                 jz      short loc_6F26DE ; 这里要跳
.text:006F2697                 push    283Eh
.text:006F269C                 lea     ecx, [esp+14h]
.text:006F26A0                 call    ds:ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>(char const *)
.text:006F26A6                 test    ebx, ebx
.text:006F26A8                 jz      short loc_6F26AD
.text:006F26AA                 mov     ebx, [ebx+20h]
.text:006F26AD
.text:006F26AD loc_6F26AD:                             
.text:006F26AD                 push    0
.text:006F26AF                 lea     ecx, [esi+48h]
.text:006F26B2                 call    ds:ATL::CSimpleStringT<char,1>::operator char const *(void)
.text:006F26B8                 push    eax
.text:006F26B9                 lea     ecx, [esp+18h]
.text:006F26BD                 call    ds:ATL::CSimpleStringT<char,1>::operator char const *(void)
.text:006F26C3                 push    eax             ; lpText
.text:006F26C4                 push    ebx             ; hWnd
.text:006F26C5                 call    ds:MessageBoxA
.text:006F26CB                 lea     ecx, [esp+10h]
.text:006F26CF                 call    ds:ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>::~CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>(void)
.text:006F26D5                 pop     esi
.text:006F26D6                 pop     ebp
.text:006F26D7                 xor     ax, ax
.text:006F26DA                 pop     ebx
.text:006F26DB                 retn    0Ch
.text:006F26DE loc_6F26DE:                            
.text:006F26DE                 push    edi
.text:006F26DF                 mov     edi, [esp+18h]  ; 注册码
.text:006F26E3                 mov     ecx, edi
.text:006F26E5                 call    ds:ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>::Trim(void)
.text:006F26EB                 mov     eax, [esi]
.text:006F26ED                 push    ebp             ; 用户名
.text:006F26EE                 push    edi             ; 注册码
.text:006F26EF                 mov     ecx, esi
.text:006F26F1                 call    dword ptr [eax+18h] ; 512FD0 ,关键CALL1,要根进
.text:006F26F4                 test    al, al
.text:006F26F6                 jnz     short loc_6F270A ; 返回0就验证失败了
.text:006F26F8                 mov     edx, [esi]
.text:006F26FA                 push    ebx
.text:006F26FB                 mov     ecx, esi
.text:006F26FD                 call    dword ptr [edx+1Ch]
.text:006F2700                 pop     edi
.text:006F2701                 pop     esi
.text:006F2702                 pop     ebp
.text:006F2703                 xor     ax, ax
.text:006F2706                 pop     ebx
.text:006F2707                 retn    0Ch
.text:006F270A
.text:006F270A loc_6F270A:                           
.text:006F270A                 push    offset Data
.text:006F270F                 push    offset asc_830788 ; "-"
.text:006F2714                 mov     ecx, edi        ; 去掉注册码中的"-"号
.text:006F2716                 call    ds:ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>::Replace(char const *,char const *)
.text:006F271C                 mov     ebx, [esi]
.text:006F271E                 mov     ecx, edi
.text:006F2720                 call    ds:ATL::CSimpleStringT<char,1>::operator char const *(void)
.text:006F2726                 push    eax             ; 取得注册码,压入堆栈
.text:006F2727                 mov     ecx, ebp
.text:006F2729                 call    ds:ATL::CSimpleStringT<char,1>::operator char const *(void)
.text:006F272F                 push    eax             ; 取得用户名,压入堆栈
.text:006F2730                 mov     ecx, esi
.text:006F2732                 call    dword ptr [ebx+24h] ; 513700 ,关键CALL2,要根进
.text:006F2735                 mov     ebx, eax
.text:006F2737                 cmp     bl, 1
.text:006F273A                 jnz     short loc_6F278F
.text:006F273C                 mov     ecx, edi
.text:006F273E                 mov     dword ptr [esi+34h], 1
.text:006F2745                 mov     dword ptr [esi+0BCh], 0
.text:006F274F                 call    ds:ATL::CSimpleStringT<char,1>::operator char const *(void)
.text:006F2755                 push    eax             ; lpValueName
.text:006F2756                 push    offset aRegistrationke ; int
.text:006F275B                 mov     ecx, esi        ; int
.text:006F275D                 call    sub_6F1E50
.text:006F2762                 mov     ecx, ebp
.text:006F2764                 call    ds:ATL::CSimpleStringT<char,1>::operator char const *(void)
.text:006F276A                 push    eax             ; lpValueName
.text:006F276B                 push    offset aRegisteredto ; int
.text:006F2770                 mov     ecx, esi        ; int
.text:006F2772                 call    sub_6F1E50
.text:006F2777                 mov     ecx, [esp+14h]
.text:006F277B                 mov     eax, [esi]
.text:006F277D                 push    edi             ; 注册码
.text:006F277E                 push    ebp             ; 注册名
.text:006F277F                 push    ecx
.text:006F2780                 mov     ecx, esi
.text:006F2782                 call    dword ptr [eax+28h] ; 513bd0
.text:006F2785                 pop     edi
.text:006F2786                 pop     esi
.text:006F2787                 pop     ebp
.text:006F2788                 mov     ax, bx
.text:006F278B                 pop     ebx
.text:006F278C                 retn    0Ch             ; lpCaption
.text:006F278F
.text:006F278F loc_6F278F:                         
.text:006F278F                 cmp     bx, 0FFFFh
.text:006F2794                 mov     eax, ebx
.text:006F2796                 jnz     short loc_6F279C
.text:006F2798                 mov     ax, [esi+40h]
.text:006F279C
.text:006F279C loc_6F279C:                            
.text:006F279C                 cmp     ah, 11
.text:006F279F                 jnz     short loc_6F27F1
.text:006F27A1                 push    10305           ; Unfortunately, your current Software Key will
                                                         not work with this version. Upgrade today and
                                                         get a new key.

        可以看出,关键CALL1要返回1,关键CALL2返回值的低8位要等于1。
        下面先跟进关键CALL1:
        
.text:00512FD0 v1_512FD0       proc near               
.text:00512FD0
.text:00512FD0 arg_0           = dword ptr  4
.text:00512FD0 arg_4           = dword ptr  8
.text:00512FD0
.text:00512FD0                 mov     eax, [esp+arg_4]
.text:00512FD4                 push    esi
.text:00512FD5                 mov     esi, [esp+4+arg_0]
.text:00512FD9                 push    eax             ; 用户名
.text:00512FDA                 push    esi             ; 注册码
.text:00512FDB                 call    sub_6F2090      ; 初步检查注册码是否合法
.text:00512FE0                 test    al, al          ; 注册码长度要大于等于14,
.text:00512FE2                 jnz     short loc_513032 ; 组成注册码的字符要在 "0123456789ABCDEF-" 里
.text:00512FE4                 push    ebx
.text:00512FE5                 push    edi
.text:00512FE6                 mov     ecx, esi        ; 注册码
.text:00512FE8                 call    ds:ATL::CSimpleStringT<char,1>::GetLength(void)
.text:00512FEE                 cmp     eax, 29         ; 长度等于29则跳
.text:00512FF1                 jz      short loc_513004
.text:00512FF3                 mov     ecx, esi
.text:00512FF5                 call    ds:ATL::CSimpleStringT<char,1>::GetLength(void)
.text:00512FFB                 cmp     eax, 25         ; 长度等于25则跳
.text:00512FFE                 jz      short loc_513004
.text:00513000                 xor     bl, bl
.text:00513002                 jmp     short loc_513006
.text:00513004
.text:00513004 loc_513004:                             
.text:00513004                                        
.text:00513004                 mov     bl, 1
.text:00513006
.text:00513006 loc_513006:                            
.text:00513006                 mov     ecx, esi
.text:00513008                 call    ds:ATL::CSimpleStringT<char,1>::operator char const *(void)
.text:0051300E                 push    offset a23456789abcdef ; "23456789ABCDEFGHJKLMNPQRSTUVWXYZ-"
.text:00513013                 push    eax             ; unsigned __int8 *
.text:00513014                 call    ds:_mbsspn      
.text:0051301A                 add     esp, 8
.text:0051301D                 mov     ecx, esi
.text:0051301F                 mov     edi, eax
.text:00513021                 call    ds:ATL::CSimpleStringT<char,1>::GetLength(void)
.text:00513027                 cmp     edi, eax
.text:00513029                 setz    cl
.text:0051302C                 and     bl, cl
.text:0051302E                 pop     edi
.text:0051302F                 mov     al, bl
.text:00513031                 pop     ebx
.text:00513032
.text:00513032 loc_513032:                             
.text:00513032                 pop     esi
.text:00513033                 retn    8
.text:00513033 v1_512FD0       endp ; sp =  14h

       这里要求注册码长度要等于29或者25,并且组成注册码的字符在字符串"23456789ABCDEFGHJKLMNPQRSTUVWXYZ-"里。
       接着根进关键CALL2:
       
.text:00513700 sub_513700      proc near               
.text:00513700
.text:00513700 var_9A_f1       = byte ptr -9Ah
.text:00513700 var_99_ver      = byte ptr -99h
.text:00513700 var_98_RegCode  = dword ptr -98h
.text:00513700 var_91_regf     = byte ptr -91h
.text:00513700 var_90          = dword ptr -90h
.text:00513700 var_8C          = dword ptr -8Ch
.text:00513700 var_88          = dword ptr -88h
.text:00513700 var_7C          = dword ptr -7Ch
.text:00513700 var_78          = dword ptr -78h
.text:00513700 var_6C          = dword ptr -6Ch
.text:00513700 var_60          = dword ptr -60h
.text:00513700 var_54          = dword ptr -54h
.text:00513700 var_50          = dword ptr -50h
.text:00513700 var_4C          = dword ptr -4Ch
.text:00513700 var_48          = word ptr -48h
.text:00513700 var_46          = byte ptr -46h
.text:00513700 var_44          = dword ptr -44h
.text:00513700 var_10          = dword ptr -10h
.text:00513700 var_C           = dword ptr -0Ch
.text:00513700 var_8           = dword ptr -8
.text:00513700 var_4           = dword ptr -4
.text:00513700 arg_0           = dword ptr  4
.text:00513700 arg_4           = dword ptr  8
.text:00513700
.text:00513700                 push    0FFFFFFFFh
.text:00513702                 push    offset loc_7DC9A5
.text:00513707                 mov     eax, large fs:0
.text:0051370D                 push    eax
.text:0051370E                 mov     large fs:0, esp
.text:00513715                 sub     esp, 90h
.text:0051371B                 mov     eax, dword_8F6114
.text:00513720                 push    ebx
.text:00513721                 push    ebp
.text:00513722                 push    esi
.text:00513723                 mov     [esp+0A8h+var_10], eax
.text:0051372A                 mov     eax, [esp+0A8h+arg_4] ; 注册码
.text:00513731                 push    edi             ; int
.text:00513732                 xor     ebx, ebx
.text:00513734                 mov     ebp, ecx
.text:00513736                 mov     [esp+0ACh+var_90], ebx
.text:0051373A                 mov     edi, 1
.text:0051373F                 push    eax
.text:00513740                 lea     ecx, [esp+0B0h+var_98_RegCode]
.text:00513744                 mov     [esp+0B0h+var_8C], ebx ; 初值0
.text:00513748                 mov     [esp+0B0h+var_7C], edi ; 初值1
.text:0051374C                 mov     [esp+0B0h+var_99_ver], 10 ; 初值10
.text:00513751                 mov     [esp+0B0h+var_91_regf], bl ; 初值0
.text:00513755                 call    ds:ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>(char const *)
.text:0051375B                 lea     ecx, [esp+0ACh+var_98_RegCode] ; 注册码
.text:0051375F                 mov     [esp+0ACh+var_4], ebx
.text:00513766                 call    ds:ATL::CSimpleStringT<char,1>::GetLength(void)
.text:0051376C                 cmp     eax, 29         ; 比较长度是否等于29
.text:0051376F                 jz      loc_51398A
.text:00513775                 lea     ecx, [esp+0ACh+var_98_RegCode]
.text:00513779                 call    ds:ATL::CSimpleStringT<char,1>::GetLength(void)
.text:0051377F                 cmp     eax, 25         ; 比较长度是否等于25
.text:00513782                 jz      loc_51398A

                                                       ;这里我删去了旧版本里留下来的代码
                                                       ;从上面可以看出,注册码长度必须等于25或者29
                                                       ;删去的这些事实上永远不会执行
                                                       
.text:0051398A loc_51398A:                            
.text:0051398A                 lea     ecx, [esp+0ACh+var_98_RegCode] ; 注册码
.text:0051398E                 lea     esi, [ebp+0D4h] ; 这里要返回一个数组
.text:00513994                 call    ds:ATL::CSimpleStringT<char,1>::operator char const *(void)
.text:0051399A                 push    eax             ; 注册码
.text:0051399B                 mov     ecx, esi        ; 返回值
.text:0051399D                 call    v_6F38C0        ; 关键CALL,要跟进******
.text:005139A2                 test    al, al
.text:005139A4                 jz      short loc_5139C6
.text:005139A6                 cmp     [ebp+0D8h], edi ; [1]必须为1
.text:005139AC                 jnz     short loc_5139C6
.text:005139AE                 lea     ecx, [esp+0ACh+var_88]
.text:005139B2                 push    ecx
.text:005139B3                 mov     ecx, esi
.text:005139B5                 call    sub_513450
.text:005139BA                 cmp     dword ptr [eax], 0 ; 比较协议类型是否等于0
.text:005139BD                 mov     ebx, edi
.text:005139BF                 mov     [esp+0ACh+var_9A_f1], 1
.text:005139C4                 jnz     short loc_5139CB
.text:005139C6
.text:005139C6 loc_5139C6:                             
.text:005139C6                 mov     [esp+0ACh+var_9A_f1], 0
.text:005139CB
.text:005139CB loc_5139CB:                           
.text:005139CB                 test    bl, 1
.text:005139CE                 jz      short loc_5139DC
.text:005139D0                 lea     ecx, [esp+0ACh+var_88]
.text:005139D4                 and     ebx, 0FFFFFFFEh
.text:005139D7                 call    sub_4FCCA0      ; 最低位不为1则协议字符串释放
.text:005139DC
.text:005139DC loc_5139DC:                         
.text:005139DC                 mov     al, [esp+0ACh+var_9A_f1]
.text:005139E0                 test    al, al
.text:005139E2                 jz      loc_513B89
.text:005139E8                 push    0
.text:005139EA                 push    0
.text:005139EC                 push    8
.text:005139EE                 lea     ecx, [esp+0B8h+var_78]
.text:005139F2                 call    formver_61E3F0
.text:005139F7                 mov     edi, eax
.text:005139F9                 lea     edx, [esp+0ACh+var_88]
.text:005139FD                 push    edx
.text:005139FE                 mov     ecx, esi
.text:00513A00                 call    getver_512E80
.text:00513A05                 push    edi
.text:00513A06                 mov     ecx, eax
.text:00513A08                 mov     byte ptr [esp+0B0h+var_4], 2
.text:00513A10                 call    compver_61E410  ; 检查版本信息
.text:00513A15                 lea     ecx, [esp+0ACh+var_88]
.text:00513A19                 mov     [esp+0ACh+var_9A_f1], al
.text:00513A1D                 mov     byte ptr [esp+0ACh+var_4], 1
.text:00513A25                 call    nullcall
.text:00513A2A                 lea     ecx, [esp+0ACh+var_78]
.text:00513A2E                 mov     byte ptr [esp+0ACh+var_4], 0
.text:00513A36                 call    nullcall
.text:00513A3B                 mov     al, [esp+0ACh+var_9A_f1]
.text:00513A3F                 test    al, al
.text:00513A41                 jz      short loc_513A80
.text:00513A43                 lea     eax, [esp+0ACh+var_88]
.text:00513A47                 push    eax
.text:00513A48                 mov     ecx, esi
.text:00513A4A                 mov     [esp+0B0h+var_91_regf], 1 ; 注册成功标志
.text:00513A4F                 call    sub_513450
.text:00513A54                 mov     eax, [eax]
.text:00513A56                 lea     ecx, [ebp+0CCh]
.text:00513A5C                 push    eax
.text:00513A5D                 mov     byte ptr [esp+0B0h+var_4], 3
.text:00513A65                 call    GetLicType_61E070
.text:00513A6A                 lea     ecx, [esp+0ACh+var_88]
.text:00513A6E                 mov     byte ptr [esp+0ACh+var_4], 0
.text:00513A76                 call    sub_4FCCA0
.text:00513A7B                 jmp     loc_513B89
.text:00513A80 
.text:00513A80 loc_513A80:                            
                                            ;删除一些检查是否是老版本的注册码的代码
.text:00513B7C
.text:00513B7C loc_513B7C:                             
.text:00513B7C                 mov     al, [esp+0ACh+var_9A_f1]
.text:00513B80                 test    al, al
.text:00513B82                 jz      short loc_513B89
.text:00513B84                 mov     [esp+0ACh+var_99_ver], 11 ; 旧版本标志
.text:00513B89
.text:00513B89 loc_513B89:                             
.text:00513B89                 lea     ecx, [esp+0ACh+var_98_RegCode]
.text:00513B8D                 call    ds:ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>::~CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>(void)
.text:00513B93                 mov     ecx, [esp+0ACh+var_C]
.text:00513B9A                 xor     eax, eax
.text:00513B9C                 mov     ah, [esp+0ACh+var_99_ver] ; 旧版本标志
.text:00513BA0                 pop     edi
.text:00513BA1                 pop     esi
.text:00513BA2                 pop     ebp
.text:00513BA3                 mov     large fs:0, ecx
.text:00513BAA                 mov     ecx, [esp+0A0h+var_10]
.text:00513BB1                 pop     ebx
.text:00513BB2                 mov     al, [esp+9Ch+var_91_regf] ; 注册成功标志
.text:00513BB6                 call    sub_6FBECD
.text:00513BBB                 add     esp, 9Ch
.text:00513BC1                 retn    8
.text:00513BC1 sub_513700      endp

       继续跟进 v_6F38C0 这个关键CALL,胜利在望,但痛苦才刚刚开始..
       
.text:006F38C0 v_6F38C0        proc near               
.text:006F38C0
.text:006F38C0 var_4C_r21      = dword ptr -4Ch
.text:006F38C0 var_48_md5s     = dword ptr -48h
.text:006F38C0 var_44_RegCode  = dword ptr -44h
.text:006F38C0 var_40          = dword ptr -40h
.text:006F38C0 var_3C_r4       = dword ptr -3Ch
.text:006F38C0 var_38_s        = dword ptr -38h
.text:006F38C0 var_34_sa2      = dword ptr -34h
.text:006F38C0 var_30_pStr     = dword ptr -30h
.text:006F38C0 var_2C_Len      = dword ptr -2Ch
.text:006F38C0 var_28          = dword ptr -28h
.text:006F38C0 var_24          = dword ptr -24h
.text:006F38C0 var_20_sa1      = dword ptr -20h
.text:006F38C0 var_1C_pStr     = dword ptr -1Ch
.text:006F38C0 var_18_Len      = dword ptr -18h
.text:006F38C0 var_14          = dword ptr -14h
.text:006F38C0 var_10          = dword ptr -10h
.text:006F38C0 var_4           = dword ptr -4
.text:006F38C0 arg_0           = dword ptr  4
.text:006F38C0
.text:006F38C0                 push    0FFFFFFFFh
.text:006F38C2                 push    offset loc_7F70CF
.text:006F38C7                 mov     eax, large fs:0
.text:006F38CD                 push    eax
.text:006F38CE                 mov     large fs:0, esp
.text:006F38D5                 sub     esp, 40h
.text:006F38D8                 mov     eax, [esp+4Ch+arg_0]
.text:006F38DC                 push    ebx
.text:006F38DD                 push    ebp
.text:006F38DE                 push    esi
.text:006F38DF                 push    edi
.text:006F38E0                 mov     [esp+5Ch+var_40], ecx
.text:006F38E4                 push    eax             ; 注册码
.text:006F38E5                 lea     ecx, [esp+60h+var_44_RegCode] ; 保存到这里
.text:006F38E9                 call    ds:ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>(char const *)
.text:006F38EF                 lea     ecx, [esp+5Ch+var_44_RegCode] ; 去掉两边的空格
.text:006F38F3                 mov     [esp+5Ch+var_4], 0
.text:006F38FB                 call    ds:ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>::Trim(void)
.text:006F3901                 push    '-'
.text:006F3903                 lea     ecx, [esp+60h+var_44_RegCode] ; 删除注册码中的'-'
.text:006F3907                 call    ds:ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>::Remove(char)
.text:006F390D                 push    ' '
.text:006F390F                 lea     ecx, [esp+60h+var_44_RegCode] ; 删除注册码中的空格
.text:006F3913                 call    ds:ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>::Remove(char)
.text:006F3919                 lea     ecx, [esp+5Ch+var_44_RegCode] ; 转换成大写
.text:006F391D                 call    ds:ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>::MakeUpper(void)
.text:006F3923                 lea     ecx, [esp+5Ch+var_44_RegCode]
.text:006F3927                 mov     byte ptr [esp+5Ch+arg_0], 0
.text:006F392C                 call    ds:ATL::CSimpleStringT<char,1>::GetLength(void) ; 取注册码长度
.text:006F3932                 cmp     eax, 25
.text:006F3935                 jnz     loc_6F3E86      ; 长度不等于25则验证失败
.text:006F393B                 push    4
.text:006F393D                 lea     ecx, [esp+60h+var_3C_r4] ; 取右边4个字符保存在r4
.text:006F3941                 push    ecx
.text:006F3942                 lea     ecx, [esp+64h+var_44_RegCode]
.text:006F3946                 call    ds:ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>::Right(int)
.text:006F394C                 push    21
.text:006F394E                 lea     edx, [esp+60h+var_4C_r21] ; 取左边21个字符保存在r21
.text:006F3952                 push    edx
.text:006F3953                 lea     ecx, [esp+64h+var_44_RegCode]
.text:006F3957                 mov     byte ptr [esp+64h+var_4], 1
.text:006F395C                 call    ds:ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>::Left(int)
.text:006F3962                 push    5               ; 取r21的第6个字符
.text:006F3964                 lea     ecx, [esp+60h+var_4C_r21]
.text:006F3968                 mov     byte ptr [esp+60h+var_4], 2
.text:006F396D                 call    ds:ATL::CSimpleStringT<char,1>::operator[](int)
.text:006F3973                 or      edi, 0FFFFFFFFh ; 没找到则返回-1
.text:006F3976                 xor     ecx, ecx
.text:006F3978
.text:006F3978 loc_6F3978:                            
.text:006F3978                 cmp     al, byte ptr ds:Table1_865058[ecx] ; "CA5BDWF4H9PJK3SUM2XEL7GRZNQTY6V8"
.text:006F397E                 jz      short loc_6F3988
.text:006F3980                 inc     ecx
.text:006F3981                 cmp     ecx, 32
.text:006F3984                 jl      short loc_6F3978
.text:006F3986                 jmp     short loc_6F398A ; 查表
.text:006F3988
.text:006F3988 loc_6F3988:                             
.text:006F3988                 mov     edi, ecx        ; 取得第6个字符在表中的索引i6
.text:006F398A
.text:006F398A loc_6F398A:                            
.text:006F398A                 push    1
.text:006F398C                 push    5
.text:006F398E                 lea     ecx, [esp+64h+var_4C_r21] ; 删除r21中第六个字符
.text:006F3992                 call    ds:ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>::Delete(int,int)
.text:006F3998                 push    10              ; 取r21的第11个字符
.text:006F399A                 lea     ecx, [esp+60h+var_4C_r21]
.text:006F399E                 call    ds:ATL::CSimpleStringT<char,1>::operator[](int)
.text:006F39A4                 or      esi, 0FFFFFFFFh ; 没找到则返回-1
.text:006F39A7                 xor     ecx, ecx
.text:006F39A9                 lea     esp, [esp+0]
.text:006F39B0
.text:006F39B0 loc_6F39B0:                             
.text:006F39B0                 cmp     al, byte ptr ds:Table1_865058[ecx] ; "CA5BDWF4H9PJK3SUM2XEL7GRZNQTY6V8"
.text:006F39B6                 jz      short loc_6F39C0
.text:006F39B8                 inc     ecx
.text:006F39B9                 cmp     ecx, 32
.text:006F39BC                 jl      short loc_6F39B0
.text:006F39BE                 jmp     short loc_6F39C2 ; 查表
.text:006F39C0
.text:006F39C0 loc_6F39C0:                             
.text:006F39C0                 mov     esi, ecx        ; 取得第11个字符在表中的索引i11
.text:006F39C2
.text:006F39C2 loc_6F39C2:                           
.text:006F39C2                 push    1
.text:006F39C4                 push    10
.text:006F39C6                 lea     ecx, [esp+64h+var_4C_r21] ; 删除r21中第11个字符
.text:006F39CA                 call    ds:ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>::Delete(int,int)
.text:006F39D0                 xor     eax, eax
.text:006F39D2                 mov     ebp, (offset Table1_865058+20h) ; 构造一个动态数组
.text:006F39D7                 mov     [esp+5Ch+var_20_sa1], ebp
.text:006F39DB                 mov     [esp+5Ch+var_1C_pStr], eax
.text:006F39DF                 mov     [esp+5Ch+var_10], eax
.text:006F39E3                 mov     [esp+5Ch+var_14], eax
.text:006F39E7                 mov     [esp+5Ch+var_18_Len], eax
.text:006F39EB                 lea     eax, [esp+5Ch+var_20_sa1]
.text:006F39EF                 mov     bl, 3
.text:006F39F1                 push    eax             ; 压入堆栈
.text:006F39F2                 lea     ecx, [esp+60h+var_4C_r21]
.text:006F39F6                 mov     byte ptr [esp+60h+var_4], bl
.text:006F39FA                 call    ds:ATL::CSimpleStringT<char,1>::operator char const *(void)
.text:006F3A00                 push    eax             ; r21
.text:006F3A01                 call    fun1_6F37C0
.text:006F3A06                 add     esi, 32         ; i11 += 32
.text:006F3A09                 add     esp, 8
.text:006F3A0C                 cmp     esi, 0FFFFFFFFh ; if i11 == -1
.text:006F3A0F                 jnz     short loc_6F3A16
.text:006F3A11                 mov     esi, [esp+5Ch+var_18_Len] ; i11 = strlen(r21) * 5 - 1
.text:006F3A15                 dec     esi
.text:006F3A16
.text:006F3A16 loc_6F3A16:                            
.text:006F3A16                 mov     eax, edi        ; i6
.text:006F3A18                 cdq
.text:006F3A19                 lea     ecx, [esi+1]    ; i11 + 1
.text:006F3A1C                 idiv    ecx
.text:006F3A1E                 push    esi             ; 参数4: i11
.text:006F3A1F                 push    0               ; 参数3: 0
.text:006F3A21                 sub     ecx, edx
.text:006F3A23                 push    ecx             ; 参数2: (i11 + 1) - i6 % (i11 + 1)
.text:006F3A24                 lea     ecx, [esp+68h+var_20_sa1]
.text:006F3A28                 push    ecx             ; 参数1: 数组sa1
.text:006F3A29                 call    fun2_6F35B0
.text:006F3A2E                 lea     edx, [esp+6Ch+var_20_sa1]
.text:006F3A32                 push    edx
.text:006F3A33                 lea     eax, [esp+70h+var_38_s]
.text:006F3A37                 push    eax
.text:006F3A38                 call    fun3_6F36E0
.text:006F3A3D                 add     esp, 18h
.text:006F3A40                 push    eax
.text:006F3A41                 lea     ecx, [esp+60h+var_4C_r21] ; r21
.text:006F3A45                 mov     byte ptr [esp+60h+var_4], 4
.text:006F3A4A                 call    ds:ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>::operator=(ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>> const &)
.text:006F3A50                 lea     ecx, [esp+5Ch+var_38_s]
.text:006F3A54                 mov     byte ptr [esp+5Ch+var_4], bl
.text:006F3A58                 call    ds:ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>::~CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>(void)
.text:006F3A5E                 push    10              ; 取r21的第11个字符
.text:006F3A60                 lea     ecx, [esp+60h+var_4C_r21]
.text:006F3A64                 call    ds:ATL::CSimpleStringT<char,1>::operator[](int)
.text:006F3A6A                 or      esi, 0FFFFFFFFh ; 没找到则返回-1
.text:006F3A6D                 xor     ecx, ecx
.text:006F3A6F                 nop
.text:006F3A70
.text:006F3A70 loc_6F3A70:                           
.text:006F3A70                 cmp     al, byte ptr ds:Table1_865058[ecx] ; "CA5BDWF4H9PJK3SUM2XEL7GRZNQTY6V8"
.text:006F3A76                 jz      short loc_6F3A80
.text:006F3A78                 inc     ecx
.text:006F3A79                 cmp     ecx, 20h
.text:006F3A7C                 jl      short loc_6F3A70
.text:006F3A7E                 jmp     short loc_6F3A82 ; 查表
.text:006F3A80
.text:006F3A80 loc_6F3A80:                           
.text:006F3A80                 mov     esi, ecx        ; 取得第11个字符在表中的索引i11
.text:006F3A82
.text:006F3A82 loc_6F3A82:                            
.text:006F3A82                 push    1
.text:006F3A84                 push    10              ; 删除第11个字符
.text:006F3A86                 lea     ecx, [esp+64h+var_4C_r21]
.text:006F3A8A                 call    ds:ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>::Delete(int,int)
.text:006F3A90                 lea     ecx, [esp+5Ch+var_20_sa1]
.text:006F3A94                 push    ecx             ; 动态数组
.text:006F3A95                 lea     ecx, [esp+60h+var_4C_r21]
.text:006F3A99                 call    ds:ATL::CSimpleStringT<char,1>::operator char const *(void)
.text:006F3A9F                 push    eax             ; r21
.text:006F3AA0                 call    fun1_6F37C0
.text:006F3AA5                 push    0FFFFFFFFh      ; 参数4: -1
.text:006F3AA7                 xor     edi, edi
.text:006F3AA9                 push    edi             ; 参数3: 0
.text:006F3AAA                 lea     edx, [esp+6Ch+var_20_sa1]
.text:006F3AAE                 push    esi             ; 参数2: i11
.text:006F3AAF                 push    edx             ; 参数1: 动态数组sa1
.text:006F3AB0                 call    fun2_6F35B0
.text:006F3AB5                 lea     eax, [esp+74h+var_20_sa1]
.text:006F3AB9                 push    eax
.text:006F3ABA                 lea     ecx, [esp+78h+var_38_s]
.text:006F3ABE                 push    ecx
.text:006F3ABF                 call    fun3_6F36E0
.text:006F3AC4                 add     esp, 20h
.text:006F3AC7                 push    eax
.text:006F3AC8                 lea     ecx, [esp+60h+var_4C_r21] ; r21
.text:006F3ACC                 mov     byte ptr [esp+60h+var_4], 5
.text:006F3AD1                 call    ds:ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>::operator=(ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>> const &)
.text:006F3AD7                 lea     ecx, [esp+5Ch+var_38_s]
.text:006F3ADB                 mov     byte ptr [esp+5Ch+var_4], bl
.text:006F3ADF                 call    ds:ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>::~CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>(void)
.text:006F3AE5                 lea     edx, [esp+5Ch+var_4C_r21] ; r21
.text:006F3AE9                 push    edx
.text:006F3AEA                 lea     eax, [esp+60h+var_48_md5s]
.text:006F3AEE                 push    eax
.text:006F3AEF                 call    md5_6224C0      ; 标准MD5,变换成小写字符串
.text:006F3AF4                 add     esp, 8
.text:006F3AF7                 push    4
.text:006F3AF9                 lea     ecx, [esp+60h+var_38_s] ; 取md5s的左边4个字符
.text:006F3AFD                 push    ecx
.text:006F3AFE                 lea     ecx, [esp+64h+var_48_md5s]
.text:006F3B02                 mov     byte ptr [esp+64h+var_4], 6
.text:006F3B07                 call    ds:ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>::Left(int)
.text:006F3B0D                 push    eax
.text:006F3B0E                 lea     ecx, [esp+60h+var_48_md5s] ; 保存到这里
.text:006F3B12                 mov     byte ptr [esp+60h+var_4], 7
.text:006F3B17                 call    ds:ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>::operator=(ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>> const &)
.text:006F3B1D                 lea     ecx, [esp+5Ch+var_38_s]
.text:006F3B21                 mov     byte ptr [esp+5Ch+var_4], 6
.text:006F3B26                 call    ds:ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>::~CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>(void)
.text:006F3B2C                 xor     esi, esi
.text:006F3B2E                 mov     edi, edi
.text:006F3B30
.text:006F3B30 loc_6F3B30:                            
.text:006F3B30                 push    esi
.text:006F3B31                 lea     ecx, [esp+60h+var_48_md5s]
.text:006F3B35                 call    ds:ATL::CSimpleStringT<char,1>::operator[](int)
.text:006F3B3B                 cmp     al, '0'         ; 把'0'替换成'R'
.text:006F3B3D                 lea     ecx, [esp+5Ch+var_48_md5s]
.text:006F3B41                 jnz     short loc_6F3B47
.text:006F3B43                 push    'R'
.text:006F3B45                 jmp     short loc_6F3B58
.text:006F3B47
.text:006F3B47 loc_6F3B47:                             
.text:006F3B47                 push    esi
.text:006F3B48                 call    ds:ATL::CSimpleStringT<char,1>::operator[](int)
.text:006F3B4E                 cmp     al, '1'         ; 把'1'替换成'M'
.text:006F3B50                 jnz     short loc_6F3B5F
.text:006F3B52                 push    'M'
.text:006F3B54                 lea     ecx, [esp+60h+var_48_md5s]
.text:006F3B58
.text:006F3B58 loc_6F3B58:                             
.text:006F3B58                 push    esi
.text:006F3B59                 call    ds:ATL::CSimpleStringT<char,1>::SetAt(int,char)
.text:006F3B5F
.text:006F3B5F loc_6F3B5F:                            
.text:006F3B5F                 inc     esi
.text:006F3B60                 cmp     esi, 4
.text:006F3B63                 jl      short loc_6F3B30
.text:006F3B65                 lea     ecx, [esp+5Ch+var_48_md5s] ; 转换成大写
.text:006F3B69                 call    ds:ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>::MakeUpper(void)
.text:006F3B6F                 lea     ecx, [esp+5Ch+var_3C_r4]
.text:006F3B73                 call    ds:ATL::CSimpleStringT<char,1>::operator char const *(void)
.text:006F3B79                 push    eax
.text:006F3B7A                 lea     ecx, [esp+60h+var_48_md5s]
.text:006F3B7E                 call    ds:ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>::Compare(char const *)
.text:006F3B84                 test    eax, eax        ; 和注册码的最后4个字符比较
.text:006F3B86                 jnz     loc_6F3E52      ; 不等则校验失败
.text:006F3B8C                 mov     [esp+5Ch+var_34_sa2], ebp ; 构造一个动态数组
.text:006F3B90                 mov     [esp+5Ch+var_30_pStr], edi
.text:006F3B94                 mov     [esp+5Ch+var_24], edi
.text:006F3B98                 mov     [esp+5Ch+var_28], edi
.text:006F3B9C                 mov     [esp+5Ch+var_2C_Len], edi
.text:006F3BA0                 push    0FFFFFFFFh
.text:006F3BA2                 push    60              ; 数组大小
.text:006F3BA4                 lea     ecx, [esp+64h+var_34_sa2]
.text:006F3BA8                 mov     byte ptr [esp+64h+var_4], 8
.text:006F3BAD                 call    new_6F3410      ; 分配60个字节空间
.text:006F3BB2                 lea     ecx, [esp+5Ch+var_4C_r21] ; r21
.text:006F3BB6                 xor     esi, esi
.text:006F3BB8                 xor     ebx, ebx
.text:006F3BBA                 call    ds:ATL::CSimpleStringT<char,1>::GetLength(void)
.text:006F3BC0                 test    eax, eax
.text:006F3BC2                 jle     loc_6F3C4E
.text:006F3BC8                 xor     ebp, ebp
.text:006F3BCA                 lea     ebx, [ebx+0]
.text:006F3BD0
.text:006F3BD0 loc_6F3BD0:                            
.text:006F3BD0                 push    ebx
.text:006F3BD1                 lea     ecx, [esp+60h+var_4C_r21] ; 取r21一个字符
.text:006F3BD5                 call    ds:ATL::CSimpleStringT<char,1>::operator[](int)
.text:006F3BDB                 or      edi, 0FFFFFFFFh ; 没找到则返回-1
.text:006F3BDE                 xor     ecx, ecx
.text:006F3BE0
.text:006F3BE0 loc_6F3BE0:                             
.text:006F3BE0                 cmp     al, byte ptr ds:Table1_865058[ecx] ; "CA5BDWF4H9PJK3SUM2XEL7GRZNQTY6V8"
.text:006F3BE6                 jz      short loc_6F3BF0
.text:006F3BE8                 inc     ecx
.text:006F3BE9                 cmp     ecx, 32
.text:006F3BEC                 jl      short loc_6F3BE0
.text:006F3BEE                 jmp     short loc_6F3BF2 ; 查表
.text:006F3BF0
.text:006F3BF0 loc_6F3BF0:                            
.text:006F3BF0                 mov     edi, ecx        ; 取得在表中的索引
.text:006F3BF2
.text:006F3BF2 loc_6F3BF2:                           
.text:006F3BF2                 xor     ecx, ecx
.text:006F3BF4
.text:006F3BF4 loc_6F3BF4:                            
.text:006F3BF4                 lea     edx, [ecx+ebp]
.text:006F3BF7                 mov     eax, offset Table2_864FE0
.text:006F3BFC                 lea     esp, [esp+0]
.text:006F3C00
.text:006F3C00 loc_6F3C00:                             
.text:006F3C00                 cmp     edx, [eax]
.text:006F3C02                 jz      short loc_6F3C34
.text:006F3C04                 add     eax, 4
.text:006F3C07                 cmp     eax, offset Table1_865058 ; "CA5BDWF4H9PJK3SUM2XEL7GRZNQTY6V8"
.text:006F3C0C                 jl      short loc_6F3C00
.text:006F3C0E                 test    esi, esi
.text:006F3C10                 jl      failed_6F3EA9
.text:006F3C16                 cmp     esi, [esp+5Ch+var_2C_Len]
.text:006F3C1A                 jge     failed_6F3EA9
.text:006F3C20                 mov     edx, 1
.text:006F3C25                 shl     edx, cl
.text:006F3C27                 test    edx, edi
.text:006F3C29                 mov     edx, [esp+5Ch+var_30_pStr]
.text:006F3C2D                 setnz   al
.text:006F3C30                 mov     [edx+esi], al
.text:006F3C33                 inc     esi
.text:006F3C34
.text:006F3C34 loc_6F3C34:                            
.text:006F3C34                 inc     ecx
.text:006F3C35                 cmp     ecx, 5
.text:006F3C38                 jl      short loc_6F3BF4
.text:006F3C3A                 lea     ecx, [esp+5Ch+var_4C_r21]
.text:006F3C3E                 inc     ebx
.text:006F3C3F                 add     ebp, 5
.text:006F3C42                 call    ds:ATL::CSimpleStringT<char,1>::GetLength(void)
.text:006F3C48                 cmp     ebx, eax
.text:006F3C4A                 jl      short loc_6F3BD0
.text:006F3C4C                 xor     edi, edi
.text:006F3C4E
.text:006F3C4E loc_6F3C4E:                            
.text:006F3C4E                 mov     esi, [esp+5Ch+var_30_pStr]
.text:006F3C52                 mov     ebx, [esp+5Ch+var_2C_Len]
.text:006F3C56                 xor     edx, edx
.text:006F3C58                 mov     eax, 21
.text:006F3C5D                 lea     ecx, [ecx+0]
.text:006F3C60
.text:006F3C60 loc_6F3C60:                             
.text:006F3C60                 cmp     eax, edi
.text:006F3C62                 jl      failed_6F3EA9
.text:006F3C68                 cmp     eax, ebx
.text:006F3C6A                 jge     failed_6F3EA9
.text:006F3C70                 cmp     byte ptr [esi+eax], 0
.text:006F3C74                 jz      short loc_6F3C82
.text:006F3C76                 lea     ecx, [eax-21]
.text:006F3C79                 mov     ebp, 1
.text:006F3C7E                 shl     ebp, cl
.text:006F3C80                 or      edx, ebp
.text:006F3C82
.text:006F3C82 loc_6F3C82:                            
.text:006F3C82                 inc     eax
.text:006F3C83                 cmp     eax, 26
.text:006F3C86                 jle     short loc_6F3C60 ; 21-26,必须为0
.text:006F3C88                 cmp     edx, edi
.text:006F3C8A                 mov     eax, [esp+5Ch+var_40]
.text:006F3C8E                 mov     [eax], edx      ; 保存结果
.text:006F3C90                 jnz     loc_6F3E40
.text:006F3C96                 xor     eax, eax
.text:006F3C98                 xor     ecx, ecx
.text:006F3C9A                 lea     ebx, [ebx+0]
.text:006F3CA0
.text:006F3CA0 loc_6F3CA0:                             
.text:006F3CA0                 cmp     ecx, edi
.text:006F3CA2                 jl      failed_6F3EA9
.text:006F3CA8                 cmp     ecx, ebx
.text:006F3CAA                 jge     failed_6F3EA9
.text:006F3CB0                 cmp     byte ptr [esi+ecx], 0
.text:006F3CB4                 jz      short loc_6F3CBF
.text:006F3CB6                 mov     edx, 1
.text:006F3CBB                 shl     edx, cl
.text:006F3CBD                 or      eax, edx
.text:006F3CBF
.text:006F3CBF loc_6F3CBF:                            
.text:006F3CBF                 inc     ecx
.text:006F3CC0                 cmp     ecx, 4          ; 0-4
.text:006F3CC3                 jle     short loc_6F3CA0
.text:006F3CC5                 mov     ebp, [esp+5Ch+var_40]
.text:006F3CC9                 mov     [ebp+1Ch], eax  ; 保存结果
.text:006F3CCC                 xor     edi, edi
.text:006F3CCE                 mov     eax, 5
.text:006F3CD3
.text:006F3CD3 loc_6F3CD3:                           
.text:006F3CD3                 test    eax, eax
.text:006F3CD5                 jl      failed_6F3EA9
.text:006F3CDB                 cmp     eax, ebx
.text:006F3CDD                 jge     failed_6F3EA9
.text:006F3CE3                 cmp     byte ptr [esi+eax], 0
.text:006F3CE7                 jz      short loc_6F3CF5
.text:006F3CE9                 lea     ecx, [eax-5]
.text:006F3CEC                 mov     edx, 1
.text:006F3CF1                 shl     edx, cl
.text:006F3CF3                 or      edi, edx
.text:006F3CF5
.text:006F3CF5 loc_6F3CF5:                            
.text:006F3CF5                 inc     eax
.text:006F3CF6                 cmp     eax, 8          ; 5-8,主版本号
.text:006F3CF9                 jle     short loc_6F3CD3
.text:006F3CFB                 xor     esi, esi
.text:006F3CFD                 mov     eax, 9
.text:006F3D02
.text:006F3D02 loc_6F3D02:                            
.text:006F3D02                 test    eax, eax
.text:006F3D04                 jl      failed_6F3EA9
.text:006F3D0A                 cmp     eax, ebx
.text:006F3D0C                 jge     failed_6F3EA9
.text:006F3D12                 mov     ecx, [esp+5Ch+var_30_pStr]
.text:006F3D16                 cmp     byte ptr [ecx+eax], 0
.text:006F3D1A                 jz      short loc_6F3D28
.text:006F3D1C                 lea     ecx, [eax-9]
.text:006F3D1F                 mov     edx, 1
.text:006F3D24                 shl     edx, cl
.text:006F3D26                 or      esi, edx
.text:006F3D28
.text:006F3D28 loc_6F3D28:                             
.text:006F3D28                 inc     eax
.text:006F3D29                 cmp     eax, 12         ; 9-12,从版本号
.text:006F3D2C                 jle     short loc_6F3D02
.text:006F3D2E                 xor     edx, edx
.text:006F3D30                 mov     eax, 13
.text:006F3D35
.text:006F3D35 loc_6F3D35:                            
.text:006F3D35                 test    eax, eax
.text:006F3D37                 jl      failed_6F3EA9
.text:006F3D3D                 cmp     eax, ebx
.text:006F3D3F                 jge     failed_6F3EA9
.text:006F3D45                 mov     ecx, [esp+5Ch+var_30_pStr]
.text:006F3D49                 cmp     byte ptr [ecx+eax], 0
.text:006F3D4D                 jz      short loc_6F3D5F
.text:006F3D4F                 lea     ecx, [eax-13]
.text:006F3D52                 mov     ebx, 1
.text:006F3D57                 shl     ebx, cl
.text:006F3D59                 or      edx, ebx
.text:006F3D5B                 mov     ebx, [esp+5Ch+var_2C_Len]
.text:006F3D5F
.text:006F3D5F loc_6F3D5F:                            
.text:006F3D5F                 inc     eax
.text:006F3D60                 cmp     eax, 16         ; 13-16,从版本号
.text:006F3D63                 jle     short loc_6F3D35
.text:006F3D65                 push    edx
.text:006F3D66                 push    esi
.text:006F3D67                 push    edi
.text:006F3D68                 lea     ecx, [ebp+8]
.text:006F3D6B                 call    sub_61E140
.text:006F3D70                 mov     esi, [esp+5Ch+var_30_pStr]
.text:006F3D74                 xor     edx, edx
.text:006F3D76                 mov     eax, 17
.text:006F3D7B                 jmp     short loc_6F3D80
.text:006F3D7D                 lea     ecx, [ecx+0]
.text:006F3D80
.text:006F3D80 loc_6F3D80:                            
.text:006F3D80                 test    eax, eax
.text:006F3D82                 jl      failed_6F3EA9
.text:006F3D88                 cmp     eax, ebx
.text:006F3D8A                 jge     failed_6F3EA9
.text:006F3D90                 cmp     byte ptr [esi+eax], 0
.text:006F3D94                 jz      short loc_6F3DA2
.text:006F3D96                 lea     ecx, [eax-11h]
.text:006F3D99                 mov     edi, 1
.text:006F3D9E                 shl     edi, cl
.text:006F3DA0                 or      edx, edi
.text:006F3DA2
.text:006F3DA2 loc_6F3DA2:                             
.text:006F3DA2                 inc     eax
.text:006F3DA3                 cmp     eax, 20         ; 17-20 协议类型
.text:006F3DA6                 jle     short loc_6F3D80
.text:006F3DA8                 push    edx
.text:006F3DA9                 lea     ecx, [ebp+14h]
.text:006F3DAC                 call    GetLicType_61E070
.text:006F3DB1                 xor     edx, edx
.text:006F3DB3                 mov     eax, 27
.text:006F3DB8
.text:006F3DB8 loc_6F3DB8:                             
.text:006F3DB8                 test    eax, eax
.text:006F3DBA                 jl      failed_6F3EA9
.text:006F3DC0                 cmp     eax, ebx
.text:006F3DC2                 jge     failed_6F3EA9
.text:006F3DC8                 cmp     byte ptr [esi+eax], 0
.text:006F3DCC                 jz      short loc_6F3DDA
.text:006F3DCE                 lea     ecx, [eax-1Bh]
.text:006F3DD1                 mov     edi, 1
.text:006F3DD6                 shl     edi, cl
.text:006F3DD8                 or      edx, edi
.text:006F3DDA
.text:006F3DDA loc_6F3DDA:                            
.text:006F3DDA                 inc     eax
.text:006F3DDB                 cmp     eax, 31         ; 27-31,必须为1
.text:006F3DDE                 jle     short loc_6F3DB8
.text:006F3DE0                 mov     [ebp+4], edx
.text:006F3DE3                 xor     eax, eax
.text:006F3DE5                 mov     edx, 32
.text:006F3DEA                 lea     ebx, [ebx+0]
.text:006F3DF0
.text:006F3DF0 loc_6F3DF0:                           
.text:006F3DF0                 test    edx, edx
.text:006F3DF2                 jl      failed_6F3EA9
.text:006F3DF8                 cmp     edx, ebx
.text:006F3DFA                 jge     failed_6F3EA9
.text:006F3E00                 cmp     byte ptr [esi+edx], 0
.text:006F3E04                 jz      short loc_6F3E12
.text:006F3E06                 lea     ecx, [edx-32]
.text:006F3E09                 mov     edi, 1
.text:006F3E0E                 shl     edi, cl
.text:006F3E10                 or      eax, edi
.text:006F3E12
.text:006F3E12 loc_6F3E12:                             
.text:006F3E12                 inc     edx
.text:006F3E13                 cmp     edx, 45         ; 32-45
.text:006F3E16                 jle     short loc_6F3DF0 ; Cnbragon说这个是试用版天数限制:)
.text:006F3E18                 push    0
.text:006F3E1A                 cdq
.text:006F3E1B                 push    15180h
.text:006F3E20                 push    edx             ; 0
.text:006F3E21                 push    eax
.text:006F3E22                 call    __allmul
.text:006F3E27                 mov     esi, [esp+5Ch+var_30_pStr]
.text:006F3E2B                 add     eax, 301DDF00h
.text:006F3E30                 adc     edx, 0
.text:006F3E33                 mov     [ebp+20h], eax
.text:006F3E36                 mov     [ebp+24h], edx
.text:006F3E39                 mov     byte ptr [esp+5Ch+arg_0], 1
.text:006F3E3E                 xor     edi, edi
.text:006F3E40
.text:006F3E40 loc_6F3E40:                             
.text:006F3E40                 cmp     esi, edi
.text:006F3E42                 mov     byte ptr [esp+5Ch+var_4], 6
.text:006F3E47                 jz      short loc_6F3E52
.text:006F3E49                 push    esi
.text:006F3E4A                 call    operator delete[](void *)
.text:006F3E4F                 add     esp, 4
.text:006F3E52
.text:006F3E52 loc_6F3E52:                            
.text:006F3E52                 lea     ecx, [esp+5Ch+var_48_md5s]
.text:006F3E56                 call    ds:ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>::~CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>(void)
.text:006F3E5C                 mov     eax, [esp+5Ch+var_1C_pStr]
.text:006F3E60                 cmp     eax, edi
.text:006F3E62                 mov     byte ptr [esp+5Ch+var_4], 2
.text:006F3E67                 jz      short loc_6F3E72
.text:006F3E69                 push    eax
.text:006F3E6A                 call    operator delete[](void *)
.text:006F3E6F                 add     esp, 4
.text:006F3E72
.text:006F3E72 loc_6F3E72:                             
.text:006F3E72                 lea     ecx, [esp+5Ch+var_4C_r21]
.text:006F3E76                 call    ds:ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>::~CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>(void)
.text:006F3E7C                 lea     ecx, [esp+5Ch+var_3C_r4]
.text:006F3E80                 call    ds:ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>::~CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>(void)
.text:006F3E86
.text:006F3E86 loc_6F3E86:                            
.text:006F3E86                 lea     ecx, [esp+5Ch+var_44_RegCode]
.text:006F3E8A                 call    ds:ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>::~CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>(void)
.text:006F3E90                 mov     ecx, [esp+50h]
.text:006F3E94                 mov     al, byte ptr [esp+5Ch+arg_0]
.text:006F3E98                 pop     edi
.text:006F3E99                 pop     esi
.text:006F3E9A                 pop     ebp
.text:006F3E9B                 pop     ebx
.text:006F3E9C                 mov     large fs:0, ecx
.text:006F3EA3                 add     esp, 4Ch
.text:006F3EA6                 retn    4
.text:006F3EA9
.text:006F3EA9 failed_6F3EA9:                          
.text:006F3EA9                 call    AfxThrowInvalidArgException(void)
.text:006F3EAF v_6F38C0        endp

        从上面也可以看出,注册码长度必须为25。
        最后解析出来的60个位就是key的内容了。
        我逆向了部分及其中的3个子程序,如下:
        
char * Table1[] = {"CA5BDWF4H9PJK3SUM2XEL7GRZNQTY6V8"};
int Table2[30] = {0   ,    6, 0x0B, 0x0C, 0x11, 0x16, 0x19, 0x1C, 0x1D, 0x1E,
                  0x1F, 0x26, 0x27, 0x28, 0x29, 0x2F, 0x30, 0x31, 0x32, 0x37,
                  0x3C, 0x41, 0x44, 0x45, 0x46, 0x47, 0x4D, 0x4E, 0x54, 0x59};
CString sLic[] = {"Eval",
                  "Single",
                  "Multi",
                  "Academic"};
struct strarray{
    int len;
    unsigned char * sp;
};

int funv1(int retValue[],CString RegCode)
{
    
    CString      r21,r4,md5s;
    char         c1;
    int          len,i,j,k,l,n,m;
    int          i6,i11;
    unsigned int x;

    RegCode.TrimLeft();
    RegCode.TrimRight();
    RegCode.Remove('-');
    RegCode.Remove(' ');
    RegCode.MakeUpper();
    if(RegCode.GetLength() != 25)return 0;
    r4 = RegCode.Left(4);
    r21 = RegCode.Right(21);
    c1 = r21[5];
    i6 = -1;
    for(i = 0; i < 32; i ++)
    {
        if(c1 == Table1[i])
        {
            i6 = i;
            break;
        }
    }
    r21.Delete(5,1);
    c1 = r21[10];
    i11 = -1;
    for(i = 0; i < 32; i ++)
    {
        if(c1 == Table1[i])
        {
            i11 = i;
            break;
        }
    }
    r21.Delete(10,1);
    
    strarray sa1;
    sa1.len = 0;
    sa1.sp = NULL;
    
    fun1(r21,&sa1);   
    i11 += 32;
    if(i11 == -1)i11 = sa1.len - 1;
    i = (i11 + 1) - i6 % (i11 + 1);
    fun2(&sa1,i,0,i11);
    r21 = fun3(&sa1);
    
    c1 = r21[10];
    i11 = -1;
    for(i = 0; i < 32; i ++)
    {
        if(c1 == Table1[i])
        {
            i11 = i;
            break;
        }
    }
    r21.Delete(10,1);
    
    fun1(r21,&sa1);
    fun2(&sa1,i11,0,-1);
    r21 = fun3(&sa1);
    
    md5s = md5(r21);
    md5s = md5s.Left(4);
    for(i = 0; i < 4; i ++)
    {
        if(md5s[i] == '0')
            md5s.SetAt(i,'R');
        esle if(md5s[i] == '1')
            md5s.SetAt(i,'M');
    }
    md5s.MakeUpper();
    
    if(md5s.Compare(r4) != 0)return 0;
        
    strarray sa2;
    sa2.len = 0;
    sa2.sp = NULL;
    
    sa2.sp = new unsigned char[60];
    sa2.len = 60;
    memset(sa2.sp,0,60);
    
    m = 0;
    l = 0;
    if(r21.GetLength() > 0)
    {
        for(j = 0; j < r21.GetLength(); j ++)
        {
            i6 = -1;
            c1 = r21[j];
            for(i = 0; i < 32; i ++)
            {
                if(c1 == Table1[i])
                {
                    i6 = i;
                    break;
                }
            }
            
            k = 0;
            n = 0;            
            for(k = 0; k < 5; k ++)
            {
                for(n = 0; n < 30; n ++)
                    if((k+l) == Table2[n])
                        goto next1;
                sa2.sp[m] = (((1 << k) & i6) != 0) ? 1 : 0;
                m ++;
next1:            
            }
            l += 5;    
        }
    }
    
    x = 0;
    for(i = 21; i <= 26; i ++)  //取key的21到26位,这里必须为0
    {
        if(sa2.sp[i] != 0)
        {
            x |= (1 << (i - 21));
        }
    }
    retValue[0] = x;
    if(x != 0)return 0;
            
    x = 0;
    for(i = 0; i <= 4; i ++)
    {
        if(sa2.sp[i] != 0)
        {
            x |= (1 << i);
        }
    }
    retValue[7] = x;
    
    x = 0;
    for(i = 5; i <= 8; i ++)
    {
        if(sa2.sp[i] != 0)
        {
            x |= (1 <<(i-5));
        }
    }
    retValue[2] = x;
    
    x = 0;
    for(i = 9; i <= 12; i ++)
    {
        if(sa2.sp[i] != 0)
        {
            x |= (1 <<(i-9));
        }
    }
    retValue[3] = x;        

    x = 0;
    for(i = 13; i <= 16; i ++)
    {
        if(sa2.sp[i] != 0)
        {
            x |= (1 <<(i-13));
        }
    }
    retValue[4] = x;

    x = 0;
    for(i = 17; i <= 20; i ++)
    {
        if(sa2.sp[i] != 0)
        {
            x |= (1 <<(i-17));
        }
    }
    if((x < 0) || (x >= 4)) x = 0;
    retValue[5] = x;
    retValue[6] = sLic[x];
    
    x = 0;
    for(i = 27; i <= 31; i ++)
    {
        if(sa2.sp[i] != 0)
        {
            x |= (1 <<(i-27));
        }
    }
    retValue[1] = x;
    
    x = 0;
    for(i = 32; i <= 45; i ++)
    {
        if(sa2.sp[i] != 0)
        {
            x |= (1 <<(i-32));
        }
    }

    __int64 y = Int32x32To64(x,0x15180);
    y += 0x301DDF00;
    *(__int64*)(&retvalue[8]) = y;
    
    if(sa2.sp != NULL)delete [] sa2.sp;
    sa2.sp = NULL;
    sa2.len = 0;
    if(sa1.sp != NULL)delete [] sa1.sp;
    sa1.sp = NULL;
    sa1.len = 0;
}
    
    下面是其中3个子程序的逆向:
    
=======================================================================================
.text:006F37C0 fun1_6F37C0     proc near               
.text:006F37C0
.text:006F37C0 var_10          = dword ptr -10h
.text:006F37C0 var_8           = dword ptr -8
.text:006F37C0 var_4           = dword ptr -4
.text:006F37C0 arg_0           = dword ptr  4
.text:006F37C0 arg_4           = dword ptr  8
.text:006F37C0
.text:006F37C0                 push    0FFFFFFFFh
.text:006F37C2                 push    offset loc_7F7069
.text:006F37C7                 mov     eax, large fs:0
.text:006F37CD                 push    eax
.text:006F37CE                 mov     large fs:0, esp
.text:006F37D5                 push    ecx
.text:006F37D6                 mov     eax, [esp+10h+arg_0] ; 注册码
.text:006F37DA                 push    ebx
.text:006F37DB                 push    ebp
.text:006F37DC                 push    esi
.text:006F37DD                 push    edi
.text:006F37DE                 push    eax
.text:006F37DF                 lea     ecx, [esp+24h+var_10] ; 保存到这里
.text:006F37E3                 call    ds:ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>(char const *)
.text:006F37E9                 mov     esi, [esp+20h+arg_4] ; 动态数组
.text:006F37ED                 mov     eax, [esi+4]    ; 取数组长度
.text:006F37F0                 xor     ebp, ebp
.text:006F37F2                 cmp     eax, ebp
.text:006F37F4                 mov     [esp+20h+var_4], ebp
.text:006F37F8                 jz      short loc_6F3806
.text:006F37FA                 push    eax
.text:006F37FB                 call    operator delete[](void *) ; 数组已经分配则先释放
.text:006F3800                 add     esp, 4
.text:006F3803                 mov     [esi+4], ebp
.text:006F3806
.text:006F3806 loc_6F3806:                             
.text:006F3806                 push    0FFFFFFFFh
.text:006F3808                 lea     ecx, [esp+24h+var_10] ; 注册码
.text:006F380C                 mov     [esi+0Ch], ebp
.text:006F380F                 mov     [esi+8], ebp
.text:006F3812                 call    ds:ATL::CSimpleStringT<char,1>::GetLength(void)
.text:006F3818                 lea     ecx, [eax+eax*4] ; 长度乘以5
.text:006F381B                 push    ecx
.text:006F381C                 mov     ecx, esi
.text:006F381E                 call    new_6F3410      ; 分配空间
.text:006F3823                 lea     ecx, [esp+20h+var_10] ; 注册码
.text:006F3827                 call    ds:ATL::CSimpleStringT<char,1>::GetLength(void)
.text:006F382D                 test    eax, eax        ; 取注册码长度
.text:006F382F                 jle     short loc_6F389C
.text:006F3831                 mov     [esp+20h+arg_4], ebp ; 计数器清零,这里使用的一个参数空间作为变量
.text:006F3835
.text:006F3835 loc_6F3835:                             
.text:006F3835                 push    ebp             ; 取一个字符
.text:006F3836                 lea     ecx, [esp+24h+var_10]
.text:006F383A                 call    ds:ATL::CSimpleStringT<char,1>::operator[](int)
.text:006F3840                 or      edi, 0FFFFFFFFh
.text:006F3843                 xor     ecx, ecx
.text:006F3845
.text:006F3845 loc_6F3845:                             
.text:006F3845                 cmp     al, byte ptr ds:Table1_865058[ecx]
.text:006F384B                 jz      short loc_6F3855
.text:006F384D                 inc     ecx
.text:006F384E                 cmp     ecx, 32
.text:006F3851                 jl      short loc_6F3845
.text:006F3853                 jmp     short loc_6F3857 ; 检查是否在表中
.text:006F3855
.text:006F3855 loc_6F3855:                            
.text:006F3855                 mov     edi, ecx        ; 取得索引
.text:006F3857
.text:006F3857 loc_6F3857:                             
.text:006F3857                 mov     eax, [esp+20h+arg_4]
.text:006F385B                 xor     ecx, ecx
.text:006F385D                 lea     ecx, [ecx+0]
.text:006F3860
.text:006F3860 loc_6F3860:                            
.text:006F3860                 test    eax, eax
.text:006F3862                 jl      short loc_6F38B9 ; 计数器小于0则跳
.text:006F3864                 cmp     eax, [esi+8]
.text:006F3867                 jge     short loc_6F38B9 ; 计数器大于等于注册码长度*5则跳
.text:006F3869                 mov     ebx, [esi+4]    ; 取动态内存地址
.text:006F386C                 mov     edx, 1
.text:006F3871                 shl     edx, cl
.text:006F3873                 test    edx, edi
.text:006F3875                 setnz   dl              ; 取出索引的0-5位
.text:006F3878                 inc     ecx
.text:006F3879                 mov     [eax+ebx], dl
.text:006F387C                 inc     eax
.text:006F387D                 cmp     ecx, 5
.text:006F3880                 jl      short loc_6F3860
.text:006F3882                 mov     edx, [esp+20h+arg_4]
.text:006F3886                 add     edx, 5          ; 计数器加上5
.text:006F3889                 lea     ecx, [esp+10h]
.text:006F388D                 inc     ebp
.text:006F388E                 mov     [esp+20h+arg_4], edx
.text:006F3892                 call    ds:ATL::CSimpleStringT<char,1>::GetLength(void)
.text:006F3898                 cmp     ebp, eax
.text:006F389A                 jl      short loc_6F3835 ; 没处理完则继续
.text:006F389C
.text:006F389C loc_6F389C:                           
.text:006F389C                 lea     ecx, [esp+20h+var_10]
.text:006F38A0                 call    ds:ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>::~CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>(void)
.text:006F38A6                 mov     ecx, [esp+14h]
.text:006F38AA                 pop     edi
.text:006F38AB                 pop     esi
.text:006F38AC                 pop     ebp
.text:006F38AD                 pop     ebx
.text:006F38AE                 mov     large fs:0, ecx
.text:006F38B5                 add     esp, 10h
.text:006F38B8                 retn
.text:006F38B9
.text:006F38B9 loc_6F38B9:                             
.text:006F38B9                                        
.text:006F38B9                 jmp     AfxThrowInvalidArgException(void)
.text:006F38B9 fun1_6F37C0     endp

=======================================================================================

struct strarray{
    int len;
    char * sp;
};

strarray sa;
char Table[] = {"CA5BDWF4H9PJK3SUM2XEL7GRZNQTY6V8"};


void fun1(CString s,strarray * p)
{
    int          i,j,k,index;
    unsigned int x;
    
    if(p -> len != 0)
        delete [](p -> sp);
    p -> sp = 0;
    p -> len = s.GetLength() * 5;
    p -> sp = new char[p -> len];
    memset(p -> sp,0,p -> len);
    if(s.GetLength() <= 0)return;
    
    j = 0;
    k = 0;
    do{
        index = -1;    
        for(i = 0; i < 32; i++)
        {
            if(s[j] = Table[i])
            {
                index = i;
                break;
            }
        }
        for(i = 0; i < 5; i++)
        {
            x = 1;
            x = x << i;
            if(x & index)
                (p -> sa)[k] = 1;
            k ++;
        }
        j ++;
    }while(j < s.GetLength());
}

=======================================================================================
.text:006F35B0 fun2_6F35B0     proc near              
.text:006F35B0
.text:006F35B0 var_20          = dword ptr -20h
.text:006F35B0 var_1C_pStr     = dword ptr -1Ch
.text:006F35B0 var_18_Len      = dword ptr -18h
.text:006F35B0 var_14          = dword ptr -14h
.text:006F35B0 var_10          = dword ptr -10h
.text:006F35B0 var_C           = dword ptr -0Ch
.text:006F35B0 var_4           = dword ptr -4
.text:006F35B0 arg_0           = dword ptr  4
.text:006F35B0 arg_4           = dword ptr  8
.text:006F35B0 arg_8           = dword ptr  0Ch
.text:006F35B0 arg_C           = dword ptr  10h
.text:006F35B0
.text:006F35B0                 mov     eax, large fs:0
.text:006F35B6                 push    0FFFFFFFFh
.text:006F35B8                 push    offset loc_7F7028
.text:006F35BD                 push    eax
.text:006F35BE                 mov     large fs:0, esp
.text:006F35C5                 sub     esp, 14h
.text:006F35C8                 push    ebx
.text:006F35C9                 push    ebp
.text:006F35CA                 mov     ebp, [esp+28h+arg_C] ; 参数4
.text:006F35CE                 cmp     ebp, 0FFFFFFFFh
.text:006F35D1                 push    esi
.text:006F35D2                 push    edi
.text:006F35D3                 mov     edi, [esp+30h+arg_0] ; 参数1,结构地址
.text:006F35D7                 jnz     short loc_6F35DD
.text:006F35D9                 mov     ebp, [edi+8]    ; 5F
.text:006F35DC                 dec     ebp
.text:006F35DD
.text:006F35DD loc_6F35DD:                            
.text:006F35DD                 mov     ebx, [esp+30h+arg_8] ; 参数3:0
.text:006F35E1                 xor     eax, eax
.text:006F35E3                 mov     esi, ebp
.text:006F35E5                 sub     esi, ebx
.text:006F35E7                 inc     esi             ; 参数4-参数3+1
.text:006F35E8                 mov     [esp+30h+var_20], offset off_865078
.text:006F35F0                 mov     [esp+30h+var_1C_pStr], eax
.text:006F35F4                 mov     [esp+30h+var_10], eax
.text:006F35F8                 mov     [esp+30h+var_14], eax
.text:006F35FC                 mov     [esp+30h+var_18_Len], eax
.text:006F3600                 push    0FFFFFFFFh
.text:006F3602                 push    esi             ; 大小
.text:006F3603                 lea     ecx, [esp+38h+var_20]
.text:006F3607                 mov     [esp+38h+var_4], eax
.text:006F360B                 call    new_6F3410      ; 分配空间
.text:006F3610                 xor     ecx, ecx
.text:006F3612                 cmp     ebx, ebp
.text:006F3614                 mov     eax, ebx
.text:006F3616                 jg      short loc_6F3657
.text:006F3618                 jmp     short loc_6F3620
.text:006F361A
.text:006F361A loc_6F361A:                             
.text:006F361A                 mov     edi, [esp+30h+arg_0] ; 参数1,结构地址
.text:006F361E                 mov     edi, edi
.text:006F3620
.text:006F3620 loc_6F3620:                             
.text:006F3620                 test    eax, eax
.text:006F3622                 jl      loc_6F36D2
.text:006F3628                 cmp     eax, [edi+8]
.text:006F362B                 jge     loc_6F36D2
.text:006F3631                 mov     edi, [edi+4]    ; 字符串指针
.text:006F3634                 add     edi, eax
.text:006F3636                 test    ecx, ecx
.text:006F3638                 jl      loc_6F36D2
.text:006F363E                 cmp     ecx, [esp+30h+var_18_Len]
.text:006F3642                 jge     loc_6F36D2
.text:006F3648                 mov     dl, [edi]
.text:006F364A                 mov     edi, [esp+30h+var_1C_pStr] ; 新建结构的字符串指针
.text:006F364E                 inc     eax
.text:006F364F                 mov     [edi+ecx], dl   ; 复制结构中的部分值
.text:006F3652                 inc     ecx
.text:006F3653                 cmp     eax, ebp
.text:006F3655                 jle     short loc_6F361A
.text:006F3657
.text:006F3657 loc_6F3657:                             
.text:006F3657                 mov     eax, [esp+30h+arg_4] ; 参数2
.text:006F365B                 cdq
.text:006F365C                 idiv    esi             ; 新分配的空间大小
.text:006F365E                 xor     ebp, ebp
.text:006F3660                 test    esi, esi
.text:006F3662                 mov     ecx, ebx        ; 参数3:0
.text:006F3664                 jle     short loc_6F36A6
.text:006F3666                 mov     eax, edx        ; 参数2模空间大小的值
.text:006F3668                 sub     eax, ebx        ; 减去参数3
.text:006F366A                 mov     [esp+30h+arg_C], eax ; 保存结果
.text:006F366E                 jmp     short loc_6F3674
.text:006F3670
.text:006F3670 loc_6F3670:                            
.text:006F3670                 mov     eax, [esp+30h+arg_C]
.text:006F3674
.text:006F3674 loc_6F3674:                             
.text:006F3674                 add     eax, ecx
.text:006F3676                 cdq
.text:006F3677                 idiv    esi
.text:006F3679                 mov     edi, edx        ; 取模
.text:006F367B                 test    edi, edi
.text:006F367D                 jl      short loc_6F36D2
.text:006F367F                 cmp     edi, [esp+30h+var_18_Len]
.text:006F3683                 jge     short loc_6F36D2
.text:006F3685                 test    ecx, ecx
.text:006F3687                 jl      short loc_6F36D2
.text:006F3689                 mov     eax, [esp+30h+arg_0] ; 取参数1:结构地址
.text:006F368D                 cmp     ecx, [eax+8]
.text:006F3690                 jge     short loc_6F36D2
.text:006F3692                 mov     eax, [eax+4]    ; 取指针地址
.text:006F3695                 mov     edx, [esp+30h+var_1C_pStr] ; 取新建结构的指针
.text:006F3699                 mov     dl, [edx+edi]
.text:006F369C                 add     eax, ecx
.text:006F369E                 inc     ebp
.text:006F369F                 inc     ecx
.text:006F36A0                 cmp     ebp, esi
.text:006F36A2                 mov     [eax], dl
.text:006F36A4                 jl      short loc_6F3670
.text:006F36A6
.text:006F36A6 loc_6F36A6:                            
.text:006F36A6                 mov     eax, [esp+30h+var_1C_pStr]
.text:006F36AA                 test    eax, eax
.text:006F36AC                 mov     [esp+30h+var_4], 0FFFFFFFFh
.text:006F36B4                 jz      short loc_6F36BF
.text:006F36B6                 push    eax
.text:006F36B7                 call    operator delete[](void *)
.text:006F36BC                 add     esp, 4
.text:006F36BF
.text:006F36BF loc_6F36BF:                             
.text:006F36BF                 mov     ecx, [esp+24h]
.text:006F36C3                 pop     edi
.text:006F36C4                 pop     esi
.text:006F36C5                 pop     ebp
.text:006F36C6                 pop     ebx
.text:006F36C7                 mov     large fs:0, ecx
.text:006F36CE                 add     esp, 20h
.text:006F36D1                 retn
.text:006F36D2
.text:006F36D2 loc_6F36D2:                                                                                                        
.text:006F36D2                 jmp     AfxThrowInvalidArgException(void)
.text:006F36D2 fun2_6F35B0     endp
=======================================================================================

void fun2(strarray * p,int a1,int a2,int a3)
{
    int       i,j,k;
    strarray  q;
       
    if(a3 == -1)a3 = (p -> len) - 1;
    i = a3 - a2 + 1;
    q.sp = 0;
    q.len = i;
    q.sp = new char[i];
    memset(q.sp,0,i);
    
    if(a2 <= a3)
    {
        i = a2;
        do{
            q.sp[i] = (p -> sp)[i];
            i ++;
        }while(i <= a3);
    }
    
    i = a1 % q.len - a2;
    if(q.len > 0)
    {
        j = 0;
        do{
            k = (i + a2) % q.len;
            (p -> sp)[a2] = q.sp[k];
            a2 ++;
            j ++;
        }while(j < q.len);
    }
    
    if(q.sp != 0)delete []q.sp;
}

=======================================================================================
.text:006F36E0 fun3_6F36E0     proc near               
.text:006F36E0
.text:006F36E0 var_14          = dword ptr -14h
.text:006F36E0 var_10_cnt      = dword ptr -10h
.text:006F36E0 var_4           = dword ptr -4
.text:006F36E0 arg_0           = dword ptr  4
.text:006F36E0 arg_4           = dword ptr  8
.text:006F36E0
.text:006F36E0                 push    0FFFFFFFFh
.text:006F36E2                 push    offset loc_7F7049
.text:006F36E7                 mov     eax, large fs:0
.text:006F36ED                 push    eax
.text:006F36EE                 mov     large fs:0, esp
.text:006F36F5                 sub     esp, 8
.text:006F36F8                 push    ebx
.text:006F36F9                 push    ebp
.text:006F36FA                 push    esi
.text:006F36FB                 xor     esi, esi
.text:006F36FD                 push    edi
.text:006F36FE                 lea     ecx, [esp+24h+var_14] ; 构造一个字符串
.text:006F3702                 mov     [esp+24h+var_10_cnt], esi
.text:006F3706                 call    ds:ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>(void)
.text:006F370C                 mov     ebx, [esp+24h+arg_4] ; 传进来的结构地址
.text:006F3710                 mov     ecx, [ebx+8]    ; 取长度
.text:006F3713                 mov     eax, 66666667h
.text:006F3718                 imul    ecx
.text:006F371A                 sar     edx, 1
.text:006F371C                 mov     ebp, edx
.text:006F371E                 shr     ebp, 31
.text:006F3721                 add     ebp, edx        ; /5,得到解码后的字符串长度
.text:006F3723                 cmp     ebp, esi
.text:006F3725                 mov     [esp+24h+var_4], esi
.text:006F3729                 mov     [esp+24h+var_10_cnt], esi
.text:006F372D                 jle     short loc_6F3788
.text:006F372F                 nop
.text:006F3730
.text:006F3730 loc_6F3730:                            
.text:006F3730                 lea     edx, [esi+4]    ; 加上4
.text:006F3733                 xor     edi, edi
.text:006F3735                 xor     ecx, ecx
.text:006F3737                 cmp     esi, edx
.text:006F3739                 mov     eax, esi
.text:006F373B                 jg      short loc_6F3765
.text:006F373D                 lea     ecx, [ecx+0]
.text:006F3740
.text:006F3740 loc_6F3740:                          
.text:006F3740                 test    eax, eax
.text:006F3742                 jl      short loc_6F37B8
.text:006F3744                 cmp     eax, [ebx+8]
.text:006F3747                 jge     short loc_6F37B8
.text:006F3749                 mov     ebx, [ebx+4]
.text:006F374C                 cmp     byte ptr [eax+ebx], 0
.text:006F3750                 jz      short loc_6F375B
.text:006F3752                 mov     ebx, 1
.text:006F3757                 shl     ebx, cl
.text:006F3759                 or      edi, ebx
.text:006F375B
.text:006F375B loc_6F375B:                             
.text:006F375B                 mov     ebx, [esp+24h+arg_4]
.text:006F375F                 inc     ecx
.text:006F3760                 inc     eax
.text:006F3761                 cmp     eax, edx
.text:006F3763                 jle     short loc_6F3740
.text:006F3765
.text:006F3765 loc_6F3765:                            
.text:006F3765                 xor     eax, eax
.text:006F3767                 mov     al, ds:Table1_865058[edi] ; 查表,连接到字符串
.text:006F376D                 lea     ecx, [esp+24h+var_14]
.text:006F3771                 push    eax
.text:006F3772                 call    ds:ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>::operator+=(char)
.text:006F3778                 mov     eax, [esp+24h+var_10_cnt]
.text:006F377C                 inc     eax
.text:006F377D                 add     esi, 5
.text:006F3780                 cmp     eax, ebp
.text:006F3782                 mov     [esp+24h+var_10_cnt], eax
.text:006F3786                 jl      short loc_6F3730
.text:006F3788
.text:006F3788 loc_6F3788:                             
.text:006F3788                 mov     esi, [esp+24h+arg_0] ; 返回这个字符串
.text:006F378C                 lea     ecx, [esp+24h+var_14]
.text:006F3790                 push    ecx
.text:006F3791                 mov     ecx, esi
.text:006F3793                 call    ds:ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>(CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>> const &)
.text:006F3799                 lea     ecx, [esp+24h+var_14]
.text:006F379D                 call    ds:ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>::~CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>(void)
.text:006F37A3                 mov     ecx, [esp+18h]
.text:006F37A7                 pop     edi
.text:006F37A8                 mov     eax, esi
.text:006F37AA                 pop     esi
.text:006F37AB                 pop     ebp
.text:006F37AC                 pop     ebx
.text:006F37AD                 mov     large fs:0, ecx
.text:006F37B4                 add     esp, 14h
.text:006F37B7                 retn
.text:006F37B8
.text:006F37B8 loc_6F37B8:                           
.text:006F37B8                 jmp     AfxThrowInvalidArgException(void)
.text:006F37B8 fun3_6F36E0     endp
=======================================================================================
CString fun3(strarray *p)
{
    int          cnt,i,j,k,m,n;
    unsigned int x;
    CString s;
    
    cnt = p -> len / 5;
    if(cnt <= 0)return s; 
    
    j = 0;
    i = 0;   
    do{            
        k = j + 4;
        x = 0;
        m = 0;
        
        if(j <= k)
        {
            do{
                n = j;
                if((p -> sp)[n] != 0)
                {
                    x = x | (1 << m);
                }
                m ++;
                n ++;
            }while(n <= k);
        
        }
        s = s + Table[x];
        j = j + 5;
        i ++;     
    }while(i < cnt);
     
    return s;
}

=======================================================================================

        算法部分先对注册码左边21个字符使用了两次使用了查表变换(BASE32?),得到一个18个字符
        的字符串。然后对这18个字符取md5,得到md5字符串左边4个字符,替换掉其中的'0'和'1'后
        转换成大写,和注册码后4个字符比较。然后用18个字符的字符串变换出下面的key结构:
       
        0-4  : 未知
        5-8  : >= 8
        9-12 : 0
        13-16: 0
        17-20: 协议类型:1:Single 2 Multi 3 Academic
        21-26: 0
        27-31: 1
        32-45: 未知,形成一整数
        46-59: 随意
        
        这不是一个完整的分析,我没有时间继续去追踪了。老板要发彪了:(
        感兴趣的朋友可以继续分析启动时的验证。
        
=======================================================================================
        【全文完】

  • 标 题: 答复
  • 作 者:ViperDodge
  • 时 间:2006-04-02 15:47

哈哈,刚才看了些,我那样找Button断点还是适合这MFC程序
虽然这是VC 7.0写的,不过同样可以在MFC71.DLL库中搜索
PUSH    DWORD PTR [EAX+14]
PUSH    DWORD PTR [EBP+C]
PUSH    DWORD PTR [EBP+8]
PUSH    EDI

会来到这里
7C1718FD    FF75 14         PUSH    DWORD PTR [EBP+14]
7C171900    FF70 10         PUSH    DWORD PTR [EAX+10]
7C171903    FF75 10         PUSH    DWORD PTR [EBP+10]
7C171906    FF70 14         PUSH    DWORD PTR [EAX+14]
7C171909    FF75 0C         PUSH    DWORD PTR [EBP+C]
7C17190C    FF75 08         PUSH    DWORD PTR [EBP+8]
7C17190F    57              PUSH    EDI                              ; WINSPOOL.72F735D8
7C171910    E8 9FFFFFFF     CALL    7C1718B4                         ; MFC71.7C1718B4

7C171900    FF70 10         PUSH    DWORD PTR [EAX+10] 是消息代号, 在没点'ok'按钮前,老有个0x39消息,屏蔽掉它,条件断点[EAX+10]!=39

再去点'ok'按钮,就会断下来了
7C171906    FF70 14         PUSH    DWORD PTR [EAX+14] 
内的值显示是7C1500F0位置

再过去几步到了这,大概是CDialog类的OnOk()和OnCancal虚函数
7C1477EC    56              PUSH    ESI                              ; MFC71.7C170060
7C1477ED    6A 01           PUSH    1
7C1477EF    8BF1            MOV     ESI, ECX
7C1477F1    E8 EE5E0000     CALL    7C14D6E4                         ; MFC71.7C14D6E4
7C1477F6    85C0            TEST    EAX, EAX                         ; SnagIt32.008650B8
7C1477F8    74 09           JE      SHORT 7C147803                   ; MFC71.7C147803
7C1477FA    6A 01           PUSH    1
7C1477FC    8BCE            MOV     ECX, ESI                         ; MFC71.7C170060
7C1477FE    E8 02000000     CALL    7C147805                         ; MFC71.7C147805
7C147803    5E              POP     ESI                              ; MFC71.7C1746CC
7C147804    C3              RETN

往CALL    7C14D6E4里走。。。。
里边的CALL    [EAX+FC]函数就是去往Snaglt32.exe判断注册部分了