sqlserver 屬性 TextHeader 不可用於 StoredProcedure“[dbo].[x]”該物件可能沒有此屬性,也可能是訪問許可權不足而無法檢索。 該文字已加密。

龐順龍發表於2019-05-10

開啟sqlserver proc 儲存過程錯誤:屬性 TextHeader 不可用於 StoredProcedure“[dbo].[x]”。該物件可能沒有此屬性,也可能是訪問許可權不足而無法檢索。  該文字已加密。 (Microsoft.SqlServer.Smo),提示如下圖錯誤:

注:本文基於SQLserver 2008R2,其他版本沒有測試過

解決方法:

1、使用原有資料庫從新匯出非加密指令碼重新建立資料庫(略過)

2、使用解密proc方式從新生成proc指令碼

步驟整理:

1、使用sql dac功能登入資料庫,首先要啟用dac,否則會報錯:不支援專用管理員連線

USE master;
GO
SP_CONFIGURE'remote admin connections';
SP_CONFIGURE 'remote admin connections', 1; --0 表示僅允許本地連線使用 DAC,1表示允許遠端連線使用 DAC
GO
RECONFIGURE WITH OVERRIDE;
GO

選擇新建連線->資料庫引擎查詢,然後輸入admin:機器名登入即可。


連線中可能出現如下錯誤:

這說明已經連線過併成功,不能再次連線,也可以使用sql配置管理器重啟sqlserver服務,從新來過

2、成功使用DAC功能登入後,如下圖:


3、選擇要解密操作的資料庫

4、建立解密儲存表

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
5、建立解密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
6、執行解密proc

EXEC dbo.DECODE_PROC 'proc名稱'

7、查詢解密儲存表,會發現已經儲存了要解密的proc指令碼

8、將指令碼拷貝到查詢視窗格式化後無誤,執行建立即可,原加密proc被刪除了已經,新的proc已經不帶有加密鎖標記了


參考整理:

SQLSERVER資料庫管理員的專用連線DAC 

SQL2005解密已經被加密的儲存過程

[SQL Server 2005/2008]專用管理員連線(DAC)

龐順龍最後編輯於:3年前

內容均為作者獨立觀點,不代表八零IT人立場,如涉及侵權,請及時告知。

相關文章