【标题】【VC】pdfFactory Pro 2.51 注册算法分析
【作者】forever[RCT]
【语言】VC
【保护】无壳,注册码
【难度】中等
【工具】ollydgb,ida,peid
【简介】pdfFactory 是一个无须 Acrobat 创建 Adobe PDF 文件的打印机驱动程序。pdfFactory 提供的创建 PDF 文件的方法比其他方法更方便和高效。 功能包括: 多个文档整合到一个 PDF 文件中; 内嵌字体; 通过 E-mail 发送; 预览; 自动压缩优化。pdfFactory Pro 除了 pdfFactory 的所有功能,还增加了: 128 位加密; 书签; 可用 URLs; 可变的窗口大小; 状态条。

【正文】这个软件的破解有点麻烦。原因是它没有界面,紧紧是个打印机驱动。
不过还好了,输入注册码错误时有个错误提示。用od载入,下断点bp MessageBoxA,
点注册按钮时被od拦截下来。会来到下面这个位置:

.text:2601C85A                 mov     ecx, offset unk_261971C8
.text:2601C85F                 call    sub_2601C0AB
.text:2601C864                 push    eax             ; hWnd
.text:2601C865                 call    ds:MessageBoxA
.text:2601C86B                 mov     [ebp+var_88], eax
.text:2601C871                 cmp     [ebp+var_84], 0
.text:2601C878                 jz      short loc_2601C891
.text:2601C87A                 mov     ecx, hhk
.text:2601C880                 push    ecx             ; hhk
.text:2601C881                 call    ds:UnhookWindowsHookEx

    仔细看一下没什么用。这个不是我们想要的。返回时会返回到消息循环。
    在od的加载的模块里看一下,加载的文件在system32\spool目录下。其中
fppui2a.dll是处理这个消息的模块。
    用ida反汇编fppui2a.dll,找到UpdateData这个函数。MFC的程序这个函数
是一般都是要调用的,用来获取控件里的值。在UpdateData这个函数上下个断点,
输入注册码时拦截到下面位置:

text:26046FFF                 push    1
.text:26047001                 mov     ecx, [ebp+var_C]
.text:26047004                 call    CWnd::UpdateData(int)
.text:26047009                 mov     ecx, [ebp+var_C]
.text:2604700C                 mov     edx, [ecx+0ECh]
.text:26047012                 mov     dword ptr [edx], 0
.text:26047018                 mov     eax, [ebp+var_C]
.text:2604701B                 mov     ecx, [eax+2A0h]
.text:26047021                 mov     [ebp+var_8], ecx
.text:26047024                 mov     edx, [ebp+var_C]
.text:26047027                 add     edx, 0F4h
.text:2604702D                 push    edx
.text:2604702E                 mov     eax, [ebp+var_C]
.text:26047031                 mov     ecx, [eax+0F0h]
.text:26047037                 push    ecx
.text:26047038                 mov     edx, [ebp+var_8]
.text:2604703B                 push    edx
.text:2604703C                 call    sub_2604EBB4          //这个CALL要根进看看了
.text:26047041                 mov     eax, [ebp+var_C]
.text:26047044                 mov     ecx, [eax+0F0h]
.text:2604704A                 mov     edx, [ecx]
.text:2604704C                 cmp     edx, dword_261978BC   //注意1
.text:26047052                 jnz     short loc_26047075
.text:26047054                 mov     eax, [ebp+var_C]
.text:26047057                 xor     ecx, ecx
.text:26047059                 mov     cl, [eax+0F4h]
.text:2604705F                 and     ecx, 2                //注意2
.text:26047062                 test    ecx, ecx
.text:26047064                 jz      short loc_26047075
.text:26047066                 mov     edx, [ebp+var_C]
.text:26047069                 mov     eax, [edx+0ECh]
.text:2604706F                 mov     dword ptr [eax], 1    //置注册成功标准

    上面两个要注意的地方最后再解释。先跟进2604EBB4这个CALL再说。
    
.text:2604EBB4                 push    ebp
.text:2604EBB5                 mov     ebp, esp
.text:2604EBB7                 sub     esp, 10h
.text:2604EBBA                 mov     [ebp+var_C], 0
.text:2604EBC1                 mov     byte ptr [ebp+var_4], 0
.text:2604EBC5                 mov     [ebp+var_8], 0
.text:2604EBCC                 mov     eax, hInstance
.text:2604EBD1                 push    eax
.text:2604EBD2                 mov     ecx, [ebp+arg_0]
.text:2604EBD5                 push    ecx
.text:2604EBD6                 push    0
.text:2604EBD8                 push    0
.text:2604EBDA                 call    sub_260D440D           //这个CALL是验证的CALL,要根据 
.text:2604EBDF                 mov     [ebp+var_10], eax
.text:2604EBE2                 cmp     [ebp+var_10], 0
.text:2604EBE6                 jz      short loc_2604EBF5
.text:2604EBE8                 mov     byte ptr [ebp+var_4], 2
.text:2604EBEC                 mov     [ebp+var_8], 1
.text:2604EBF3                 jmp     short loc_2604EC25
.text:2604EBF5
.text:2604EBF5 loc_2604EBF5:                         
.text:2604EBF5                 push    0
.text:2604EBF7                 lea     edx, [ebp+var_4]
.text:2604EBFA                 push    edx
.text:2604EBFB                 push    0
.text:2604EBFD                 push    0
.text:2604EBFF                 push    0
.text:2604EC01                 push    0
.text:2604EC03                 push    0
.text:2604EC05                 push    0
.text:2604EC07                 lea     eax, [ebp+var_C]
.text:2604EC0A                 push    eax
.text:2604EC0B                 mov     ecx, [ebp+arg_0]
.text:2604EC0E                 push    ecx
.text:2604EC0F                 call    sub_2604E130         //这里先略过
.text:2604EC14                 test    eax, eax
.text:2604EC16                 jz      short loc_2604EC25
.text:2604EC18                 mov     edx, [ebp+var_C]
.text:2604EC1B                 mov     [ebp+var_10], edx
.text:2604EC1E                 mov     [ebp+var_8], 1
.text:2604EC25
                          
    继续跟进260D440D,一直跟到这个位置:
                      
.text:260D3F8B                 push    ebp
.text:260D3F8C                 mov     ebp, esp
.text:260D3F8E                 sub     esp, 10h
.text:260D3F91                 mov     [ebp+var_C], ecx
.text:260D3F94                 mov     eax, [ebp+arg_0]
.text:260D3F97                 push    eax             ; char *
.text:260D3F98                 call    _strlen
.text:260D3F9D                 add     esp, 4
.text:260D3FA0                 cmp     eax, 14               //检查注册码长度是否是14个字符长
.text:260D3FA3                 jz      short loc_260D3FAC
.text:260D3FA5                 xor     eax, eax
.text:260D3FA7                 jmp     loc_260D4057
.text:260D3FAC
.text:260D3FAC loc_260D3FAC:                           
.text:260D3FAC                 mov     [ebp+var_4_cn1], 0    //计数器1清零
.text:260D3FB3                 jmp     short loc_260D3FBE
.text:260D3FB5
.text:260D3FB5 loc_260D3FB5:                           
.text:260D3FB5                 mov     ecx, [ebp+var_4_cn1]
.text:260D3FB8                 add     ecx, 1
.text:260D3FBB                 mov     [ebp+var_4_cn1], ecx
.text:260D3FBE
.text:260D3FBE loc_260D3FBE:                         
.text:260D3FBE                 cmp     [ebp+var_4_cn1], 3
.text:260D3FC2                 jge     loc_260D404B
.text:260D3FC8                 mov     [ebp+var_8], 0        //计数器2清零
.text:260D3FCF                 jmp     short loc_260D3FDA
.text:260D3FD1
.text:260D3FD1 loc_260D3FD1:                        
.text:260D3FD1                 mov     edx, [ebp+var_8]
.text:260D3FD4                 add     edx, 1
.text:260D3FD7                 mov     [ebp+var_8], edx
.text:260D3FDA
.text:260D3FDA loc_260D3FDA:                          
.text:260D3FDA                 cmp     [ebp+var_8], 4
.text:260D3FDE                 jge     short loc_260D4028
.text:260D3FE0                 mov     eax, [ebp+arg_0]
.text:260D3FE3                 mov     cl, [eax]
.text:260D3FE5                 mov     [ebp+var_D], cl
.text:260D3FE8                 mov     dl, [ebp+var_D]
.text:260D3FEB                 push    edx
.text:260D3FEC                 mov     eax, [ebp+arg_0]
.text:260D3FEF                 add     eax, 1
.text:260D3FF2                 mov     [ebp+arg_0], eax
.text:260D3FF5                 call    sub_260D43BD    ; 查表“5WB9FRK4VTP3CQ6ASN8HX2JMUZYLEDG7”
.text:260D3FFA                 mov     ecx, [ebp+var_4_cn1]
.text:260D3FFD                 mov     edx, [ebp+var_C]
.text:260D4000                 lea     ecx, [edx+ecx*4]
.text:260D4003                 mov     edx, [ebp+var_8]
.text:260D4006                 mov     [ecx+edx], al   ; 保存索引
.text:260D4009                 mov     eax, [ebp+var_4_cn1]
.text:260D400C                 mov     ecx, [ebp+var_C]
.text:260D400F                 lea     edx, [ecx+eax*4]
.text:260D4012                 mov     eax, [ebp+var_8]
.text:260D4015                 xor     ecx, ecx
.text:260D4017                 mov     cl, [edx+eax]
.text:260D401A                 cmp     ecx, 0FFh       ; 该字符不在表中则返回 -1
.text:260D4020                 jnz     short loc_260D4026
.text:260D4022                 xor     eax, eax
.text:260D4024                 jmp     short loc_260D4057
.text:260D4026
.text:260D4026 loc_260D4026:                          
.text:260D4026                 jmp     short loc_260D3FD1
.text:260D4028
.text:260D4028 loc_260D4028:                          
.text:260D4028                 cmp     [ebp+var_4_cn1], 1
.text:260D402C                 jg      short loc_260D4046
.text:260D402E                 mov     edx, [ebp+arg_0]
.text:260D4031                 movsx   eax, byte ptr [edx]
.text:260D4034                 mov     ecx, [ebp+arg_0]
.text:260D4037                 add     ecx, 1
.text:260D403A                 mov     [ebp+arg_0], ecx
.text:260D403D                 cmp     eax, 2Dh
.text:260D4040                 jz      short loc_260D4046
.text:260D4042                 xor     eax, eax
.text:260D4044                 jmp     short loc_260D4057
.text:260D4046
.text:260D4046 loc_260D4046:                          
.text:260D4046                                         
.text:260D4046                 jmp     loc_260D3FB5
.text:260D404B
.text:260D404B loc_260D404B:                        
.text:260D404B                 mov     edx, [ebp+arg_4]
.text:260D404E                 push    edx
.text:260D404F                 mov     ecx, [ebp+var_C] ; 转换后的12个字符
.text:260D4052                 call    sub_260D405D     ; 继续跟进这个CALL 
.text:260D4057
.text:260D4057 loc_260D4057:                          
.text:260D4057                                        
.text:260D4057                 mov     esp, ebp
.text:260D4059                 pop     ebp
.text:260D405A                 retn    8

    上面那段就是把14的注册码 XXXX-XXXX-XXXX 去掉'-'号,然后取索引值形成一个整数数组,
也就是3个整数保存。要继续跟进260D405D里看看怎么验证的。

.text:260D405E                 mov     ebp, esp
.text:260D4060                 sub     esp, 30h
.text:260D4063                 push    ebx
.text:260D4064                 push    esi
.text:260D4065                 mov     [ebp+var_28], ecx
.text:260D4068                 mov     [ebp+var_4], 0
.text:260D406F                 mov     eax, [ebp+var_28]   
.text:260D4072                 cmp     dword ptr [eax+0Ch], 0
.text:260D4076                 jz      loc_260D410A
.text:260D407C                 mov     ecx, [ebp+var_28]  //取第一组整数
.text:260D407F                 mov     edx, [ecx]
.text:260D4081                 push    edx             ; lParam  
.text:260D4082                 push    0               ; wParam
.text:260D4084                 push    0FFF0h          ; Msg
.text:260D4089                 mov     eax, [ebp+var_28]
.text:260D408C                 mov     ecx, [eax+0Ch]
.text:260D408F                 push    ecx             ; hWnd
.text:260D4090                 call    ds:SendMessageA    //发送消息FFF0H
.text:260D4096                 test    eax, eax
.text:260D4098                 jnz     short loc_260D40A1
.text:260D409A                 xor     eax, eax
.text:260D409C                 jmp     loc_260D43B5
.text:260D40A1
.text:260D40A1 loc_260D40A1:                          
.text:260D40A1                 mov     edx, [ebp+var_28]
.text:260D40A4                 mov     eax, [edx+4]       //取第二组整数
.text:260D40A7                 push    eax             ; lParam
.text:260D40A8                 push    0               ; wParam
.text:260D40AA                 push    0FFF1h          ; Msg
.text:260D40AF                 mov     ecx, [ebp+var_28]
.text:260D40B2                 mov     edx, [ecx+0Ch]
.text:260D40B5                 push    edx             ; hWnd
.text:260D40B6                 call    ds:SendMessageA    //发送消息FFF1H
.text:260D40BC                 test    eax, eax
.text:260D40BE                 jnz     short loc_260D40C7
.text:260D40C0                 xor     eax, eax
.text:260D40C2                 jmp     loc_260D43B5
.text:260D40C7
.text:260D40C7 loc_260D40C7:                           
.text:260D40C7                 mov     eax, [ebp+var_28]
.text:260D40CA                 mov     ecx, [eax+8]       //取第三组整数
.text:260D40CD                 push    ecx             ; lParam
.text:260D40CE                 push    0               ; wParam
.text:260D40D0                 push    0FFF2h          ; Msg
.text:260D40D5                 mov     edx, [ebp+var_28]
.text:260D40D8                 mov     eax, [edx+0Ch]
.text:260D40DB                 push    eax             ; hWnd
.text:260D40DC                 call    ds:SendMessageA   //发送消息FFF2H
.text:260D40E2                 test    eax, eax
.text:260D40E4                 jnz     short loc_260D40ED
.text:260D40E6                 xor     eax, eax
.text:260D40E8                 jmp     loc_260D43B5
.text:260D40ED
.text:260D40ED loc_260D40ED:                           
.text:260D40ED                 mov     ecx, [ebp+lParam] //用于取返回值
.text:260D40F0                 push    ecx             ; lParam
.text:260D40F1                 push    0               ; wParam
.text:260D40F3                 push    0FFF3h          ; Msg
.text:260D40F8                 mov     edx, [ebp+var_28]
.text:260D40FB                 mov     eax, [edx+0Ch]
.text:260D40FE                 push    eax             ; hWnd
.text:260D40FF                 call    ds:SendMessageA  //发送消息FFF3H
.text:260D4105                 jmp     loc_260D43B5
.text:260D410A

    这个是作者有意这样做的。其实处理消息的地方就在下面。

.text:260D410A loc_260D410A:                         
.text:260D410A                 mov     ecx, [ebp+var_28] //这里是上面那3个整数的数组,也可以看成3组4字节数组
.text:260D410D                 call    fun1_260D3940     //这个函数用于检查其中一组是否有重复字符,有返回1
.text:260D4112                 mov     esi, eax
.text:260D4114                 mov     ecx, [ebp+var_28]
.text:260D4117                 add     ecx, 4
.text:260D411A                 call    fun1_260D3940   
.text:260D411F                 add     esi, eax
.text:260D4121                 mov     ecx, [ebp+var_28]
.text:260D4124                 add     ecx, 8
.text:260D4127                 call    fun1_260D3940
.text:260D412C                 add     esi, eax
.text:260D412E                 cmp     esi, 1
.text:260D4131                 jz      short loc_260D413A //必须在其中一组里要有重复字符(只能一组)
.text:260D4133                 xor     eax, eax
.text:260D4135                 jmp     loc_260D43B5
.text:260D413A
.text:260D413A loc_260D413A:                           
.text:260D413A                 mov     ecx, [ebp+var_28]
.text:260D413D                 call    fun1_260D3940
.text:260D4142                 test    eax, eax
.text:260D4144                 jz      short loc_260D414D
.text:260D4146                 mov     [ebp+var_4], 0     //第一组有重复字符这里放0
.text:260D414D
.text:260D414D loc_260D414D:                           
.text:260D414D                 mov     ecx, [ebp+var_28]
.text:260D4150                 add     ecx, 4
.text:260D4153                 call    fun1_260D3940
.text:260D4158                 test    eax, eax
.text:260D415A                 jz      short loc_260D4163
.text:260D415C                 mov     [ebp+var_4], 1     //第二组有重复字符这里放1
.text:260D4163
.text:260D4163 loc_260D4163:                           
.text:260D4163                 mov     ecx, [ebp+var_28]
.text:260D4166                 add     ecx, 8
.text:260D4169                 call    fun1_260D3940
.text:260D416E                 test    eax, eax
.text:260D4170                 jz      short loc_260D4179
.text:260D4172                 mov     [ebp+var_4], 2     //第三组有重复字符这里放2
.text:260D4179
.text:260D4179 loc_260D4179:                           
.text:260D4179                 cmp     [ebp+lParam], 0
.text:260D417D                 jnz     short loc_260D41B5
.text:260D417F                 mov     ecx, [ebp+var_4]   //我们先假定这个变量为i
.text:260D4182                 mov     edx, [ebp+var_28]  //并且假定这个数组是unsigned int ci[3]
.text:260D4185                 lea     eax, [edx+ecx*4]   //取有重复字符那组
.text:260D4188                 mov     [ebp+var_8], eax
.text:260D418B                 mov     ecx, [ebp+var_8]
.text:260D418E                 xor     edx, edx
.text:260D4190                 mov     dl, [ecx+3]
.text:260D4193                 mov     eax, [ebp+var_8]
.text:260D4196                 xor     ecx, ecx
.text:260D4198                 mov     cl, [eax+2]
.text:260D419B                 mov     eax, [ebp+var_8]
.text:260D419E                 xor     ebx, ebx
.text:260D41A0                 mov     bl, [eax+1]
.text:260D41A3                 mov     esi, [ebp+var_8]
.text:260D41A6                 xor     eax, eax
.text:260D41A8                 mov     al, [esi]
.text:260D41AA                 add     eax, ebx
.text:260D41AC                 add     eax, ecx
.text:260D41AE                 add     eax, edx
.text:260D41B0                 mov     [ebp+lParam], eax  //重复的那组索引累加和要等于60h或者61h
.text:260D41B3                 jmp     short loc_260D41F2
.text:260D41B5
.text:260D41B5 loc_260D41B5:                          
.text:260D41B5                 mov     ecx, [ebp+var_4]
.text:260D41B8                 mov     edx, [ebp+var_28]
.text:260D41BB                 lea     eax, [edx+ecx*4]
.text:260D41BE                 mov     [ebp+var_C], eax
.text:260D41C1                 mov     ecx, [ebp+var_C]
.text:260D41C4                 xor     edx, edx
.text:260D41C6                 mov     dl, [ecx+3]
.text:260D41C9                 mov     eax, [ebp+var_C]
.text:260D41CC                 xor     ecx, ecx
.text:260D41CE                 mov     cl, [eax+2]
.text:260D41D1                 mov     eax, [ebp+var_C]
.text:260D41D4                 xor     ebx, ebx
.text:260D41D6                 mov     bl, [eax+1]
.text:260D41D9                 mov     esi, [ebp+var_C]
.text:260D41DC                 xor     eax, eax
.text:260D41DE                 mov     al, [esi]
.text:260D41E0                 add     eax, ebx
.text:260D41E2                 add     eax, ecx
.text:260D41E4                 add     eax, edx
.text:260D41E6                 cmp     eax, [ebp+lParam]
.text:260D41E9                 jz      short loc_260D41F2
.text:260D41EB                 xor     eax, eax
.text:260D41ED                 jmp     loc_260D43B5
.text:260D41F2
.text:260D41F2 loc_260D41F2:                           
.text:260D41F2                                         
.text:260D41F2                 mov     ecx, [ebp+lParam]
.text:260D41F5                 mov     [ebp+var_2C], ecx
.text:260D41F8                 cmp     [ebp+var_2C], 60h
.text:260D41FC                 jz      short loc_260D420D  //和等于60H跳
.text:260D41FE                 cmp     [ebp+var_2C], 61h
.text:260D4202                 jz      loc_260D42D7        //和等于61H跳
.text:260D4208                 jmp     loc_260D434C
.text:260D420D
.text:260D420D loc_260D420D:                           
.text:260D420D                 mov     eax, [ebp+var_4]  //和60H,
.text:260D4210                 add     eax, 1
.text:260D4213                 cdq
.text:260D4214                 mov     ecx, 3
.text:260D4219                 idiv    ecx
.text:260D421B                 mov     eax, [ebp+var_28]
.text:260D421E                 mov     eax, [eax+edx*4]  //i = (i + 1) % 3
.text:260D4221                 xor     edx, edx
.text:260D4223                 mov     ecx, 3
.text:260D4228                 div     ecx
.text:260D422A                 test    edx, edx          //ci[i] % 3 要等于 0
.text:260D422C                 jz      short loc_260D4235
.text:260D422E                 xor     eax, eax
.text:260D4230                 jmp     loc_260D43B5
.text:260D4235
.text:260D4235 loc_260D4235:                           
.text:260D4235                 mov     eax, [ebp+var_4]
.text:260D4238                 add     eax, 2
.text:260D423B                 cdq
.text:260D423C                 mov     ecx, 3
.text:260D4241                 idiv    ecx
.text:260D4243                 mov     eax, [ebp+var_28]
.text:260D4246                 mov     eax, [eax+edx*4]  //i = (i + 2) % 3
.text:260D4249                 xor     edx, edx
.text:260D424B                 mov     ecx, 3
.text:260D4250                 div     ecx
.text:260D4252                 test    edx, edx          //ci[i] % 3 要等于 0
.text:260D4254                 jz      short loc_260D425D
.text:260D4256                 xor     eax, eax
.text:260D4258                 jmp     loc_260D43B5
.text:260D425D
.text:260D425D loc_260D425D:                           
.text:260D425D                 mov     eax, [ebp+var_4]
.text:260D4260                 add     eax, 1
.text:260D4263                 cdq
.text:260D4264                 mov     ecx, 3
.text:260D4269                 idiv    ecx
.text:260D426B                 mov     eax, [ebp+var_28]
.text:260D426E                 mov     eax, [eax+edx*4] //i = (i + 1) % 3
.text:260D4271                 xor     edx, edx
.text:260D4273                 mov     ecx, 5
.text:260D4278                 div     ecx
.text:260D427A                 test    edx, edx         //ci[i] % 5 要等于 0 
.text:260D427C                 jz      short loc_260D4285
.text:260D427E                 xor     eax, eax
.text:260D4280                 jmp     loc_260D43B5
.text:260D4285
.text:260D4285 loc_260D4285:                           
.text:260D4285                 mov     eax, [ebp+var_4]
.text:260D4288                 add     eax, 2
.text:260D428B                 cdq
.text:260D428C                 mov     ecx, 3
.text:260D4291                 idiv    ecx
.text:260D4293                 mov     eax, [ebp+var_28]
.text:260D4296                 mov     eax, [eax+edx*4] //i = (i + 2) % 3
.text:260D4299                 xor     edx, edx
.text:260D429B                 mov     ecx, 5
.text:260D42A0                 div     ecx
.text:260D42A2                 test    edx, edx         //ci[i] % 5 要等于 0
.text:260D42A4                 jz      short loc_260D42AD
.text:260D42A6                 xor     eax, eax
.text:260D42A8                 jmp     loc_260D43B5
.text:260D42AD
.text:260D42AD loc_260D42AD:                           
.text:260D42AD                 mov     eax, [ebp+var_4]
.text:260D42B0                 add     eax, 2
.text:260D42B3                 cdq
.text:260D42B4                 mov     ecx, 3
.text:260D42B9                 idiv    ecx
.text:260D42BB                 mov     eax, [ebp+var_28]
.text:260D42BE                 mov     eax, [eax+edx*4] //i = (i + 2) % 3
.text:260D42C1                 xor     edx, edx
.text:260D42C3                 mov     ecx, 0Bh
.text:260D42C8                 div     ecx
.text:260D42CA                 test    edx, edx         //ci[i] % 11 要等于 0
.text:260D42CC                 jz      short loc_260D42D5
.text:260D42CE                 xor     eax, eax
.text:260D42D0                 jmp     loc_260D43B5
.text:260D42D5
.text:260D42D5 loc_260D42D5:                           
.text:260D42D5                 jmp     short loc_260D434C
.text:260D42D7
.text:260D42D7 loc_260D42D7:                           
.text:260D42D7                 mov     eax, [ebp+var_4]
.text:260D42DA                 add     eax, 1
.text:260D42DD                 cdq
.text:260D42DE                 mov     ecx, 3
.text:260D42E3                 idiv    ecx
.text:260D42E5                 mov     eax, [ebp+var_28]
.text:260D42E8                 mov     eax, [eax+edx*4] //i = (i + 1) % 3 
.text:260D42EB                 xor     edx, edx
.text:260D42ED                 mov     ecx, 3
.text:260D42F2                 div     ecx
.text:260D42F4                 test    edx, edx        //ci[i] % 3 要等于 0
.text:260D42F6                 jz      short loc_260D42FF
.text:260D42F8                 xor     eax, eax
.text:260D42FA                 jmp     loc_260D43B5
.text:260D42FF
.text:260D42FF loc_260D42FF:                           
.text:260D42FF                 mov     eax, [ebp+var_4]
.text:260D4302                 add     eax, 2
.text:260D4305                 cdq
.text:260D4306                 mov     ecx, 3
.text:260D430B                 idiv    ecx
.text:260D430D                 mov     eax, [ebp+var_28]
.text:260D4310                 mov     eax, [eax+edx*4] //i = (i + 2) % 3
.text:260D4313                 xor     edx, edx
.text:260D4315                 mov     ecx, 3
.text:260D431A                 div     ecx
.text:260D431C                 test    edx, edx         //ci[i] % 3 要等于 0
.text:260D431E                 jz      short loc_260D4327
.text:260D4320                 xor     eax, eax
.text:260D4322                 jmp     loc_260D43B5
.text:260D4327
.text:260D4327 loc_260D4327:                           
.text:260D4327                 mov     eax, [ebp+var_4]
.text:260D432A                 add     eax, 2
.text:260D432D                 cdq
.text:260D432E                 mov     ecx, 3
.text:260D4333                 idiv    ecx
.text:260D4335                 mov     eax, [ebp+var_28]
.text:260D4338                 mov     eax, [eax+edx*4] //i = (i + 2) % 3
.text:260D433B                 xor     edx, edx
.text:260D433D                 mov     ecx, 0Bh
.text:260D4342                 div     ecx
.text:260D4344                 test    edx, edx         //ci[i] % 11 要等于 0
.text:260D4346                 jz      short loc_260D434C
.text:260D4348                 xor     eax, eax
.text:260D434A                 jmp     short loc_260D43B5
.text:260D434C
.text:260D434C loc_260D434C:                           
.text:260D434C                                        
.text:260D434C                 mov     edx, [ebp+lParam]
.text:260D434F                 mov     [ebp+var_30], edx
.text:260D4352                 cmp     [ebp+var_30], 60h
.text:260D4356                 jb      short loc_260D4362
.text:260D4358                 cmp     [ebp+var_30], 61h
.text:260D435C                 jbe     short loc_260D4360
.text:260D435E                 jmp     short loc_260D4362
.text:260D4360
.text:260D4360 loc_260D4360:                          
.text:260D4360                 jmp     short loc_260D43B2
.text:260D4362
.text:260D4362 loc_260D4362:                          
.text:260D4362                                         
.text:260D4362                 mov     eax, [ebp+var_28]
.text:260D4365                 mov     ecx, [eax]
.text:260D4367                 mov     [ebp+var_10], ecx
.text:260D436A                 mov     edx, [ebp+var_28]
.text:260D436D                 mov     eax, [edx+4]
.text:260D4370                 mov     [ebp+var_14], eax
.text:260D4373                 mov     ecx, [ebp+var_10]
.text:260D4376                 cmp     ecx, [ebp+var_14]
.text:260D4379                 jz      short loc_260D43AE
.text:260D437B                 mov     edx, [ebp+var_28]
.text:260D437E                 mov     eax, [edx]
.text:260D4380                 mov     [ebp+var_18], eax
.text:260D4383                 mov     ecx, [ebp+var_28]
.text:260D4386                 mov     edx, [ecx+8]
.text:260D4389                 mov     [ebp+var_1C], edx
.text:260D438C                 mov     eax, [ebp+var_18]
.text:260D438F                 cmp     eax, [ebp+var_1C]
.text:260D4392                 jz      short loc_260D43AE
.text:260D4394                 mov     ecx, [ebp+var_28]
.text:260D4397                 mov     edx, [ecx+4]
.text:260D439A                 mov     [ebp+var_20], edx
.text:260D439D                 mov     eax, [ebp+var_28]
.text:260D43A0                 mov     ecx, [eax+8]
.text:260D43A3                 mov     [ebp+var_24], ecx
.text:260D43A6                 mov     edx, [ebp+var_20]
.text:260D43A9                 cmp     edx, [ebp+var_24]
.text:260D43AC                 jnz     short loc_260D43B2
.text:260D43AE
.text:260D43AE loc_260D43AE:                        
.text:260D43AE                                       
.text:260D43AE                 xor     eax, eax
.text:260D43B0                 jmp     short loc_260D43B5
.text:260D43B2
.text:260D43B2 loc_260D43B2:                          
.text:260D43B2                                         
.text:260D43B2                 mov     eax, [ebp+lParam]
.text:260D43B5
.text:260D43B5 loc_260D43B5:                           
.text:260D43B5                                        
.text:260D43B5                 pop     esi
.text:260D43B6                 pop     ebx
.text:260D43B7                 mov     esp, ebp
.text:260D43B9                 pop     ebp
.text:260D43BA                 retn    4
.text:260D43BA sub_260D405D    endp
  
    先总结一下:
    软件先把注册码查表转换成 unsigned int ci[3] 这个样子的一个数组。
    我们先把这个数组看成是unsigned char ci[3][4]这样子,要求其中有且只有
一组有重复字符。有重复字符那组的字符累加和要等于60h或者61h.
    如果和为60h,则要求满足下面条件:
    1. i = (i + 1) % 3 
       ci[i] % 3 要等于 0
   
    2. i = (i + 2) % 3
       ci[i] % 3 要等于 0
   
    3. i = (i + 1) % 3
       ci[i] % 5 要等于 0 
  
    4. i = (i + 2) % 3
       ci[i] % 5 要等于 0 

    5. i = (i + 2) % 3
       ci[i] % 11 要等于 0
       
    如果和为61h,则要求满足下面条件:
    1. i = (i + 1) % 3 
       ci[i] % 3 要等于 0
   
    2. i = (i + 2) % 3
       ci[i] % 3 要等于 0
   
    3. i = (i + 2) % 3
       ci[i] % 11 要等于 0
       
    这样真的可以吗?如果你构造一组注册码,它会提示你是以前版本的。:)
    我在上面有两个要注意的地方,再复制下来:
    
.text:26047041                 mov     eax, [ebp+var_C]
.text:26047044                 mov     ecx, [eax+0F0h]
.text:2604704A                 mov     edx, [ecx]          //这里是有重复字符那组的累加和
.text:2604704C                 cmp     edx, dword_261978BC //这个值是64h
.text:26047052                 jnz     short loc_26047075
.text:26047054                 mov     eax, [ebp+var_C]
.text:26047057                 xor     ecx, ecx
.text:26047059                 mov     cl, [eax+0F4h]  //这里是有重复字符的那组的索引
.text:2604705F                 and     ecx, 2          //屏蔽低2位
.text:26047062                 test    ecx, ecx
.text:26047064                 jz      short loc_26047075 //不能为0。这说明只能第三组注册码里有重复

    看到这里就明白了。有重复字符那组的累加和要等于64h,并且只能是第三组注册码。:)
    上面还有个CALL没有分析,在这个位置啦:
    
.text:2604EC0E                 push    ecx
.text:2604EC0F                 call    sub_2604E130         //这里先略过

    这个我没有去分析,猜测应该是不同协议类型的验证。等有时间再分析了。
    反正是老外的软件,最后给一组能用的注册码:CB5W-MK5S-JUUG
    注册名用你自己的就可以了。
    
    【全文完】