摘要: 本文主要从三个方面介绍了计算机软件注册与加密技术: DOS 系统下软件注册与加密, Windows 系统软件注册与加密以及共享软件网络注册方法。文中介绍的许多方法现在仍在沿用,也有的方法和技术早已过时,但大都值得我们借鉴学习。在分析注册加密过程和方法的同时,引用了不少源代码以突出其实现过程。
关键词: 软件加密、软件注册、共享软件
引言
随着计算机科学与技术的发展,计算机软件学科已经成为计算机科学的重要组成部分,软件产品也在计算机产品市场上占有重要地位。由于软件产品的可复制性和可篡改性,它能很容易的被非法复制并销售,严重损害了软件设计者的合法权益。为此,软件设计者们经过不懈努力,精心为自己的软件加密,以保证自己的权益不被侵犯。他们成功过,但也曾对计算机安全产生了不良影响,有的设计者为了严厉打击盗版,在程序代码中加入“逻辑炸弹”,更有甚者,设计出带有“自杀性”和病毒的软件,当发现有复制操作进行时,便使用这段代码把自己销毁并将病毒传播出去,这些举动都对计算机系统的安全造成威胁。
要了解当今流行的计算机软件注册和加密技术,我们必须首先深入 DOS 系统,深刻理解 DOS 环境下的软件注册和加密的原理和实现方法。虽然 Windows 已一统天下, DOS 早已失去了它的光芒,但基于这一平台的许多软件设计思想都是值得借鉴的,因为它具有 Windows 系统不可替代的特性:对硬件操作更加方便,软件的加密方法更加多样化也更容易实现。 Windows 系统的出现,又给软件设计者们带来了新的机遇:注册表、动态连接库、多线程技术和计算机网络给软件注册和加密提供了新的途径。如果能将这两种完全不同结构的系统下软件注册加密技术结合的话,我想,所能实现的效果是任何一种技术都不可比拟的。
本文讨论的重点并不在于数据的加密过程,而是在于如何充分利用操作系统的特性和提供的 API 才能使软件加密更加安全。或者说,对于如何实现数据加密和通过什么途径来实现软件加密这两个问题,我们更加关心后者。软件加密和数据加密不同,方法不同,目的也不同,但软件加密离不开数据加密。
一、 DOS 系统下软件注册和加密技术
许多共享软件都有这样的特点:使用了一段时间后,要求用户输入用户名和注册码,用户名由用户自己定义,而注册码则需要通过付款给软件著作人的途径来取得,得到注册码后,用户将编码填入对话框后,软件便能继续使用,否则将无法运行。这一过程是一等价交换的过程:设计者获得其价值,用户获得使用价值,软件成为商品。那么,软件本身是如何知道用户填入的信息是合法的呢?其实很简单:著作人和软件本身使用了同一套注册机制,或称之为“协议”,用户并不知道这一协议,所以无法破解注册码,只能从著作人处购买。其实所有的注册型软件都有一段类似于下面的程序代码:
program MyProgram (Input, Output);
function GetKey (UserName,OtherInfo:String):KeyType;
begin
//...
end;
function Registered (UserName,OtherInfor:String;UserInput:KeyType):Boolean;
begin
if GetKey(UserName,OtherInfo)=UserInput then begin
result:=TRUE;
Exit;
end;
result:=FALSE;
end;
begin
//...
if (not Registered) then begin
ShowMessage ('Not Registered!!');
Exit;
end;
//...
end.
在这段代码中, GetKey 函数用于通过用户的用户名和一些其它信息生成注册码, Registered 函数用于返回用户是否正确注册。上面已经提到过,软件加密与数据加密不同,软件加密在注重数据加密算法的同时,更加注重数据密码的隐蔽性。下面从三个方面来介绍 DOS 系统下的常用加密技术。
1、 使用磁盘的隐藏扇区实现加密
这是最古老的加密技术。仍然是上面这个问题,为什么软件使用一段时间以后或者是使用了多少次以后,它会提示用户注册?它怎么会知道用户用了多长时间或用了多少次?我们可以这样想:在软件被安装程序安装的时候,一些记录用户合法性和安装时间的信息被写到本地计算机中,在今后运行软件时,只要判断这些信息是否合法就可以决定是让用户继续使用还是立即注册。这种方法在一定程度上也增强了软件本身的防复制性,因为复制品在其它未正确安装的机器上找不到合法用户信息,也就无法正确运行。在计算机设备中,能保存数据的最直接的地方就是磁盘,而用硬盘的隐藏扇区保存这些密码信息又最可靠。在硬盘的数据结构中,每个硬盘逻辑分区的第一个柱面是隐藏的,整个物理硬盘的最后几个柱面也是隐藏的。说它是隐藏的,也就是说,在 DOS 系统中,普通的 INT 21H 所提供的对磁盘读写的中断调用无法管辖这部分区域,要操作这部分隐藏的磁盘空间,就必须通过 INT 13H 来进行。
以下一段函数代码实现了对磁盘的任何部分(包括隐藏扇区)的读写操作,它能把一个扇区的信息读入缓冲区,也能把缓冲区中的信息存入磁盘的一个扇区。值得注意的是,这个函数只能对小于 8.4GB 的数据区进行操作,大于 8.4GB 的数据区需要 INT 13 Extension 的支持,在此不多讨论,有兴趣的读者可以参阅笔者所写的《大容量硬盘的读写操作》。对于一般的隐藏扇区加密的实现,使用这个函数已经足够了。
#include
1<stdio.h>
2
3#include <dos.h>
4
5int DiskIo (int drive,
6
7int operation,
8
9unsigned int cylinder,
10
11unsigned int head,
12
13unsigned short sector,
14
15unsigned char * buffer)
16
17{
18
19union REGS regs;
20
21struct SREGS sregs;
22
23regs.h.ah=operation; regs.h.al=1;
24
25regs.x.bx=FP_OFF(buffer); sregs.es=FP_SEG(buffer);
26
27regs.h.ch=cylinder; regs.h.cl=sector;
28
29regs.h.dh=head; regs.h.dl=drive;
30
31int86x(0x13,&regs,&regs,&sregs);
32
33return regs.h.ah;
34
35}
36
37最后说明一点,在设计软件中的 GetKey 函数时,尽量使用本机的硬件信息和用户名来生成密码,再将其存入隐藏扇区,这样使密码既有保密性,又有安全性。
38
392、 使用激光穿孔法实现软件防复制加密
40
41这种方法主要是利用程序设计中的“陷阱技术”来实现的。基本设计思路是这样的:在软盘表面穿孔,使部分扇区遭到破坏,这是物理损坏,无法用工具软件修复。设计者在开发软件以前,用通用的检测工具对磁盘表面全面扫描,找到已被损坏的扇区,将它们记录下来,以后设计软件时,只要让软件判断这些扇区是否损坏就能判断软件是否已被复制。
42
43对于生产少量的软件产品而言,这种方法不失为一种经济有效的加密方法,但是如果软件要被大量生产,这种方法就变得更加繁杂:每次穿孔的位置不一定一样,软件所要判断的扇区编号也不一样,实现相当困难,但设计思想是值得借鉴的。
44
453、 特殊磁道防复制加密技术
46
47虽然激光穿孔技术能达到很好的防复制加密效果,但其实现过程是相当复杂的。特殊磁道防复制加密技术实现简单,也能够很好的对软件起到加密作用。为了简单起见,在此仅对软盘进行讨论。
48
49平时我们所讨论的磁盘扇区都是指的数据区,其实一个扇区由标识区和数据区以及两个间隙组成,一些磁道(柱面)的 ID 信息被保存在非数据区中。在 DOS 系统启动的时候,软盘磁盘基数表被装载到起始地址为 0000:0525 的内存单元中, INT 13H 的许多操作都是根据这一基数表来确定扇区大小的。那么,只要我们修改磁盘基数表,再用普通的 INT 13H 来操作磁盘,就能很容易的将软件密钥写到磁盘扇区间隙处。一般情况下,对于这种特殊扇区,磁盘控制器无法在磁盘上写出,这样,一般的复制程序也就无法将其复制,但在被加密的软件程序中可以将间隙处的密钥作为特殊扇区的一部分读出,判断密钥信息就可以确定软件是否已被复制。
50
51以下是采用这种方法读取一个扇区长为 4096B 的数据区的例子,读取的是软盘的 0 面 0 道,读出的信息被保存在 DS 段偏移量为 1000H 的内存单元中。
52
53C:\WINDOWS>debug
54
55-e0000:0525
56
570000:0525 02.05 3F .01
58
59-a100
60
611288:0100 mov ax,201
62
631288:0103 mov bx,1000
64
651288:0106 mov cx,0
66
671288:0109 mov dx,0
68
691288: 010C int 13
70
711288:010E int 3
72
731288: 010F
74
75-g=100
76
77特殊磁道加密是这样实现的: INT 13H AH=05H 功能是根据 BX 所指向的内存单元的参数来对磁盘进行格式化的。上面已经提到,每个扇区都有一个 ID , ID 是由柱面号、磁头号和扇区字节长度组成,那么只要修改 ID 参数,并用这种奇特的参数格式化磁盘,就会产生特殊磁道。剩下的工作和对特殊扇区的操作相同:将密钥写入特殊磁道,就能实现软件防复制。下面是一个对 360K 、 DSDD 磁盘磁道格式化的 C 语言函数,其中 trktbl 数组存放的就是磁盘扇区的 ID 参数。
78
79int fmt_trk (int dsk, int trk, int head)
80
81{
82
83union REGS regs;
84
85struct SREGS sregs;
86
87char trktbl[36];
88
89int i;
90
91for (i=0;i<9;i++) {
92
93trktbl[i*4] = trk;
94
95trktbl[i*4+1] = head;
96
97trktbl[i*4+2] = i;
98
99trktbl[i*4+3] = 2;
100
101}
102
103regs.h.ah=0x05; regs.h.ch=trk;
104
105regs.h.dh=head; regs.h.dl=dsk;
106
107regs.x.bx=FP_OFF(trktbl); sregs.es=FP_SEG(trktbl);
108
109int86x (0x13, &regs, &regs, &sregs);
110
111return (regs.h.ah);
112
113}
114
115二、 Windows 系统下软件注册加密技术
116
1171、 利用 Windows 注册表实现软件注册加密
118
119相信大多数软件都是采用这种方法来实现注册功能的。 Windows 系统注册表信息量相当大,几乎所有 Windows 系统和计算机系统配置信息都保存在注册表中。如果软件密钥被写入注册表,那么寻找密钥保存位置无异于海底捞针,不采用一定的技术(如线程跟踪等)是无法得到密钥的。
120
121Windows 系统注册表有六个主键: HKEY_CLASS_ROOT 、 HKEY_CURRENT_USER 、 HKEY_LOCAL_MACHINE 、 HKEY_USERS 、 HKEY_CURRENT_CONFIG 和 HKEY_DYN_DATA 。每个主键下面又分若干个子键,每个子键下又可新建子键和项,整个注册表呈树状结构。每个项都有名称和值,值可以是二进制、十进制、十六进制和字符串型。
122
123用程序实现注册表的操作是相当简便的。以下 Delphi 程序段用以在 HKEY_CURRENT_USER 的子键 Software 下创建一个名为 Arcobet 的子键,并将字符串“ ChenQingyang ”写入该字符串中。
124
125unit Unit1;
126
127interface
128
129uses
130
131Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, Registry, StdCtrls;
132
133type
134
135TForm1 = class(TForm)
136
137Button1: TButton;
138
139procedure Button1Click(Sender: TObject);
140
141private
142
143{ Private declarations }
144
145public
146
147{ Public declarations }
148
149end;
150
151var
152
153Form1: TForm1;
154
155implementation
156
157{$R *.dfm}
158
159procedure TForm1.Button1Click(Sender: TObject);
160
161var regs:TRegistry;
162
163begin
164
165regs:=TRegistry.Create;
166
167regs.RootKey := HKEY_CURRENT_USER;
168
169if (not regs.OpenKey('Software\Arcobet',False)) then
170
171regs.CreateKey ('Software\Arcobet');
172
173regs.WriteString('UserName','ChenQingyang');
174
175regs.CloseKey;
176
177regs.Destroy;
178
179end;
180
181end.
182
1832、 Windows 系统下的特殊磁道法
184
185这种方法的基本原理同上述 DOS 下的特殊磁道法原理相同,但必须注意的是:在 32bit Application 中直接使用 INT 13H , Windows 系统会弹出保护性错误的对话框,禁止程序的继续执行。
186
187解决这种问题的基本方法是采用虚拟设备驱动程序“ VWIN32.VxD ”,而使用该 VxD 又是通过 DeviceIoControl 来实现的,它能完成 INT 13H 、 INT 25H 、 INT 26H 的各种功能。通过 CreateFile 打开 VWIN32.VxD 后获得控制句柄,进而执行各种控制命令。打开 VWIN32.VxD 格式如下:
188
189HANDLE hDevice=CreateFile (“ \\\\\\\\.\\\VWIN32 ”, GENERIC_WRITE|GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
190
191在所有操作完成后,应使用 CloseHandle (hDevice) 来关闭打开的 VWIN32.VxD 。
192
193如何使用这种方法读写磁盘在此不作讨论,请读者自己参考有关文献。
194
195三、共享软件网上注册方法简介
196
197随着 Internet 的发展,共享软件也随之出现。共享软件允许用户对软件试用,并通过 Internet 网上注册的途径来购买软件。共享软件有一个最大的好处就是其可试用性,通过用户的免费试用,能及时的将使用结果反馈给软件作者,作者便可以根据这些反馈信息对软件的结构和功能改进。可以说,共享软件给用户和作者提供了更为广泛的交流空间。另一方面,软件购买也变的更加简单,大大减少了软件在市场上的周转期,使软件版本的更新也更快。
198
199许多优秀的软件如《 Windows 优化大师》等在被用户使用了一段时间后都会要求用户注册方能继续使用。此时,用户应根据界面提示填写好用户名,程序会自动生成一个序列号,只要将这个序列号和注册费用一起邮寄给软件作者,便可以得到注册码,最后把注册码填入软件指定的位置并确认后,共享软件注册过程就完成了。
200
201为了方便用户的注册,许多共享软件网站都有代理注册的服务,其作用相当于用户和作者之间的一座桥梁,帮助双方方便的完成注册过程。用户只需要将序列号和注册费上交到网站,网站定期地将用户名单、序列号和注册费转交给作者,作者根据网站发送的信息生成每个用户的注册码后反馈给网站,最后网站再将获得的注册码分发到每个用户手里。
202
203结论
204
205软件加密注册方法还有很多,以软件手段加密的比如 CRC 错误校验法、弱位法、硬盘锁、软件狗等,以硬件手段加密的有硬件狗等,在此不一一说明。总之,只要我们能够好好的利用操作系统给我们带来的程序资源和接口,我们就能够利用这些接口和特性设计出很好的注册加密方法。有兴趣的读者可以按照本文介绍的方法或者参考其它文献动手试一试,相信这样做能给你带来更大的收获。
206
207参考文献
208
2091 、《软件加密与计算机安全技术》孙兆林 主编 中国水利出版社 2001 年 9 月
210
2112 、《 DOS 程序员参考手册》 Terry Dettmann 著 清华大学出版社 1996 年 1 月
212
2133 、《 For Win9X 系统下额外磁道防复制技术》 刘兴平(《电脑编程技巧与维护》 2000-5 )
214
2154 、《 Windows 系统注册表完全精通》 电脑爱好者杂志社 2001 年 5 月
216
2175 、《加密解密方法与实例》 e-Age Technology&Development 北京腾图电子出版社
218
2196 、《深入 DOS 编程》 求伯君 著 1993 年
220
2217 、《 Microsoft Software Developer Network ( MSDN )》 Microsoft Press, July 2001
222
2238 、《利用互斥磁盘锁定保护磁盘数据》 江天送 (《电脑编程技巧与维护》 2000-10 )
224
2259 、《 DOS6.22 内核分析与内存管理技术》 肖金秀 著 中国大地出版社 1998 年 1 月
226
22710 、 CSDN 网站: http://www.csdn.net
228
22911 、 DDCOPY :硬盘全盘复制软件: http://ddcopy.yeah.net</dos.h></stdio.h>