摘要:本文主要從三個方面介紹了計算機軟件注冊與加密技術:DOS系統下軟件注冊與加密,Windows系統軟件注冊與加密以及共享軟件網絡注冊方法。文中介紹的許多方法現在仍在沿用,也有的方法和技術早已過時,但大都值得我們借鑒學習。在分析注冊加密過程和方法的同時,引用了不少源代碼以突出其實現過程。
關鍵詞:軟件加密、軟件注冊、共享軟件
引言<?XML:namespace prefix = o ns = "urn:schemas-microsoft-com:office:Office" />
隨著計算機科學與技術的發展,計算機軟件學科已經成為計算機科學的重要組成部分,軟件產品也在計算機產品市場上占有重要地位。由於軟件產品的可復制性和可篡改性,它能很容易的被非法復制並銷售,嚴重損害了軟件設計者的合法權益。為此,軟件設計者們經過不懈努力,精心為自己的軟件加密,以保證自己的權益不被侵犯。他們成功過,但也曾對計算機安全產生了不良影響,有的設計者為了嚴厲打擊盜版,在程序代碼中加入“邏輯炸彈”,更有甚者,設計出帶有“自殺性”和病毒的軟件,當發現有復制操作進行時,便使用這段代碼把自己銷毀並將病毒傳播出去,這些舉動都對計算機系統的安全造成威脅。
要了解當今流行的計算機軟件注冊和加密技術,我們必須首先深入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 <stdio.h>
#include <DOS.h>
int DiskIo (int drive,
int Operation,
unsigned int cylinder,
unsigned int head,
unsigned short sector,
unsigned char * buffer)
{
union REGS regs;
struct SREGS sregs;
regs.h.ah=Operation; regs.h.al=1;
regs.x.bx=FP_OFF(buffer); sregs.es=FP_SEG(buffer);
regs.h.ch=cylinder; regs.h.cl=sector;
regs.h.dh=head; regs.h.dl=drive;
int86x(0x13,®s,®s,&sregs);
return regs.h.ah;
}
最後說明一點,在設計軟件中的GetKey函數時,盡量使用本機的硬件信息和用戶名來生成密碼,再將其存入隱藏扇區,這樣使密碼既有保密性,又有安全性。
2、 使用激光穿孔法實現軟件防復制加密
這種方法主要是利用程序設計中的“陷阱技術”來實現的。基本設計思路是這樣的:在軟盤表面穿孔,使部分扇區遭到破壞,這是物理損壞,無法用工具軟件修復。設計者在開發軟件以前,用通用的檢測工具對磁盤表面全面掃描,找到已被損壞的扇區,將它們記錄下來,以後設計軟件時,只要讓軟件判斷這些扇區是否損壞就能判斷軟件是否已被復制。
對於生產少量的軟件產品而言,這種方法不失為一種經濟有效的加密方法,但是如果軟件要被大量生產,這種方法就變得更加繁雜:每次穿孔的位置不一定一樣,軟件所要判斷的扇區編號也不一樣,實現相當困難,但設計思想是值得借鑒的。
3、 特殊磁道防復制加密技術
雖然激光穿孔技術能達到很好的防復制加密效果,但其實現過程是相當復雜的。特殊磁道防復制加密技術實現簡單,也能夠很好的對軟件起到加密作用。為了簡單起見,在此僅對軟盤進行討論。
平時我們所討論的磁盤扇區都是指的數據區,其實一個扇區由標識區和數據區以及兩個間隙組成,一些磁道(柱面)的ID信息被保存在非數據區中。在DOS系統啟動的時候,軟盤磁盤基數表被裝載到起始地址為0000:0525的內存單元中,INT 13H的許多操作都是根據這一基數表來確定扇區大小的。那麼,只要我們修改磁盤基數表,再用普通的INT 13H來操作磁盤,就能很容易的將軟件密鑰寫到磁盤扇區間隙處。一般情況下,對於這種特殊扇區,磁盤控制器無法在磁盤上寫出,這樣,一般的復制程序也就無法將其復制,但在被加密的軟件程序中可以將間隙處的密鑰作為特殊扇區的一部分讀出,判斷密鑰信息就可以確定軟件是否已被復制。
以下是采用這種方法讀取一個扇區長為4096B的數據區的例子,讀取的是軟盤的0面0道,讀出的信息被保存在DS段偏移量為1000H的內存單元中。
C:Windows>debug
-e0000:0525
0000:0525 02.05 <?XML:namespace prefix = st1 ns = "urn:schemas-microsoft-com:Office:smarttags" />
-a100
1288:0100 mov ax,201
1288:0103 mov bx,1000
1288:0106 mov cx,0
1288:0109 mov dx,0
1288:
1288:010E int 3
1288:
-g=100
特殊磁道加密是這樣實現的:INT 13H AH=05H功能是根據BX所指向的內存單元的參數來對磁盤進行格式化的。上面已經提到,每個扇區都有一個ID,ID是由柱面號、磁頭號和扇區字節長度組成,那麼只要修改ID參數,並用這種奇特的參數格式化磁盤,就會產生特殊磁道。剩下的工作和對特殊扇區的操作相同:將密鑰寫入特殊磁道,就能實現軟件防復制。下面是一個對360K、DSDD磁盤磁道格式化的C語言函數,其中trktbl數組存放的就是磁盤扇區的ID參數。
int fmt_trk (int dsk, int trk, int head)
{
union REGS regs;
struct SREGS sregs;
char trktbl[36];
int i;
for (i=0;i<9;i++) {
trktbl[i*4] = trk;
trktbl[i*4+1] = head;
trktbl[i*4+2] = i;
trktbl[i*4+3] = 2;
}
regs.h.ah=0x05; regs.h.ch=trk;
regs.h.dh=head; regs.h.dl=dsk;
regs.x.bx=FP_OFF(trktbl); sregs.es=FP_SEG(trktbl);
int86x (0x13, ®s, ®s, &sregs);
return (regs.h.ah);
}
二、Windows系統下軟件注冊加密技術
1、利用Windows注冊表實現軟件注冊加密
相信大多數軟件都是采用這種方法來實現注冊功能的。Windows系統注冊表信息量相當大,幾乎所有Windows系統和計算機系統配置信息都保存在注冊表中。如果軟件密鑰被寫入注冊表,那麼尋找密鑰保存位置無異於海底撈針,不采用一定的技術(如線程跟蹤等)是無法得到密鑰的。
Windows系統注冊表有六個主鍵:HKEY_CLASS_ROOT、HKEY_CURRENT_USER、HKEY_LOCAL_MacHINE、HKEY_USERS、HKEY_CURRENT_CONFIG和HKEY_DYN_DATA。每個主鍵下面又分若干個子鍵,每個子鍵下又可新建子鍵和項,整個注冊表呈樹狀結構。每個項都有名稱和值,值可以是二進制、十進制、十六進制和字符串型。
用程序實現注冊表的操作是相當簡便的。以下Delphi程序段用以在HKEY_CURRENT_USER的子鍵Software下創建一個名為Arcobet的子鍵,並將字符串“ChenQingyang”寫入該字符串中。
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, Registry, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var regs:TRegistry;
begin
regs:=TRegistry.Create;
regs.RootKey := HKEY_CURRENT_USER;
if (not regs.OpenKey('SoftwareArcobet',False)) then
regs.CreateKey ('SoftwareArcobet');
regs.WriteString('UserName','ChenQingyang');
regs.CloseKey;
regs.Destroy;
end;
end.
2、Windows系統下的特殊磁道法
這種方法的基本原理同上述DOS下的特殊磁道法原理相同,但必須注意的是:在32bit Application中直接使用INT 13H,Windows系統會彈出保護性錯誤的對話框,禁止程序的繼續執行。
解決這種問題的基本方法是采用虛擬設備驅動程序“VWIN32.VxD”,而使用該VxD又是通過DeviceIoControl來實現的,它能完成INT 13H、INT 25H、INT 26H的各種功能。通過CreateFile打開VWIN32.VxD後獲得控制句柄,進而執行各種控制命令。打開VWIN32.VxD格式如下:
HANDLE hDevice=CreateFile (“.VWIN32”, GENERIC_WRITE|GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
在所有操作完成後,應使用CloseHandle (hDevice)來關閉打開的VWIN32.VxD。
如何使用這種方法讀寫磁盤在此不作討論,請讀者自己參考有關文獻。
三、共享軟件網上注冊方法簡介
隨著Internet的發展,共享軟件也隨之出現。共享軟件允許用戶對軟件試用,並通過Internet網上注冊的途徑來購買軟件。共享軟件有一個最大的好處就是其可試用性,通過用戶的免費試用,能及時的將使用結果反饋給軟件作者,作者便可以根據這些反饋信息對軟件的結構和功能改進。可以說,共享軟件給用戶和作者提供了更為廣泛的交流空間。另一方面,軟件購買也變的更加簡單,大大減少了軟件在市場上的周轉期,使軟件版本的更新也更快。
許多優秀的軟件如《Windows優化大師》等在被用戶使用了一段時間後都會要求用戶注冊方能繼續使用。此時,用戶應根據界面提示填寫好用戶名,程序會自動生成一個序列號,只要將這個序列號和注冊費用一起郵寄給軟件作者,便可以得到注冊碼,最後把注冊碼填入軟件指定的位置並確認後,共享軟件注冊過程就完成了。
為了方便用戶的注冊,許多共享軟件網站都有代理注冊的服務,其作用相當於用戶和作者之間的一座橋梁,幫助雙方方便的完成注冊過程。用戶只需要將序列號和注冊費上交到網站,網站定期地將用戶名單、序列號和注冊費轉交給作者,作者根據網站發送的信息生成每個用戶的注冊碼後反饋給網站,最後網站再將獲得的注冊碼分發到每個用戶手裡。
結論
軟件加密注冊方法還有很多,以軟件手段加密的比如CRC錯誤校驗法、弱位法、硬盤鎖、軟件狗等,以硬件手段加密的有硬件狗等,在此不一一說明。總之,只要我們能夠好好的利用操作系統給我們帶來的程序資源和接口,我們就能夠利用這些接口和特性設計出很好的注冊加密方法。有興趣的讀者可以按照本文介紹的方法或者參考其它文獻動手試一試,相信這樣做能給你帶來更大的收獲。
參考文獻
1、《軟件加密與計算機安全技術》孫兆林 主編 中國水利出版社 2001年9月
2、《DOS程序員參考手冊》Terry Dettmann 著 清華大學出版社 1996年1月
3、《For Win9X系統下額外磁道防復制技術》 劉興平(《電腦編程技巧與維護》2000-5)
4、《Windows系統注冊表完全精通》 電腦愛好者雜志社 2001年5月
5、《加密解密方法與實例》e-Age Technology&Development 北京騰圖電子出版社
6、《深入DOS編程》 求伯君 著 1993年
7、《Microsoft Software Developer Network(MSDN)》Microsoft Press, July 2001
8、《利用互斥磁盤鎖定保護磁盤數據》 江天送 (《電腦編程技巧與維護》2000-10)
9、《DOS6.22內核分析與內存管理技術》 肖金秀 著 中國大地出版社 1998年1月
10、CSDN網站:http://www.csdn.Net
11、DDCOPY:硬盤全盤復?h2>