1. SQL Server Management Studio 실행
2. 파일 - 새로 만들기 - 데이터베이스 엔진 쿼리
3. 로그인 할 서버이름 앞에 admin: 을 붙이고 로그인 (예: (local) → admin:(local) / . → admin:. / 127.0.0.1 → admin:127.0.0.1 )
4. 아래 쿼리를 복사해서 넣고 윗 부분의 USE문과 @ObjectOwnerOrSchema, @ObjectName 값을 수정 후 실행
USE DB -- DB명 DECLARE @ObjectOwnerOrSchema NVARCHAR(128) DECLARE @ObjectName NVARCHAR(128) SET @ObjectOwnerOrSchema = 'dbo' -- 스키마 SET @ObjectName = 'Stored_Procedure' -- 프로시저 DECLARE @i INT DECLARE @ObjectDataLength INT DECLARE @ContentOfEncryptedObject NVARCHAR(MAX) DECLARE @ContentOfDecryptedObject NVARCHAR(MAX) DECLARE @ContentOfFakeObject NVARCHAR(MAX) DECLARE @ContentOfFakeEncryptedObject NVARCHAR(MAX) DECLARE @ObjectType NVARCHAR(128) DECLARE @ObjectID INT SET NOCOUNT ON SET @ObjectID = OBJECT_ID('[' + @ObjectOwnerOrSchema + '].[' + @ObjectName + ']') -- Check that the provided object exists in the database. IF @ObjectID IS NULL BEGIN RAISERROR('The object name or schema provided does not exist in the database', 16, 1) RETURN END -- Check that the provided object is encrypted. IF NOT EXISTS(SELECT TOP 1 * FROM syscomments WHERE id = @ObjectID AND encrypted = 1) BEGIN RAISERROR('The object provided exists however it is not encrypted. Aborting.', 16, 1) RETURN END -- Determine the type of the object IF OBJECT_ID('[' + @ObjectOwnerOrSchema + '].[' + @ObjectName + ']', 'PROCEDURE') IS NOT NULL SET @ObjectType = 'PROCEDURE' ELSE IF OBJECT_ID('[' + @ObjectOwnerOrSchema + '].[' + @ObjectName + ']', 'TRIGGER') IS NOT NULL SET @ObjectType = 'TRIGGER' ELSE IF OBJECT_ID('[' + @ObjectOwnerOrSchema + '].[' + @ObjectName + ']', 'VIEW') IS NOT NULL SET @ObjectType = 'VIEW' ELSE SET @ObjectType = 'FUNCTION' -- Get the binary representation of the object- syscomments no longer holds -- the content of encrypted object. SELECT TOP 1 @ContentOfEncryptedObject = imageval FROM sys.sysobjvalues WHERE objid = OBJECT_ID('[' + @ObjectOwnerOrSchema + '].[' + @ObjectName + ']') AND valclass = 1 and subobjid = 1 SET @ObjectDataLength = DATALENGTH(@ContentOfEncryptedObject)/2 -- We need to alter the existing object and make it into a dummy object -- in order to decrypt its content. This is done in a transaction -- (which is later rolled back) to ensure that all changes have a minimal -- impact on the database. SET @ContentOfFakeObject = N'ALTER ' + @ObjectType + N' [' + @ObjectOwnerOrSchema + N'].[' + @ObjectName + N'] WITH ENCRYPTION AS' WHILE DATALENGTH(@ContentOfFakeObject)/2 < @ObjectDataLength BEGIN IF DATALENGTH(@ContentOfFakeObject)/2 + 4000 < @ObjectDataLength SET @ContentOfFakeObject = @ContentOfFakeObject + REPLICATE(N'-', 4000) ELSE SET @ContentOfFakeObject = @ContentOfFakeObject + REPLICATE(N'-', @ObjectDataLength - (DATALENGTH(@ContentOfFakeObject)/2)) END -- Since we need to alter the object in order to decrypt it, this is done -- in a transaction SET XACT_ABORT OFF BEGIN TRAN EXEC(@ContentOfFakeObject) IF @@ERROR <> 0 ROLLBACK TRAN -- Get the encrypted content of the new "fake" object. SELECT TOP 1 @ContentOfFakeEncryptedObject = imageval FROM sys.sysobjvalues WHERE objid = OBJECT_ID('[' + @ObjectOwnerOrSchema + '].[' + @ObjectName + ']') AND valclass = 1 and subobjid = 1 IF @@TRANCOUNT > 0 ROLLBACK TRAN -- Generate a CREATE script for the dummy object text. SET @ContentOfFakeObject = N'CREATE ' + @ObjectType + N' [' + @ObjectOwnerOrSchema + N'].[' + @ObjectName + N'] WITH ENCRYPTION AS' WHILE DATALENGTH(@ContentOfFakeObject)/2 < @ObjectDataLength BEGIN IF DATALENGTH(@ContentOfFakeObject)/2 + 4000 < @ObjectDataLength SET @ContentOfFakeObject = @ContentOfFakeObject + REPLICATE(N'-', 4000) ELSE SET @ContentOfFakeObject = @ContentOfFakeObject + REPLICATE(N'-', @ObjectDataLength - (DATALENGTH(@ContentOfFakeObject)/2)) END SET @i = 1 --Fill the variable that holds the decrypted data with a filler character SET @ContentOfDecryptedObject = N'' WHILE DATALENGTH(@ContentOfDecryptedObject)/2 < @ObjectDataLength BEGIN IF DATALENGTH(@ContentOfDecryptedObject)/2 + 4000 < @ObjectDataLength SET @ContentOfDecryptedObject = @ContentOfDecryptedObject + REPLICATE(N'A', 4000) ELSE SET @ContentOfDecryptedObject = @ContentOfDecryptedObject + REPLICATE(N'A', @ObjectDataLength - (DATALENGTH(@ContentOfDecryptedObject)/2)) END WHILE @i <= @ObjectDataLength BEGIN --xor real & fake & fake encrypted SET @ContentOfDecryptedObject = STUFF(@ContentOfDecryptedObject, @i, 1, NCHAR( UNICODE(SUBSTRING(@ContentOfEncryptedObject, @i, 1)) ^ ( UNICODE(SUBSTRING(@ContentOfFakeObject, @i, 1)) ^ UNICODE(SUBSTRING(@ContentOfFakeEncryptedObject, @i, 1)) ))) SET @i = @i + 1 END -- PRINT the content of the decrypted object PRINT(CAST(@ContentOfDecryptedObject AS NTEXT))
프로시저 내용이 길 경우 PRINT(@ContentOfDecryptedObject) 로 하면 내용이 짤린다. 위처럼 NTEXT로 변환해주면 안짤리고 잘 나오나 NTEXT로 변환해준 것 역시 내용이 더 길어지면 역시 짤린다. PRINT로 안하고 SELECT로 하면 짤리진 않는 것 같다. SELECT로 할 경우 보기 좋게 하기 위한 추가 작업이 필요하긴 하지만. 반복문 돌리면서 @ContentOfDecryptedObject를 특정 길이만큼씩만 짤라서 PRINT 하는 것도 생각해봐야 할듯.
댓글 없음:
댓글 쓰기