频道栏目
首页 > 数据库 > SQL Server > 正文
SQL存储过程解密研究
2011-05-29 11:06:04           
收藏   我要投稿
从网上搜索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(NA, (datalength(@real_01) /2 ))
乍一看没什么问题,但我们使用LEN(@real_decrypt_01)输出看看,最大输出长度为4000,可能问题就出现NVARCHAR的长度上了,理论上NVARCHAR(MAX)支持2G的大小。为什么会出现这种情况没有研究过,但有人给出了解决方法,进行显示转换:
SET @real_decrypt_01 = replicate(CONVERT(NVARCHAR(MAX), NA), (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<
点击复制链接 与好友分享!回本站首页
相关TAG标签 过程
上一篇:Windows Server 2008 r2 64bit 运行ASP提示ADODB.Connection&nb
下一篇:了解SQL Server触发器及触发器中的事务
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站