crackvip 发表于 2014-11-12 15:31:14

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


附上注册机


附上注册机源码






wgz001 发表于 2014-11-12 15:43:32

这次我是沙发 {:soso_e113:}

轩轩1018 发表于 2014-11-12 15:57:08

大赞。女子有如此才华,佩服

cfc1680 发表于 2014-11-12 16:23:14

厉害厉害!

my1229 发表于 2014-11-12 16:25:44

支持楼主的作品,分析详细来学习了。

Dxer 发表于 2014-11-12 16:26:43

我来了。谢谢vip。我已经在学习了

kghong 发表于 2014-11-12 16:50:54

这个可以有,谢谢分享

pentium450 发表于 2014-11-12 17:16:32

太给力了!难得一见的好文章!!赞

GGLHY 发表于 2014-11-12 17:40:35

VIP妹子的文章,我一定友情强顶,好好学习{:soso_e113:}

PS,建议以后分析文章和成品分开发表~~

Nisy 发表于 2014-11-12 17:47:05

次忒必火 广告位招租 ...
页: [1] 2 3 4 5
查看完整版本: Universal Viewer Pro 从注册码分析到注册机写作