Universal Viewer Pro 从注册码分析到注册机写作
本帖最后由 crackvip 于 2014-11-12 16:21 编辑原文请参考
Universal Viewer Pro 注册信息两组
https://www.chinapyg.com/thread-74847-1-1.html
(出处: 中国飘云阁(PYG官方论坛) )
static/image/hrline/2.gif
本着一颗爱你的心,来完成此文,从一个不懂开机到会装电脑,从不懂汇编到会写注册机的黄毛丫头。。一路走来。。有你真好。。
这里我就不写感谢的话了,太多了,篇幅有限,要写的话写不完。。。
static/image/hrline/5.gif
【软件分析部分】
下载安装Universal Viewer Pro
运行后,没有可以填注册码的地方,后来参考GGLHY的帖子,才知道,原来,呵呵,是keyfile注册的。。
直接OD载入
008251B8 >55 PUSH EBP ;停在这里
008251B9 .8BEC MOV EBP, ESP
008251BB .83C4 F0 ADD ESP, -0x10
008251BE .B8 38418200 MOV EAX, Viewer.00824138
008251C3 .E8 5022BEFF CALL Viewer.00407418
008251C8 .A1 F4348600 MOV EAX, DWORD PTR DS:
008251CD .8B00 MOV EAX, DWORD PTR DS:[EAX]
008251CF .E8 18F0C7FF CALL Viewer.004A41EC
008251D4 .A1 F4348600 MOV EAX, DWORD PTR DS:
008251D9 .8B00 MOV EAX, DWORD PTR DS:[EAX]
008251DB .BA 48528200 MOV EDX, Viewer.00825248 ;Universal Viewer
关键字,找关键点。找算法CALL的方法
查找关键字key.txt
<font face="宋体">中文搜索引擎, 条目 6948
地址=00707F9B
反汇编=MOV EDX, Viewer.007080A0
文本字符串=Key.txt</font>
可以找到这个,直接双击来到
<font face="宋体">00707F9B .BA A0807000 MOV EDX, Viewer.007080A0 ;Key.txt</font>
然后,我们往下看,
00707F9B .BA A0807000 MOV EDX, Viewer.007080A0 ;Key.txt
00707FA0 .E8 57CFCFFF CALL Viewer.00404EFC
00707FA5 .8B4D E8 MOV ECX, DWORD PTR SS:[EBP-0x18]
00707FA8 .B2 01 MOV DL, 0x1
00707FAA .A1 78B74400 MOV EAX, DWORD PTR DS: ;姆D
00707FAF .E8 7438D4FF CALL Viewer.0044B828
00707FB4 .8945 EC MOV DWORD PTR SS:[EBP-0x14], EAX
00707FB7 .33C0 XOR EAX, EAX
00707FB9 .55 PUSH EBP
00707FBA .68 5B807000 PUSH Viewer.0070805B
00707FBF .64:FF30 PUSH DWORD PTR FS:[EAX]
00707FC2 .64:8920 MOV DWORD PTR FS:[EAX], ESP
00707FC5 .6A 00 PUSH 0x0
00707FC7 .8D45 F4 LEA EAX, DWORD PTR SS:[EBP-0xC]
00707FCA .50 PUSH EAX
00707FCB .B9 B0807000 MOV ECX, Viewer.007080B0 ;Name
00707FD0 .BA C0807000 MOV EDX, Viewer.007080C0 ;Key
00707FD5 .8B45 EC MOV EAX, DWORD PTR SS:[EBP-0x14] ;取用户名
00707FD8 .8B18 MOV EBX, DWORD PTR DS:[EAX]
00707FDA .FF13 CALL NEAR DWORD PTR DS:[EBX]
00707FDC .6A 00 PUSH 0x0
00707FDE .8D45 F0 LEA EAX, DWORD PTR SS:[EBP-0x10]
00707FE1 .50 PUSH EAX
00707FE2 .B9 C0807000 MOV ECX, Viewer.007080C0 ;Key
00707FE7 .BA C0807000 MOV EDX, Viewer.007080C0 ;Key
00707FEC .8B45 EC MOV EAX, DWORD PTR SS:[EBP-0x14] ;取KEY
00707FEF .8B18 MOV EBX, DWORD PTR DS:[EAX]
00707FF1 .FF13 CALL NEAR DWORD PTR DS:[EBX] ;已全部取出
00707FF3 .837D F4 00 CMP DWORD PTR SS:[EBP-0xC], 0x0 ;判断是否输入了用户名
00707FF7 .74 06 JE SHORT Viewer.00707FFF
00707FF9 .837D F0 00 CMP DWORD PTR SS:[EBP-0x10], 0x0 ;判断是否输入了KEY
00707FFD .75 07 JNZ SHORT Viewer.00708006
00707FFF >E8 2CC6CFFF CALL Viewer.00404630
00708004 .EB 5C JMP SHORT Viewer.00708062
00708006 >8B55 F0 MOV EDX, DWORD PTR SS:[EBP-0x10] ;假码到EDX
00708009 .8B45 F4 MOV EAX, DWORD PTR SS:[EBP-0xC] ;用户名到EAX
0070800C .E8 CBFDFFFF CALL Viewer.00707DDC ;算法CALL
00708011 .84C0 TEST AL, AL ;AL必须不等于0,否则Game OVER
00708013 .74 30 JE SHORT Viewer.00708045 ;关键跳
我们直接F7,进入算法CALL
<font face="宋体">0070800C .E8 CBFDFFFF CALL Viewer.00707DDC ;算法CALL,F7进入</font>
进入后是这样
00707DDC/[ DISCUZ_CODE_1823 ]nbsp; 53 PUSH EBX ;算法1开始
00707DDD|.56 PUSH ESI
00707DDE|.57 PUSH EDI
00707DDF|.51 PUSH ECX
00707DE0|.8BFA MOV EDI, EDX
00707DE2|.8BF0 MOV ESI, EAX
00707DE4|.33DB XOR EBX, EBX
00707DE6|.8BC6 MOV EAX, ESI
00707DE8|.E8 07D1CFFF CALL Viewer.00404EF4 ;用户名长度
00707DED|.83F8 02 CMP EAX, 0x2 ;判断是否大于2
00707DF0|.0F8C 27010000 JL Viewer.00707F1D ;小于则挂了
00707DF6|.8BC7 MOV EAX, EDI
00707DF8|.E8 F7D0CFFF CALL Viewer.00404EF4 ;假码长度
00707DFD|.83F8 13 CMP EAX, 0x13 ;不等于0x13则挂了,19位
00707E00|.0F85 17010000 JNZ Viewer.00707F1D
00707E06|.807F 04 2D CMP BYTE PTR DS:[EDI+0x4], 0x2D ;-,第5位为-号
00707E0A|.0F85 0D010000 JNZ Viewer.00707F1D
00707E10|.807F 09 2D CMP BYTE PTR DS:[EDI+0x9], 0x2D ;-,第10位为-号
00707E14|.0F85 03010000 JNZ Viewer.00707F1D
00707E1A|.807F 0E 2D CMP BYTE PTR DS:[EDI+0xE], 0x2D ;-,第15位为-号
00707E1E|.0F85 F9000000 JNZ Viewer.00707F1D
00707E24|.8A0F MOV CL, BYTE PTR DS:[EDI]
00707E26|.8BC1 MOV EAX, ECX ;第一段转ASCII到EAX
00707E28|.2C 42 SUB AL, 0x42 ;AL-0x42,字母B的ASCII
00707E2A|.74 0C JE SHORT Viewer.00707E38
00707E2C|.2C 11 SUB AL, 0x11 ;0x42+0x11=字母S的ASCII
00707E2E|.74 08 JE SHORT Viewer.00707E38
00707E30|.2C 02 SUB AL, 0x2 ;0x42+0x11+2=字母U的ASCII
00707E32|.0F85 E5000000 JNZ Viewer.00707F1D ;这里跳就挂了
00707E38|>33C0 XOR EAX, EAX
00707E3A|.8AC1 MOV AL, CL ;首字母到AL
00707E3C|.33D2 XOR EDX, EDX
00707E3E|.8A57 01 MOV DL, BYTE PTR DS:[EDI+0x1] ;第2位
00707E41|.03C2 ADD EAX, EDX
00707E43|.33D2 XOR EDX, EDX
00707E45|.8A57 02 MOV DL, BYTE PTR DS:[EDI+0x2] ;第3位
00707E48|.03C2 ADD EAX, EDX
00707E4A|.33D2 XOR EDX, EDX
00707E4C|.8A57 03 MOV DL, BYTE PTR DS:[EDI+0x3] ;第4位
00707E4F|.03C2 ADD EAX, EDX ;第1-4位之和
00707E51|.B9 14000000 MOV ECX, 0x14 ;被除数
00707E56|.33D2 XOR EDX, EDX
00707E58|.F7F1 DIV ECX ;EAX div ECX ,商放EAX,余数放EDX
00707E5A|.83FA 0E CMP EDX, 0xE ;余数必须为13
00707E5D|.0F85 BA000000 JNZ Viewer.00707F1D
00707E63|.33C0 XOR EAX, EAX ;第二段注册码计算验证开始,与第一段类似
00707E65|.8A47 05 MOV AL, BYTE PTR DS:[EDI+0x5]
00707E68|.33D2 XOR EDX, EDX
00707E6A|.8A57 06 MOV DL, BYTE PTR DS:[EDI+0x6]
00707E6D|.03C2 ADD EAX, EDX
00707E6F|.33D2 XOR EDX, EDX
00707E71|.8A57 07 MOV DL, BYTE PTR DS:[EDI+0x7]
00707E74|.03C2 ADD EAX, EDX
00707E76|.33D2 XOR EDX, EDX
00707E78|.8A57 08 MOV DL, BYTE PTR DS:[EDI+0x8]
00707E7B|.03C2 ADD EAX, EDX ;第二组注册码ASCII之和
00707E7D|.B9 28000000 MOV ECX, 0x28 ;被除数
00707E82|.33D2 XOR EDX, EDX
00707E84|.F7F1 DIV ECX ;除以0x28之后,余数要为0xF
00707E86|.83FA 0F CMP EDX, 0xF ;余数
00707E89|.0F85 8E000000 JNZ Viewer.00707F1D
00707E8F|.33C0 XOR EAX, EAX ;第三段注册码计算验证开始
00707E91|.8A47 0A MOV AL, BYTE PTR DS:[EDI+0xA]
00707E94|.33D2 XOR EDX, EDX
00707E96|.8A57 0B MOV DL, BYTE PTR DS:[EDI+0xB]
00707E99|.03C2 ADD EAX, EDX
00707E9B|.33D2 XOR EDX, EDX
00707E9D|.8A57 0C MOV DL, BYTE PTR DS:[EDI+0xC]
00707EA0|.03C2 ADD EAX, EDX
00707EA2|.33D2 XOR EDX, EDX
00707EA4|.8A57 0D MOV DL, BYTE PTR DS:[EDI+0xD]
00707EA7|.03C2 ADD EAX, EDX
00707EA9|.B9 28000000 MOV ECX, 0x28 ;被除数
00707EAE|.33D2 XOR EDX, EDX
00707EB0|.F7F1 DIV ECX ;除以0x28之后,余数要为0x11
00707EB2|.83FA 11 CMP EDX, 0x11 ;余数
00707EB5|.75 66 JNZ SHORT Viewer.00707F1D
00707EB7|.33C0 XOR EAX, EAX ;第四段注册码计算验证开始
00707EB9|.8A47 0F MOV AL, BYTE PTR DS:[EDI+0xF]
00707EBC|.33D2 XOR EDX, EDX
00707EBE|.8A57 10 MOV DL, BYTE PTR DS:[EDI+0x10]
00707EC1|.03C2 ADD EAX, EDX
00707EC3|.33D2 XOR EDX, EDX
00707EC5|.8A57 11 MOV DL, BYTE PTR DS:[EDI+0x11]
00707EC8|.03C2 ADD EAX, EDX
00707ECA|.33D2 XOR EDX, EDX
00707ECC|.8A57 12 MOV DL, BYTE PTR DS:[EDI+0x12]
00707ECF|.03C2 ADD EAX, EDX
00707ED1|.B9 28000000 MOV ECX, 0x28 ;第四段被除数
00707ED6|.33D2 XOR EDX, EDX
00707ED8|.F7F1 DIV ECX ;除以0x28之后,余数要为0x14
00707EDA|.83FA 14 CMP EDX, 0x14 ;余数
00707EDD|.75 3E JNZ SHORT Viewer.00707F1D
走完这段代码,接着往 下看,算法2,验证部分
......
00707ED1|.B9 28000000 MOV ECX, 0x28 ;第四段被除数
00707ED6|.33D2 XOR EDX, EDX
00707ED8|.F7F1 DIV ECX ;除以0x28之后,余数要为0x14
00707EDA|.83FA 14 CMP EDX, 0x14 ;余数
00707EDD|.75 3E JNZ SHORT Viewer.00707F1D
00707EDF|.8D4424 02 LEA EAX, DWORD PTR SS:[ESP+0x2]
00707EE3|.50 PUSH EAX
00707EE4|.8D4424 07 LEA EAX, DWORD PTR SS:[ESP+0x7]
00707EE8|.50 PUSH EAX
00707EE9|.8D4C24 09 LEA ECX, DWORD PTR SS:[ESP+0x9]
00707EED|.8D5424 08 LEA EDX, DWORD PTR SS:[ESP+0x8]
00707EF1|.8BC6 MOV EAX, ESI
00707EF3|.E8 80FBFFFF CALL Viewer.00707A78 ;算法2,取验证码
00707EF8|.8A47 01 MOV AL, BYTE PTR DS:[EDI+0x1] ;注册码的第2位
00707EFB|.3A0424 CMP AL, BYTE PTR SS:[ESP] ;用户名的第1位转大写
00707EFE|.75 1D JNZ SHORT Viewer.00707F1D
00707F00|.8A47 05 MOV AL, BYTE PTR DS:[EDI+0x5] ;注册码的第6位
00707F03|.3A4424 01 CMP AL, BYTE PTR SS:[ESP+0x1] ;第i位,这个i是根据用户名的长度计算的,i=长度 shr 1(但SAR是带进位右移,SAR可以移动带符号数而保持符号不变. )
00707F07|.75 14 JNZ SHORT Viewer.00707F1D ;所以用户名最好是大于2位,在上面有判断,如果小于2位直接不成功
00707F09|.8A47 0A MOV AL, BYTE PTR DS:[EDI+0xA] ;第11位
00707F0C|.3A4424 02 CMP AL, BYTE PTR SS:[ESP+0x2] ;第i+1位
00707F10|.75 0B JNZ SHORT Viewer.00707F1D
00707F12|.8A47 0F MOV AL, BYTE PTR DS:[EDI+0xF] ;第16位
00707F15|.3A4424 03 CMP AL, BYTE PTR SS:[ESP+0x3] ;最后一位;
00707F19|.75 02 JNZ SHORT Viewer.00707F1D
00707F1B|.B3 01 MOV BL, 0x1
00707F1D|>8BC3 MOV EAX, EBX
......
来到算法2,验证特征部分(F7跟进)
00707EF3|.E8 80FBFFFF CALL Viewer.00707A78 ;算法2,取验证码
F7后来到这里
00707A78/[ DISCUZ_CODE_1825 ]nbsp; 55 PUSH EBP ;算法2部分
00707A79|.8BEC MOV EBP, ESP
00707A7B|.51 PUSH ECX
00707A7C|.B9 07000000 MOV ECX, 0x7
00707A81|>6A 00 /PUSH 0x0
00707A83|.6A 00 |PUSH 0x0
00707A85|.49 |DEC ECX
00707A86|.^ 75 F9 \JNZ SHORT Viewer.00707A81
00707A88|.874D FC XCHG DWORD PTR SS:[EBP-0x4], ECX
00707A8B|.53 PUSH EBX
00707A8C|.56 PUSH ESI ;用户名入栈
00707A8D|.8BF1 MOV ESI, ECX
00707A8F|.8BDA MOV EBX, EDX
00707A91|.8945 FC MOV DWORD PTR SS:[EBP-0x4], EAX
00707A94|.8B45 FC MOV EAX, DWORD PTR SS:[EBP-0x4]
00707A97|.E8 48D6CFFF CALL Viewer.004050E4
00707A9C|.33C0 XOR EAX, EAX ;以下为替换特殊字符
00707A9E|.55 PUSH EBP
00707A9F|.68 1E7D7000 PUSH Viewer.00707D1E
00707AA4|.64:FF30 PUSH DWORD PTR FS:[EAX]
00707AA7|.64:8920 MOV DWORD PTR FS:[EAX], ESP
00707AAA|.A0 307D7000 MOV AL, BYTE PTR DS:
00707AAF|.50 PUSH EAX
00707AB0|.8D45 F8 LEA EAX, DWORD PTR SS:[EBP-0x8]
00707AB3|.50 PUSH EAX
00707AB4|.33C9 XOR ECX, ECX
00707AB6|.BA 3C7D7000 MOV EDX, Viewer.00707D3C ;空格
00707ABB|.8B45 FC MOV EAX, DWORD PTR SS:[EBP-0x4]
00707ABE|.E8 31ACD0FF CALL Viewer.004126F4
00707AC3|.8B55 F8 MOV EDX, DWORD PTR SS:[EBP-0x8]
00707AC6|.8D45 FC LEA EAX, DWORD PTR SS:[EBP-0x4]
00707AC9|.E8 D2D1CFFF CALL Viewer.00404CA0
00707ACE|.A0 307D7000 MOV AL, BYTE PTR DS:
00707AD3|.50 PUSH EAX
00707AD4|.8D45 F4 LEA EAX, DWORD PTR SS:[EBP-0xC]
00707AD7|.50 PUSH EAX
00707AD8|.33C9 XOR ECX, ECX
00707ADA|.BA 487D7000 MOV EDX, Viewer.00707D48 ;_
00707ADF|.8B45 FC MOV EAX, DWORD PTR SS:[EBP-0x4]
00707AE2|.E8 0DACD0FF CALL Viewer.004126F4
00707AE7|.8B55 F4 MOV EDX, DWORD PTR SS:[EBP-0xC]
00707AEA|.8D45 FC LEA EAX, DWORD PTR SS:[EBP-0x4]
00707AED|.E8 AED1CFFF CALL Viewer.00404CA0
00707AF2|.A0 307D7000 MOV AL, BYTE PTR DS:
00707AF7|.50 PUSH EAX
00707AF8|.8D45 F0 LEA EAX, DWORD PTR SS:[EBP-0x10]
00707AFB|.50 PUSH EAX
00707AFC|.33C9 XOR ECX, ECX
00707AFE|.BA 547D7000 MOV EDX, Viewer.00707D54 ;.
00707B03|.8B45 FC MOV EAX, DWORD PTR SS:[EBP-0x4]
00707B06|.E8 E9ABD0FF CALL Viewer.004126F4
00707B0B|.8B55 F0 MOV EDX, DWORD PTR SS:[EBP-0x10]
00707B0E|.8D45 FC LEA EAX, DWORD PTR SS:[EBP-0x4]
00707B11|.E8 8AD1CFFF CALL Viewer.00404CA0
00707B16|.A0 307D7000 MOV AL, BYTE PTR DS:
00707B1B|.50 PUSH EAX
00707B1C|.8D45 EC LEA EAX, DWORD PTR SS:[EBP-0x14]
00707B1F|.50 PUSH EAX
00707B20|.33C9 XOR ECX, ECX
00707B22|.BA 607D7000 MOV EDX, Viewer.00707D60 ;,
00707B27|.8B45 FC MOV EAX, DWORD PTR SS:[EBP-0x4]
00707B2A|.E8 C5ABD0FF CALL Viewer.004126F4
00707B2F|.8B55 EC MOV EDX, DWORD PTR SS:[EBP-0x14]
00707B32|.8D45 FC LEA EAX, DWORD PTR SS:[EBP-0x4]
00707B35|.E8 66D1CFFF CALL Viewer.00404CA0
00707B3A|.A0 307D7000 MOV AL, BYTE PTR DS:
00707B3F|.50 PUSH EAX
00707B40|.8D45 E8 LEA EAX, DWORD PTR SS:[EBP-0x18]
00707B43|.50 PUSH EAX
00707B44|.33C9 XOR ECX, ECX
00707B46|.BA 6C7D7000 MOV EDX, Viewer.00707D6C ;;
00707B4B|.8B45 FC MOV EAX, DWORD PTR SS:[EBP-0x4]
00707B4E|.E8 A1ABD0FF CALL Viewer.004126F4
00707B53|.8B55 E8 MOV EDX, DWORD PTR SS:[EBP-0x18]
00707B56|.8D45 FC LEA EAX, DWORD PTR SS:[EBP-0x4]
00707B59|.E8 42D1CFFF CALL Viewer.00404CA0
00707B5E|.A0 307D7000 MOV AL, BYTE PTR DS:
00707B63|.50 PUSH EAX
00707B64|.8D45 E4 LEA EAX, DWORD PTR SS:[EBP-0x1C]
00707B67|.50 PUSH EAX
00707B68|.33C9 XOR ECX, ECX
00707B6A|.BA 787D7000 MOV EDX, Viewer.00707D78 ;-
00707B6F|.8B45 FC MOV EAX, DWORD PTR SS:[EBP-0x4]
00707B72|.E8 7DABD0FF CALL Viewer.004126F4
00707B77|.8B55 E4 MOV EDX, DWORD PTR SS:[EBP-0x1C]
00707B7A|.8D45 FC LEA EAX, DWORD PTR SS:[EBP-0x4]
00707B7D|.E8 1ED1CFFF CALL Viewer.00404CA0
00707B82|.A0 307D7000 MOV AL, BYTE PTR DS:
00707B87|.50 PUSH EAX
00707B88|.8D45 E0 LEA EAX, DWORD PTR SS:[EBP-0x20]
00707B8B|.50 PUSH EAX
00707B8C|.33C9 XOR ECX, ECX
00707B8E|.BA 847D7000 MOV EDX, Viewer.00707D84 ;/
00707B93|.8B45 FC MOV EAX, DWORD PTR SS:[EBP-0x4]
00707B96|.E8 59ABD0FF CALL Viewer.004126F4
00707B9B|.8B55 E0 MOV EDX, DWORD PTR SS:[EBP-0x20]
00707B9E|.8D45 FC LEA EAX, DWORD PTR SS:[EBP-0x4]
00707BA1|.E8 FAD0CFFF CALL Viewer.00404CA0
00707BA6|.A0 307D7000 MOV AL, BYTE PTR DS:
00707BAB|.50 PUSH EAX
00707BAC|.8D45 DC LEA EAX, DWORD PTR SS:[EBP-0x24]
00707BAF|.50 PUSH EAX
00707BB0|.33C9 XOR ECX, ECX
00707BB2|.BA 907D7000 MOV EDX, Viewer.00707D90 ;\
00707BB7|.8B45 FC MOV EAX, DWORD PTR SS:[EBP-0x4]
00707BBA|.E8 35ABD0FF CALL Viewer.004126F4
00707BBF|.8B55 DC MOV EDX, DWORD PTR SS:[EBP-0x24]
00707BC2|.8D45 FC LEA EAX, DWORD PTR SS:[EBP-0x4]
00707BC5|.E8 D6D0CFFF CALL Viewer.00404CA0
00707BCA|.A0 307D7000 MOV AL, BYTE PTR DS:
00707BCF|.50 PUSH EAX
00707BD0|.8D45 D8 LEA EAX, DWORD PTR SS:[EBP-0x28]
00707BD3|.50 PUSH EAX
00707BD4|.33C9 XOR ECX, ECX
00707BD6|.BA 9C7D7000 MOV EDX, Viewer.00707D9C ;"
00707BDB|.8B45 FC MOV EAX, DWORD PTR SS:[EBP-0x4]
00707BDE|.E8 11ABD0FF CALL Viewer.004126F4
00707BE3|.8B55 D8 MOV EDX, DWORD PTR SS:[EBP-0x28]
00707BE6|.8D45 FC LEA EAX, DWORD PTR SS:[EBP-0x4]
00707BE9|.E8 B2D0CFFF CALL Viewer.00404CA0
00707BEE|.A0 307D7000 MOV AL, BYTE PTR DS:
00707BF3|.50 PUSH EAX
00707BF4|.8D45 D4 LEA EAX, DWORD PTR SS:[EBP-0x2C]
00707BF7|.50 PUSH EAX
00707BF8|.33C9 XOR ECX, ECX
00707BFA|.BA A87D7000 MOV EDX, Viewer.00707DA8 ;'
00707BFF|.8B45 FC MOV EAX, DWORD PTR SS:[EBP-0x4]
00707C02|.E8 EDAAD0FF CALL Viewer.004126F4
00707C07|.8B55 D4 MOV EDX, DWORD PTR SS:[EBP-0x2C]
00707C0A|.8D45 FC LEA EAX, DWORD PTR SS:[EBP-0x4]
00707C0D|.E8 8ED0CFFF CALL Viewer.00404CA0
00707C12|.A0 307D7000 MOV AL, BYTE PTR DS:
00707C17|.50 PUSH EAX
00707C18|.8D45 D0 LEA EAX, DWORD PTR SS:[EBP-0x30]
00707C1B|.50 PUSH EAX
00707C1C|.33C9 XOR ECX, ECX
00707C1E|.BA B47D7000 MOV EDX, Viewer.00707DB4 ;(
00707C23|.8B45 FC MOV EAX, DWORD PTR SS:[EBP-0x4]
00707C26|.E8 C9AAD0FF CALL Viewer.004126F4
00707C2B|.8B55 D0 MOV EDX, DWORD PTR SS:[EBP-0x30]
00707C2E|.8D45 FC LEA EAX, DWORD PTR SS:[EBP-0x4]
00707C31|.E8 6AD0CFFF CALL Viewer.00404CA0
00707C36|.A0 307D7000 MOV AL, BYTE PTR DS:
00707C3B|.50 PUSH EAX
00707C3C|.8D45 CC LEA EAX, DWORD PTR SS:[EBP-0x34]
00707C3F|.50 PUSH EAX
00707C40|.33C9 XOR ECX, ECX
00707C42|.BA C07D7000 MOV EDX, Viewer.00707DC0 ;)
00707C47|.8B45 FC MOV EAX, DWORD PTR SS:[EBP-0x4]
00707C4A|.E8 A5AAD0FF CALL Viewer.004126F4
00707C4F|.8B55 CC MOV EDX, DWORD PTR SS:[EBP-0x34]
00707C52|.8D45 FC LEA EAX, DWORD PTR SS:[EBP-0x4]
00707C55|.E8 46D0CFFF CALL Viewer.00404CA0
00707C5A|.A0 307D7000 MOV AL, BYTE PTR DS:
00707C5F|.50 PUSH EAX
00707C60|.8D45 C8 LEA EAX, DWORD PTR SS:[EBP-0x38]
00707C63|.50 PUSH EAX
00707C64|.33C9 XOR ECX, ECX
00707C66|.BA CC7D7000 MOV EDX, Viewer.00707DCC ;[
00707C6B|.8B45 FC MOV EAX, DWORD PTR SS:[EBP-0x4]
00707C6E|.E8 81AAD0FF CALL Viewer.004126F4
00707C73|.8B55 C8 MOV EDX, DWORD PTR SS:[EBP-0x38]
00707C76|.8D45 FC LEA EAX, DWORD PTR SS:[EBP-0x4]
00707C79|.E8 22D0CFFF CALL Viewer.00404CA0
00707C7E|.A0 307D7000 MOV AL, BYTE PTR DS:
00707C83|.50 PUSH EAX
00707C84|.8D45 C4 LEA EAX, DWORD PTR SS:[EBP-0x3C]
00707C87|.50 PUSH EAX
00707C88|.33C9 XOR ECX, ECX
00707C8A|.BA D87D7000 MOV EDX, Viewer.00707DD8
00707C8F|.8B45 FC MOV EAX, DWORD PTR SS:[EBP-0x4]
00707C92|.E8 5DAAD0FF CALL Viewer.004126F4
00707C97|.8B55 C4 MOV EDX, DWORD PTR SS:[EBP-0x3C]
00707C9A|.8D45 FC LEA EAX, DWORD PTR SS:[EBP-0x4]
00707C9D|.E8 FECFCFFF CALL Viewer.00404CA0
00707CA2|.8B45 FC MOV EAX, DWORD PTR SS:[EBP-0x4]
00707CA5|.8A00 MOV AL, BYTE PTR DS:[EAX] ;第1位
00707CA7|.E8 B4B2CFFF CALL Viewer.00402F60
00707CAC|.8803 MOV BYTE PTR DS:[EBX], AL
00707CAE|.8B45 FC MOV EAX, DWORD PTR SS:[EBP-0x4]
00707CB1|.E8 3ED2CFFF CALL Viewer.00404EF4
00707CB6|.D1F8 SAR EAX, 1 ;用户名长度右移1位,相当于除2
00707CB8|.79 03 JNS SHORT Viewer.00707CBD
00707CBA|.83D0 00 ADC EAX, 0x0
00707CBD|>8B55 FC MOV EDX, DWORD PTR SS:[EBP-0x4]
00707CC0|.8A4402 FF MOV AL, BYTE PTR DS:[EDX+EAX-0x1] ;用户名第i位,也就是取中间位
00707CC4|.E8 97B2CFFF CALL Viewer.00402F60 ;转大写
00707CC9|.8806 MOV BYTE PTR DS:[ESI], AL
00707CCB|.8B45 FC MOV EAX, DWORD PTR SS:[EBP-0x4]
00707CCE|.E8 21D2CFFF CALL Viewer.00404EF4
00707CD3|.D1F8 SAR EAX, 1
00707CD5|.79 03 JNS SHORT Viewer.00707CDA
00707CD7|.83D0 00 ADC EAX, 0x0
00707CDA|>8B55 FC MOV EDX, DWORD PTR SS:[EBP-0x4]
00707CDD|.8A0402 MOV AL, BYTE PTR DS:[EDX+EAX] ;第i+1位
00707CE0|.E8 7BB2CFFF CALL Viewer.00402F60
00707CE5|.8B55 0C MOV EDX, DWORD PTR SS:[EBP+0xC]
00707CE8|.8802 MOV BYTE PTR DS:[EDX], AL
00707CEA|.8B45 FC MOV EAX, DWORD PTR SS:[EBP-0x4]
00707CED|.E8 02D2CFFF CALL Viewer.00404EF4 ;取长度
00707CF2|.8B55 FC MOV EDX, DWORD PTR SS:[EBP-0x4]
00707CF5|.8A4402 FF MOV AL, BYTE PTR DS:[EDX+EAX-0x1] ;用户名取后一位
00707CF9|.E8 62B2CFFF CALL Viewer.00402F60 ;转大写
00707CFE|.8B55 08 MOV EDX, DWORD PTR SS:[EBP+0x8]
00707D01|.8802 MOV BYTE PTR DS:[EDX], AL
00707D03|.33C0 XOR EAX, EAX
00707D05|.5A POP EDX
00707D06|.59 POP ECX
00707D07|.59 POP ECX
00707D08|.64:8910 MOV DWORD PTR FS:[EAX], EDX
00707D0B|.68 257D7000 PUSH Viewer.00707D25
00707D10|>8D45 C4 LEA EAX, DWORD PTR SS:[EBP-0x3C]
00707D13|.BA 0F000000 MOV EDX, 0xF
00707D18|.E8 0FCFCFFF CALL Viewer.00404C2C
00707D1D\.C3 RETN
好了,算法分析完毕。先总结一下
static/image/hrline/1.gif
【算法总结】
1.注册码与用户是有关系的
2.用户名部分
A.用户名长度必须大于等于2位;
B.用户名用于计算时,首先替换掉 _.,;-/\"'()[]这些字符(或者叫删除);
C.最终用于计算的长度则为替换(或删除)特殊字符后的长度;
D.分别取用户名的第1,中间,中间+1,最后一位,作为注册码的第2,6,11,16位。全部要转大写;
3.注册码部分
A.注册码分四部分,每部分为4字节,每部分用“-”连起来;
B.注册码的第1位,只能取字线B,S,U这几个字母;
C.第一组注册码的ASCII之和,除以0x14之后的余数为0xE,第2位为用户名的大写首字母;
D.第二组注册码的ASCII之和,除以0x28之后的余数为0xF,第1位为用户名的大写第i位字母(注册码总长的第6位)---[这个i为用户名替换特殊字符后的长度 SAR 1(相当于长度除2)];
E.第三组注册码的ASCII之和,除以0x28之后的余数为0x11,第1位为用户名的大写第(i+1)位字母(注册码总长的第11位)---[同上];
F.第四组注册码的ASCII之和,除以0x28之后的余数为0x14,第1位为用户名的大写最后一位字母(注册码总长的第16位);
G.注册码的其它位随机产生。
static/image/hrline/1.gif
【算法实现-注册机写作】
这里以DELPHI为演示实例;
这里我尽可能的注释每一条代码,使你更能够理解
打开delphi,新建一个工程文件,然后在窗体中放以下控件
RadioButton 控件 3个; //用于判断或选择不同的版本
edit 控件 2个;//用于输入用户名和显示注册码
label 控件2个;//一个用于标注是用户名,一个是注册码
Button 控件2个;//一个用于计算,一个用于生成文件
-------------------如下-----------------------
RadioButton1: TRadioButton;
RadioButton2: TRadioButton;
RadioButton3: TRadioButton;
edt1: TEdit;
lbl1: TLabel;
lbl2: TLabel;
edt2: TEdit;
btn1: TButton;
btn2: TButton;
========代码开始=============
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
RadioButton1: TRadioButton;
RadioButton2: TRadioButton;
RadioButton3: TRadioButton;
edt1: TEdit;
lbl1: TLabel;
lbl2: TLabel;
edt2: TEdit;
btn1: TButton;
btn2: TButton;
procedure btn1Click(Sender: TObject);
procedure btn2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
const
C = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789~!@#$%^&*()_+-=":;[]{}<>,./?|\'''; //计算注册码显示这些可见字符串;
//C = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';//计算注册码只显示大小写字母及数字 //不想注册码里面看起来是有乱码的,就用这句
implementation
{$R *.dfm}
//生成一个随机可见字符
function rand_CHAR(): Char;
begin
Randomize; //置随机种子,使下次生成随机数字时不会是一样的;
Sleep(2); //停顿一下,防止随机速度太快产生两个一个的字符;
Result := C[Random(Length(C) - 1) + 1]; //生成一个随机数。这里的意思是从指定字符串中随机提取一个字符;
end;
procedure TForm1.btn1Click(Sender: TObject);
var Str1, Str2, Str3, Str4: string; //申请四个变量,每个变量用来放注册码的每组
tmp1, tmp2, tmp3, tmp4: Char; //申请四个字符变量作为每组数据的字符,这样好理解一些。
t_Num1, t_Num2: integer; //两个临时变量,用于计算注册码时有地方放;
Num_Sum: Integer; //计算码的总和用的;
CodeName: string; //注册用户名用的一个临时变量,这样好操作;
begin
if RadioButton1.Checked then tmp1 := 'B'; //第一组注册码的第1位;
if RadioButton2.Checked then tmp1 := 'S'; //第一组注册码的第1位;
if RadioButton3.Checked then tmp1 := 'U'; //第一组注册码的第1位;
CodeName := edt1.Text;
//判断用户名是否大于等于2位 ,如果小于2位,则退出计算;
if Length(CodeName)<2 then Exit;
//用户名替换特殊字符
CodeName := StringReplace(CodeName, ' ', '', );
CodeName := StringReplace(CodeName, '_', '', );
CodeName := StringReplace(CodeName, '.', '', );
CodeName := StringReplace(CodeName, ',', '', );
CodeName := StringReplace(CodeName, ';', '', );
CodeName := StringReplace(CodeName, '-', '', );
CodeName := StringReplace(CodeName, '/', '', );
CodeName := StringReplace(CodeName, '\', '', );
CodeName := StringReplace(CodeName, '"', '', );
CodeName := StringReplace(CodeName, '''', '', );
CodeName := StringReplace(CodeName, '(', '', );
CodeName := StringReplace(CodeName, ')', '', );
CodeName := StringReplace(CodeName, '[', '', );
CodeName := StringReplace(CodeName, ']', '', );
tmp2 := UpCase(CodeName); // 取用户名第1位转大写作为注册码的第二位;
tmp3 := rand_CHAR(); //第一组注册码的第3位;随机生成
t_Num1 := Ord(tmp1) + Ord(tmp2) + Ord(tmp3); //前三个字符串ASCII之和;
t_Num2 := (((t_Num1 div $14) - 1) * $14 + $E) - t_Num1; //这里减1,使其没那么大,等下可以做加法;
tmp4 := Char(t_Num2); //ASCII转成字符
while Pos(tmp4, C) < 1 do //判断是否在指定字串内
begin
t_Num2 := t_Num2 + $14; //不在则累加,使字符在指定串里面
tmp4 := Char(t_Num2); //ASCII转成字符
end;
Str1 := tmp1 + tmp2 + tmp3 + tmp4; //把每个字母连起来,组成第一组注册码
//-==========第二组注册码==============
// tmp1 := rand_CHAR();
tmp1 := UpCase(CodeName[(Length(CodeName) shr 1)]); // 取用户名第i位转大写作为注册码的第6位;
tmp2 := rand_CHAR(); //第二组注册码的第2位;随机生成
tmp3 := rand_CHAR(); //第二组注册码的第3位;随机生成
t_Num1 := Ord(tmp1) + Ord(tmp2) + Ord(tmp3); //前三个字符串ASCII之和;
t_Num2 := (((t_Num1 div $28) - 1) * $28 + $F) - t_Num1; //这里减1,使其没那么大,等下可以做加法;
tmp4 := Char(t_Num2); //ASCII转成字符
while Pos(tmp4, C) < 1 do //判断是否在指定字串内
begin
t_Num2 := t_Num2 + $28;
tmp4 := Char(t_Num2); //ASCII转成字符
end;
Str2 := tmp1 + tmp2 + tmp3 + tmp4; //把每个字母连起来,组成第二组注册码
//-=============第三组注册码,算法和第二组差不多===========
tmp1 := UpCase(CodeName[(Length(CodeName) shr 1) + 1]); // 取用户名第i+1位转大写作为注册码的第11位;
tmp2 := rand_CHAR(); //第三组注册码的第2位;随机生成
tmp3 := rand_CHAR(); //第三组注册码的第3位;随机生成
t_Num1 := Ord(tmp1) + Ord(tmp2) + Ord(tmp3); //前三个字符串ASCII之和;
t_Num2 := (((t_Num1 div $28) - 1) * $28 + $11) - t_Num1; //这里减1,使其没那么大,等下可以做加法;
tmp4 := Char(t_Num2); //ASCII转成字符
while Pos(tmp4, C) < 1 do //判断是否在指定字串内
begin
t_Num2 := t_Num2 + $28;
tmp4 := Char(t_Num2); //ASCII转成字符
end;
Str3 := tmp1 + tmp2 + tmp3 + tmp4; //把每个字母连起来,组成第三组注册码
//-============第四组注册码,算法和第二组差不多============
tmp1 := UpCase(CodeName[Length(CodeName)]); // 取用户名最后一位转大写作为注册码的第16位;
tmp2 := rand_CHAR(); //第四组注册码的第2位;随机生成
tmp3 := rand_CHAR(); //第四组注册码的第3位;随机生成
t_Num1 := Ord(tmp1) + Ord(tmp2) + Ord(tmp3); //前三个字符串ASCII之和;
t_Num2 := (((t_Num1 div $28) - 1) * $28 + $14) - t_Num1; //这里减1,使其没那么大,等下可以做加法;
tmp4 := Char(t_Num2); //ASCII转成字符
while Pos(tmp4, C) < 1 do //判断是否在指定字串内
begin
t_Num2 := t_Num2 + $28; //不在里面则连加,加到在为止。
tmp4 := Char(t_Num2); //ASCII转成字符
end;
Str4 := tmp1 + tmp2 + tmp3 + tmp4; //把每个字母连起来,组成第四组注册码
edt2.Text := Format('%s-%s-%s-%s', ); //连接显示字符串
end;
procedure TForm1.btn2Click(Sender: TObject);
var Tlist: TStrings;
begin
//同目录下写出文件 key.txt;
//先判断是否输入了用户名和点了注册码,如果没有则直接不响应操作
if ((edt1.Text = '') or (edt2.Text = '')) then Exit;
Tlist := TStringList.Create;
Tlist.Clear;
//如果想装逼,可以在这里加上
// Tlist.Add(Format('%s', ['本注册文件由XXX生成']));
Tlist.Add(Format('[%s]', ['key'])); //写出注册文件的第1行,软件启动只认这三行
Tlist.Add(Format('name=%s', )); //写出注册文件的第2行,软件启动只认这三行
Tlist.Add(Format('key=%s', )); //写出注册文件的第3行,软件启动只认这三行
//如果想装逼,可以在这里加上 Tlist.Add(Format('[%s]', ['本品出自XXX组织。。']));
//也可以写更多装逼的东东;
try
Tlist.SaveToFile(ExtractFilePath(Application.ExeName) + 'key.txt');
ShowMessage('生成文件成功!'#10#13'保存为本根目录下的key.txt');
except
ShowMessage('生成文件失败!'); //如果生成不成功,则提示失败;
end;
Tlist.Free; //释放创建的 Tlist;
end;
end.
========代码结束=============
static/image/hrline/4.gif
效果图如下
static/image/hrline/line6.png
附上注册机
附上注册机源码
这次我是沙发 {:soso_e113:} 大赞。女子有如此才华,佩服 厉害厉害! 支持楼主的作品,分析详细来学习了。 我来了。谢谢vip。我已经在学习了 这个可以有,谢谢分享 太给力了!难得一见的好文章!!赞 VIP妹子的文章,我一定友情强顶,好好学习{:soso_e113:}
PS,建议以后分析文章和成品分开发表~~ 次忒必火 广告位招租 ...