从网上搜索SQL存储过程解密,可以看到一大堆的资料,其内容都基本上都一致,这是先放上一篇:
解密存储过程
本文将以此为基础进行研究,虽能解密成功,但其中解密那一段究其原理是到底是什么,一直也弄不明白,望了解内情的朋友告知。
先谈问题:
网上得来的存储过和经试验存在几个问题:
1、并没有删除原存储重建,仅仅在控制台做了一个输出,拷贝出来很不方便。
2、对于长度大点的加密数据会解密失败。
带着这两个问题来改造此存储过程。

先做准备工作,首先需要知道DAC这么个东西, 指的是数据库专用管理员连接,为管理员提供的一种特殊的诊断连接。
知道了后得先打开它,以SQL2008为例:
右击“对象浏览器”,找到“Facets”,点击,如图:
 
找到“Sruface Area Configuration”,选择“RemoteDacEnabled”,设为True:

然后进行DAC登录,CMD模式下敲如下命令,不清楚原理的可以自行研究:
sqlcmd -A -S 192.168.1.101 -U sa -P 123456 
命令提示行下打开需处理的数据库:
>USE TEST
>GO

准备就绪,复制搜索得到的存储过程(这里有些语法问题,做些小调整即可),生成解密存储程,然后我们准备两个加密后的存储过程,其中一个长度较大(可自行循环创建一个500行的存储程,本文不再提供),验证得出结论,短小的存储过程很快即解密成功,并输出,但长度较大的却解密失败。
接下来看看其如何解密的:
先看这句
select @maxColID = max(subobjid),@intEncrypted = imageval FROM sys.sysobjvalues WHERE objid = object_id(@procedure)
指的是加密后的数据存放在“sys.sysobjvalues”表中,其内容存放于“imageval”字段。

知道了加密后的数据,就得进行解密,它定义了4个关键字段:
DECLARE @real_01 nvarchar(max)
DECLARE @fake_01 nvarchar(max)
DECLARE @fake_encrypt_01 nvarchar(max)
DECLARE @real_decrypt_01 nvarchar(max)
分别指的原始加密数据内容、原始加密存储过程的CREATE语句、自己构造的假的存储过程加密后的数据、最终解密后的存储过程。
其方法是按位将@real_01、@fake_encrypt_01、@real_decrypt_01进行异或运算,此处为何如此处理,原理不明!!!
WHILE @intProcSpace<=(datalength(@real_01)/2)
BEGIN
--xor real & fake & fake encrypted
SET @real_decrypt_01 = stuff(@real_decrypt_01, @intProcSpace, 1,NCHAR(UNICODE(substring(@real_01, @intProcSpace, 1)) ^(UNICODE(substring(@fake_01, @intProcSpace, 1)) ^UNICODE(substring(@fake_encrypt_01, @intProcSpace, 1)))))
SET @intProcSpace=@intProcSpace+1
END
实际上到此为止,加密后的存储过程已解密出来了。

其下面还有一大段语句没有仔细研究,但基本上是利用sp_helptext将内容输出,方法比较繁索,而且没有达到我们要的效果,我们将换一种方法进行输出。
基本上就这么简单,除了原理不清楚外,基本上已达到要求,接下来要解决开始提出的两个问题。
首先是长度问题,为什么长度一大就解密失败,来看看@real_decrypt_01的定义并进行初始化@real_decrypt_01的语句:
DECLARE @real_decrypt_01 nvarchar(max)
SET @real_decrypt_01 = replicate(N'A', (datalength(@real_01) /2 ))
乍一看没什么问题,但我们使用LEN(@real_decrypt_01)输出看看,最大输出长度为4000,可能问题就出现NVARCHAR的长度上了,理论上NVARCHAR(MAX)支持2G的大小。为什么会出现这种情况没有研究过,但有人给出了解决方法,进行显示转换:
SET @real_decrypt_01 = replicate(CONVERT(NVARCHAR(MAX), N'A'), (datalength(@real_01) /2 ))
其它的几还有几处也是该原因,改正后进行重新运行,问题解决,长度较大的存储过程也解密成功。

第一个问题解决了,如何能方便的输出呢,试验了删除重建,但未成功,那么就用最简单的方法吧,利用xp_cmdshell将内容输出到文本。
先建立一个物理表,用于存储解密后的数据:

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

然后建立一个存储过程,遍历所有加密过的存储过程,调用解密存储过程进行解密,解密后输出:

CREATE PROCEDURE [dbo].[DECODE_DATABASE]
AS
SET NOCOUNT ON
BEGIN

DECLARE @PROC_NAME VARCHAR(256)
SET @PROC_NAME = ''
DECLARE @ROWS INT
DECLARE @TEMP TABLE(
NAME VARCHAR(256)
)
INSERT INTO @TEMP SELECT NAME FROM sysobjects WHERE TYPE = 'P'
AND NAME NOT IN (
'DECODE_DATABASE', 'DECODE_PROC'
)
SET @ROWS = @@ROWCOUNT
WHILE @ROWS > 0
BEGIN
SELECT @PROC_NAME = NAME FROM (
SELECT ROW_NUMBER() OVER (ORDER by NAME) AS ROW, NAME FROM @TEMP
) T
WHERE ROW = @ROWS
EXEC [DECODE_PROC] @PROC_NAME
PRINT @PROC_NAME
SET @ROWS = @ROWS - 1
END

RETURN

EXEC master..xp_cmdshell 'bcp "SELECT [SQLTEXT] FROM TEST.dbo.[SQL_DECODE]" queryout C:\decode.txt -c -T -S PC2011043012JUJ'
END

GO

最后是改造后的存储过程:

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

至此,解密全过程大功告成,命令行模式下运行:
>EXEC [DECODE_DATABASE]
>GO
在C盘根目录下,解密后的存储过程文本生成成功。
运行前别忘记打开xp_cmdshell使用权限,同打开DAC一样:

或者命令行模式下敲如下命令:
>sp_configure 'show advanced options',1
>reconfigure
>go
>sp_configure 'xp_cmdshell',1
>reconfigure
>go

转载于:https://www.cnblogs.com/FlySoul/archive/2011/05/13/FM.html

SQL存储过程解密研究相关推荐

  1. Sql存储过程加密和解密

    可用于加密SQL存储过程或者触发器(这是SQL Server本身提供的,也就是说这是微软的加密算法) http://www.mscto.com 使用 WITH ENCRYPTION 选项 WITH E ...

  2. SQL2005存储过程解密

    问题一: DAC连接问题 自己尝试了n次,最后总结一下连接步骤: 1 先用有sysadmin角色的用户登陆SQL Server Management Studio: 2 在工具栏上选数据库引擎查询:服 ...

  3. sql存储过程编写_您可以针对任何存储过程编写三个标准SQL单元测试

    sql存储过程编写 This article talks about the three standard SQL unit tests which can be written against an ...

  4. SQL2008,SQL2005存储过程解密

    下载:附件 SQL2008,SQL2005存储过程解密 第一步操作步骤:'程序'->'Sql Server2005'-> '配置工具'-> 'Sql Server 外围应用配置器'- ...

  5. SQL存储过程(☆)

    1.sql存储过程概述 2.SQL存储过程创建 3.sql存储过程及应用 4.各种存储过程使用指南 5.ASP中存储过程调用的两种方式及比较 6.SQL存储过程在.NET数据库中的应用 7.使用SQL ...

  6. access下的分页方案(仿sql存储过程)

    using System; using System.Collections.Generic; using System.Text; using System.Data; using System.D ...

  7. SQL存储过程实例具体解释

    SQL存储过程实例具体解释 本文用3个题目,从建立数据库到创建存储过程,具体解说数据库的功能. 题目1 学校图书馆借书信息管理系统建立三个表: 学生信息表:student 字段名称 数据类型 说明 s ...

  8. sql 解析字符串添加到临时表中 sql存储过程in 参数输入

    sql 解析字符串添加到临时表中  sql存储过程in 参数输入 解决方法 把字符串解析 添加到 临时表中 SELECT * into #临时表   FROM dbo.Func_SplitOneCol ...

  9. SQL存储过程分页(通用的拼接SQL语句思路实现)

    多表通用的SQL存储过程分页 案例一: USE [Community] GO/****** Object: StoredProcedure [dbo].[Common_PageList] Script ...

最新文章

  1. 蓝桥杯 历届试题 九宫重排
  2. CISCO路由器配置手册--第五章 虚拟局域网(VLAN)路由
  3. 盘它:1200 天积淀,超 750 篇干货,为你甄选这 100 + 篇精华!
  4. 使用Jackson和Super类型令牌进行Json反序列化
  5. 电脑键盘练习_用键盘打字怎样才能练得快,有什么窍门没?
  6. Qt文档阅读笔记-stackUnder官方解析与实例
  7. 动态规划——雇佣员工(hdu1158)
  8. #内存不够,swap来凑# Linux上创建SWAP文件/分区
  9. 标准模板库(STL)之 list 列传
  10. linux如何杀死ping进程,linux下ping命令使用详解
  11. jQuery实现页面元素置顶时悬浮
  12. 高德地图在android上的开发汇总
  13. cmos和ttl_TTL和CMOS的比较
  14. macOS 汇编指南
  15. java读取mp3文件_java读取mp3文件 | 学步园
  16. Excel表格的35招必学秘技,必看!
  17. 学习《User and entity behavior analysis under urban big data》(UEBA)
  18. 基于 WebRTC 的 P2P 文件传输
  19. NIST原子光谱数据库使用说明
  20. C语言对于变量如何取整,C语言如何进行取整

热门文章

  1. python怎么安装matplotlib-python安装matplotlib
  2. python中的装饰器有哪些-python 装饰器以及开发中常用的例子
  3. python界面设计-python图形化界面设计tkinter
  4. python画折线图详解-利用python画出折线图
  5. 学python编程-趣学python编程中文版 PDF 下载
  6. 普通人学python有用吗-普通人学Python有什么用?
  7. python装饰器类-Python装饰器15-开始使用类作为装饰器
  8. python实现文件下载-Python 实现文件下载
  9. python创建打开文件-Python文件处理:创建、打开、追加、
  10. 零基础自学python的建议-你是如何自学 Python 的?