forked from ktaranov/sqlserver-kit
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Decrypt T-SQL module.sql
139 lines (112 loc) · 4.27 KB
/
Decrypt T-SQL module.sql
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/*
Author: Daniel Hutmacher
Original link: https://sqlsunday.com/2013/03/24/decrypting-sql-objects/
-- Enable Dedicated Administrator Connection
EXEC sp_configure 'remote admin connections', 1;
GO
RECONFIGURE
GO
-- Who using the Dedicated Admin Connection
SELECT
CASE
WHEN ses.session_id= @@SPID THEN 'It''s me! '
ELSE '' END
+ coalesce(ses.login_name,'???') as WhosGotTheDAC,
ses.session_id,
ses.login_time,
ses.status,
ses.original_login_name
FROM sys.endpoints as en
INNER JOIN sys.dm_exec_sessions ses ON en.endpoint_id=ses.endpoint_id
WHERE en.name='Dedicated Admin Connection';
*/
SET NOCOUNT ON
DECLARE @owner sysname='dbo', @name sysname='sp_someprocedure';
-----------------------------------------------------------
--- Declarations:
DECLARE @offset int=1;
DECLARE @datalength int;
DECLARE @encrypted_object nvarchar(max);
DECLARE @decrypted_object nvarchar(max)=N'';
DECLARE @fake_object nvarchar(max);
DECLARE @fake_encrypted_object nvarchar(max);
DECLARE @lf nvarchar(max)=NCHAR(13)+NCHAR(10);
DECLARE @type varchar(128);
DECLARE @object_id int=OBJECT_ID('['+@owner+'].['+@name+']');
DECLARE @a int, @b int, @c int;
--- Check that the object exists
IF (@object_id IS NULL) BEGIN;
RAISERROR('Object does not exist.', 16, 1);
RETURN;
END;
--- Check that the object really is encrypted.
IF (NOT EXISTS (SELECT TOP 1 * FROM sys.sql_modules
WHERE [object_id]=@object_id AND [definition] IS NULL)) BEGIN;
RAISERROR('Object is not encrypted.', 16, 1);
RETURN;
END;
--- Store the SQL type name of the object in @type
SELECT @type=(CASE [type]
WHEN 'P' THEN 'PROCEDURE'
WHEN 'TR' THEN 'TRIGGER'
WHEN 'V' THEN 'VIEW'
ELSE 'FUNCTION' END)
FROM sys.objects
WHERE [object_id]=@object_id;
--- @encrypted_object is the encrypted, binary, version of the code:
SELECT TOP 1 @encrypted_object=imageval
FROM sys.sysobjvalues
WHERE [objid]=@object_id AND valclass=1 and subobjid=1;
SET @datalength=DATALENGTH(@encrypted_object)/2;
--- We're going to ALTER the existing object to a "known plaintext"
--- with encryption. That way, we can reverse-engineer the encryption
--- key, using the new encrypted object.
--- All of this is done in a transaction that we'll roll back when
--- we're done with it.
SET @fake_object=N'ALTER '+@type+N' ['+@owner+N'].['+@name+N']
WITH ENCRYPTION AS
';
--- Fill the fake object with dashes ("-") until it's as long as
--- the encrypted object.
WHILE (DATALENGTH(@fake_object)/2<@datalength) BEGIN;
IF (DATALENGTH(@fake_object)/2+4000<@datalength)
SET @fake_object=@fake_object+REPLICATE(N'-', 4000);
ELSE
SET @fake_object=@fake_object+REPLICATE(N'-',
@datalength-(DATALENGTH(@fake_object)/2));
END;
BEGIN TRANSACTION;
--- Implement the fake encrypted object:
EXEC(@fake_object);
--- Retrieve the encrypted version of the "known plaintext".
SELECT TOP 1 @fake_encrypted_object=imageval
FROM sys.sysobjvalues
WHERE [objid]=@object_id AND valclass=1 and subobjid=1;
--- Now that we have the encrypted fake object, roll back
--- the transaction, so we don't break the original object.
ROLLBACK TRANSACTION;
--- Change the @fake_object from ALTER to CREATE (because this is
--- how the encrypted objects are stored in the database!)
SET @fake_object='CREATE'+SUBSTRING(@fake_object, 6, LEN(@fake_object));
-----------------------------------------------------------
--- Perform decryption using the three versions: the encrypted
--- code, the plaintext fake code and the encrypted fake code.
WHILE (@offset<=@datalength) BEGIN;
SELECT
@a=UNICODE(SUBSTRING(@encrypted_object, @offset, 1)),
@b=UNICODE(SUBSTRING(@fake_object, @offset, 1)),
@c=UNICODE(SUBSTRING(@fake_encrypted_object, @offset, 1));
SELECT @decrypted_object=@decrypted_object+NCHAR(@a^(@b^@c)),
@offset=@offset+1;
END;
-----------------------------------------------------------
--- Print the results:
WHILE (@decrypted_object IS NOT NULL) BEGIN;
PRINT LEFT(@decrypted_object,
CHARINDEX(@lf, @decrypted_object+@lf)-1);
SET @decrypted_object=NULLIF(
SUBSTRING(@decrypted_object,
CHARINDEX(@lf, @decrypted_object+@lf)+LEN(@lf),
LEN(@decrypted_object)), '');
END;
GO