(4.16)存储过程的加密与解密

摘要:
加密的SP,获取相关创建脚本会报错。

(4.16)存储过程的加密与解密

存储过程加密概念:无法查看到过程的内容,也无法右键生成create等脚本

适用范围:从SQL2008到SQL2016,2017和2019还没试过,2005反正不行

【1】先决条件DAC

【1.1】远程DAC启用(如果本机就不用这一步)

--执行下面的SQL可以启用远程使用DAC:
Usemaster
GO
/*0 = Allow Local Connection, 1 = Allow Remote Connections*/sp_configure 'remote admin connections', 1 
GO
RECONFIGURE
GO

【1.2】SSMS启动DAC

注意,要以DAC的方式新建查询才能够使用~(详情参考:SQL Server DAC——专用管理员连接

在主菜单的“文件”中,依次选“新建”、“数据库引擎查询”,在弹出的“连接到服务器”对话窗口的“服务器名称”框中,
输入“admin:<你的实例的名称>”。

(4.16)存储过程的加密与解密第1张

(4.16)存储过程的加密与解密第2张

【2】推荐加密解密

【2.1】SP加密

usemaster
go
alter proceduresp_test
@num int withencryption
as
begin
    select 1 union all
    select 2

    select * fromtest1
    updatetest1
    set str=10
end

加密后,有把锁,如下图。

(4.16)存储过程的加密与解密第3张

加密的SP,获取相关创建脚本会报错。如下图

(4.16)存储过程的加密与解密第4张(4.16)存储过程的加密与解密第5张

【2.2】查看加密SP

--列出当前数据库中所有加密的存储过程
select DB_NAME() dbname,SCHEMA_NAME(A.schema_id) schemaname,A.name spname,case when A.object_id not in(
                                  select distinct object_id fromsys.numbered_procedures) 
                        then 0 else 1 
                        endis_numbered
from sys.all_objects A inner joinsys.sql_modules B 
on A.object_id=B.object_id  where A.type='P' and A.is_ms_shipped=0 and B.definition is null 
and A.object_id>0 and A.name not like 'dbtwin_%'
go

(4.16)存储过程的加密与解密第6张

【2.3】解密

(1)解密SP

/****** Object:  StoredProcedure [dbo].[dbtwin_sp_decrypt]    Script Date: 01/01/2020 21:09:31 ******/
IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[dbtwin_sp_decrypt]') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[dbtwin_sp_decrypt]
GO

/****** Object:  StoredProcedure [dbo].[dbtwin_sp_decrypt]    Script Date: 01/01/2020 21:09:31 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE PROCEDURE [dbo].[dbtwin_sp_decrypt](@procname sysname = NULL)
AS
DECLARE @encrypted        NVARCHAR(MAX)
DECLARE @encryptedLength  INT
DECLARE @tempStr          NVARCHAR(MAX)
DECLARE @tempHead         NVARCHAR(MAX)
DECLARE @tempBody         NVARCHAR(MAX)
DECLARE @dummySp          NVARCHAR(MAX)
DECLARE @dummyEncrypted   NVARCHAR(MAX)
DECLARE @decryptedMessage NVARCHAR(MAX)
DECLARE @cnt              INT
DECLARE @decryptedChar    NCHAR(1)

SET NOCOUNT ON
SET @encrypted = (SELECT imageval FROM sys.sysobjvalues WHERE object_name(objid)=@procname)
SET @encryptedLength=DATALENGTH(@encrypted) / 2
SET @tempStr  = N'PROCEDURE ' + @procname + N'WITH ENCRYPTION AS'

BEGIN TRAN
    SET @tempHead = N'ALTER ' + @tempStr
    SET @tempBody = REPLICATE(N' ',(@encryptedLength - LEN(@tempHead))) 
    EXEC(@tempHead + @tempBody)
    SET @dummyEncrypted = (SELECT imageval FROM sys.sysobjvalues WHERE object_name(objid)=@procname)
ROLLBACK TRAN

SET @dummySp =N'CREATE ' + @tempStr + @tempBody
SET @decryptedMessage =''
SET @cnt = 1

WHILE @cnt <> @encryptedLength
BEGIN
 SET @decryptedChar =NCHAR(UNICODE(SUBSTRING(@encrypted,      @cnt, 1)) ^
                           UNICODE(SUBSTRING(@dummySp,        @cnt, 1)) ^
                           UNICODE(SUBSTRING(@dummyEncrypted, @cnt, 1)))
 SET @decryptedChar=ISNULL(@decryptedChar,N' ')
 SET @decryptedMessage = @decryptedMessage + @decryptedChar
 SET @cnt = @cnt + 1
END
SELECT @decryptedMessage

GO

解密演示

(4.16)存储过程的加密与解密第7张

【2.4】解密优化版

/****** Object:  StoredProcedure [dbo].[dbtwin_sp_decrypt]    Script Date: 01/04/2020 19:27:12 ******/
IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[dbtwin_sp_decrypt]') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[dbtwin_sp_decrypt]
GO

/****** Object:  StoredProcedure [dbo].[dbtwin_sp_decrypt]    Script Date: 01/04/2020 19:27:12 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE PROCEDURE [dbo].[dbtwin_sp_decrypt](@procname sysname = NULL)
AS
DECLARE @encrypted        NVARCHAR(MAX)
DECLARE @encryptedLength  INT

DECLARE @tempStr          NVARCHAR(MAX)
DECLARE @tempHead         NVARCHAR(MAX)
DECLARE @tempBody         NVARCHAR(MAX)

DECLARE @dummySp          NVARCHAR(MAX)
DECLARE @dummyEncrypted   NVARCHAR(MAX)

DECLARE @decryptedMessage NVARCHAR(MAX)
DECLARE @cnt              INT
DECLARE @decryptedChar    NCHAR(1)
DECLARE @x                NVARCHAR(MAX)

SET NOCOUNT ON

SET @encrypted = (SELECT imageval FROM sys.sysobjvalues WHERE object_name(objid)=@procname)
SET @encryptedLength=DATALENGTH(@encrypted) / 2

SET @tempStr  = N'PROCEDURE ' + @procname + N'WITH ENCRYPTION AS'

BEGIN TRAN
SET @tempHead = N'ALTER ' + @tempStr
SET @x=N'-'
SET @tempBody = REPLICATE(@x,(@encryptedLength - LEN(@tempHead))) 
EXEC(@tempHead + @tempBody)
SET @dummyEncrypted = (SELECT imageval FROM sys.sysobjvalues WHERE object_name(objid)=@procname)
ROLLBACK TRAN

SET @dummySp =N'CREATE ' + @tempStr + @tempBody

SET @decryptedMessage =''
SET @cnt              = 1

WHILE @cnt <> @encryptedLength
BEGIN
 SET @decryptedChar =NCHAR(UNICODE(SUBSTRING(@encrypted,      @cnt, 1)) ^
                           UNICODE(SUBSTRING(@dummySp,        @cnt, 1)) ^
                           UNICODE(SUBSTRING(@dummyEncrypted, @cnt, 1)))
 SET @decryptedMessage = @decryptedMessage + ISNULL(@decryptedChar,N' ')
 SET @cnt = @cnt + 1
END

DECLARE @TextLength int
DECLARE @BasePos    int
DECLARE @CurrentPos int

SET @BasePos   =1
SET @CurrentPos=1
SET @TextLength = DATALENGTH(@decryptedMessage) / 2 
WHILE @CurrentPos != 0  
BEGIN  
   --通过回车查找行的结束  
   SET @CurrentPos = CHARINDEX(nchar(13)+ nchar(10), @decryptedMessage,@BasePos) 
   IF @CurrentPos != 0  
   BEGIN  
     PRINT SUBSTRING(@decryptedMessage, @BasePos, @CurrentPos - @BasePos)
   END  
   ELSE  
   BEGIN  
    IF @BasePos <= @TextLength  
    BEGIN  
     PRINT SUBSTRING(@decryptedMessage, @BasePos, @TextLength - @BasePos)
    END
   END   
   SET @BasePos = @CurrentPos + 2
END

GO

【3】另外一种方法

【3.1】SP加密

usetest
go
alter proceduresp_test
@num int withencryption
as
begin

    select 1 union all
    select 2

    select * fromtest..test1
    updatetest..test1
    set num=10,num1=10
    where id = @num
end

【3.2】解密

create proceduresp_DecryptObject 
(
    @Object sysname,    --要解密的对象名:函数,存储过程,视图或触发器
    @MaxLength int=4000 --评估内容的长度)

as
set nocount on
/*1. 解密 */
if not exists(select 1 from sys.objects a where a.object_id=object_id(@Object) And a.type in('P','V','TR','FN','IF','TF'))
begin
    --SQL Server 2008
    raiserror ( N'无效的对象!要解密的对象必须是函数,存储过程,视图或触发器。' ,16,1)
    --SQL Server 2012
    --throw 50001, N'无效的对象!要解密的对象必须是函数,存储过程,视图或触发器。',1   
    return
end
if exists(select 1 from sys.sql_modules a where a.object_id=object_id(@Object) and a.definition is not null)
begin
   --SQL Server 2008
    raiserror (N'对象没有加密!' ,16,1)
    --SQL Server 2012
    --throw 50001, N'无效的对象!要解密的对象必须是函数,存储过程,视图或触发器。',1 
    return
end
declare  @sql nvarchar(max)                --解密出来的SQL语句,@imageval nvarchar(max)        --加密字符串,@tmpStr nvarchar(max)            --临时SQL语句,@tmpStr_imageval nvarchar(max) --临时SQL语句(加密后),@type char(2)                    --对象类型('P','V','TR','FN','IF','TF'),@objectID int                    --对象ID,@i int                            --While循环使用,@Oject1 nvarchar(1000)
set @objectID=object_id(@Object)
set @type=(select a.type from sys.objects a where a.object_id=@objectID)
declare @Space4000 nchar(4000)
set @Space4000=replicate('-',4000)
/*
@tmpStr 会构造下面的SQL语句
-------------------------------------------------------------------------------
alter trigger Tr_Name on Table_Name with encryption for update as return /**/
alter proc Proc_Name with encryption  as select 1 as col /**/
alter view View_Name with encryption as select 1 as col /**/
alter function Fn_Name() returns int with encryption as begin return(0) end/**/
*/
set @Oject1=quotename(object_schema_name(@objectID))+'.'+quotename(@Object)
set @tmpStr=
        case     
            when @type ='P ' then N'Alter Procedure '+@Oject1+'with encryption as select 1 as column1 '
            when @type ='V ' then N'Alter View '+@Oject1+'with encryption as select 1 as column1 '
            when @type ='FN' then N'Alter Function '+@Oject1+'() returns int with encryption as begin return(0) end '
            when @type ='IF' then N'Alter Function '+@Oject1+'() returns table with encryption as return(Select a.name from sys.types a) '
            when @type ='TF' then N'Alter Function '+@Oject1+'() returns @t table(name nvarchar(50)) with encryption as begin return end '
            else 'Alter Trigger '+@Oject1+'on '+quotename(object_schema_name(@objectID))+'.'+(select Top(1) quotename(object_name(parent_id)) from sys.triggers a where a.object_id=@objectID)+'with encryption for update as return ' 
        end          

set @tmpStr=@tmpStr+'/*'+@Space4000
set @i=0
while @i < (ceiling(@MaxLength*1.0/4000)-1)
begin
    set @tmpStr=@tmpStr+ @Space4000
    Set @i=@i+1
end
set @tmpStr=@tmpStr+'*/'

------------
set @imageval =(select top(1) a.imageval from sys.sysobjvalues a where a.objid=@objectID and a.valclass=1)
begin tran
exec(@tmpStr)
set @tmpStr_imageval =(select top(1) a.imageval from sys.sysobjvalues a where a.objid=@objectID and a.valclass=1)
rollback tran
-------------

set @tmpStr=stuff(@tmpStr,1,5,'create')
set @sql=''
set @i=1
while @i<= (datalength(@imageval)/2)
begin
   set @sql=@sql+isnull(nchar(unicode(substring(@tmpStr,@i,1)) ^ unicode(substring(@tmpStr_imageval,@i,1))^unicode(substring(@imageval,@i,1)) ),'')
   Set @i+=1
end

/*2. 列印 */


declare @patindex int    
while @sql>''
begin
    set @patindex=patindex('%'+char(13)+char(10)+'%',@sql)
    if @patindex >0
    begin
        print substring(@sql,1,@patindex-1)
        set @sql=stuff(@sql,1,@patindex+1,'')
    end    
    else 
    begin
        set @patindex=patindex('%'+char(13)+'%',@sql)
        if @patindex >0
        begin
            print substring(@sql,1,@patindex-1)
            set @sql=stuff(@sql,1,@patindex,'')
        end
        else
        begin
           set @patindex=patindex('%'+char(10)+'%',@sql)
           if @patindex >0
            begin
                print substring(@sql,1,@patindex-1)
                set @sql=stuff(@sql,1,@patindex,'')
            end        
            else
            begin
               print @sql
               set @sql=''
            end    
        end        
    end       
end

成功破解

(4.16)存储过程的加密与解密第8张

【4】解密过程原理

SQL SERVER SP解密过程推导
在SQL SERVER里,已知微软在加密和解密存储过程时用的是RC4算法。下面是解密存储过程的解题思路,读者可以据此自己写个解密小程序。
想解密SP,其实就是解答下列一道证明题。
已知条件:
1. 已知需要解密的存储过程SP_A的密文为Ma。
2. 用一个已知明文的SP_B替换SP_A,这样得到SP_B的明文和密文分别为Tb和Mb。
求证:Ta=Ma⊕Tb⊕Mb,Ta即为需要解密的存储过程的明文。
证明过程:
1. 用DAC登录SQLSERVER,获取Ma和Mb: SELECT imageval FROM sys.sysobjvalues where …
2. 由于RC4算法的加密和解密使用的是相同的秘钥,假设秘钥为K,那么:
a. Mb=Tb⊕K
b. 根据异或运算公式,可以得到下列该存储过程加解秘时使用的秘钥为:
K=K⊕0=K⊕Tb⊕Tb=(K⊕Tb)⊕Tb=(Tb⊕K)⊕Tb=Mb⊕Tb
3. 因为Ma=Ta⊕K,则再次利用异或运算公式,得到下列推导结果:
Ta=Ta⊕0=Ta⊕(K⊕K)=(Ta⊕K)⊕K=Ma⊕K=Ma⊕Mb⊕Tb
4. 即Ta=Ma⊕Tb⊕Mb,Ta就是需要解密的存储过程的明文。

参考自:DBTWIN 无锡SQL集群服务商

免责声明:文章转载自《(4.16)存储过程的加密与解密》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇SSH Secure File Transfer上传文件错误:encountered 1 errors during the transfer解决办法字符编码及基本文件操作下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

RSA加密算法的加密与解密

转发原文链接:RSA加密算法加密与解密过程解析 1.加密算法概述   加密算法根据内容是否可以还原分为可逆加密和非可逆加密。   可逆加密根据其加密解密是否使用的同一个密钥而可以分为对称加密和非对称加密。   所谓对称加密即是指在加密和解密时使用的是同一个密钥:举个简单的例子,对一个字符串C做简单的加密处理,对于每个字符都和A做异或,形成密文S。解密的时候...

1 MySQL优化专题

优化 ER图,数据建模与数据字典 1、存储引擎选择 2、列表类型选择 3、范式 4、慢日志查询 5、精准时间记录查询 6、计划任务explain 7、索引 8、锁与事务 9、查询缓存 10、存储过程 11、触发器 12、分区(分表,分库) 14、sphinx 15、读写分离 16、搜索优化 17、网站静态优化 https://www.cnblogs.com...

mysql开发总结

一、理解MySQL基本概念   1、MySQL软件:MySQL实际上就是一软件,是一工具,是关系型数据库管理系统软件   2、MySQL数据库:就是按照数据结构来组织、存储和管理数据的仓库   3、MySQL数据库实例:     ①MySQL是单进程多线程(而oracle是多进程),也就是说MySQL实例在系统上表现就是一个服务进程,即进程;     ②M...

互联网项目中mysql应该选什么事务隔离级别 转

 出处: 互联网项目中mysql应该选什么事务隔离级别 1:一般互联网项目中mysql的事务隔离级别设置成 Read Commited 读已提交 Oracle,SqlServer 的默认事务隔离级别是读已提交(Read Commited); Mysql 的默认事务隔离级别是可重复读(Repeatable Read); 为什么mysql的默认事务级别设置成R...

MySQL的截取字符串和链接字符串函数

MySQL在查询或者更新数据的时候,有字符串函数可用。 截取字符串函数:substring、instr 用法如下: update `table` set field5 = SUBSTRING(field5 , 1 , INSTR( field5 ,'-')-1) where id = 1; //这里,要从field5里面最开始一直截取到‘-’的地方(不包...

数据库管理工具

NO1   Webyog | 管理和监控MySQL服务器的工具,官网:https://www.webyog.com/   SQLyog Ultimate V12.5 64bit 中文破解版(附注册码),下载地址:http://www.jb51.net/database/598306.html   SQLyong是一款功能强大的数据库管理程序,新版本增加更...