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   CALL  004879C8 ; 该call中调用了deviceiocontrol 来获取硬盘序列号
00849AB2   .  8BF0          MOV ESI,EAX



二、调试中遇到的一些关键位置:
0084E2CF   .  0FBF85 28FFFF>MOVSX EAX,WORD PTR SS:[EBP-D8]  
0084E2D6   .  85C0          TEST EAX,EAX                 ;关键跳转由硬盘型号决定
0084E2D8   .  0F84 8B000000 JE  0084E369   
0084E2DE   .  C745 FC 07000>MOV DWORD PTR SS:[EBP-4],7   ;串口硬盘跳到这
。。。。。。
0084E2FF   .  8985 30FFFFFF MOV DWORD PTR SS:[EBP-D0],EAX
0084E305   .  68 847D4800   PUSH  00487D84    硬盘序列号初始值MIP3HN8COML
。。。。。。
0084E369   > \C745 FC 09000>MOV DWORD PTR SS:[EBP-4],9    ;老式硬盘跳到这
0084E370   .  8B4D 08       MOV ECX,DWORD PTR SS:[EBP+8]
0084E373   .  8B11          MOV EDX,DWORD PTR DS:[ECX]
0084E375   .  8B45 08       MOV EAX,DWORD PTR SS:[EBP+8]
。。。。。。
0084E404   .  8985 28FFFFFF MOV DWORD PTR SS:[EBP-D8],EAX
0084E40A   .  C745 B0 0E000>MOV DWORD PTR SS:[EBP-50],0E
0084E411   .  C745 A8 02000>MOV DWORD PTR SS:[EBP-58],2
0084E418   .  8B45 D8       MOV EAX,DWORD PTR SS:[EBP-28]  ;算出的硬盘序列号
0084E41B   .  8985 0CFFFFFF MOV DWORD PTR SS:[EBP-F4],EAX
0084E421   .  C745 D8 00000>MOV DWORD PTR SS:[EBP-28],0
0084E428   .  8B8D 0CFFFFFF MOV ECX,DWORD PTR SS:[EBP-F4]
0084E42E   .  894D C0       MOV DWORD PTR SS:[EBP-40],ECX
0084E431   .  C745 B8 08000>MOV DWORD PTR SS:[EBP-48],8
0084E438   .  8D55 A8       LEA EDX,DWORD PTR SS:[EBP-58]
0084E43B   .  52            PUSH EDX                        
0084E43C   .  8D45 B8       LEA EAX,DWORD PTR SS:[EBP-48]
0084E43F   .  50            PUSH EAX
0084E440   .  E8 8B730400   CALL  008957D0                 ;算注册码的关键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就是保存的注册码
001939C4  7B 5C 72 74 66 31 5C 61 6E 73 69 5C 64 65 66 66  {\rtf1\ansi\deff
001939D4  30 7B 5C 66 6F 6E 74 74 62 6C 7B 5C 66 30 5C 66  0{\fonttbl{\f0\f
001939E4  6E 69 6C 5C 66 63 68 61 72 73 65 74 31 33 34 20  nil\fcharset134
001939F4  5C 27 63 62 5C 27 63 65 5C 27 63 63 5C 27 65 35  \'cb\'ce\'cc\'e5
00193A04  3B 7D 7D 0D 0A 5C 76 69 65 77 6B 69 6E 64 34 5C  ;}}..\viewkind4\
00193A14  75 63 31 5C 70 61 72 64 5C 6C 61 6E 67 32 30 35  uc1\pard\lang205
00193A24  32 5C 66 30 5C 66 73 31 38 20 57 38 3B 3C 39 3A  2\f0\fs18 W8;<9:
00193A34  32 38 55 0D 0A 5C 70 61 72 20 7D 0D 0A 00 00 00  28U..\par }.....
也就是说算出的注册码与id.sim中结尾处倒数第二个以0D 0A结尾的ascII字符串的字符相同就可以在软件开始运行时蒙混过关,成为注册版。但注册失败时id.sim中的内容发生了变化,通过分析发现了一个小秘密,下面细述。

三、保护渗透具体步骤:
1、根据软件在求硬盘序列号时的一个小小漏洞,我们可以利用一下以下这个条件判断:
0084E2D6   .  85C0          TEST EAX,EAX ;关键跳转由是否算出硬盘序列号决定
0084E2D8   .  0F84 8B000000 JE  0084E369 
简单的将其nop掉即可,这样不管是何种硬盘,算出的注册码都是JNR9IO5HQSM。

2、通过调试发现如果运行了未注册版本的软件的话,软件将自动重新生成一个新的590字节的id.sim文件(内容如下),通过对比注册成功时的128字节的id.sim文件内容可以猜测注册成功时的注册码应该是放在文件的结尾处。未注册成功时这里是空的。
00000000   7B 5C 72 74 66 31 5C 61  6E 73 69 5C 61 6E 73 69   {\rtf1\ansi\ansi
00000010   63 70 67 39 33 36 5C 64  65 66 66 30 5C 64 65 66   cpg936\deff0\def
00000020   6C 61 6E 67 31 30 33 33  5C 64 65 66 6C 61 6E 67   lang1033\deflang
00000030   66 65 32 30 35 32 7B 5C  66 6F 6E 74 74 62 6C 7B   fe2052{\fonttbl{
00000040   5C 66 30 5C 66 6E 69 6C  5C 66 63 68 61 72 73 65   \f0\fnil\fcharse
00000050   74 31 33 34 20 5C 27 63  62 5C 27 63 65 5C 27 63   t134 \'cb\'ce\'c
00000060   63 5C 27 65 35 3B 7D 7D  0D 0A 7B 5C 69 6E 66 6F   c\'e5;}}..{\info
00000070   7B 5C 68 6F 72 7A 64 6F  63 7D 7B 5C 2A 5C 6C 63   {\horzdoc}{\*\lc
00000080   68 61 72 73 20 28 5B 5C  7B 5C 27 61 31 5C 27 61   hars ([\{\'a1\'a
00000090   65 5C 27 61 31 5C 27 62  30 5C 27 61 31 5C 27 62   e\'a1\'b0\'a1\'b
000000A0   32 5C 27 61 31 5C 27 62  34 5C 27 61 31 5C 27 62   2\'a1\'b4\'a1\'b
000000B0   36 5C 27 61 31 5C 27 62  38 5C 27 61 31 5C 27 62   6\'a1\'b8\'a1\'b
000000C0   61 5C 27 61 31 5C 27 62  63 5C 27 61 31 5C 27 62   a\'a1\'bc\'a1\'b
000000D0   65 5C 27 61 33 5C 27 61  38 5C 27 61 33 5C 27 64   e\'a3\'a8\'a3\'d
000000E0   62 5C 27 61 33 5C 27 66  62 5C 27 61 33 5C 27 61   b\'a3\'fb\'a3\'a
000000F0   65 5C 27 61 31 5C 27 61  34 7D 7B 5C 2A 5C 66 63   e\'a1\'a4}{\*\fc
00000100   68 61 72 73 20 21 29 2C  2E 3A 5C 27 33 62 3F 5C   hars !),.:\'3b?\
00000110   7D 5D 5C 27 61 31 5C 27  61 32 5C 27 61 31 5C 27   }]\'a1\'a2\'a1\'
00000120   61 33 5C 27 61 31 5C 27  61 34 5C 27 61 31 5C 27   a3\'a1\'a4\'a1\'
00000130   61 35 5C 27 61 31 5C 27  61 36 5C 27 61 31 5C 27   a5\'a1\'a6\'a1\'
00000140   61 37 5C 27 61 31 5C 27  61 38 5C 27 61 31 5C 27   a7\'a1\'a8\'a1\'
00000150   61 39 5C 27 61 31 5C 27  61 61 5C 27 61 31 5C 27   a9\'a1\'aa\'a1\'
00000160   61 62 5C 27 61 31 5C 27  61 63 5C 27 61 31 5C 27   ab\'a1\'ac\'a1\'
00000170   61 64 5C 27 61 31 5C 27  61 66 5C 27 61 31 5C 27   ad\'a1\'af\'a1\'
00000180   62 31 5C 27 61 31 5C 27  62 33 5C 27 61 31 5C 27   b1\'a1\'b3\'a1\'
00000190   62 35 5C 27 61 31 5C 27  62 37 5C 27 61 31 5C 27   b5\'a1\'b7\'a1\'
000001A0   62 39 5C 27 61 31 5C 27  62 62 5C 27 61 31 5C 27   b9\'a1\'bb\'a1\'
000001B0   62 64 5C 27 61 31 5C 27  62 66 5C 27 61 31 5C 27   bd\'a1\'bf\'a1\'
000001C0   63 33 5C 27 61 33 5C 27  61 31 5C 27 61 33 5C 27   c3\'a3\'a1\'a3\'
000001D0   61 32 5C 27 61 33 5C 27  61 37 5C 27 61 33 5C 27   a2\'a3\'a7\'a3\'
000001E0   61 39 5C 27 61 33 5C 27  61 63 5C 27 61 33 5C 27   a9\'a3\'ac\'a3\'
000001F0   61 65 5C 27 61 33 5C 27  62 61 5C 27 61 33 5C 27   ae\'a3\'ba\'a3\'
00000200   62 62 5C 27 61 33 5C 27  62 66 5C 27 61 33 5C 27   bb\'a3\'bf\'a3\'
00000210   64 64 5C 27 61 33 5C 27  65 30 7D 7D 0D 0A 5C 76   dd\'a3\'e0}}..\v
00000220   69 65 77 6B 69 6E 64 34  5C 75 63 31 5C 70 61 72   iewkind4\uc1\par
00000230   64 5C 6C 61 6E 67 32 30  35 32 5C 66 30 5C 66 73   d\lang2052\f0\fs
00000240   31 38 20 0D 0A 5C 70 61  72 20 7D 0D 0A 00         18 ..\par }...
                   
因此步骤之二就是生成相应的id.sim文件。内容如下:(注意结尾处是由默认的硬盘序列号生成的默认的注册码)
00000000   7B 5C 72 74 66 31 5C 61  6E 73 69 5C 61 6E 73 69   {\rtf1\ansi\ansi
00000010   63 70 67 39 33 36 5C 64  65 66 66 30 5C 64 65 66   cpg936\deff0\def
00000020   6C 61 6E 67 31 30 33 33  5C 64 65 66 6C 61 6E 67   lang1033\deflang
00000030   66 65 32 30 35 32 7B 5C  66 6F 6E 74 74 62 6C 7B   fe2052{\fonttbl{
00000040   5C 66 30 5C 66 6E 69 6C  5C 66 63 68 61 72 73 65   \f0\fnil\fcharse
00000050   74 31 33 34 20 5C 27 63  62 5C 27 63 65 5C 27 63   t134 \'cb\'ce\'c
00000060   63 5C 27 65 35 3B 7D 7D  0D 0A 7B 5C 69 6E 66 6F   c\'e5;}}..{\info
00000070   7B 5C 68 6F 72 7A 64 6F  63 7D 7B 5C 2A 5C 6C 63   {\horzdoc}{\*\lc
00000080   68 61 72 73 20 28 5B 5C  7B 5C 27 61 31 5C 27 61   hars ([\{\'a1\'a
00000090   65 5C 27 61 31 5C 27 62  30 5C 27 61 31 5C 27 62   e\'a1\'b0\'a1\'b
000000A0   32 5C 27 61 31 5C 27 62  34 5C 27 61 31 5C 27 62   2\'a1\'b4\'a1\'b
000000B0   36 5C 27 61 31 5C 27 62  38 5C 27 61 31 5C 27 62   6\'a1\'b8\'a1\'b
000000C0   61 5C 27 61 31 5C 27 62  63 5C 27 61 31 5C 27 62   a\'a1\'bc\'a1\'b
000000D0   65 5C 27 61 33 5C 27 61  38 5C 27 61 33 5C 27 64   e\'a3\'a8\'a3\'d
000000E0   62 5C 27 61 33 5C 27 66  62 5C 27 61 33 5C 27 61   b\'a3\'fb\'a3\'a
000000F0   65 5C 27 61 31 5C 27 61  34 7D 7B 5C 2A 5C 66 63   e\'a1\'a4}{\*\fc
00000100   68 61 72 73 20 21 29 2C  2E 3A 5C 27 33 62 3F 5C   hars !),.:\'3b?\
00000110   7D 5D 5C 27 61 31 5C 27  61 32 5C 27 61 31 5C 27   }]\'a1\'a2\'a1\'
00000120   61 33 5C 27 61 31 5C 27  61 34 5C 27 61 31 5C 27   a3\'a1\'a4\'a1\'
00000130   61 35 5C 27 61 31 5C 27  61 36 5C 27 61 31 5C 27   a5\'a1\'a6\'a1\'
00000140   61 37 5C 27 61 31 5C 27  61 38 5C 27 61 31 5C 27   a7\'a1\'a8\'a1\'
00000150   61 39 5C 27 61 31 5C 27  61 61 5C 27 61 31 5C 27   a9\'a1\'aa\'a1\'
00000160   61 62 5C 27 61 31 5C 27  61 63 5C 27 61 31 5C 27   ab\'a1\'ac\'a1\'
00000170   61 64 5C 27 61 31 5C 27  61 66 5C 27 61 31 5C 27   ad\'a1\'af\'a1\'
00000180   62 31 5C 27 61 31 5C 27  62 33 5C 27 61 31 5C 27   b1\'a1\'b3\'a1\'
00000190   62 35 5C 27 61 31 5C 27  62 37 5C 27 61 31 5C 27   b5\'a1\'b7\'a1\'
000001A0   62 39 5C 27 61 31 5C 27  62 62 5C 27 61 31 5C 27   b9\'a1\'bb\'a1\'
000001B0   62 64 5C 27 61 31 5C 27  62 66 5C 27 61 31 5C 27   bd\'a1\'bf\'a1\'
000001C0   63 33 5C 27 61 33 5C 27  61 31 5C 27 61 33 5C 27   c3\'a3\'a1\'a3\'
000001D0   61 32 5C 27 61 33 5C 27  61 37 5C 27 61 33 5C 27   a2\'a3\'a7\'a3\'
000001E0   61 39 5C 27 61 33 5C 27  61 63 5C 27 61 33 5C 27   a9\'a3\'ac\'a3\'
000001F0   61 65 5C 27 61 33 5C 27  62 61 5C 27 61 33 5C 27   ae\'a3\'ba\'a3\'
00000200   62 62 5C 27 61 33 5C 27  62 66 5C 27 61 33 5C 27   bb\'a3\'bf\'a3\'
00000210   64 64 5C 27 61 33 5C 27  65 30 7D 7D 0D 0A 5C 76   dd\'a3\'e0}}..\v
00000220   69 65 77 6B 69 6E 64 34  5C 75 63 31 5C 70 61 72   iewkind4\uc1\par
00000230   64 5C 6C 61 6E 67 32 30  35 32 5C 66 30 5C 66 73   d\lang2052\f0\fs
00000240   31 38 20 4A 4E 52 39 49  4F 35 48 51 53 4D 0D 0A   18 JNR9IO5HQSM..
00000250   5C 70 61 72 20 7D 0D 0A  00                        \par }...

通过以上的两个步骤之后不管在怎样的机器上都已经是注册软件了。因为软件开始运行时我们强制让它生成了默认的注册码JNR9IO5HQSM,且与其从id.sim文件相应位置读取的注册码相同,从而程序断定现在已经通过注册了。
  
3、编制补丁程序,贴代码如下:
program Project1;
uses  SysUtils,Windows,Classes;
const
        OFFSET_FILE =$44e2d6;
        data: array[0..600] 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 );

procedure  operation();
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 then  WriteFile(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[11]={-3,5,2,6,1,1,-3,5,2,6,1};
           if 机器码 <= 11 then  regcode= regcode+机器码第i个字符加上对应位置的偏移量
           else  regcode= regcode+机器码前11位字符中第i个字符加上对应位置的偏移量 ;注册码最长只能是11位

       我不喜欢的软件通常不会浪费时间去研究它,这款软件的确不错。如果你英语学的不错了,可以推荐给你喜欢的人。谢谢大家!                          by 天易love    2009.7.30