【轉】SQL存儲過程解密

【原文】https://www.cnblogs.com/vinsonLu/p/5913242.html

首先要建立一張表和一個存儲過程:

1)建表,用於保存解密後的存儲過程SQL腳本內容

CREATE TABLE [dbo].[SQL_DECODE](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [SQLTEXT] [nvarchar](max) NOT NULL,
 CONSTRAINT [ID] PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)
) ON [PRIMARY]

GO

2)解密存儲過程DECODE_PROC
CREATE PROCEDURE [dbo].[DECODE_PROC](
    @PROC_NAME SYSNAME = NULL
)
AS
SET NOCOUNT ON

DECLARE @PROC_NAME_LEN INT    --存儲過程名長度
DECLARE @MAX_COL_ID SMALLINT    --最大列ID
SELECT @MAX_COL_ID = MAX(subobjid) FROM sys.sysobjvalues WHERE objid = OBJECT_ID(@PROC_NAME) GROUP BY imageval

SELECT @PROC_NAME_LEN = DATALENGTH(@PROC_NAME) + 29
DECLARE @REAL_01 NVARCHAR(MAX)    --真實加密存儲過程數據
DECLARE @FACK_01 NVARCHAR(MAX)    --修改爲假的存儲過程,長度(40003 - 存在過程名長度),原理不明?
DECLARE @FACK_ENCRYPT_01 NVARCHAR(MAX)    --僞加密存儲過街程數據
DECLARE @REAL_DECRYPT_01 NVARCHAR(MAX)    --最終解密後的數據,初始化爲原始加密長度的一半的“A”,原理不明?

SET @REAL_01 = (
    SELECT imageval FROM sys.sysobjvalues WHERE objid = object_id(@PROC_NAME) AND valclass = 1 AND subobjid = 1
)

DECLARE @REAL_DATA_LEN BIGINT
SET @REAL_DATA_LEN = DATALENGTH(@REAL_01)
--PRINT @REAL_DATA_LEN

DECLARE @FACK_LEN BIGINT
SET @FACK_LEN = @REAL_DATA_LEN * 10    --改造:假的長度在原真實數據長度上放大10倍

--此處需將NVARCHAR顯示轉換成NVARCHAR(MAX),不然將只能產生4K長度
SET @FACK_01 = 'ALTER PROCEDURE ' + @PROC_NAME + ' WITH ENCRYPTION AS ' + REPLICATE(CONVERT(NVARCHAR(MAX), '-'), @FACK_LEN - @PROC_NAME_LEN)
--PRINT '@FACK_01 = ' + STR(LEN(@FACK_01))
EXECUTE (@FACK_01)
SET @FACK_ENCRYPT_01 = (
    SELECT imageval FROM sys.sysobjvalues WHERE objid = object_id(@PROC_NAME) AND valclass = 1 AND subobjid = 1
)

SET @FACK_01 = 'CREATE PROCEDURE ' + @PROC_NAME + ' WITH ENCRYPTION AS ' + REPLICATE(CONVERT(VARCHAR(MAX), '-'), @FACK_LEN - @PROC_NAME_LEN)
SET @REAL_DECRYPT_01 = REPLICATE(CONVERT(NVARCHAR(MAX), N'A'), (DATALENGTH(@REAL_01) /2))
--PRINT 'LEN(@REAL_DECRYPT_01) = ' + STR(LEN(@REAL_DECRYPT_01))


--按位對 @REAL_01、 @FACK_01、 @REAL_DECRYPT_01 進行異或操作。
DECLARE @INT_PROC_SPACE BIGINT
SET @INT_PROC_SPACE = 1
WHILE @INT_PROC_SPACE <= (DATALENGTH(@REAL_01) /2 )
BEGIN
    SET @REAL_DECRYPT_01 = STUFF(
        @REAL_DECRYPT_01, 
        @INT_PROC_SPACE, 
        1, 
        NCHAR(UNICODE(SUBSTRING(@REAL_01, @INT_PROC_SPACE, 1)) ^ (UNICODE(SUBSTRING(@FACK_01, @INT_PROC_SPACE, 1)) ^ UNICODE(SUBSTRING(@FACK_ENCRYPT_01, @INT_PROC_SPACE, 1))))
    )
    SET @INT_PROC_SPACE = @INT_PROC_SPACE + 1
END

--移除WITH ENCRYPTION
SET @REAL_DECRYPT_01 = REPLACE(@REAL_DECRYPT_01, 'WITH ENCRYPTION', '')
INSERT INTO [SQL_DECODE] VALUES (@REAL_DECRYPT_01)

--PRINT '@REAL_DECRYPT_01 = ' + @REAL_DECRYPT_01
--PRINT 'LEN(@REAL_DECRYPT_01) = ' + STR(LEN(@REAL_DECRYPT_01))

--刪除原存儲過程
SET @FACK_01 = 'DROP PROCEDURE ' + @PROC_NAME
EXEC(@FACK_01)

GO

然後使用DAC登錄數據庫:admin:計算機名稱,需要在數據庫所在的電腦登錄,不能使用客戶端遠程操作這些步驟。

(DAC 登錄 通過SSMS [SQL Server xxxx Management Studio] 中的,菜單:文件----> 新建 ----> 數據庫引擎查詢,輸入admin:[本地計算機名稱],使用sa登錄。具體DAC相關知識和連接步驟,請從網絡查詢)


然後執行存儲過程:

exec dbo.DECODE_PROC '存儲過程名'

如果執行成功,SQL_DECODE表會增加一條記錄:


複製裏面的內容出來就解密後的存儲過程了。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章