当前位置: 首页  >  SqlServer  >  SQL2005解密已经被加密的存储过程

SQL2005解密已经被加密的存储过程 TOP

第一步:打开DAC连接功能

第二步:在MASTER数据库创建一个解密存储过程

 
  1. USE master   
  2. GO   
  3. CREATE PROCEDURE [dbo].[sp__windbi$decrypt]   
  4. (   
  5.   @procedure SYSNAME = NULL ,   
  6.   @revfl INT = 1   
  7. )   
  8. AS /**//*   
  9. 王成辉翻译整理,转贴请注明出自微软BI开拓者www.windbi.com   
  10. 调用形式为:   
  11. exec dbo.sp__windbi$decrypt @procedure,0   
  12. 如果第二个参数使用1的话,会给出该存储过程的一些提示。   
  13. --版本4.0  修正存储过程过长解密出来是空白的问题   
  14. */   
  15. SET NOCOUNT ON  
  16. IF @revfl = 1    
  17.     BEGIN  
  18.         PRINT ''警告:该存储过程会删除并重建原始的存储过程。''  
  19.         PRINT '' 在运行该存储过程之前确保你的数据库有一个备份。''  
  20.         PRINT '' 该存储过程通常应该运行在产品环境的一个备份的非产品环境下。''  
  21.         PRINT '' 为了运行这个存储过程,将参数@refl的值更改为0。''  
  22.         RETURN 0   
  23.     END  
  24. DECLARE @intProcSpace BIGINT ,   
  25.     @t BIGINT ,   
  26.     @maxColID SMALLINT ,   
  27.     @procNameLength INT  
  28. SELECT  @maxColID = MAX(subobjid)   
  29. FROM    sys.sysobjvalues   
  30. WHERE   objid = OBJECT_ID(@procedure)   
  31. --select @maxColID as ''Rows in sys.sysobjvalues''   
  32. SELECT  @procNameLength = DATALENGTH(@procedure) + 29   
  33. DECLARE @real_01 NVARCHAR(MAX)   
  34. DECLARE @fake_01 NVARCHAR(MAX)   
  35. DECLARE @fake_encrypt_01 NVARCHAR(MAX)   
  36. DECLARE @real_decrypt_01 NVARCHAR(MAX) ,   
  37.     @real_decrypt_01a NVARCHAR(MAX)   
  38. DECLARE @objtype VARCHAR(2) ,   
  39.     @ParentName NVARCHAR(MAX)   
  40. SELECT  @real_decrypt_01a = ''''  
  41. --提取对象的类型如是存储过程还是函数,如果是触发器,还要得到其父对象的名称   
  42. SELECT  @objtype = type, @parentname = OBJECT_NAME(parent_object_id)   
  43. FROM    sys.objects   
  44. WHERE   [object_id] = OBJECT_ID(@procedure)   
  45. -- 从sys.sysobjvalues里提出加密的imageval记录   
  46. SET @real_01 = ( SELECT TOP 1   
  47.                         imageval   
  48.                  FROM   sys.sysobjvalues   
  49.                  WHERE  objid = OBJECT_ID(@procedureAND valclass = 1   
  50.                  ORDER BY subobjid   
  51.                )   
  52. --创建一个临时表   
  53. CREATE TABLE #output  
  54. (   
  55.   [ident] [int] IDENTITY(1, 1)   
  56.                 NOT NULL ,   
  57.   [real_decrypt] NVARCHAR(MAX)   
  58. )   
  59. ------------------------------------------------------------   
  60.   
  61. --开始一个事务,稍后回滚   
  62. BEGIN TRAN   
  63.   
  64. --更改原始的存储过程,用短横线替换   
  65. IF @objtype = ''P''    
  66.     SET @fake_01 = ''ALTER PROCEDURE '' + @procedure + '' WITH ENCRYPTION AS select 1   
  67.   /**//*'' + REPLICATE(CAST(''*'' AS NVARCHAR(MAX)),   
  68.                       DATALENGTH(@real_01) / 2 - @procNameLength) + ''*/''  
  69. ELSE    
  70.     IF @objtype = ''FN''    
  71.         SET @fake_01 = ''ALTER FUNCTION '' + @procedure + ''() RETURNS INT WITH ENCRYPTION AS BEGIN RETURN 1   
  72.   /**//*'' + REPLICATE(CAST(''*'' AS NVARCHAR(MAX)),   
  73.                       DATALENGTH(@real_01) / 2 - @procNameLength) + ''*/ END''  
  74.     ELSE    
  75.         IF @objtype = ''V''    
  76.             SET @fake_01 = ''ALTER view '' + @procedure + '' WITH ENCRYPTION AS select 1 as col   
  77.   /**//*'' + REPLICATE(CAST(''*'' AS NVARCHAR(MAX)),   
  78.                       DATALENGTH(@real_01) / 2 - @procNameLength) + ''*/''  
  79.         ELSE    
  80.             IF @objtype = ''TR''    
  81.                 SET @fake_01 = ''ALTER trigger '' + @procedure + '' ON '' + @parentname + ''WITH ENCRYPTION AFTER INSERT AS RAISERROR (''''N'''',16,10)   
  82.   /**//*'' + REPLICATE(CAST(''*'' AS NVARCHAR(MAX)),   
  83.                       DATALENGTH(@real_01) / 2 - @procNameLength) + ''*/''  
  84. EXECUTE (@fake_01)   
  85. --从sys.sysobjvalues里提出加密的假的   
  86. SET @fake_encrypt_01 = ( SELECT TOP 1   
  87.                                 imageval   
  88.                          FROM   sys.sysobjvalues   
  89.                          WHERE  objid = OBJECT_ID(@procedureAND valclass = 1   
  90.                          ORDER BY subobjid   
  91.                        )   
  92. IF @objtype = ''P''    
  93.     SET @fake_01 = ''Create PROCEDURE '' + @procedure + '' WITH ENCRYPTION AS select 1   
  94.   /**//*'' + REPLICATE(CAST(''*'' AS NVARCHAR(MAX)),   
  95.                       DATALENGTH(@real_01) / 2 - @procNameLength) + ''*/''  
  96. ELSE    
  97.     IF @objtype = ''FN''    
  98.         SET @fake_01 = ''CREATE FUNCTION '' + @procedure + ''() RETURNS INT WITH ENCRYPTION AS BEGIN RETURN 1   
  99.   /**//*'' + REPLICATE(CAST(''*'' AS NVARCHAR(MAX)),   
  100.                       DATALENGTH(@real_01) / 2 - @procNameLength) + ''*/ END''  
  101.     ELSE    
  102.         IF @objtype = ''V''    
  103.             SET @fake_01 = ''Create view '' + @procedure + '' WITH ENCRYPTION AS select 1 as col   
  104.   /**//*'' + REPLICATE(CAST(''*'' AS NVARCHAR(MAX)),   
  105.                       DATALENGTH(@real_01) / 2 - @procNameLength) + ''*/''  
  106.         ELSE    
  107.             IF @objtype = ''TR''    
  108.                 SET @fake_01 = ''Create trigger '' + @procedure + '' ON '' + @parentname + ''WITH ENCRYPTION AFTER INSERT AS RAISERROR (''''N'''',16,10)   
  109.   /**//*'' + REPLICATE(CAST(''*'' AS NVARCHAR(MAX)),   
  110.                       DATALENGTH(@real_01) / 2 - @procNameLength) + ''*/''  
  111. --开始计数   
  112. SET @intProcSpace = 1   
  113. --使用字符填充临时变量   
  114. SET @real_decrypt_01 = REPLICATE(CAST(''A'' AS NVARCHAR(MAX)),   
  115.                                  ( DATALENGTH(@real_01) / 2 ))   
  116. --循环设置每一个变量,创建真正的变量   
  117. --每次一个字节   
  118. SET @intProcSpace = 1   
  119. --如有必要,遍历每个@real_xx变量并解密   
  120. WHILE @intProcSpace <= ( DATALENGTH(@real_01) / 2 )    
  121.     BEGIN  
  122. --真的和假的和加密的假的进行异或处理   
  123.         SET @real_decrypt_01 = STUFF(@real_decrypt_01, @intProcSpace, 1,   
  124.                                      NCHAR(UNICODE(SUBSTRING(@real_01,   
  125.                                                              @intProcSpace, 1)) ^ ( UNICODE(SUBSTRING(@fake_01,   
  126.                                                               @intProcSpace, 1)) ^ UNICODE(SUBSTRING(@fake_encrypt_01,   
  127.                                                               @intProcSpace, 1)) )))   
  128.         SET @intProcSpace = @intProcSpace + 1   
  129.     END  
  130. --通过sp_helptext逻辑向表#output里插入变量   
  131. INSERT  #output ( real_decrypt )   
  132.         SELECT  @real_decrypt_01   
  133. --select real_decrypt AS ''#output chek'' from #output --测试   
  134. -- -------------------------------------   
  135. --开始从sp_helptext提取   
  136. -- -------------------------------------   
  137. DECLARE @dbname SYSNAME ,   
  138.     @BlankSpaceAdded INT ,   
  139.     @BasePos INT ,   
  140.     @CurrentPos INT ,   
  141.     @TextLength INT ,   
  142.     @LineId INT ,   
  143.     @AddOnLen INT ,   
  144.     @LFCR INT --回车换行的长度   
  145.     ,   
  146.     @DefinedLength INT ,   
  147.     @SyscomText NVARCHAR(MAX) ,   
  148.     @Line NVARCHAR(255)   
  149. SELECT  @DefinedLength = 255   
  150. SELECT  @BlankSpaceAdded = 0 --跟踪行结束的空格。注意Len函数忽略了多余的空格   
  151. CREATE TABLE #CommentText   
  152. (   
  153.   LineId INT ,   
  154.   Text NVARCHAR(255) COLLATE database_default   
  155. )   
  156. --使用#output代替sys.sysobjvalues   
  157. DECLARE ms_crs_syscom CURSOR LOCAL  
  158. FOR  
  159. SELECT  real_decrypt   
  160. FROM    #output  
  161. ORDER BY ident FOR READ ONLY  
  162. --获取文本   
  163. SELECT  @LFCR = 2   
  164. SELECT  @LineId = 1   
  165. OPEN ms_crs_syscom   
  166. FETCH NEXT FROM ms_crs_syscom INTO @SyscomText   
  167.   
  168. WHILE @@fetch_status >= 0    
  169.     BEGIN  
  170.         SELECT  @BasePos = 1   
  171.         SELECT  @CurrentPos = 1   
  172.         SELECT  @TextLength = LEN(@SyscomText)   
  173.         WHILE @CurrentPos != 0    
  174.             BEGIN  
  175.         --通过回车查找行的结束   
  176.                 SELECT  @CurrentPos = CHARINDEX(CHAR(13) + CHAR(10),   
  177.                                                 @SyscomText, @BasePos)   
  178.         --如果找到回车   
  179.                 IF @CurrentPos != 0    
  180.                     BEGIN  
  181.                 --如果@Lines的长度的新值比设置的大就插入@Lines目前的内容并继续   
  182.                         WHILE ( ISNULL(LEN(@Line), 0) + @BlankSpaceAdded + @CurrentPos - @BasePos + @LFCR ) > @DefinedLength    
  183.                             BEGIN  
  184.                                 SELECT  @AddOnLen = @DefinedLength - ( ISNULL(LEN(@Line),   
  185.                                                               0) + @BlankSpaceAdded )   
  186.                                 INSERT  #CommentText   
  187.                                 VALUES  ( @LineId,   
  188.                                           ISNULL(@Line, N'''') + ISNULL(SUBSTRING(@SyscomText,   
  189.                                                               @BasePos,   
  190.                                                               @AddOnLen), N'''') )   
  191.                                 SELECT  @Line = NULL, @LineId = @LineId + 1,   
  192.                                         @BasePos = @BasePos + @AddOnLen,   
  193.                                         @BlankSpaceAdded = 0   
  194.                             END  
  195.                         SELECT  @Line = ISNULL(@Line, N'''') + ISNULL(SUBSTRING(@SyscomText,   
  196.                                                               @BasePos,   
  197.                                                               @CurrentPos - @BasePos + @LFCR),   
  198.                                                               N'''')   
  199.                         SELECT  @BasePos = @CurrentPos + 2   
  200.                         INSERT  #CommentText   
  201.                         VALUES  ( @LineId, @Line )   
  202.                         SELECT  @LineId = @LineId + 1   
  203.                         SELECT  @Line = NULL  
  204.                     END  
  205.                 ELSE  
  206. --如果回车没找到   
  207.                     BEGIN  
  208.                         IF @BasePos <= @TextLength    
  209.                             BEGIN  
  210.                         --如果@Lines长度的新值大于定义的长度   
  211.                                 WHILE ( ISNULL(LEN(@Line), 0) + @BlankSpaceAdded + @TextLength - @BasePos + 1 ) > @DefinedLength    
  212.                                     BEGIN  
  213.                                         SELECT  @AddOnLen = @DefinedLength - ( ISNULL(LEN(@Line),   
  214.                                                               0) + @BlankSpaceAdded )   
  215.                                         INSERT  #CommentText   
  216.                                         VALUES  ( @LineId,   
  217.                                                   ISNULL(@Line, N'''') + ISNULL(SUBSTRING(@SyscomText,   
  218.                                                               @BasePos,   
  219.                                                               @AddOnLen), N'''') )   
  220.                                         SELECT  @Line = NULL,   
  221.                                                 @LineId = @LineId + 1,   
  222.                                                 @BasePos = @BasePos + @AddOnLen,   
  223.                                                 @BlankSpaceAdded = 0   
  224.                                     END  
  225.                                 SELECT  @Line = ISNULL(@Line, N'''') + ISNULL(SUBSTRING(@SyscomText,   
  226.                                                               @BasePos,   
  227.                                                               @TextLength - @BasePos + 1),   
  228.                                                               N'''')   
  229.                                 IF LEN(@Line) < @DefinedLength AND CHARINDEX('' '',   
  230.                                                               @SyscomText,   
  231.                                                               @TextLength + 1) > 0    
  232.                                     BEGIN  
  233.                                         SELECT  @Line = @Line + '' '',   
  234.                                                 @BlankSpaceAdded = 1   
  235.                                     END  
  236.                             END  
  237.                     END  
  238.             END  
  239.         FETCH NEXT FROM ms_crs_syscom INTO @SyscomText   
  240.     END  
  241.        
  242.        
  243. IF @Line IS NOT NULL    
  244.     INSERT  #CommentText   
  245.     VALUES  ( @LineId, @Line )   
  246. SELECT  Text   
  247. FROM    #CommentText   
  248. ORDER BY LineId   
  249. CLOSE ms_crs_syscom   
  250. DEALLOCATE ms_crs_syscom   
  251. DROP TABLE #CommentText   
  252. -- -------------------------------------   
  253. --结束从sp_helptext提取   
  254. -- -------------------------------------   
  255. --删除用短横线创建的存储过程并重建原始的存储过程   
  256. ROLLBACK TRAN   
  257. DROP TABLE #output  
  258. GO  

第三步:在新建查询的时候选择DAC连接

不明白的可以看一下这篇文章:SQLSERVER数据库管理员的专用连接DAC

第四步:执行之前点击一下“以文本格式显示结果”按钮

我这里被加密的存储过程存放在pratice数据库

1 USE PRATICE
2 GO
3 EXEC master.dbo.sp__windbi$decrypt ''dbo.creat_test_Encryption'', 0

 

第五步:执行刚才创建的存储过程,代入被加密的存储过程的名字然后执行查询

可以看到creat_test_Encryption这个存储过程里面的内容还是比较少的

只有一句select top 100 * from dbo.test13

 


为什麽需要使用DAC连接???

因为如果不用DAC连接是访问不了系统表的,执行的时候会报错

1 消息 208,级别 16,状态 1,过程 sp__windbi$decrypt,第 262 对象名 ''sys.sysobjvalues'' 无效。

 

Views:1724   Posted at:2013-10-24
收藏 推荐 打印 | 录入:Admin | 阅读:0