-----------------------------------------------------------------------(转载)----
【标题】【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 //这里先略过
这个我没有去分析,猜测应该是不同协议类型的验证。等有时间再分析了。