标 题: apIt8.01注册算法初步分析
作 者: ForEver
时 间: 2006-04-02 14:11
链 接: http://bbs.pediy.com/showthread.php?threadid=23500
详细信息:

【标题】【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   &