Khái quát

Khả năng giải mã một đối tượng bị mã hóa trong SQL Server như stored procedure, view, function hoặc trigger là những thứ tôi đã thử một vài lần. Trong bài này tôi sẽ chỉ cho bạn làm thế nào để có thể giải mã bất kỳ đối tượng SQL nào bằng cách sử dụng một đoạn script đơn giản và nêu rõ những thứ cần nhận biết.

Đầu tiên điều phiền phức của tôi khi sử dụng dấu ngoặc kép là những thứ mà bạn đã chú ý và đó là bởi vì khi bạn sử dụng “WITH ENCRYPTION” bạn thực sự chỉ đang làm ẩn đi định nghĩa của đối tượng. Quá trình để giải mã là rất đơn giản và yêu cầu chỉ một điều kiện tiên quyết Dedicated Admin Connection (DAC) và tôi sẽ giải thích sau nhưng đầu tiên tôi muốn nói về giải pháp này cần thiết thế nào

Lịch sử của giải pháp

Khi lần đầu tiên tôi cần giải mã những đối tượng cho SQL Server 2000, tôi đã luôn sử dụng một giải pháp được đăng bởi Joseph Gama dựa trên công trình của shoeboy. Đây là link tới SQL 2000 solution đó. Tuy nhiên khi tôi sử dụng giải pháp này trên SQL 2005 nó đã không còn làm việc.

Lý do tại sao giải pháp SQL 2000 đã không còn chức năng này nữa là bởi vì những giá trị của đối tượng mã hóa đã không còn xuất hiện trong cột ctext của bảng syscomments. Họ đã chuyển nó tới cột imageval của sys.sysobjvalues và chỉ có thể truy cập được nó khi sử dụng Dedicated Admin Connection (DAC).

Dedicated Admin Connection (DAC) là một kết nối đơn cho người quản trị của SQL Server để truy cập instance. Điều này là quan trọng bởi vì nó đưa quyền truy cập tới những đối tượng đã bị ẩn theo cách khác.

Vì vậy đó là khái quát cơ bản về giải pháp cập nhật này. Tôi cần giải mã những đối tượng trong những phiên bản mới hơn của SQL Server và vì vậy tôi đã viết lại một giải pháp sử dụng cùng phương thức giải mã của bản gốc nhưng sử dụng vị trí mới cho những định nghĩa của đối tượng mã hóa. Tôi cũng muốn tránh xóa những đối tượng mã hóa và vì vậy thay đổi điều này thành một alter với rollback cũng như thêm vào những kiểu đối tượng mới.

Tôi đã giữ phần viết lại của mình cho bản thân cho một thời gian cho tới khi nó được nêu lên trên diễn đàn trong năm 2010 http://social.msdn.microsoft.com/Forums/en-US/transactsql/thread/e7056ca8-94cd-4d36-a676-04c64bf96330/ .

Tôi đã nhận ra rằng có lẽ đây không đủ để nó được nhìn thấy và vì vậy tôi đã đưa nó tới một ngôi nhà mới mà ở đây hy vọng tôi có thể nhận được phản hồi và trả lời bất kỳ lỗi kỹ thuật nào (những chức năng không dựa trên tư liệu) mà không phải sửa lại bài đăng đó.

Nó hoạt động thế nào

Phương thức giải mã hoạt động giống như đã thực hiện trong tất cả những phiên bản tương tự của đoạn mã này.

Encrypted Object ^ Template Object ^ Dummy Encrypted Object

Dành cho những ai quan tâm chính xác những gì đang xảy ra vui lòng xem mục XOR_cipher trên wikipedia.

Đưa nó vào hoạt động

Để giải mã những đối tượng như tôi đã nói bạn sẽ cần truy cập một đối tượng không thể dùng được qua kết nối chuẩn vì vậy để làm được bạn cần kích hoạt Dedicated Admin Connection (DAC) nếu nó chưa được kích hoạt.

EXEC sp_configure 'remote admin connections', 1
GO
RECONFIGURE
GO

Ngoài ra nếu bạn đang sử dụng SQL Express bạn sẽ cần kích hoạt trace flag 7806.

Sau đó làm xong với cái này mở SSMS chọn File, New, Database Engine Query và cài đặt ServerName của bạn thành admin:ServerName

dac

Bước cuối cùng là đổi những dòng mã để tham chiếu tới đối tượng bạn muốn xem thông tin đã mã hóa và sau đó kiểm tra tab messages.

Đoạn mã bên dưới:

--http://jongurgul.com/blog/sql-object-decryption/
DECLARE @EncObj VARBINARY(MAX),@DummyEncObj VARBINARY(MAX),@ObjectNameStmTemplate NVARCHAR(MAX)
SET NOCOUNT ON
/*
--You must be using a DAC.
SELECT * FROM sys.dm_exec_connections ec JOIN sys.endpoints e
on (ec.[endpoint_id]=e.[endpoint_id])
WHERE e.[name]='Dedicated Admin Connection'
AND ec.[session_id] = @@SPID
*/
USE [master] --change to where your encrypted object resides
DECLARE @object_id INT,@name sysname
SELECT @object_id = [object_id],@name = [name]
FROM sys.all_objects
WHERE name = N'jjj' --<=Either put your object name here or make sure @object_id is set, and that the object it relates to is encrypted.

SELECT TOP 1
 @ObjectNameStmTemplate = [ObjectStmTemplate]
,@EncObj = [imageval]
FROM
(
SELECT
SPACE(1)+
(
CASE WHEN [type] = 'P' THEN N'PROCEDURE'
WHEN [type] = 'V' THEN 'VIEW'
WHEN [type] IN ('FN','TF','IF') THEN N'FUNCTION'
WHEN [type] IN ('TR') THEN N'TRIGGER'
ELSE [type]
END
)
+SPACE(1)+QUOTENAME(SCHEMA_NAME([schema_id]))+'.'+QUOTENAME(ao.[name])+SPACE(1)+
(
CASE WHEN [type] = 'P' THEN N'WITH ENCRYPTION AS'
WHEN [type] = 'V' THEN N'WITH ENCRYPTION AS SELECT 123 ABC'
WHEN [type] IN ('FN') THEN N'() RETURNS INT WITH ENCRYPTION AS BEGIN RETURN 1 END'
WHEN [type] IN ('TF') THEN N'() RETURNS @t TABLE(i INT) WITH ENCRYPTION AS BEGIN RETURN END'
WHEN [type] IN ('IF') THEN N'() RETURNS TABLE WITH ENCRYPTION AS RETURN SELECT 1 N'
WHEN [type] IN ('TR') THEN N' ON ' + OBJECT_NAME(ao.[parent_object_id]) + ' WITH ENCRYPTION FOR DELETE AS SELECT 1 N'
ELSE [type]
END
) +REPLICATE(CAST(N'-' AS NVARCHAR(MAX)),DATALENGTH(sov.[imageval])) COLLATE DATABASE_DEFAULT
,sov.[imageval]
FROM sys.all_objects ao
INNER JOIN sys.sysobjvalues sov ON sov.[valclass] = 1 AND ao.[Object_id] = sov.[objid]
WHERE [type] NOT IN ('S','U','PK','F','D','SQ','IT','X','PC','FS','AF','TR') AND ao.[object_id] = @object_id
UNION ALL
--Server Triggers
SELECT SPACE(1)+'TRIGGER'+SPACE(1)+QUOTENAME(st.[name])+SPACE(1)+N'ON ALL SERVER WITH ENCRYPTION FOR DDL_LOGIN_EVENTS AS SELECT 1'
 +REPLICATE(CAST(N'-' AS NVARCHAR(MAX)),DATALENGTH(sov.[imageval])) COLLATE DATABASE_DEFAULT
,sov.[imageval]
FROM sys.server_triggers st
INNER JOIN sys.sysobjvalues sov ON sov.[valclass] = 1 AND st.[object_id] = sov.[objid] WHERE st.[object_id] = @object_id
--Database Triggers
UNION ALL
SELECT SPACE(1)+'TRIGGER'+SPACE(1)+QUOTENAME(dt.[name])+SPACE(1)+N'ON DATABASE WITH ENCRYPTION FOR CREATE_TABLE AS SELECT 1'
 +REPLICATE(CAST(N'-' AS NVARCHAR(MAX)),DATALENGTH(sov.[imageval])) COLLATE DATABASE_DEFAULT
,sov.[imageval]
FROM sys.triggers dt
INNER JOIN sys.sysobjvalues sov ON sov.[valclass] = 1 AND dt.[object_id] = sov.[objid] AND dt.[parent_class_desc] = 'DATABASE' WHERE dt.[object_id] = @object_id
) x([ObjectStmTemplate],[imageval])

--Alter the existing object, then revert so that we have the dummy object encrypted value
BEGIN TRANSACTION
    DECLARE @sql NVARCHAR(MAX)
    SET @sql = N'ALTER'+@ObjectNameStmTemplate
    EXEC sp_executesql @sql
    SELECT @DummyEncObj = sov.[imageval]
    FROM sys.all_objects ao
    INNER JOIN sys.sysobjvalues sov ON sov.[valclass]=1 AND ao.[Object_id]=sov.[objid]
    WHERE ao.[object_id] = @object_id
ROLLBACK TRANSACTION

DECLARE @Final NVARCHAR(MAX)
SET @Final = N''
DECLARE @Pos INT
SET @Pos = 1
WHILE @Pos <= DATALENGTH(@EncObj)/2
BEGIN
    SET @Final = @Final + NCHAR(UNICODE(SUBSTRING(CAST(@EncObj AS NVARCHAR(MAX)),@Pos,1))^(UNICODE(SUBSTRING(N'CREATE'+@ObjectNameStmTemplate COLLATE DATABASE_DEFAULT,@Pos,1))^UNICODE(SUBSTRING(CAST(@DummyEncObj AS NVARCHAR(MAX)),@Pos,1))))
    SET @Pos = @Pos + 1
END

--If the object is small then just print, else print in chunks
IF DATALENGTH(@Final) <= 8000
BEGIN
    PRINT '--SMALL--'
    PRINT @Final
END
ELSE
BEGIN
    PRINT '--BIG--'
    DECLARE @c INT
    SET @c = 0
    WHILE @c <= (DATALENGTH(@Final)/8000)
    BEGIN
        PRINT SUBSTRING(@Final,1+(@c*4000),4000)
        SET @c = @c + 1
    END
END

Nguồn: http://jongurgul.com/blog/sql-object-decryption/

Advertisements