首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> Delphi

Delphi 編譯軟體版權保護元件:主機板序列號綁定、運行次數限制與註冊碼驗證完整實作

     編輯:Delphi

設計目標

  • 硬體綁定:讀取主機板序列號作為機器碼
  • 試用限制:最大運行次數 (如 30 次)
  • 註冊機制:機器碼 = 註冊碼才能正式使用
  • 防破解:運行計數寫入系統目錄偽裝檔案、日期修改無效
  • 元件化:拖放即用,屬性設定公司名、郵箱、試用次數

核心元件類別


type
  TRegObj = class
  private
    FSerial: string;      // 主機板序列號
    FKey: string;         // 使用者註冊碼
    FMaxTimes: Integer;   // 最大試用次數
    FCompany: string;     // 公司名
    FEmail: string;       // 聯繫郵箱
  protected
    procedure GetSerial;           // 讀取主機板序列號
    procedure GetKey;              // 讀取註冊檔
    function GetTimes: Integer;    // 讀取/遞增運行計數
    function CheckKey: Boolean;    // 驗證註冊碼
  public
    constructor Create;
    function Execute: Boolean;     // 執行保護邏輯
  published
    property Company: string read FCompany write FCompany;
    property MaxTimes: Integer read FMaxTimes write FMaxTimes;
    property Email: string read FEmail write FEmail;
  end;

關鍵實作細節

讀取主機板序列號 (舊技巧,現代需 WMI/SMBIOS)


procedure TRegObj.GetSerial;
begin
  FSerial := String(PChar(Ptr($FEC71))); // 直接讀取 BIOS 記憶體區段 (僅 Win9x/舊機型有效)
end;

現代替代:使用 WMIC BaseBoard Get SerialNumber 或 ISWbemLocator 查詢 Win32_BaseBoard。

運行計數存儲 (偽裝 DLL 檔案)


function TRegObj.GetTimes: Integer;
const Tmp = 'ispnet.dll'; // 偽裝系統 DLL 名稱
var
  List: TStringList; Ch: Char; Dir: array[0..255] of Char; Fn: string; I: Integer;
begin
  GetSystemDirectory(@Dir, 255);
  for I := 0 to 255 do if Ord(Dir[I]) = 0 then Break else Fn := Fn + Dir[I];
  Fn := Fn + '\' + Tmp;
  List := TStringList.Create;
  try
    if not FileExists(Fn) then Ch := #1
    else begin List.LoadFromFile(Fn); Ch := List.Text[1]; Ch := Chr(Ord(Ch) + 1); end;
    List.Text := Ch; List.SaveToFile(Fn);
    Result := Ord(Ch);
  finally List.Free; end;
end;

註冊碼讀取與驗證


procedure TRegObj.GetKey;
const Sn = 'Key.dat';
var List: TStringList; Fn, Path: string;
begin
  Path := ExtractFilePath(Application.ExeName);
  Fn := Path + Sn;
  if not FileExists(Fn) then begin FKey := ''; Exit; end;
  List := TStringList.Create;
  try List.LoadFromFile(Fn); FKey := List.Values['Key']; finally List.Free; end;
end;

function TRegObj.CheckKey: Boolean;
begin Result := (FKey = FSerial); end; // 簡單比對,實際可加密/雜湊

執行邏輯


function TRegObj.Execute: Boolean;
var Msg: string; T: Integer;
begin
  T := GetTimes;
  GetKey; GetSerial;
  if FKey <> FSerial then begin
    Msg := Format('這是第 %d 次運行 (最多 %d 次)!', [T, FMaxTimes]);
    Application.MessageBox(PChar(Msg), '使用者資訊', MB_OK + MB_ICONWARNING);
    Msg := '歡迎使用 ' + Company + ' 軟體,滿意請購買正版!';
    Application.MessageBox(PChar(Msg), '建議', MB_OK + MB_ICONINFORMATION);
    if T > FMaxTimes then begin
      if Application.MessageBox('是否註冊?', '註冊', MB_YESNO + MB_ICONQUESTION) = ID_YES then begin
        Msg := '您的註冊碼是:"' + FSerial + '"' + #13#10 + '請 Email 至:' + FEmail;
        Application.MessageBox(PChar(Msg), '軟體註冊', MB_OK + MB_ICONINFORMATION);
      end;
      Application.Terminate;
    end;
  end;
  Result := True;
end;

使用方式


procedure TForm1.FormCreate(Sender: TObject);
var Obj: TRegObj;
begin
  Obj := TRegObj.Create;
  try
    Obj.MaxTimes := 30;
    Obj.Company := '吉星軟體工作室';
    Obj.Email := 'test@1112.net';
    Obj.Execute;
  finally Obj.Free; end;
end;

安全性評估與改進建議

弱點改進方向
主機板序列號讀取不可靠 (舊 BIOS 位址)改用 WMI Win32_BaseBoard 或 Win32_Processor (ProcessorId)
註冊碼明文比對,易被 Keygen非對稱加密 (RSA/ECC) 簽名驗證,或雜湊 + 鹽值
計數檔案易被刪除/修改寫入 Registry 隱藏鍵值、加密儲存、多重備份校驗
無網路驗證,離線破解容易引入線上授權伺服器、硬體鎖 (USB Dongle)
Application.Terminate 可被 Hook 繞過關鍵邏輯執行 Halt(0)、執行緒終止、關鍵函數完整性校驗

總結

此元件展示了 Delphi 版權保護的**經典單機模式邏輯**:硬體指紋 + 本地計數 + 註冊碼比對。雖具教學價值,但現代商業軟體需結合**非對稱加密授權、線上驗證、虛擬機偵測、反調試、代碼混淆**等多層防護。建議作為學習基礎,實際產品請採用成熟授權方案 (如 Enigma Protector、VMProtect、自建授權伺服器)。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved