某款英语学习机软件保护的另类渗透
标 题: 【原创】某款英语学习机软件保护的另类渗透作 者: 天易love
时 间: 2009-08-16,13:18:46
链 接: http://bbs.pediy.com/showthread.php?t=95869
by 天易love 2009.7.30
概述:该软件功能比较强大,但注册码算法很简单口算就行了。有人写过内存注册机(就是先运行该软件,然后从软件的进程地址空间的某处读出程序算好的注册码并显示出来),这里主要是介绍一下它的保护中的一个小小的漏洞,具体的调试细节就不赘述了。
一、软件保护的大致原理:
简单讲一下,软件先由硬盘序列号算出注册码,再和当前文件夹下id.sim中的某个位置的字符串比较看是否一致,如果一致就算注册成功。pic1
注:该软件通过调用deviceiocontrol函数来获取硬盘序列号。由于使用的参数iocontrolcode为0x7c088,所以老式的IDE硬盘可以获取硬盘序列号(本人04年买的笔记本的ide硬盘就能读出),而新式串口硬盘获取不到。因为获取新式串口硬盘的序列号必须采用0x4d008作为入口参数。所以使用串口硬盘的在以后的处理中将采用默认的初始值MIP3HN8COML来计算注册码。00487D84处就是硬盘序列号初始值MIP3HN8COML的地址。
00849A9E .68 10020000 PUSH 210
00849AA3 .51 PUSH ECX
00849AA4 .6A 20 PUSH 20
00849AA6 .56 PUSH ESI
00849AA7 .68 88C00700 PUSH 7C088;iocontrolcode
00849AAC .52 PUSH EDX
00849AAD .E8 16DFC3FF CALL004879C8 ; 该call中调用了deviceiocontrol 来获取硬盘序列号
00849AB2 .8BF0 MOV ESI,EAX
二、调试中遇到的一些关键位置:
0084E2CF .0FBF85 28FFFF>MOVSX EAX,WORD PTR SS:
0084E2D6 .85C0 TEST EAX,EAX ;关键跳转由硬盘型号决定
0084E2D8 .0F84 8B000000 JE0084E369
0084E2DE .C745 FC 07000>MOV DWORD PTR SS:,7 ;串口硬盘跳到这
。。。。。。
0084E2FF .8985 30FFFFFF MOV DWORD PTR SS:,EAX
0084E305 .68 847D4800 PUSH00487D84 硬盘序列号初始值MIP3HN8COML
。。。。。。
0084E369 > \C745 FC 09000>MOV DWORD PTR SS:,9 ;老式硬盘跳到这
0084E370 .8B4D 08 MOV ECX,DWORD PTR SS:
0084E373 .8B11 MOV EDX,DWORD PTR DS:
0084E375 .8B45 08 MOV EAX,DWORD PTR SS:
。。。。。。
0084E404 .8985 28FFFFFF MOV DWORD PTR SS:,EAX
0084E40A .C745 B0 0E000>MOV DWORD PTR SS:,0E
0084E411 .C745 A8 02000>MOV DWORD PTR SS:,2
0084E418 .8B45 D8 MOV EAX,DWORD PTR SS:;算出的硬盘序列号
0084E41B .8985 0CFFFFFF MOV DWORD PTR SS:,EAX
0084E421 .C745 D8 00000>MOV DWORD PTR SS:,0
0084E428 .8B8D 0CFFFFFF MOV ECX,DWORD PTR SS:
0084E42E .894D C0 MOV DWORD PTR SS:,ECX
0084E431 .C745 B8 08000>MOV DWORD PTR SS:,8
0084E438 .8D55 A8 LEA EDX,DWORD PTR SS:
0084E43B .52 PUSH EDX
0084E43C .8D45 B8 LEA EAX,DWORD PTR SS:
0084E43F .50 PUSH EAX
0084E440 .E8 8B730400 CALL008957D0 ;算注册码的关键call
以下是注册成功的前提下获取当前文件夹下id.sim中内容时,堆栈中的情形:
0012F5F8 2000EC89/CALL 到 CreateFileA 来自 richtx32.2000EC83
0012F5FC 0012F66C|FileName = "E:\英语学习机\id.sim"
0012F600 80000000|Access = GENERIC_READ
0012F604 00000001|ShareMode = FILE_SHARE_READ
0012F608 00000000|pSecurity = NULL
0012F60C 00000003|Mode = OPEN_EXISTING
0012F610 00000080|Attributes = NORMAL
0012F614 00000000\hTemplateFile = NULL
0012E028 2000F6B1/CALL 到 ReadFile 来自 richtx32.2000F6AB
0012E02C 00000140|hFile = 00000140 (窗口)
0012E030 001939C4|Buffer = 001939C4
0012E034 00000FFC|BytesToRead = FFC (4092.)
0012E038 0012E05C|pBytesRead = 0012E05C
0012E03C 00000000\pOverlapped = NULL
以下就是文件内容读到缓冲区后的情形:W8;<9:28U就是保存的注册码
001939C47B 5C 72 74 66 31 5C 61 6E 73 69 5C 64 65 66 66{\rtf1\ansi\deff
001939D430 7B 5C 66 6F 6E 74 74 62 6C 7B 5C 66 30 5C 660{\fonttbl{\f0\f
001939E46E 69 6C 5C 66 63 68 61 72 73 65 74 31 33 34 20nil\fcharset134
001939F45C 27 63 62 5C 27 63 65 5C 27 63 63 5C 27 65 35\'cb\'ce\'cc\'e5
00193A043B 7D 7D 0D 0A 5C 76 69 65 77 6B 69 6E 64 34 5C;}}..\viewkind4\
00193A1475 63 31 5C 70 61 72 64 5C 6C 61 6E 67 32 30 35uc1\pard\lang205
00193A2432 5C 66 30 5C 66 73 31 38 20 57 38 3B 3C 39 3A2\f0\fs18 W8;<9:
00193A3432 38 55 0D 0A 5C 70 61 72 20 7D 0D 0A 00 00 0028U..\par }.....
也就是说算出的注册码与id.sim中结尾处倒数第二个以0D 0A结尾的ascII字符串的字符相同就可以在软件开始运行时蒙混过关,成为注册版。但注册失败时id.sim中的内容发生了变化,通过分析发现了一个小秘密,下面细述。
三、保护渗透具体步骤:
1、根据软件在求硬盘序列号时的一个小小漏洞,我们可以利用一下以下这个条件判断:
0084E2D6 .85C0 TEST EAX,EAX ;关键跳转由是否算出硬盘序列号决定
0084E2D8 .0F84 8B000000 JE0084E369
简单的将其nop掉即可,这样不管是何种硬盘,算出的注册码都是JNR9IO5HQSM。
2、通过调试发现如果运行了未注册版本的软件的话,软件将自动重新生成一个新的590字节的id.sim文件(内容如下),通过对比注册成功时的128字节的id.sim文件内容可以猜测注册成功时的注册码应该是放在文件的结尾处。未注册成功时这里是空的。
00000000 7B 5C 72 74 66 31 5C 616E 73 69 5C 61 6E 73 69 {\rtf1\ansi\ansi
00000010 63 70 67 39 33 36 5C 6465 66 66 30 5C 64 65 66 cpg936\deff0\def
00000020 6C 61 6E 67 31 30 33 335C 64 65 66 6C 61 6E 67 lang1033\deflang
00000030 66 65 32 30 35 32 7B 5C66 6F 6E 74 74 62 6C 7B fe2052{\fonttbl{
00000040 5C 66 30 5C 66 6E 69 6C5C 66 63 68 61 72 73 65 \f0\fnil\fcharse
00000050 74 31 33 34 20 5C 27 6362 5C 27 63 65 5C 27 63 t134 \'cb\'ce\'c
00000060 63 5C 27 65 35 3B 7D 7D0D 0A 7B 5C 69 6E 66 6F c\'e5;}}..{\info
00000070 7B 5C 68 6F 72 7A 64 6F63 7D 7B 5C 2A 5C 6C 63 {\horzdoc}{\*\lc
00000080 68 61 72 73 20 28 5B 5C7B 5C 27 61 31 5C 27 61 hars ([\{\'a1\'a
00000090 65 5C 27 61 31 5C 27 6230 5C 27 61 31 5C 27 62 e\'a1\'b0\'a1\'b
000000A0 32 5C 27 61 31 5C 27 6234 5C 27 61 31 5C 27 62 2\'a1\'b4\'a1\'b
000000B0 36 5C 27 61 31 5C 27 6238 5C 27 61 31 5C 27 62 6\'a1\'b8\'a1\'b
000000C0 61 5C 27 61 31 5C 27 6263 5C 27 61 31 5C 27 62 a\'a1\'bc\'a1\'b
000000D0 65 5C 27 61 33 5C 27 6138 5C 27 61 33 5C 27 64 e\'a3\'a8\'a3\'d
000000E0 62 5C 27 61 33 5C 27 6662 5C 27 61 33 5C 27 61 b\'a3\'fb\'a3\'a
000000F0 65 5C 27 61 31 5C 27 6134 7D 7B 5C 2A 5C 66 63 e\'a1\'a4}{\*\fc
00000100 68 61 72 73 20 21 29 2C2E 3A 5C 27 33 62 3F 5C hars !),.:\'3b?\
00000110 7D 5D 5C 27 61 31 5C 2761 32 5C 27 61 31 5C 27 }]\'a1\'a2\'a1\'
00000120 61 33 5C 27 61 31 5C 2761 34 5C 27 61 31 5C 27 a3\'a1\'a4\'a1\'
00000130 61 35 5C 27 61 31 5C 2761 36 5C 27 61 31 5C 27 a5\'a1\'a6\'a1\'
00000140 61 37 5C 27 61 31 5C 2761 38 5C 27 61 31 5C 27 a7\'a1\'a8\'a1\'
00000150 61 39 5C 27 61 31 5C 2761 61 5C 27 61 31 5C 27 a9\'a1\'aa\'a1\'
00000160 61 62 5C 27 61 31 5C 2761 63 5C 27 61 31 5C 27 ab\'a1\'ac\'a1\'
00000170 61 64 5C 27 61 31 5C 2761 66 5C 27 61 31 5C 27 ad\'a1\'af\'a1\'
00000180 62 31 5C 27 61 31 5C 2762 33 5C 27 61 31 5C 27 b1\'a1\'b3\'a1\'
00000190 62 35 5C 27 61 31 5C 2762 37 5C 27 61 31 5C 27 b5\'a1\'b7\'a1\'
000001A0 62 39 5C 27 61 31 5C 2762 62 5C 27 61 31 5C 27 b9\'a1\'bb\'a1\'
000001B0 62 64 5C 27 61 31 5C 2762 66 5C 27 61 31 5C 27 bd\'a1\'bf\'a1\'
000001C0 63 33 5C 27 61 33 5C 2761 31 5C 27 61 33 5C 27 c3\'a3\'a1\'a3\'
000001D0 61 32 5C 27 61 33 5C 2761 37 5C 27 61 33 5C 27 a2\'a3\'a7\'a3\'
000001E0 61 39 5C 27 61 33 5C 2761 63 5C 27 61 33 5C 27 a9\'a3\'ac\'a3\'
000001F0 61 65 5C 27 61 33 5C 2762 61 5C 27 61 33 5C 27 ae\'a3\'ba\'a3\'
00000200 62 62 5C 27 61 33 5C 2762 66 5C 27 61 33 5C 27 bb\'a3\'bf\'a3\'
00000210 64 64 5C 27 61 33 5C 2765 30 7D 7D 0D 0A 5C 76 dd\'a3\'e0}}..\v
00000220 69 65 77 6B 69 6E 64 345C 75 63 31 5C 70 61 72 iewkind4\uc1\par
00000230 64 5C 6C 61 6E 67 32 3035 32 5C 66 30 5C 66 73 d\lang2052\f0\fs
00000240 31 38 20 0D 0A 5C 70 6172 20 7D 0D 0A 00 18 ..\par }...
因此步骤之二就是生成相应的id.sim文件。内容如下:(注意结尾处是由默认的硬盘序列号生成的默认的注册码)
00000000 7B 5C 72 74 66 31 5C 616E 73 69 5C 61 6E 73 69 {\rtf1\ansi\ansi
00000010 63 70 67 39 33 36 5C 6465 66 66 30 5C 64 65 66 cpg936\deff0\def
00000020 6C 61 6E 67 31 30 33 335C 64 65 66 6C 61 6E 67 lang1033\deflang
00000030 66 65 32 30 35 32 7B 5C66 6F 6E 74 74 62 6C 7B fe2052{\fonttbl{
00000040 5C 66 30 5C 66 6E 69 6C5C 66 63 68 61 72 73 65 \f0\fnil\fcharse
00000050 74 31 33 34 20 5C 27 6362 5C 27 63 65 5C 27 63 t134 \'cb\'ce\'c
00000060 63 5C 27 65 35 3B 7D 7D0D 0A 7B 5C 69 6E 66 6F c\'e5;}}..{\info
00000070 7B 5C 68 6F 72 7A 64 6F63 7D 7B 5C 2A 5C 6C 63 {\horzdoc}{\*\lc
00000080 68 61 72 73 20 28 5B 5C7B 5C 27 61 31 5C 27 61 hars ([\{\'a1\'a
00000090 65 5C 27 61 31 5C 27 6230 5C 27 61 31 5C 27 62 e\'a1\'b0\'a1\'b
000000A0 32 5C 27 61 31 5C 27 6234 5C 27 61 31 5C 27 62 2\'a1\'b4\'a1\'b
000000B0 36 5C 27 61 31 5C 27 6238 5C 27 61 31 5C 27 62 6\'a1\'b8\'a1\'b
000000C0 61 5C 27 61 31 5C 27 6263 5C 27 61 31 5C 27 62 a\'a1\'bc\'a1\'b
000000D0 65 5C 27 61 33 5C 27 6138 5C 27 61 33 5C 27 64 e\'a3\'a8\'a3\'d
000000E0 62 5C 27 61 33 5C 27 6662 5C 27 61 33 5C 27 61 b\'a3\'fb\'a3\'a
000000F0 65 5C 27 61 31 5C 27 6134 7D 7B 5C 2A 5C 66 63 e\'a1\'a4}{\*\fc
00000100 68 61 72 73 20 21 29 2C2E 3A 5C 27 33 62 3F 5C hars !),.:\'3b?\
00000110 7D 5D 5C 27 61 31 5C 2761 32 5C 27 61 31 5C 27 }]\'a1\'a2\'a1\'
00000120 61 33 5C 27 61 31 5C 2761 34 5C 27 61 31 5C 27 a3\'a1\'a4\'a1\'
00000130 61 35 5C 27 61 31 5C 2761 36 5C 27 61 31 5C 27 a5\'a1\'a6\'a1\'
00000140 61 37 5C 27 61 31 5C 2761 38 5C 27 61 31 5C 27 a7\'a1\'a8\'a1\'
00000150 61 39 5C 27 61 31 5C 2761 61 5C 27 61 31 5C 27 a9\'a1\'aa\'a1\'
00000160 61 62 5C 27 61 31 5C 2761 63 5C 27 61 31 5C 27 ab\'a1\'ac\'a1\'
00000170 61 64 5C 27 61 31 5C 2761 66 5C 27 61 31 5C 27 ad\'a1\'af\'a1\'
00000180 62 31 5C 27 61 31 5C 2762 33 5C 27 61 31 5C 27 b1\'a1\'b3\'a1\'
00000190 62 35 5C 27 61 31 5C 2762 37 5C 27 61 31 5C 27 b5\'a1\'b7\'a1\'
000001A0 62 39 5C 27 61 31 5C 2762 62 5C 27 61 31 5C 27 b9\'a1\'bb\'a1\'
000001B0 62 64 5C 27 61 31 5C 2762 66 5C 27 61 31 5C 27 bd\'a1\'bf\'a1\'
000001C0 63 33 5C 27 61 33 5C 2761 31 5C 27 61 33 5C 27 c3\'a3\'a1\'a3\'
000001D0 61 32 5C 27 61 33 5C 2761 37 5C 27 61 33 5C 27 a2\'a3\'a7\'a3\'
000001E0 61 39 5C 27 61 33 5C 2761 63 5C 27 61 33 5C 27 a9\'a3\'ac\'a3\'
000001F0 61 65 5C 27 61 33 5C 2762 61 5C 27 61 33 5C 27 ae\'a3\'ba\'a3\'
00000200 62 62 5C 27 61 33 5C 2762 66 5C 27 61 33 5C 27 bb\'a3\'bf\'a3\'
00000210 64 64 5C 27 61 33 5C 2765 30 7D 7D 0D 0A 5C 76 dd\'a3\'e0}}..\v
00000220 69 65 77 6B 69 6E 64 345C 75 63 31 5C 70 61 72 iewkind4\uc1\par
00000230 64 5C 6C 61 6E 67 32 3035 32 5C 66 30 5C 66 73 d\lang2052\f0\fs
00000240 31 38 20 4A 4E 52 39 494F 35 48 51 53 4D 0D 0A 18 JNR9IO5HQSM..
00000250 5C 70 61 72 20 7D 0D 0A00 \par }...
通过以上的两个步骤之后不管在怎样的机器上都已经是注册软件了。因为软件开始运行时我们强制让它生成了默认的注册码JNR9IO5HQSM,且与其从id.sim文件相应位置读取的注册码相同,从而程序断定现在已经通过注册了。
3、编制补丁程序,贴代码如下:
program Project1;
usesSysUtils,Windows,Classes;
const
OFFSET_FILE =$44e2d6;
data: array of byte = (
$7B, $5C, $72, $74, $66, $31, $5C, $61, $6E, $73, $69, $5C, $61, $6E, $73, $69,
$63, $70, $67, $39, $33, $36, $5C, $64, $65, $66, $66, $30, $5C, $64, $65, $66,
$6C, $61, $6E, $67, $31, $30, $33, $33, $5C, $64, $65, $66, $6C, $61, $6E, $67,
$66, $65, $32, $30, $35, $32, $7B, $5C, $66, $6F, $6E, $74, $74, $62, $6C, $7B,
$5C, $66, $30, $5C, $66, $6E, $69, $6C, $5C, $66, $63, $68, $61, $72, $73, $65,
$74, $31, $33, $34, $20, $5C, $27, $63, $62, $5C, $27, $63, $65, $5C, $27, $63,
$63, $5C, $27, $65, $35, $3B, $7D, $7D, $0D, $0A, $7B, $5C, $69, $6E, $66, $6F,
$7B, $5C, $68, $6F, $72, $7A, $64, $6F, $63, $7D, $7B, $5C, $2A, $5C, $6C, $63,
$68, $61, $72, $73, $20, $28, $5B, $5C, $7B, $5C, $27, $61, $31, $5C, $27, $61,
$65, $5C, $27, $61, $31, $5C, $27, $62, $30, $5C, $27, $61, $31, $5C, $27, $62,
$32, $5C, $27, $61, $31, $5C, $27, $62, $34, $5C, $27, $61, $31, $5C, $27, $62,
$36, $5C, $27, $61, $31, $5C, $27, $62, $38, $5C, $27, $61, $31, $5C, $27, $62,
$61, $5C, $27, $61, $31, $5C, $27, $62, $63, $5C, $27, $61, $31, $5C, $27, $62,
$65, $5C, $27, $61, $33, $5C, $27, $61, $38, $5C, $27, $61, $33, $5C, $27, $64,
$62, $5C, $27, $61, $33, $5C, $27, $66, $62, $5C, $27, $61, $33, $5C, $27, $61,
$65, $5C, $27, $61, $31, $5C, $27, $61, $34, $7D, $7B, $5C, $2A, $5C, $66, $63,
$68, $61, $72, $73, $20, $21, $29, $2C, $2E, $3A, $5C, $27, $33, $62, $3F, $5C,
$7D, $5D, $5C, $27, $61, $31, $5C, $27, $61, $32, $5C, $27, $61, $31, $5C, $27,
$61, $33, $5C, $27, $61, $31, $5C, $27, $61, $34, $5C, $27, $61, $31, $5C, $27,
$61, $35, $5C, $27, $61, $31, $5C, $27, $61, $36, $5C, $27, $61, $31, $5C, $27,
$61, $37, $5C, $27, $61, $31, $5C, $27, $61, $38, $5C, $27, $61, $31, $5C, $27,
$61, $39, $5C, $27, $61, $31, $5C, $27, $61, $61, $5C, $27, $61, $31, $5C, $27,
$61, $62, $5C, $27, $61, $31, $5C, $27, $61, $63, $5C, $27, $61, $31, $5C, $27,
$61, $64, $5C, $27, $61, $31, $5C, $27, $61, $66, $5C, $27, $61, $31, $5C, $27,
$62, $31, $5C, $27, $61, $31, $5C, $27, $62, $33, $5C, $27, $61, $31, $5C, $27,
$62, $35, $5C, $27, $61, $31, $5C, $27, $62, $37, $5C, $27, $61, $31, $5C, $27,
$62, $39, $5C, $27, $61, $31, $5C, $27, $62, $62, $5C, $27, $61, $31, $5C, $27,
$62, $64, $5C, $27, $61, $31, $5C, $27, $62, $66, $5C, $27, $61, $31, $5C, $27,
$63, $33, $5C, $27, $61, $33, $5C, $27, $61, $31, $5C, $27, $61, $33, $5C, $27,
$61, $32, $5C, $27, $61, $33, $5C, $27, $61, $37, $5C, $27, $61, $33, $5C, $27,
$61, $39, $5C, $27, $61, $33, $5C, $27, $61, $63, $5C, $27, $61, $33, $5C, $27,
$61, $65, $5C, $27, $61, $33, $5C, $27, $62, $61, $5C, $27, $61, $33, $5C, $27,
$62, $62, $5C, $27, $61, $33, $5C, $27, $62, $66, $5C, $27, $61, $33, $5C, $27,
$64, $64, $5C, $27, $61, $33, $5C, $27, $65, $30, $7D, $7D, $0D, $0A, $5C, $76,
$69, $65, $77, $6B, $69, $6E, $64, $34, $5C, $75, $63, $31, $5C, $70, $61, $72,
$64, $5C, $6C, $61, $6E, $67, $32, $30, $35, $32, $5C, $66, $30, $5C, $66, $73,
$31, $38, $20, $4A, $4E, $52, $39, $49, $4F, $35, $48, $51, $53, $4D, $0D, $0A,
$5C, $70, $61, $72, $20, $7D, $0D, $0A, $00 );
procedureoperation();
Var
BinaryFile:THandle;
BytesWritten: dword;
path1,path2:string;
WriteBuff: PChar;
begin
path1:=ExtractFilePath(ParamStr(0)) + 'id.sim';
path2:=ExtractFilePath(ParamStr(0)) + '英语学习机.exe';
if fileexists(path1) then
begin
DeleteFile(pchar(path1));
end;
BinaryFile:=0;
try
BinaryFile := CreateFile(pchar(path1), GENERIC_WRITE, FILE_SHARE_WRITE, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if BinaryFile<>0 thenWriteFile(BinaryFile,data, 601,BytesWritten, nil);
finally
CloseHandle(BinaryFile);
end;
try
BinaryFile:=fileopen(path2,fmOpenWrite);
if BinaryFile<>0 then
begin
fileseek(BinaryFile,OFFSET_FILE,0);
WriteBuff := PChar(StringOfChar(#144,8));
FileWrite(BinaryFile,WriteBuff^,8);
end;
finally
CloseHandle(BinaryFile);
end;
end;
begin
operation();
end.
将编译的补丁程序拷贝到软件所在文件夹中只要运行一次即可。软件显示注册成功且功能完全,截图一张,留做纪念。pic2
4、对该软件保护方法的一点建议:
建议一:简单的nop掉两行就可以得到通用的注册码,这里比较脆弱,即使你算注册码的算法再强悍又有何用?可以设置某些特殊的标志,即使你nop掉跳转的条件,软件也不能正常运行。
建议二、有了通用注册码还要与隐藏在文件中的注册码进行比较,以此决定是否已经注册。这主要是防止将软件拷贝到其他非授权电脑上使用,因为刚拷过去时id.sim文件中保存的是授权电脑中的注册码,显然与你非授权电脑中算出的不同,软件将在首次运行后更新id.sim中的内容,生成一个对应于未注册版本的id.sim,以后再运行自然都显示未经注册的。这里的弱点就在于一旦定位关键文件id.sim,通过简单分析就可以知道注册码保存的位置,从而修改此处的数据就可以绕过注册码的比较。这里可以采用一些算法将注册码各字符化整为零后加以存放,增加保护强度。
5、虽然算法很简单,但由于是vb写的要从一堆垃圾代码中看出来也不是很容易,你可以试一试。
给出一个伪算法:
offsetarray={-3,5,2,6,1,1,-3,5,2,6,1};
if 机器码 <= 11 thenregcode= regcode+机器码第i个字符加上对应位置的偏移量
elseregcode= regcode+机器码前11位字符中第i个字符加上对应位置的偏移量 ;注册码最长只能是11位
看不懂,还要好好学习…… - -咱也看不懂、 学习一下,呵呵,不简单啊!
跟大牛学习呢 好长,慢慢看了
页:
[1]