sqlserver 属性 TextHeader 不可用于 StoredProcedure“[dbo].[x]”该对象可能没有此属性,也可能是访问权限不足而无法检索。 该文本已加密。
打开sqlserver proc 存储过程错误:属性 TextHeader 不可用于 StoredProcedure“[dbo].[x]”。该对象可能没有此属性,也可能是访问权限不足而无法检索。 该文本已加密。 (Microsoft.SqlServer.Smo),提示如下图错误:
注:本文基于SQLserver 2008R2,其他版本没有测试过
解决方法:
1、使用原有数据库从新导出非加密脚本重新建立数据库(略过)
2、使用解密proc方式从新生成proc脚本
步骤整理:
1、使用sql dac功能登录数据库,首先要启用dac,否则会报错:不支持专用管理员连接
1
2
3
4
5
6
7
|
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、创建解密存储表
1
2
3
4
5
6
7
8
9
|
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 |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
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 |
1
|
EXEC
dbo.DECODE_PROC 'proc名称'
|
7、查询解密存储表,会发现已经存储了要解密的proc脚本
8、将脚本拷贝到查询窗口格式化后无误,执行创建即可,原加密proc被删除了已经,新的proc已经不带有加密锁标记了
参考整理: