- UID
- 2198
注册时间2005-6-29
阅读权限255
最后登录1970-1-1
副坛主
该用户从未签到
|
【破文作者】 rdsnow[BCG][PYG][D.4s]
【作者主页】 http://rdsnow.ys168.com
【 E-mail 】 [email protected]
【 作者QQ 】 83757177
【文章题目】 HDNTV2005的算法分析
【软件名称】 雷神高清晰度网络电视3.55.5104
【下载地址】 http://hdntv.com/download/HDNTV.exe
----------------------------------------------------------------------------------------
【加密方式】 序列号
【破解工具】 ODbyDYK v1.10[05.09]
【软件限制】 功能限制
【破解平台】 Microsoft Windows Professional Server Pack 2
----------------------------------------------------------------------------------------
【软件简介】
您是否觉得有线电视节目太有限?身处异乡的您想看家乡的电视节目吗?身处办公室的您不想错过精彩赛事怎么办?如果您是宽带上网,通过HDNTV-高清晰数字网络电视软件,一切随心所欲。
特色功能:
1.采用了先进的多地址自动协调系统、先进的播放器加速引擎和智能链接技术,软件能够自动分析网络状态并自动配置最佳播放方案,从而为用户 提供最佳收看效果。
2.通过独特的数字网络电视和广播资源,四台独立服务器提供超过400套超高清晰的卫星电视节目, 包括中央电视台及各省卫星电视节目、凤凰卫视、CNN、BBC、ESPN、华娱、星空、TVB系列等节目。
3.电视节目由专业服务器收集提供,节目收看率极高。每周专人维护,定时更新最新电视节目。
4.纯绿色软件,不产生垃圾文件,不修改注册表。软件小巧,运行速度快,占用系统资源少。
5.全自动在线升级更新,无手动下载升级之麻烦。
----------------------------------------------------------------------------------------
【文章简介】
脱壳就不多说了:UPX 0.89.6 - 1.02 / 1.05 - 1.24 (Delphi) stub -> Markus & Laszlo的壳,可能作者修改了标志,用UPX -d脱不掉,ESP定律搞定。脱壳后Borland Delphi 6.0 - 7.0。
这个程序跟很多共享软件差不多,采用了流行的非明码比较,重启验证,分段式注册码。注册码跟用户名无关。
校验过程中用到了两个功能函数F1( )和F2( ),会在后面介绍。
其中F2( )中采用了128位数据运算。就是注释中的大数运算,^_^,具体情况跟进去看看吧!
----------------------------------------------------------------------------------------
【破解过程】
输入假码,启动监视程序,检测注册码存在安装目录下config.lss文件中,可用记事本查看:
[reg]
user=rdsnow[BCG][PYG][D.4s]
serial=123456789-7654321-8765432-9876543
『一』、字符串user,serial,config.lss等都是突破口,根据这些信息来到:
00504D9D 6A 00 PUSH 0
00504D9F 8D45 E0 LEA EAX,DWORD PTR SS:[EBP-20]
00504DA2 50 PUSH EAX
00504DA3 B9 704F5000 MOV ECX,Dump.00504F70 ; ASCII "user"
00504DA8 BA 804F5000 MOV EDX,Dump.00504F80 ; ASCII "reg"
00504DAD 8BC3 MOV EAX,EBX
00504DAF 8B30 MOV ESI,DWORD PTR DS:[EAX]
00504DB1 FF16 CALL NEAR DWORD PTR DS:[ESI] ; 取用户名user
00504DB3 8B55 E0 MOV EDX,DWORD PTR SS:[EBP-20]
00504DB6 B8 68F35300 MOV EAX,Dump.0053F368
00504DBB E8 2CF5EFFF CALL Dump.004042EC
00504DC0 6A 00 PUSH 0
00504DC2 8D45 DC LEA EAX,DWORD PTR SS:[EBP-24]
00504DC5 50 PUSH EAX
00504DC6 B9 8C4F5000 MOV ECX,Dump.00504F8C ; ASCII "serial"
00504DCB BA 804F5000 MOV EDX,Dump.00504F80 ; ASCII "reg"
00504DD0 8BC3 MOV EAX,EBX
00504DD2 8B30 MOV ESI,DWORD PTR DS:[EAX]
00504DD4 FF16 CALL NEAR DWORD PTR DS:[ESI] ; 取注册码serial
00504DD6 8B55 DC MOV EDX,DWORD PTR SS:[EBP-24]
00504DD9 B8 6CF35300 MOV EAX,Dump.0053F36C
00504DDE E8 09F5EFFF CALL Dump.004042EC
00504DE3 833D 6CF35300 0>CMP DWORD PTR DS:[53F36C],0 ; 判断取注册码是否成功
00504DEA 0F84 05010000 JE Dump.00504EF5
00504DF0 A1 6CF35300 MOV EAX,DWORD PTR DS:[53F36C]
00504DF5 E8 62090000 CALL Dump.0050575C ; 关键call,跟进
00504DFA A3 60F35300 MOV DWORD PTR DS:[53F360],EAX
00504DFF A1 60F35300 MOV EAX,DWORD PTR DS:[53F360] ; 取注册标志
00504E04 83E8 01 SUB EAX,1
00504E07 72 10 JB SHORT Dump.00504E19 ; 不是1或3小就跳向试用版
00504E09 74 35 JE SHORT Dump.00504E40 ; 注册标志是1,跳向标准版
00504E0B 83E8 02 SUB EAX,2
00504E0E 0F84 84000000 JE Dump.00504E98 ; 注册标志是3,跳向钻石版
00504E14 E9 D5000000 JMP Dump.00504EEE
00504E19 B9 704F5000 MOV ECX,Dump.00504F70 ; ASCII "user"
00504E1E BA 804F5000 MOV EDX,Dump.00504F80 ; ASCII "reg"
00504E23 8BC3 MOV EAX,EBX
00504E25 8B30 MOV ESI,DWORD PTR DS:[EAX]
00504E27 FF56 50 CALL NEAR DWORD PTR DS:[ESI+50]
00504E2A B9 8C4F5000 MOV ECX,Dump.00504F8C ; ASCII "serial"
00504E2F BA 804F5000 MOV EDX,Dump.00504F80 ; ASCII "reg"
00504E34 8BC3 MOV EAX,EBX
00504E36 8B30 MOV ESI,DWORD PTR DS:[EAX]
00504E38 FF56 50 CALL NEAR DWORD PTR DS:[ESI+50] ; 检验不成功就删除保存的注册信息
00504E3B E9 AE000000 JMP Dump.00504EEE
00504E40 A1 3CF35300 MOV EAX,DWORD PTR DS:[53F33C]
【小结】
关键Call的下面的几个跳转就是爆破点,[53F360]存放注册标志,不过跟进关键Call会发现还有防暴破的暗桩。
----------------------------------------------------------------------------------------
『二』、程序的主要验证部分(关键Call内)
不忙跟进关键Call,先把假码换成qoke]SGH-hd^VL@B-ie_WMAC-jf`XNBD
这个假码怎么得到的,要跟下去几步才知道。简介一下,程序首先会根据一些位置的字符做一些替换,然后再运用下面『三』中提到的解密函数F1( )对各段注册码的每个字符转换,转换后的字符一定要是数字,否则在将字符串转为十六进制数值时会发生异常,然后直接跳到试用版本。
可以先写一个F1( )的逆函数转换一下。具体情况参考『三』
上面的这个假码经过转化后会得到12345678-7654321-8765432-9876543
好了,现在跟进00504DF5 CALL Dump.0050575C,再跟进0050577D CALL Dump.00501E58
00501E58 55 PUSH EBP
00501E59 8BEC MOV EBP,ESP
00501E5B B9 18000000 MOV ECX,18
00501E60 6A 00 PUSH 0
00501E62 6A 00 PUSH 0
00501E64 49 DEC ECX
00501E65 ^ 75 F9 JNZ SHORT Dump.00501E60
00501E67 53 PUSH EBX
00501E68 56 PUSH ESI
00501E69 57 PUSH EDI
00501E6A 8945 FC MOV DWORD PTR SS:[EBP-4],EAX
00501E6D 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4]
00501E70 E8 E328F0FF CALL Dump.00404758
00501E75 33C0 XOR EAX,EAX
00501E77 55 PUSH EBP
00501E78 68 7B285000 PUSH Dump.0050287B
00501E7D 64:FF30 PUSH DWORD PTR FS:[EAX]
00501E80 64:8920 MOV DWORD PTR FS:[EAX],ESP
00501E83 33C0 XOR EAX,EAX
00501E85 8945 F8 MOV DWORD PTR SS:[EBP-8],EAX
00501E88 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4]
00501E8B E8 D826F0FF CALL Dump.00404568 ; 取注册码长度
00501E90 83F8 1E CMP EAX,1E ; 注册码的长度不小于30
00501E93 0F8C BC090000 JL Dump.00502855
00501E99 8B55 FC MOV EDX,DWORD PTR SS:[EBP-4]
00501E9C B8 94285000 MOV EAX,OFFSET <Dump."-">
00501EA1 E8 062AF0FF CALL Dump.004048AC ; 返回注册码中"-"的位置
00501EA6 85C0 TEST EAX,EAX
00501EA8 0F84 A7090000 JE Dump.00502855
00501EAE 33D2 XOR EDX,EDX
00501EB0 55 PUSH EBP
00501EB1 68 46285000 PUSH Dump.00502846
00501EB6 64:FF32 PUSH DWORD PTR FS:[EDX]
00501EB9 64:8922 MOV DWORD PTR FS:[EDX],ESP
00501EBC 8D45 E0 LEA EAX,DWORD PTR SS:[EBP-20]
00501EBF E8 D423F0FF CALL Dump.00404298
00501EC4 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4]
00501EC7 8078 04 41 CMP BYTE PTR DS:[EAX+4],41 ; 第5个字符是不是"A"
00501ECB 75 35 JNZ SHORT Dump.00501F02 ; 不是"A"就跳
00501ECD 8D45 DC LEA EAX,DWORD PTR SS:[EBP-24]
00501ED0 50 PUSH EAX
00501ED1 B9 05000000 MOV ECX,5
00501ED6 BA 01000000 MOV EDX,1
00501EDB 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4]
00501EDE E8 E528F0FF CALL Dump.004047C8 ; 取注册码的前5位
00501EE3 8B45 DC MOV EAX,DWORD PTR SS:[EBP-24]
00501EE6 8D55 EC LEA EDX,DWORD PTR SS:[EBP-14]
00501EE9 E8 1E6CF0FF CALL Dump.00408B0C ; 大写转小写
00501EEE 8D45 FC LEA EAX,DWORD PTR SS:[EBP-4]
00501EF1 B9 05000000 MOV ECX,5
00501EF6 BA 01000000 MOV EDX,1
00501EFB E8 0829F0FF CALL Dump.00404808
00501F00 EB 33 JMP SHORT Dump.00501F35
00501F02 8D45 D8 LEA EAX,DWORD PTR SS:[EBP-28] ; 注册码第5位不是"A"就跳到这里继续
00501F05 50 PUSH EAX
00501F06 B9 04000000 MOV ECX,4
00501F0B BA 01000000 MOV EDX,1
00501F10 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4]
00501F13 E8 B028F0FF CALL Dump.004047C8 ; 取注册码的前4位
00501F18 8B45 D8 MOV EAX,DWORD PTR SS:[EBP-28]
00501F1B 8D55 EC LEA EDX,DWORD PTR SS:[EBP-14]
00501F1E E8 E96BF0FF CALL Dump.00408B0C ; 大写转小写
00501F23 8D45 FC LEA EAX,DWORD PTR SS:[EBP-4]
00501F26 B9 04000000 MOV ECX,4
00501F2B BA 01000000 MOV EDX,1
00501F30 E8 D328F0FF CALL Dump.00404808
00501F35 8D45 FC LEA EAX,DWORD PTR SS:[EBP-4] ; 注册码前4位或前5位转小写后到这里继续
00501F38 8B4D FC MOV ECX,DWORD PTR SS:[EBP-4]
00501F3B 8B55 EC MOV EDX,DWORD PTR SS:[EBP-14]
00501F3E E8 7126F0FF CALL Dump.004045B4 ; 替换注册码的前4位或前5位为小写
00501F43 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4]
00501F46 0FB640 07 MOVZX EAX,BYTE PTR DS:[EAX+7] ; 注册码的第8位
00501F4A 83C0 BF ADD EAX,-41
00501F4D 83F8 19 CMP EAX,19
00501F50 0F87 DD000000 JA Dump.00502033 ; 第8位不是大写字母就跳
00501F56 8A80 631F5000 MOV AL,BYTE PTR DS:[EAX+501F63]
00501F5C FF2485 7D1F5000 JMP NEAR DWORD PTR DS:[EAX*4+501F>
00501F63 0102 ADD DWORD PTR DS:[EDX],EAX ; 这里不是指令
00501F65 030405 0608090A ADD EAX,DWORD PTR DS:[EAX+A090806>
00501F6C 0000 ADD BYTE PTR DS:[EAX],AL ; 而是26个byte
00501F6E 0000 ADD BYTE PTR DS:[EAX],AL
00501F70 0000 ADD BYTE PTR DS:[EAX],AL ; 用于替换注册码的第8位
00501F72 0000 ADD BYTE PTR DS:[EAX],AL
00501F74 0000 ADD BYTE PTR DS:[EAX],AL ; 对应了26个字母的替换表
00501F76 0000 ADD BYTE PTR DS:[EAX],AL
00501F78 0000 ADD BYTE PTR DS:[EAX],AL ; 0表示不替换
00501F7A 0000 ADD BYTE PTR DS:[EAX],AL
00501F7C 07 POP ES ; 替换表到这里结束
00501F7D 3320 XOR ESP,DWORD PTR DS:[EAX] ; 这里也不是指令
00501F7F 50 PUSH EAX
00501F80 00A9 1F5000B7 ADD BYTE PTR DS:[ECX+B700501F],CH ; 而是11个DWORD
00501F86 1F POP DS
00501F87 50 PUSH EAX ; 保存的是11个跳转地址
00501F88 00C5 ADD CH,AL
00501F8A 1F POP DS ; 第1个是不是A-J时的跳转地址
00501F8B 50 PUSH EAX
00501F8C 00D3 ADD BL,DL
00501F8E 1F POP DS
00501F8F 50 PUSH EAX ; 其他10个分别对应了A-J时的跳转地址
00501F90 00E1 ADD CL,AH
00501F92 1F POP DS
00501F93 50 PUSH EAX
00501F94 00EF ADD BH,CH
00501F96 1F POP DS ; 对应与注册码后几段的最后一个字符的替换
00501F97 50 PUSH EAX
00501F98 00FD ADD CH,BH
00501F9A 1F POP DS
00501F9B 50 PUSH EAX
00501F9C 000B ADD BYTE PTR DS:[EBX],CL
00501F9E 2050 00 AND BYTE PTR DS:[EAX],DL
00501FA1 1920 SBB DWORD PTR DS:[EAX],ESP
00501FA3 50 PUSH EAX ; 到这里11个DWORD结束
00501FA4 0027 ADD BYTE PTR DS:[EDI],AH
00501FA6 2050 00 AND BYTE PTR DS:[EAX],DL
00501FA9 8D45 FC LEA EAX,DWORD PTR SS:[EBP-4] ; 第8位是"A"就用"1"替换
00501FAC E8 0F28F0FF CALL Dump.004047C0
00501FB1 C640 07 31 MOV BYTE PTR DS:[EAX+7],31
00501FB5 EB 7C JMP SHORT Dump.00502033
00501FB7 8D45 FC LEA EAX,DWORD PTR SS:[EBP-4]
00501FBA E8 0128F0FF CALL Dump.004047C0
00501FBF C640 07 32 MOV BYTE PTR DS:[EAX+7],32 ; 第8位是"B"就用"2"替换
00501FC3 EB 6E JMP SHORT Dump.00502033
00501FC5 8D45 FC LEA EAX,DWORD PTR SS:[EBP-4]
00501FC8 E8 F327F0FF CALL Dump.004047C0
00501FCD C640 07 33 MOV BYTE PTR DS:[EAX+7],33 ; 第8位是"C"就用"3"替换
00501FD1 EB 60 JMP SHORT Dump.00502033
00501FD3 8D45 FC LEA EAX,DWORD PTR SS:[EBP-4]
00501FD6 E8 E527F0FF CALL Dump.004047C0
00501FDB C640 07 34 MOV BYTE PTR DS:[EAX+7],34 ; 第8位是"D"就用"4"替换
00501FDF EB 52 JMP SHORT Dump.00502033
00501FE1 8D45 FC LEA EAX,DWORD PTR SS:[EBP-4]
00501FE4 E8 D727F0FF CALL Dump.004047C0
00501FE9 C640 07 35 MOV BYTE PTR DS:[EAX+7],35 ; 第8位是"E"就用"5"替换
00501FED EB 44 JMP SHORT Dump.00502033
00501FEF 8D45 FC LEA EAX,DWORD PTR SS:[EBP-4]
00501FF2 E8 C927F0FF CALL Dump.004047C0
00501FF7 C640 07 36 MOV BYTE PTR DS:[EAX+7],36 ; 第8位是"F"就用"6"替换
00501FFB EB 36 JMP SHORT Dump.00502033
00501FFD 8D45 FC LEA EAX,DWORD PTR SS:[EBP-4]
00502000 E8 BB27F0FF CALL Dump.004047C0
00502005 C640 07 37 MOV BYTE PTR DS:[EAX+7],37 ; 第8位是"Z"就用"7"替换
00502009 EB 28 JMP SHORT Dump.00502033
0050200B 8D45 FC LEA EAX,DWORD PTR SS:[EBP-4]
0050200E E8 AD27F0FF CALL Dump.004047C0
00502013 C640 07 38 MOV BYTE PTR DS:[EAX+7],38 ; 第8位是"G"就用"8"替换
00502017 EB 1A JMP SHORT Dump.00502033
00502019 8D45 FC LEA EAX,DWORD PTR SS:[EBP-4]
0050201C E8 9F27F0FF CALL Dump.004047C0
00502021 C640 07 39 MOV BYTE PTR DS:[EAX+7],39 ; 第8位是"H"就用"9"替换
00502025 EB 0C JMP SHORT Dump.00502033
00502027 8D45 FC LEA EAX,DWORD PTR SS:[EBP-4] ; 第8位是"I"就用"0"替换
0050202A E8 9127F0FF CALL Dump.004047C0
0050202F C640 07 30 MOV BYTE PTR DS:[EAX+7],30
00502033 8D45 D4 LEA EAX,DWORD PTR SS:[EBP-2C] ; 第8位不是A-J或Z就不替换跳到这里继续
00502036 50 PUSH EAX
00502037 8B55 FC MOV EDX,DWORD PTR SS:[EBP-4]
0050203A B8 94285000 MOV EAX,OFFSET <Dump."-">
0050203F E8 6828F0FF CALL Dump.004048AC ; 返回注册码中"-"的位置
00502044 8BC8 MOV ECX,EAX
00502046 49 DEC ECX
00502047 BA 01000000 MOV EDX,1
0050204C 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4]
0050204F E8 7427F0FF CALL Dump.004047C8 ; 取注册码"-"前的部分
00502054 8B45 D4 MOV EAX,DWORD PTR SS:[EBP-2C]
00502057 8D55 E4 LEA EDX,DWORD PTR SS:[EBP-1C]
0050205A E8 21D6FFFF CALL Dump.004FF680 ; F1(Sn1)="12345678"
0050205F 8D45 D0 LEA EAX,DWORD PTR SS:[EBP-30]
00502062 50 PUSH EAX
00502063 B9 06000000 MOV ECX,6
00502068 BA 02000000 MOV EDX,2
0050206D 8B45 E4 MOV EAX,DWORD PTR SS:[EBP-1C]
00502070 E8 5327F0FF CALL Dump.004047C8 ; 取F1( )结果的2到7位"234567"
00502075 8B45 D0 MOV EAX,DWORD PTR SS:[EBP-30]
00502078 E8 7B73F0FF CALL Dump.004093F8 ; 字符串"234567"转为数值,X=234567
0050207D 8BF0 MOV ESI,EAX
0050207F 8B55 FC MOV EDX,DWORD PTR SS:[EBP-4]
00502082 B8 94285000 MOV EAX,OFFSET <Dump."-">
00502087 E8 2028F0FF CALL Dump.004048AC ; 返回注册码中"-"的位置
0050208C 8BC8 MOV ECX,EAX
0050208E 8D45 FC LEA EAX,DWORD PTR SS:[EBP-4]
00502091 BA 01000000 MOV EDX,1
00502096 E8 6D27F0FF CALL Dump.00404808 ; 取"-"后的字符串
0050209B 8D45 EC LEA EAX,DWORD PTR SS:[EBP-14]
0050209E 8B55 FC MOV EDX,DWORD PTR SS:[EBP-4]
005020A1 E8 8A22F0FF CALL Dump.00404330 ; ?
005020A6 E9 B9010000 JMP Dump.00502264
005020AB 8D45 E8 LEA EAX,DWORD PTR SS:[EBP-18] ; 如果后面还有"-",就从这里继续循环
005020AE 50 PUSH EAX
005020AF 8B55 EC MOV EDX,DWORD PTR SS:[EBP-14]
005020B2 B8 94285000 MOV EAX,OFFSET <Dump."-">
005020B7 E8 F027F0FF CALL Dump.004048AC ; 返回注册码中"-"的位置
005020BC 8BC8 MOV ECX,EAX
005020BE 49 DEC ECX
005020BF BA 01000000 MOV EDX,1
005020C4 8B45 EC MOV EAX,DWORD PTR SS:[EBP-14]
005020C7 E8 FC26F0FF CALL Dump.004047C8 ; 取"-"前的字符串
005020CC 8B45 E8 MOV EAX,DWORD PTR SS:[EBP-18]
005020CF E8 9424F0FF CALL Dump.00404568 ; 取字符串长度
005020D4 8BD8 MOV EBX,EAX
005020D6 8BFB MOV EDI,EBX
005020D8 81E7 FF000000 AND EDI,0FF
005020DE 8B45 E8 MOV EAX,DWORD PTR SS:[EBP-18]
005020E1 0FB64438 FF MOVZX EAX,BYTE PTR DS:[EAX+EDI-1] ; 取得最后一位
005020E6 83C0 BF ADD EAX,-41
005020E9 83F8 09 CMP EAX,9
005020EC 0F87 C6000000 JA Dump.005021B8 ; 不是A-J就跳
005020F2 FF2485 F9205000 JMP NEAR DWORD PTR DS:[EAX*4+5020>
005020F9 2121 AND DWORD PTR DS:[ECX],ESP
005020FB 50 PUSH EAX
005020FC 0033 ADD BYTE PTR DS:[EBX],DH
005020FE 2150 00 AND DWORD PTR DS:[EAX],EDX
00502101 42 INC EDX
00502102 2150 00 AND DWORD PTR DS:[EAX],EDX
00502105 51 PUSH ECX
00502106 2150 00 AND DWORD PTR DS:[EAX],EDX
00502109 60 PUSHAD
0050210A 2150 00 AND DWORD PTR DS:[EAX],EDX
0050210D 6F OUTS DX,DWORD PTR ES:[EDI]
0050210E 2150 00 AND DWORD PTR DS:[EAX],EDX
00502111 7E 21 JLE SHORT Dump.00502134
00502113 50 PUSH EAX
00502114 008D 2150009C ADD BYTE PTR SS:[EBP+9C005021],CL
0050211A 2150 00 AND DWORD PTR DS:[EAX],EDX
0050211D AB STOS DWORD PTR ES:[EDI]
0050211E 2150 00 AND DWORD PTR DS:[EAX],EDX
00502121 8D45 E8 LEA EAX,DWORD PTR SS:[EBP-18]
00502124 E8 9726F0FF CALL Dump.004047C0
00502129 C64438 FF 31 MOV BYTE PTR DS:[EAX+EDI-1],31 ; 最后一位是"A"用"1"替换
0050212E E9 85000000 JMP Dump.005021B8
00502133 8D45 E8 LEA EAX,DWORD PTR SS:[EBP-18]
00502136 E8 8526F0FF CALL Dump.004047C0
0050213B C64438 FF 32 MOV BYTE PTR DS:[EAX+EDI-1],32 ; 最后一位是"B"用"2"替换
00502140 EB 76 JMP SHORT Dump.005021B8
00502142 8D45 E8 LEA EAX,DWORD PTR SS:[EBP-18]
00502145 E8 7626F0FF CALL Dump.004047C0
0050214A C64438 FF 33 MOV BYTE PTR DS:[EAX+EDI-1],33 ; 最后一位是"C"用"3"替换
0050214F EB 67 JMP SHORT Dump.005021B8
00502151 8D45 E8 LEA EAX,DWORD PTR SS:[EBP-18]
00502154 E8 6726F0FF CALL Dump.004047C0
00502159 C64438 FF 34 MOV BYTE PTR DS:[EAX+EDI-1],34 ; 最后一位是"D"用"4"替换
0050215E EB 58 JMP SHORT Dump.005021B8
00502160 8D45 E8 LEA EAX,DWORD PTR SS:[EBP-18]
00502163 E8 5826F0FF CALL Dump.004047C0
00502168 C64438 FF 35 MOV BYTE PTR DS:[EAX+EDI-1],35 ; 最后一位是"E"用"5"替换
0050216D EB 49 JMP SHORT Dump.005021B8
0050216F 8D45 E8 LEA EAX,DWORD PTR SS:[EBP-18]
00502172 E8 4926F0FF CALL Dump.004047C0
00502177 C64438 FF 36 MOV BYTE PTR DS:[EAX+EDI-1],36 ; 最后一位是"F"用"6"替换
0050217C EB 3A JMP SHORT Dump.005021B8
0050217E 8D45 E8 LEA EAX,DWORD PTR SS:[EBP-18]
00502181 E8 3A26F0FF CALL Dump.004047C0
00502186 C64438 FF 37 MOV BYTE PTR DS:[EAX+EDI-1],37 ; 最后一位是"G"用"7"替换
0050218B EB 2B JMP SHORT Dump.005021B8
0050218D 8D45 E8 LEA EAX,DWORD PTR SS:[EBP-18]
00502190 E8 2B26F0FF CALL Dump.004047C0
00502195 C64438 FF 38 MOV BYTE PTR DS:[EAX+EDI-1],38 ; 最后一位是"H"用"8"替换
0050219A EB 1C JMP SHORT Dump.005021B8
0050219C 8D45 E8 LEA EAX,DWORD PTR SS:[EBP-18]
0050219F E8 1C26F0FF CALL Dump.004047C0
005021A4 C64438 FF 39 MOV BYTE PTR DS:[EAX+EDI-1],39 ; 最后一位是"I"用"9"替换
005021A9 EB 0D JMP SHORT Dump.005021B8
005021AB 8D45 E8 LEA EAX,DWORD PTR SS:[EBP-18]
005021AE E8 0D26F0FF CALL Dump.004047C0
005021B3 C64438 FF 30 MOV BYTE PTR DS:[EAX+EDI-1],30 ; 最后一位是"J"用"0"替换
005021B8 8D55 CC LEA EDX,DWORD PTR SS:[EBP-34] ; 最后一位不是A-J就不替换,跳到这里继续
005021BB 8B45 E8 MOV EAX,DWORD PTR SS:[EBP-18]
005021BE E8 BDD4FFFF CALL Dump.004FF680 ; F1(Sni),(i从2到4)
005021C3 8B55 CC MOV EDX,DWORD PTR SS:[EBP-34]
005021C6 8D45 E8 LEA EAX,DWORD PTR SS:[EBP-18]
005021C9 E8 6221F0FF CALL Dump.00404330 ; ?
005021CE 8B45 E8 MOV EAX,DWORD PTR SS:[EBP-18]
005021D1 E8 9672F0FF CALL Dump.0040946C ; 数字字符串转成数据
005021D6 52 PUSH EDX
005021D7 50 PUSH EAX
005021D8 8BC6 MOV EAX,ESI
005021DA 99 CDQ
005021DB 290424 SUB DWORD PTR SS:[ESP],EAX ; 扩展为64位,减去X,结果设为a
005021DE 195424 04 SBB DWORD PTR SS:[ESP+4],EDX ; 扩展是为了准备参与下面的大数运算
005021E2 58 POP EAX
005021E3 5A POP EDX
005021E4 8945 F0 MOV DWORD PTR SS:[EBP-10],EAX
005021E7 8955 F4 MOV DWORD PTR SS:[EBP-C],EDX
005021EA 8B55 EC MOV EDX,DWORD PTR SS:[EBP-14]
005021ED B8 94285000 MOV EAX,OFFSET <Dump."-">
005021F2 E8 B526F0FF CALL Dump.004048AC ; 返回注册码中"-"的位置
005021F7 8BC8 MOV ECX,EAX
005021F9 8D45 EC LEA EAX,DWORD PTR SS:[EBP-14]
005021FC BA 01000000 MOV EDX,1
00502201 E8 0226F0FF CALL Dump.00404808 ; 取"-"后的字符串
00502206 FF75 F4 PUSH DWORD PTR SS:[EBP-C]
00502209 FF75 F0 PUSH DWORD PTR SS:[EBP-10]
0050220C FF35 44F35300 PUSH DWORD PTR DS:[53F344]
00502212 FF35 40F35300 PUSH DWORD PTR DS:[53F340]
00502218 FF35 4CF35300 PUSH DWORD PTR DS:[53F34C]
0050221E FF35 48F35300 PUSH DWORD PTR DS:[53F348] ; 取运算次数0x1385B
00502224 E8 1BEFFFFF CALL Dump.00501144 ; a=F2(a),跟进分析实际上是a的0x1385B次方%0x8908D
00502229 8945 F0 MOV DWORD PTR SS:[EBP-10],EAX
0050222C 8955 F4 MOV DWORD PTR SS:[EBP-C],EDX
0050222F FF75 F4 PUSH DWORD PTR SS:[EBP-C]
00502232 FF75 F0 PUSH DWORD PTR SS:[EBP-10]
00502235 8D45 C8 LEA EAX,DWORD PTR SS:[EBP-38]
00502238 E8 6B71F0FF CALL Dump.004093A8 ; 结果转十进制字符串
0050223D 8B55 C8 MOV EDX,DWORD PTR SS:[EBP-38]
00502240 8D45 E0 LEA EAX,DWORD PTR SS:[EBP-20]
00502243 E8 2823F0FF CALL Dump.00404570 ; a=与上轮得到的a相连
00502248 8B55 E4 MOV EDX,DWORD PTR SS:[EBP-1C]
0050224B 8B45 E0 MOV EAX,DWORD PTR SS:[EBP-20]
0050224E E8 5926F0FF CALL Dump.004048AC ; F1(Sn1)中有没有上面得到的字符串a
00502253 85C0 TEST EAX,EAX
00502255 75 0D JNZ SHORT Dump.00502264 ; 有就跳下继续
00502257 33C0 XOR EAX,EAX
00502259 5A POP EDX
0050225A 59 POP ECX
0050225B 59 POP ECX
0050225C 64:8910 MOV DWORD PTR FS:[EAX],EDX
0050225F E9 F1050000 JMP Dump.00502855 ; 没有就跳向试用版
00502264 8B55 EC MOV EDX,DWORD PTR SS:[EBP-14]
00502267 B8 94285000 MOV EAX,OFFSET <Dump."-">
0050226C E8 3B26F0FF CALL Dump.004048AC ; 返回注册码中"-"的位置
00502271 85C0 TEST EAX,EAX
00502273 ^ 0F8F 32FEFFFF JG Dump.005020AB ; 判断字符串中还有没有"-",有就跳上去循环
00502279 8B45 EC MOV EAX,DWORD PTR SS:[EBP-14]
0050227C E8 E722F0FF CALL Dump.00404568 ; 取字符串长度
00502281 85C0 TEST EAX,EAX
00502283 0F84 8C050000 JE Dump.00502815
00502289 8B45 EC MOV EAX,DWORD PTR SS:[EBP-14]
0050228C E8 D722F0FF CALL Dump.00404568 ; 取字符串长度
00502291 8BD8 MOV EBX,EAX
00502293 8BFB MOV EDI,EBX
00502295 81E7 FF000000 AND EDI,0FF
0050229B 8B45 EC MOV EAX,DWORD PTR SS:[EBP-14]
0050229E 0FB64438 FF MOVZX EAX,BYTE PTR DS:[EAX+EDI-1] ; 取得字符串的最后一位
005022A3 83C0 BF ADD EAX,-41
005022A6 83F8 09 CMP EAX,9
005022A9 0F87 C6000000 JA Dump.00502375 ; 不是A-J就跳
005022AF FF2485 B6225000 JMP NEAR DWORD PTR DS:[EAX*4+5022>
005022B6 DE22 FISUB WORD PTR DS:[EDX]
005022B8 50 PUSH EAX
005022B9 00F0 ADD AL,DH
005022BB 2250 00 AND DL,BYTE PTR DS:[EAX]
005022BE FF22 JMP NEAR DWORD PTR DS:[EDX]
005022C0 50 PUSH EAX
005022C1 000E ADD BYTE PTR DS:[ESI],CL
005022C3 2350 00 AND EDX,DWORD PTR DS:[EAX]
005022C6 1D 2350002C SBB EAX,2C005023
005022CB 2350 00 AND EDX,DWORD PTR DS:[EAX]
005022CE 3B23 CMP ESP,DWORD PTR DS:[EBX]
005022D0 50 PUSH EAX
005022D1 004A 23 ADD BYTE PTR DS:[EDX+23],CL
005022D4 50 PUSH EAX
005022D5 0059 23 ADD BYTE PTR DS:[ECX+23],BL
005022D8 50 PUSH EAX
005022D9 0068 23 ADD BYTE PTR DS:[EAX+23],CH
005022DC 50 PUSH EAX
005022DD 008D 45ECE8DA ADD BYTE PTR SS:[EBP+DAE8EC45],CL
005022E3 24 F0 AND AL,0F0
005022E5 FFC6 INC ESI
005022E7 44 INC ESP
005022E8 38FF CMP BH,BH
005022EA 31E9 XOR ECX,EBP
005022EC 8500 TEST DWORD PTR DS:[EAX],EAX
005022EE 0000 ADD BYTE PTR DS:[EAX],AL
005022F0 8D45 EC LEA EAX,DWORD PTR SS:[EBP-14]
005022F3 E8 C824F0FF CALL Dump.004047C0
005022F8 C64438 FF 32 MOV BYTE PTR DS:[EAX+EDI-1],32 ; 最后一位是"B"用"2"替换
005022FD EB 76 JMP SHORT Dump.00502375
005022FF 8D45 EC LEA EAX,DWORD PTR SS:[EBP-14]
00502302 E8 B924F0FF CALL Dump.004047C0
00502307 C64438 FF 33 MOV BYTE PTR DS:[EAX+EDI-1],33 ; 最后一位是"C"用"3"替换
0050230C EB 67 JMP SHORT Dump.00502375
0050230E 8D45 EC LEA EAX,DWORD PTR SS:[EBP-14]
00502311 E8 AA24F0FF CALL Dump.004047C0
00502316 C64438 FF 34 MOV BYTE PTR DS:[EAX+EDI-1],34 ; 最后一位是"D"用"4"替换
0050231B EB 58 JMP SHORT Dump.00502375
0050231D 8D45 EC LEA EAX,DWORD PTR SS:[EBP-14]
00502320 E8 9B24F0FF CALL Dump.004047C0
00502325 C64438 FF 35 MOV BYTE PTR DS:[EAX+EDI-1],35 ; 最后一位是"E"用"5"替换
0050232A EB 49 JMP SHORT Dump.00502375
0050232C 8D45 EC LEA EAX,DWORD PTR SS:[EBP-14]
0050232F E8 8C24F0FF CALL Dump.004047C0
00502334 C64438 FF 36 MOV BYTE PTR DS:[EAX+EDI-1],36 ; 最后一位是"F"用"6"替换
00502339 EB 3A JMP SHORT Dump.00502375
0050233B 8D45 EC LEA EAX,DWORD PTR SS:[EBP-14]
0050233E E8 7D24F0FF CALL Dump.004047C0
00502343 C64438 FF 37 MOV BYTE PTR DS:[EAX+EDI-1],37 ; 最后一位是"G"用"7"替换
00502348 EB 2B JMP SHORT Dump.00502375
0050234A 8D45 EC LEA EAX,DWORD PTR SS:[EBP-14]
0050234D E8 6E24F0FF CALL Dump.004047C0
00502352 C64438 FF 38 MOV BYTE PTR DS:[EAX+EDI-1],38 ; 最后一位是"H"用"8"替换
00502357 EB 1C JMP SHORT Dump.00502375
00502359 8D45 EC LEA EAX,DWORD PTR SS:[EBP-14]
0050235C E8 5F24F0FF CALL Dump.004047C0
00502361 C64438 FF 39 MOV BYTE PTR DS:[EAX+EDI-1],39 ; 最后一位是"I"用"9"替换
00502366 EB 0D JMP SHORT Dump.00502375
00502368 8D45 EC LEA EAX,DWORD PTR SS:[EBP-14]
0050236B E8 5024F0FF CALL Dump.004047C0
00502370 C64438 FF 30 MOV BYTE PTR DS:[EAX+EDI-1],30 ; 最后一位是"J"用"0"替换
00502375 8D55 C4 LEA EDX,DWORD PTR SS:[EBP-3C]
00502378 8B45 EC MOV EAX,DWORD PTR SS:[EBP-14]
0050237B E8 00D3FFFF CALL Dump.004FF680 ; F1( )
00502380 8B55 C4 MOV EDX,DWORD PTR SS:[EBP-3C]
00502383 8D45 EC LEA EAX,DWORD PTR SS:[EBP-14]
00502386 E8 A51FF0FF CALL Dump.00404330 ; ?
0050238B 8B45 EC MOV EAX,DWORD PTR SS:[EBP-14]
0050238E E8 D970F0FF CALL Dump.0040946C ; 十进制字符串转十六进制数据
00502393 52 PUSH EDX
00502394 50 PUSH EAX
00502395 8BC6 MOV EAX,ESI
00502397 99 CDQ
00502398 290424 SUB DWORD PTR SS:[ESP],EAX ; 扩展为64位,减去X,结果设为a
0050239B 195424 04 SBB DWORD PTR SS:[ESP+4],EDX ; 扩展是为了准备参与下面的大数运算
0050239F 58 POP EAX
005023A0 5A POP EDX
005023A1 8945 F0 MOV DWORD PTR SS:[EBP-10],EAX
005023A4 8955 F4 MOV DWORD PTR SS:[EBP-C],EDX
005023A7 A0 ACF35300 MOV AL,BYTE PTR DS:[53F3AC]
005023AC FEC8 DEC AL
005023AE 74 0D JE SHORT Dump.005023BD
005023B0 FEC8 DEC AL
005023B2 0F84 DA000000 JE Dump.00502492
005023B8 E9 AA010000 JMP Dump.00502567
005023BD 8D55 C0 LEA EDX,DWORD PTR SS:[EBP-40]
005023C0 B8 A0285000 MOV EAX,Dump.005028A0
005023C5 E8 B6D2FFFF CALL Dump.004FF680 ; F1( ),解密一些字符串
………………(这里实际是释放一些网络电视的链接地址,有很多,就省略了)
00502637 8D95 64FFFFFF LEA EDX,DWORD PTR SS:[EBP-9C]
0050263D B8 14295000 MOV EAX,Dump.00502914
00502642 E8 39D0FFFF CALL Dump.004FF680 ; F1( ),解密一些字符串
00502647 FFB5 64FFFFFF PUSH DWORD PTR SS:[EBP-9C]
0050264D 68 D8285000 PUSH Dump.005028D8
00502652 B8 A4F35300 MOV EAX,Dump.0053F3A4
00502657 BA 03000000 MOV EDX,3
0050265C E8 C71FF0FF CALL Dump.00404628
00502661 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4] ; 下面就是一个防止爆破的暗桩
00502664 E8 FF1EF0FF CALL Dump.00404568 ; 取注册码长度
00502669 85C0 TEST EAX,EAX
0050266B 0F8E 43010000 JLE Dump.005027B4
00502671 BB 01000000 MOV EBX,1
00502676 8B55 FC MOV EDX,DWORD PTR SS:[EBP-4] ; 开始循环
00502679 8A541A FF MOV DL,BYTE PTR DS:[EDX+EBX-1] ; 取注册码的ASCII
0050267D 80EA 2D SUB DL,2D ; ASCII-0x2D
00502680 0F84 26010000 JE Dump.005027AC ; 是"-"就跳
00502686 80C2 FD ADD DL,0FD
00502689 80EA 0A SUB DL,0A
0050268C 0F82 1A010000 JB Dump.005027AC ; 是数字就跳
00502692 80C2 F9 ADD DL,0F9
00502695 80EA 1A SUB DL,1A
00502698 0F82 0E010000 JB Dump.005027AC ; 是大写字母就跳
0050269E 80C2 FA ADD DL,0FA
005026A1 80EA 1A SUB DL,1A
005026A4 0F82 02010000 JB Dump.005027AC ; 是小写字母就跳
005026AA 8D95 60FFFFFF LEA EDX,DWORD PTR SS:[EBP-A0] ; 注册码中出现上述字符外的其他字符
005026B0 B8 A0285000 MOV EAX,Dump.005028A0 ; 才会跳到下面继续解压字符
005026B5 E8 C6CFFFFF CALL Dump.004FF680 ; F1( ),解密一些字符串
005026BA FFB5 60FFFFFF PUSH DWORD PTR SS:[EBP-A0]
005026C0 8D95 5CFFFFFF LEA EDX,DWORD PTR SS:[EBP-A4]
005026C6 B8 68295000 MOV EAX,Dump.00502968
005026CB E8 B0CFFFFF CALL Dump.004FF680 ; F1( ),解密一些字符串
………………(这里实际是释放一些网络电视的链接地址,有很多,就省略了)
………………(如注册码全是字母,数字和"-",就不释放下面一些链接地址造成网络电视无法正常播放)
………………(如果爆破时忽略这里,即使暴成钻石版,功能依然不全)
0050277A FFB5 48FFFFFF PUSH DWORD PTR SS:[EBP-B8]
00502780 8D95 44FFFFFF LEA EDX,DWORD PTR SS:[EBP-BC]
00502786 B8 B0295000 MOV EAX,Dump.005029B0
0050278B E8 F0CEFFFF CALL Dump.004FF680 ; F1( ),解密一些字符串
00502790 FFB5 44FFFFFF PUSH DWORD PTR SS:[EBP-BC]
00502796 68 D8285000 PUSH Dump.005028D8
0050279B B8 A4F35300 MOV EAX,Dump.0053F3A4
005027A0 BA 03000000 MOV EDX,3
005027A5 E8 7E1EF0FF CALL Dump.00404628
005027AA EB 08 JMP SHORT Dump.005027B4
005027AC 43 INC EBX
005027AD 48 DEC EAX
005027AE ^ 0F85 C2FEFFFF JNZ Dump.00502676
005027B4 FF75 F4 PUSH DWORD PTR SS:[EBP-C]
005027B7 FF75 F0 PUSH DWORD PTR SS:[EBP-10]
005027BA FF35 44F35300 PUSH DWORD PTR DS:[53F344]
005027C0 FF35 40F35300 PUSH DWORD PTR DS:[53F340]
005027C6 FF35 4CF35300 PUSH DWORD PTR DS:[53F34C]
005027CC FF35 48F35300 PUSH DWORD PTR DS:[53F348]
005027D2 E8 6DE9FFFF CALL Dump.00501144 ; a=F2(a),大数运算
005027D7 8945 F0 MOV DWORD PTR SS:[EBP-10],EAX
005027DA 8955 F4 MOV DWORD PTR SS:[EBP-C],EDX
005027DD FF75 F4 PUSH DWORD PTR SS:[EBP-C]
005027E0 FF75 F0 PUSH DWORD PTR SS:[EBP-10]
005027E3 8D85 40FFFFFF LEA EAX,DWORD PTR SS:[EBP-C0]
005027E9 E8 BA6BF0FF CALL Dump.004093A8 ; 结果转十进制字符串
005027EE 8B95 40FFFFFF MOV EDX,DWORD PTR SS:[EBP-C0]
005027F4 8D45 E0 LEA EAX,DWORD PTR SS:[EBP-20]
005027F7 E8 741DF0FF CALL Dump.00404570 ; a=与前面得到的a连接
005027FC 8B55 E4 MOV EDX,DWORD PTR SS:[EBP-1C]
005027FF 8B45 E0 MOV EAX,DWORD PTR SS:[EBP-20]
00502802 E8 A520F0FF CALL Dump.004048AC ; F1(Sn1)中有没有上面得到的字符串a
00502807 85C0 TEST EAX,EAX
00502809 75 0A JNZ SHORT Dump.00502815 ; 有就跳向标准版本或钻石版
0050280B 33C0 XOR EAX,EAX
0050280D 5A POP EDX
0050280E 59 POP ECX
0050280F 59 POP ECX
00502810 64:8910 MOV DWORD PTR FS:[EAX],EDX
00502813 EB 40 JMP SHORT Dump.00502855 ; 没有就跳向试用版
00502815 8B45 E0 MOV EAX,DWORD PTR SS:[EBP-20] ; 取得连接得到的a
00502818 8B55 E4 MOV EDX,DWORD PTR SS:[EBP-1C] ; 取F1(Sn1)
0050281B E8 941EF0FF CALL Dump.004046B4 ; 比较是否相同
00502820 75 1A JNZ SHORT Dump.0050283C ; 不相同跳向试用版
00502822 8B45 E4 MOV EAX,DWORD PTR SS:[EBP-1C]
00502825 8A40 07 MOV AL,BYTE PTR DS:[EAX+7] ; F(Sn1)的第8位
00502828 2C 36 SUB AL,36
0050282A 75 09 JNZ SHORT Dump.00502835 ; 不是"6"就跳向标准版
0050282C C745 F8 0300000>MOV DWORD PTR SS:[EBP-8],3 ; 返回3,钻石版
00502833 EB 07 JMP SHORT Dump.0050283C
00502835 C745 F8 0100000>MOV DWORD PTR SS:[EBP-8],1 ; 返回1,标准版
0050283C 33C0 XOR EAX,EAX
0050283E 5A POP EDX
0050283F 59 POP ECX
00502840 59 POP ECX
00502841 64:8910 MOV DWORD PTR FS:[EAX],EDX
00502844 EB 0F JMP SHORT Dump.00502855
00502846 ^ E9 DD10F0FF JMP Dump.00403928
0050284B 33C0 XOR EAX,EAX
0050284D 8945 F8 MOV DWORD PTR SS:[EBP-8],EAX
00502850 E8 3B14F0FF CALL Dump.00403C90
00502855 33C0 XOR EAX,EAX ; 不经过50282C或502835直接跳到这里就返回0
00502857 5A POP EDX
00502858 59 POP ECX
00502859 59 POP ECX
0050285A 64:8910 MOV DWORD PTR FS:[EAX],EDX
0050285D 68 82285000 PUSH Dump.00502882
00502862 8D85 40FFFFFF LEA EAX,DWORD PTR SS:[EBP-C0]
00502868 BA 2C000000 MOV EDX,2C
0050286D E8 4A1AF0FF CALL Dump.004042BC
00502872 8D45 FC LEA EAX,DWORD PTR SS:[EBP-4]
00502875 E8 1E1AF0FF CALL Dump.00404298
0050287A C3 RETN
【小结】
因为程序中的跳转比较多,跳转比较远,再加上偶的表达能力很烂,注释写的太乱了,下面把校验流程重写一下了:
注册码不低于30位,分几段,每段长度都没有要求,但是如果一段长度大于8,写F1( )的逆函数会麻烦一些,所以我就分成四段了!
首先将四段假码qoke]SGH-hd^VL@B-ie_WMAC-jf`XNBD的一些位置的字符替换
如果第一段的第5位是"A",第一段的第8位,第2、3、4段的最后一位如果是大写字符,就会进行替换,具体看注释
然后用F1( )转换一下得到12345678-7654321-8765432-9876543
取第一段"12345678"的2到7位"234567"转成数值X(如果转换时有字符不是数字当然会出错)
第二段"7654321"转成数值7654321,然后 F2(7654321-X)=28920,再转成字符串"282920"
第三段"8765432"转成数值8765432,然后 F2(8765432-X)=267072,再转成字符串"267072"
第四段"9876543"转成数值9876543,然后 F2(9876543-X)=336652,再转成字符串"336652"
将上面三个结果连接得到"282920267072336652"再跟第一段"12345678"比较是否相同。
不同就是试用版,相同但第一段的第八位不是"6"则是标准版,是"6"则是钻石版
另外:00502661——005026A4这段代码中有很多跳转,下面的解密一些字符串,其实是释放出一些网络电视的链接地址,如果没有注册码或注册码全是数字,字符,"-"而没有其他字符,就不释放这些链接地址,那么电视当让不能观看。
偶把他解释成防止爆破的暗桩,因为爆破一般是修改跳转或者注册标志,没有注册码或注册码是随意的一些字符数字,不释放出链接地址,即使爆破成钻石版,也看不到网络电视。
----------------------------------------------------------------------------------------
『三』、程序中多次用到的解密函数,即注释中的F1( )
跟进005021BE CALL Dump.004FF680 走几步来到:
004FF6B5 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4]
004FF6B8 E8 AB4EF0FF CALL Dump.00404568 ; 取字符串长度:Len
004FF6BD 8BF0 MOV ESI,EAX
004FF6BF 8BFE MOV EDI,ESI
004FF6C1 85FF TEST EDI,EDI
004FF6C3 7E 36 JLE SHORT Dump.004FF6FB
004FF6C5 BB 01000000 MOV EBX,1
004FF6CA 8BC6 MOV EAX,ESI ; 循环开始
004FF6CC F7EE IMUL ESI ; 字符串长度的平方
004FF6CE 8BD3 MOV EDX,EBX
004FF6D0 0FAFD3 IMUL EDX,EBX ; i的平方
004FF6D3 2BC2 SUB EAX,EDX ; 两个平方结果相减
004FF6D5 40 INC EAX ; 加1
004FF6D6 8945 F4 MOV DWORD PTR SS:[EBP-C],EAX
004FF6D9 8D45 EC LEA EAX,DWORD PTR SS:[EBP-14]
004FF6DC 8B55 FC MOV EDX,DWORD PTR SS:[EBP-4]
004FF6DF 0FB6541A FF MOVZX EDX,BYTE PTR DS:[EDX+EBX-1]
004FF6E4 2B55 F4 SUB EDX,DWORD PTR SS:[EBP-C] ; AscII-上面的结果
004FF6E7 E8 944DF0FF CALL Dump.00404480 ; 取结果的低8位
004FF6EC 8B55 EC MOV EDX,DWORD PTR SS:[EBP-14]
004FF6EF 8D45 F0 LEA EAX,DWORD PTR SS:[EBP-10]
004FF6F2 E8 794EF0FF CALL Dump.00404570
004FF6F7 43 INC EBX
004FF6F8 4F DEC EDI
004FF6F9 ^ 75 CF JNZ SHORT Dump.004FF6CA
004FF6FB 8B45 F8 MOV EAX,DWORD PTR SS:[EBP-8]
004FF6FE 8B55 F0 MOV EDX,DWORD PTR SS:[EBP-10]
004FF701 E8 E64BF0FF CALL Dump.004042EC
004FF706 33C0 XOR EAX,EAX
004FF708 5A POP EDX
004FF709 59 POP ECX
004FF70A 59 POP ECX
004FF70B 64:8910 MOV DWORD PTR FS:[EAX],EDX
004FF70E 68 30F74F00 PUSH Dump.004FF730
004FF713 8D45 EC LEA EAX,DWORD PTR SS:[EBP-14]
004FF716 BA 02000000 MOV EDX,2
004FF71B E8 9C4BF0FF CALL Dump.004042BC
004FF720 8D45 FC LEA EAX,DWORD PTR SS:[EBP-4]
004FF723 E8 704BF0FF CALL Dump.00404298
004FF728 C3 RETN
【小结】
分别对4段注册码的每个字符转换,得到Sn1-Sn2-Sn3-Sn4
Len:各段注册码的长度,i从1到Len
SnII=ASCII-(Len*Len-i*i+1);
那么逆过来就是:ASCII=SnII+(Len*Len-i*i+1);
另外Len不要超过8位,否则Len*Len太大,导致算号出错。
----------------------------------------------------------------------------------------
『四』、下面看看大数运算部分,即注释中的F2( )
跟进00502224 CALL Dump.00501144
00501180 6A 00 PUSH 0
00501182 6A 02 PUSH 2
00501184 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8]
00501187 8B55 0C MOV EDX,DWORD PTR SS:[EBP+C]
0050118A E8 2D43F0FF CALL Dump.004054BC ; 0x1385B/2=0x9C2D
0050118F 8BD8 MOV EBX,EAX
00501191 85DB TEST EBX,EBX
00501193 76 47 JBE SHORT Dump.005011DC
00501195 FF75 14 PUSH DWORD PTR SS:[EBP+14]
00501198 FF75 10 PUSH DWORD PTR SS:[EBP+10]
0050119B FF75 1C PUSH DWORD PTR SS:[EBP+1C]
0050119E FF75 18 PUSH DWORD PTR SS:[EBP+18]
005011A1 8B45 18 MOV EAX,DWORD PTR SS:[EBP+18]
005011A4 8B55 1C MOV EDX,DWORD PTR SS:[EBP+1C]
005011A7 E8 EC42F0FF CALL Dump.00405498 ; b=a*a(大数相乘)
跟进,并走几步
-> 00405498 52 PUSH EDX
-> 00405499 50 PUSH EAX
-> 0040549A 8B4424 10 MOV EAX,DWORD PTR SS:[ESP+10]
-> 0040549E F72424 MUL DWORD PTR SS:[ESP] ; 乘
-> 004054A1 89C1 MOV ECX,EAX
-> 004054A3 8B4424 04 MOV EAX,DWORD PTR SS:[ESP+4]
-> 004054A7 F76424 0C MUL DWORD PTR SS:[ESP+C] ; 乘
-> 004054AB 01C1 ADD ECX,EAX
-> 004054AD 8B0424 MOV EAX,DWORD PTR SS:[ESP]
-> 004054B0 F76424 0C MUL DWORD PTR SS:[ESP+C] ; 乘
-> 004054B4 01CA ADD EDX,ECX
-> 004054B6 59 POP ECX
-> 004054B7 59 POP ECX
-> 004054B8 C2 0800 RETN 8
005011AC E8 8743F0FF CALL Dump.00405538 ; b*(2^64)%0x8908D0000000000000000/(2^64)
005011B1 8945 E8 MOV DWORD PTR SS:[EBP-18],EAX ; 上面过程简化为:(b*b)%0x8908D
005011B4 8955 EC MOV DWORD PTR SS:[EBP-14],EDX
005011B7 FF75 14 PUSH DWORD PTR SS:[EBP+14]
005011BA FF75 10 PUSH DWORD PTR SS:[EBP+10]
005011BD FF75 F4 PUSH DWORD PTR SS:[EBP-C]
005011C0 FF75 F0 PUSH DWORD PTR SS:[EBP-10]
005011C3 8B45 E8 MOV EAX,DWORD PTR SS:[EBP-18]
005011C6 8B55 EC MOV EDX,DWORD PTR SS:[EBP-14]
005011C9 E8 CA42F0FF CALL Dump.00405498 ; b=b*上轮b(大数相乘)
005011CE E8 6543F0FF CALL Dump.00405538 ; b=b*(2^64)%0x8908D0000000000000000/(2^64)
跟进,并走几步
-> 0040556B 89CD MOV EBP,ECX
-> 0040556D B9 40000000 MOV ECX,40 ; 循环次数
-> 00405572 57 PUSH EDI
-> 00405573 31FF XOR EDI,EDI
-> 00405575 31F6 XOR ESI,ESI
-> 00405577 D1E0 SHL EAX,1 ; 循环开始
-> 00405579 D1D2 RCL EDX,1
-> 0040557B D1D6 RCL ESI,1
-> 0040557D D1D7 RCL EDI,1 ; 用四个32位寄存器保存结果
-> 0040557F 39EF CMP EDI,EBP
-> 00405581 72 0B JB SHORT Dump.-> 0040558E
-> 00405583 77 04 JA SHORT Dump.-> 00405589
-> 00405585 39DE CMP ESI,EBX
-> 00405587 72 05 JB SHORT Dump.-> 0040558E ; 如果结果的高64位大于0x8908D
-> 00405589 29DE SUB ESI,EBX
-> 0040558B 19EF SBB EDI,EBP ; 高64位就减去0x8908D
-> 0040558D 40 INC EAX
-> 0040558E ^ E2 E7 LOOPD SHORT Dump.-> 00405577 ; 64次移位,每次移动一位
-> 00405590 89F0 MOV EAX,ESI
-> 00405592 89FA MOV EDX,EDI
-> 00405594 5B POP EBX
-> 00405595 F7C3 01000000 TEST EBX,1
-> 0040559B 74 07 JE SHORT Dump.-> 004055A4
-> 0040559D F7DA NEG EDX
-> 0040559F F7D8 NEG EAX
-> 004055A1 83DA 00 SBB EDX,0
-> 004055A4 5F POP EDI
-> 004055A5 5E POP ESI
-> 004055A6 5B POP EBX
-> 004055A7 5D POP EBP
-> 004055A8 C2 0800 RETN 8
005011D3 8945 F0 MOV DWORD PTR SS:[EBP-10],EAX ; 上面过程简化为:b=(b*上轮b)%0x8908D
005011D6 8955 F4 MOV DWORD PTR SS:[EBP-C],EDX ; 每轮进行两次运算
005011D9 4B DEC EBX
005011DA ^ 75 B9 JNZ SHORT Dump.00501195 ; 共循环0x9C2D次
005011DC 8B45 F0 MOV EAX,DWORD PTR SS:[EBP-10]
005011DF 8945 F8 MOV DWORD PTR SS:[EBP-8],EAX
005011E2 8B45 F4 MOV EAX,DWORD PTR SS:[EBP-C]
005011E5 8945 FC MOV DWORD PTR SS:[EBP-4],EAX
005011E8 8B45 F8 MOV EAX,DWORD PTR SS:[EBP-8]
005011EB 8B55 FC MOV EDX,DWORD PTR SS:[EBP-4]
005011EE 5B POP EBX
005011EF 8BE5 MOV ESP,EBP
005011F1 5D POP EBP
005011F2 C2 1800 RETN 18
【小结】
这个过程是这样的,假设输入a
令b=0x8908D
N1=a ×a % b
N2=N1×a % b
N3=N2×a % b
…………
这样进行0x1385A次
最后结果等于(((a×a % b)×a % b)×a % b )×a % b ………………
共进行0x1385A次 ×a % b
偶经过推导认为这就是:a的0x1385B次方,再对b:0x8908D取余数,返回最后的余数
当让程序肯定不能直接计算 a 的0x1385B次方,数据肯定会溢出
对比一下偶写在算法注册机中的代码:
int CKeyGenDlg::Function2(int Sn)
{
//大数运算,计算Sn的0x1385B次方,然后对0x8908D取余
int i;
__int64 bigNum=Sn;
for(i=0;i<0x1385A;i++){
bigNum*=Sn;
bigNum%=0x8908D;
}
Sn=(int)bigNum;
return Sn;
}
另外有两个简单的 F2(0)=0、F2(1)=1,这两个可以在写注册机的时候用到
----------------------------------------------------------------------------------------
【解密过程】
按照『二』中的要求得到一个符合要求的注册码不容易,特别是F2( )不可能被逆向。
F2( )的结果位数不确定,一般都比较长,而注册码各段尽量不超过8位,F2(0)=0、F2(1)=1,可以被用一下。
把『二』中的验证这里再引用一下:
引用: 取第一段"12345678"的2到7位"234567"转成数值X(如果转换时有字符不是数字当然会出错)
第二段"7654321"转成数值7654321,然后 F2(7654321-X)=28920,再转成字符串"282920"
第三段"8765432"转成数值8765432,然后 F2(8765432-X)=267072,再转成字符串"267072"
第四段"9876543"转成数值9876543,然后 F2(9876543-X)=336652,再转成字符串"336652"
将上面三个结果连接得到"282920267072336652"再跟第一段"12345678"比较是否相同。
不同就是试用版,相同但第一段的第八位不是"6"则是标准版,是"6"则是钻石版
Sn3=rand() ; Sn3取一个随机数
Sn1=Function2(Sn3) ; Sn2=F2(Sn3),得到Sn1的2到7位
Sn2=Sn1 ; 如果Sn1的第一位是"0",Sn2就等于Sn1的2到7位
Sn3=Sn3+Sn1 ; 得到Sn3
Sn1=Sn2*10+6; ; Sn1的第八位是"6",第一位是"0"
好了Sn1,Sn2,Sn3都有了,剩下Sn4
我们要找一位数Y,F2(Y)=6;这样才能得到钻石版,如果不要钻石版,F2(Y)=1好了
要得到6不容易啊,最后没法,写了个程序,让Y从1开始穷举,结果Athlon XP 1600+花了近一个小时找到一个279936。F2(279936)=6
哈哈,赶快Sn4=Sn2+279936;
然后分别把Sn1、Sn2、Sn3、Sn4转成字符串,一些位置的字符替换一下,用"-"连接得到注册码了。
----------------------------------------------------------------------------------------
【算法注册机】
Microsoft Visual C++ 6.0写的MFC程序
void CKeygenDlg::OnOK()
{
// TODO: Add extra validation here
//CDialog::OnOK();
char regCode[32];
int i,Sn1,Sn2,Sn3,Sn4,codeLength;
m_Edit2="";
do{
Sn3 =rand()+90;
Sn2=Function2(Sn3);
}while(Sn2<100000);
Sn3+=Sn2;
Sn1=Sn2*10+6;
Sn4=Sn2+279936;
//得到regCode1
sprintf(regCode,"%08d",Sn1);
codeLength=strlen(regCode);
for(i=1;i<=codeLength;i++){
regCode[i-1]=regCode[i-1]+(codeLength*codeLength-i*i+1);
}
if(regCode[7]='7') regCode[7]='Z';
m_Edit2=regCode;
m_Edit2+="-";
//得到regCode2
sprintf(regCode,"%07d",Sn2);
codeLength=strlen(regCode);
for(i=1;i<=codeLength;i++){
regCode[i-1]=regCode[i-1]+(codeLength*codeLength-i*i+1);
}
if(regCode[6]>0x30 && regCode[6]<0x3A) regCode[6]+=0x10;
if(regCode[6]=='0') regCode[6]='J';
m_Edit2 += regCode;
m_Edit2+="-";
//得到regCode3
sprintf(regCode,"%07d",Sn3);
codeLength=strlen(regCode);
for(i=1;i<=codeLength;i++){
regCode[i-1]=regCode[i-1]+(codeLength*codeLength-i*i+1);
}
if(regCode[6]>0x30 && regCode[6]<0x3A) regCode[6]+=0x10;
if(regCode[6]=='0') regCode[6]='J';
m_Edit2 += regCode;
m_Edit2+="-";
//得到regCode4
sprintf(regCode,"%07d",Sn4);
codeLength=strlen(regCode);
for(i=1;i<=codeLength;i++){
regCode[i-1]=regCode[i-1]+(codeLength*codeLength-i*i+1);
}
if(regCode[6]>0x30 && regCode[6]<0x3A) regCode[6]+=0x10;
if(regCode[6]=='0') regCode[6]='J';
m_Edit2 += regCode;
UpdateData(false);
}
int CKeygenDlg::Function2(int Sn)
{
//大数运算,计算Sn的0x1385B次方,然后对0x8908D取余
int i;
__int64 bigNum=Sn;
for(i=0;i<0x1385A;i++){
bigNum*=Sn;
bigNum%=0x8908D;
}
Sn=(int)bigNum;
return Sn;
}
----------------------------------------------------------------------------------------
【破解心得】
程序中用到了128位数值运算,是非常常见得X^Y%Z运算,大数计算器中也有X^Y%Z,可见所有的大数计算在计算机中都是32位运算,这只是个简单的例子,还有很多更为复杂的。数学真是奇妙。
另外,程序中共有四处调用user、serial、config.lss等字符串,偶看了一下:
一处是保存注册码用
一处是取注册码验证用
一处是验证不成功删除保存的注册码用
还有一处,从来没有断下过,有什么用没看出来,会不会又是一个暗桩要等着我去发现。
----------------------------------------------------------------------------------------
【破解声明】
我是一只小菜鸟,偶得一点心得,愿与大家分享:)
【版权声明】 本文纯属技术交流, 转载请注明作者并保持文章的完整, 谢谢!
----------------------------------------------------------------------------------------
文章写于2005-11-1 12:07:34
[ 本帖最后由 Nisy 于 2006-8-10 22:35 编辑 ] |
|