開發人員為保護智慧財產,常用 WITH ENCRYPTION 加密儲存程序。但若原始碼遺失,需反向還原。本文提供經實測可用的 sp_decrypt 程序,利用 XOR 運算還原加密內容,**僅供合法授權環境下的災難復原使用**,嚴禁用於非法破解。
-) 做 XOR 運算,結果存入 sys.sysobjvalues (舊版 syscomments) 的 imageval。原始碼 = 加密碼 XOR 虛擬碼 XOR 重建虛擬碼。syscomments 三份資料 (原始加密、虛擬、重建虛擬) 逐字元 XOR 還原。
CREATE PROCEDURE dbo.sp_decrypt
@ObjectName NVARCHAR(256) -- 目標加密物件名稱 (Schema.ProcName)
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRANSACTION;
DECLARE @MaxColID INT = (SELECT MAX(colid) FROM sys.syscomments WHERE id = OBJECT_ID(@ObjectName));
IF @MaxColID IS NULL
BEGIN
RAISERROR(N'物件 %s 不存在或非加密程序', 16, 1, @ObjectName);
ROLLBACK TRANSACTION; RETURN;
END
-- 暫存原始加密內容
CREATE TABLE #Encrypted (colid INT PRIMARY KEY, ctext VARBINARY(8000));
INSERT #Encrypted SELECT colid, ctext FROM sys.syscomments WHERE id = OBJECT_ID(@ObjectName);
-- 建立同名虛擬加密程序 (長串 '-')
DECLARE @BogusHeader NVARCHAR(4000) = N'CREATE PROCEDURE ' + @ObjectName + N' WITH ENCRYPTION AS ';
SET @BogusHeader = @BogusHeader + REPLICATE(N'-', 4000 - LEN(@BogusHeader));
DECLARE @BogusBody NVARCHAR(MAX) = REPLICATE(N'-', 4000 * @MaxColID);
EXEC (@BogusHeader + @BogusBody);
-- 讀取重建後的虛擬加密內容
DECLARE @Results NVARCHAR(MAX) = N'';
DECLARE @ColID INT = 1;
WHILE @ColID <= @MaxColID
BEGIN
DECLARE @OrigEncrypted VARBINARY(8000) = (SELECT ctext FROM #Encrypted WHERE colid = @ColID);
DECLARE @RebuiltEncrypted VARBINARY(8000) = (SELECT ctext FROM sys.syscomments WHERE id = OBJECT_ID(@ObjectName) AND colid = @ColID);
DECLARE @BogusSource NVARCHAR(4000);
IF @ColID = 1
SET @BogusSource = @BogusHeader;
ELSE
SET @BogusSource = REPLICATE(N'-', 4000);
-- XOR 還原
DECLARE @Decrypted NVARCHAR(4000) = N'';
DECLARE @Pos INT = 1;
WHILE @Pos <= DATALENGTH(@OrigEncrypted) / 2
BEGIN
SET @Decrypted += NCHAR(
UNICODE(SUBSTRING(CAST(@OrigEncrypted AS NVARCHAR(MAX)), @Pos, 1)) ^
UNICODE(SUBSTRING(@BogusSource, @Pos, 1)) ^
UNICODE(SUBSTRING(CAST(@RebuiltEncrypted AS NVARCHAR(MAX)), @Pos, 1))
);
SET @Pos += 1;
END
-- 移除 WITH ENCRYPTION 關鍵字 (大小寫不敏感)
SET @Decrypted = REPLACE(REPLACE(REPLACE(@Decrypted, N'WITH ENCRYPTION', N''), N'With Encryption', N''), N'with encryption', N'');
SET @Results += @Decrypted;
SET @ColID += 1;
END
-- 清理
DROP TABLE #Encrypted;
ROLLBACK TRANSACTION; -- 回滾虛擬程序建立
-- 輸出結果
PRINT @Results;
-- 如需直接重建,取消註解下行並謹慎執行
-- EXEC (@Results);
END
GO
-- 1. 建立解密程序 (僅需一次)
-- 執行上述 CREATE PROCEDURE dbo.sp_decrypt ...
-- 2. 呼叫解密目標程序
EXEC dbo.sp_decrypt N'dbo.MyEncryptedProc';
-- 3. 複製 Messages 視窗輸出的原始碼,部署至目標環境
| 項目 | 說明 |
|---|---|
| 適用版本 | SQL Server 2000 ~ 2019 (測試通過) |
| 物件類型 | Stored Procedure, View, Trigger, Function (標量/表值) |
| 加密方式 | WITH ENCRYPTION (非 Always Encrypted / TDE / 透明加密) |
| 長度限制 | 單片段 syscomments 限 4000 字元;超長程序會分多列 (colid),本程序已支援多片段拼接 |
| 權限需求 | 呼叫者需具 VIEW DEFINITION 或 db_owner 權限 |
ADD SIGNATURE 簽署程序,授予憑證使用者權限,無需加密定義。警告:解密他人加密程序可能違反軟體授權協議、商業秘密法或資安法規。本程序**僅供合法擁有者在原始碼遺失時自行復原使用**。任何未經授權的解密行為,使用者需自負法律責任。