Stack Overflow profile for md5sum

Thursday, March 20, 2008

SQL Stored Procedure Decryptor

This script will decrypt an encrypted stored procedure in your database. Please note that in order to use this stored procedure, you must be connected as a remote admin. In order to do this, you must first enable remote admin connections by running this:


sp_configure 'remote admin connections', 1 ;
GO

RECONFIGURE ;
GO


After that, you need to disconnect ONLY YOUR QUERY window, not object explorer. Object explorer will not connect as remote admin. Also, you will kick out any existing connections to your database when you connect as remote admin, so do not do this on a production box. To connect as remote admin, connect your query window again, but type "ADMIN:" before the server name (minus the quotes, of course), and connect using sa or an administrator account.

Then, you can edit the <catalog>, <schema>, and <object> areas (one of each) in the following query to decrypt a stored procedure.

I take absolutely NO credit for writing this, I found it on a website, and I don't remember where, but there were no credits in it where I found it.


USE [<catalog>]
GO

DECLARE @procedure sysname
SELECT@procedure = '<schema>.<object>'
DECLARE @intProcSpace bigint
DECLARE @t bigint
DECLARE @maxColID smallint
DECLARE @intEncrypted tinyint
DECLARE @procNameLength int

DECLARE @real_01 nvarchar(max)
DECLARE @fake_01 nvarchar(max)
DECLARE @fake_encrypt_01 nvarchar(max)
DECLARE @real_decrypt_01 nvarchar(max)
DECLARE @real_decrypt_01a nvarchar(max)

create table #output
(
[ident] [int] IDENTITY(1, 1)
NOT NULL
,[real_decrypt] NVARCHAR(MAX)
)

SELECT
@maxColID = max(subobjid)
FROM
sys.sysobjvalues
WHERE
objid = object_id(@procedure)

select
@procNameLength = datalength(@procedure) + 29

select
@real_decrypt_01a = ''

SET @real_01 = (
SELECT
imageval
FROM
sys.sysobjvalues
WHERE
objid = object_id(@procedure)
and valclass = 1
and subobjid = 1
)

BEGIN TRAN

SET @fake_01 = 'ALTER PROCEDURE ' + @procedure + ' WITH ENCRYPTION AS ' + REPLICATE(cast('-' as nvarchar(max)), 40003 - @procNameLength)

EXECUTE (@fake_01)

SET @fake_encrypt_01 = (
SELECT
imageval
FROM
sys.sysobjvalues
WHERE
objid = object_id(@procedure)
and valclass = 1
and subobjid = 1
)

SET @fake_01 = 'CREATE PROCEDURE ' + @procedure + ' WITH ENCRYPTION AS ' + REPLICATE(cast('-' as nvarchar(max)), 40003 - @procNameLength)

SET @intProcSpace = 1


SET @real_decrypt_01 = replicate(cast(N'A' as nvarchar(max)), (datalength(@real_01) / 2))

SET @intProcSpace = 1

WHILE @intProcSpace <= (datalength(@real_01) / 2)
BEGIN
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

insert #output (real_decrypt) select @real_decrypt_01
declare @dbname sysname
declare @BlankSpaceAdded int
declare @BasePos int
declare @CurrentPos int
declare @TextLength int
declare @LineId int
declare @AddOnLen int
declare @LFCR int
declare @DefinedLength int
declare @SyscomText nvarchar(max)
declare @Line nvarchar(255)

Select @DefinedLength = 255
SELECT @BlankSpaceAdded = 0

CREATE TABLE #CommentText ( LineId int ,Text nvarchar(255) collate database_default )

DECLARE ms_crs_syscom CURSOR LOCAL FOR
SELECT real_decrypt from #output
ORDER BY ident
FOR READ ONLY

SELECT @LFCR = 2
SELECT @LineId = 1

OPEN ms_crs_syscom

FETCH NEXT FROM ms_crs_syscom into @SyscomText

WHILE @@fetch_status >= 0
BEGIN

SELECT
@BasePos = 1
SELECT
@CurrentPos = 1
SELECT
@TextLength = LEN(@SyscomText)

WHILE @CurrentPos != 0
BEGIN

SELECT
@CurrentPos = CHARINDEX(char(13) + char(10), @SyscomText, @BasePos)


IF @CurrentPos != 0
BEGIN

While (isnull(LEN(@Line), 0) + @BlankSpaceAdded + @CurrentPos - @BasePos + @LFCR) > @DefinedLength
BEGIN
SELECT
@AddOnLen = @DefinedLength - (isnull(LEN(@Line), 0) + @BlankSpaceAdded)

INSERT
#CommentText
VALUES
(
@LineId
,isnull(@Line, N'') + isnull(SUBSTRING(@SyscomText, @BasePos, @AddOnLen), N'')
)
SELECT
@Line = NULL
,@LineId = @LineId + 1
,@BasePos = @BasePos + @AddOnLen
,@BlankSpaceAdded = 0
END

SELECT
@Line = isnull(@Line, N'') + isnull(SUBSTRING(@SyscomText, @BasePos, @CurrentPos - @BasePos + @LFCR), N'')
SELECT
@BasePos = @CurrentPos + 2

INSERT
#CommentText
VALUES
(@LineId, @Line)
SELECT
@LineId = @LineId + 1

SELECT
@Line = NULL
END
ELSE
BEGIN
IF @BasePos <= @TextLength BEGIN

While (isnull(LEN(@Line), 0) + @BlankSpaceAdded + @TextLength - @BasePos + 1) > @DefinedLength
BEGIN
SELECT
@AddOnLen = @DefinedLength - (isnull(LEN(@Line), 0) + @BlankSpaceAdded)

INSERT
#CommentText
VALUES
(
@LineId
,isnull(@Line, N'') + isnull(SUBSTRING(@SyscomText, @BasePos, @AddOnLen), N'')
)
SELECT
@Line = NULL
,@LineId = @LineId + 1
,@BasePos = @BasePos + @AddOnLen
,@BlankSpaceAdded = 0
END

SELECT
@Line = isnull(@Line, N'') + isnull(SUBSTRING(@SyscomText, @BasePos, @TextLength - @BasePos + 1), N'')

if LEN(@Line) < @DefinedLength and charindex(' ', @SyscomText, @TextLength + 1) > 0
BEGIN
SELECT
@Line = @Line + ' '
,@BlankSpaceAdded = 1
END
END
END
END

FETCH NEXT FROM ms_crs_syscom into @SyscomText
END


IF @Line is NOT NULL
INSERT
#CommentText
VALUES
(@LineId, @Line)

select
Text
from
#CommentText
order by
LineId

CLOSE ms_crs_syscom
DEALLOCATE ms_crs_syscom
DROP TABLE #CommentText

ROLLBACK TRAN
DROP TABLE #output

GO

Friday, March 14, 2008

Auditing Your Tables

I wrote this script to use at work to create triggers on all of the tables here at work so that we can audit changes. I have modified it slightly to include the Create/Alter of the audit table. Soon I will be posting queries that will allow you to easily view the information in the audits. Please note that if you want things translated in your audit table, you can do lookups in the triggers, but this will require a manual change. So, without further anticipation:



--******************************************************--
--* Author: Nathan Wheeler *--
--* Date: 3/12/08 *--
--* Description: This query will look through each *--
--* table in the used catalog and create an auditing *--
--* trigger for each table with a primary key. *--
--* It will also create the table in which to place *--
--* the audit entries. *--
--* Licensing: Feel free to use this script to create *--
--* audits on all your catalogs, just don't give it *--
--* away without this notice. *--
--* *--
--* For more stuff like this, visit: *--
--* http://maxaffinity.blogspot.com *--
--******************************************************--
--Insert catalog name here.
USE [<catalog>]
GO
SET NOCOUNT ON
--If the AuditTable is there alter it, otherwise create it.
IF OBJECT_ID(('AuditTable'), 'U') IS NOT NULL
PRINT 'CREATE TABLE [dbo].[AuditTable]'
ELSE
PRINT 'ALTER TABLE [dbo].[AuditTable]'
PRINT ' ('
PRINT ' [AuditID] [int] IDENTITY(1, 1)'
PRINT ' NOT NULL'
PRINT ' ,[TableName] [varchar](50) NOT NULL'
PRINT ' ,[KeyName] [varchar](50) NOT NULL'
PRINT ' ,[KeyValue] [varchar](50) NOT NULL'
PRINT ' ,[FieldName] [varchar](50) NOT NULL'
PRINT ' ,[FieldOldValue] [varchar](8000) NULL'
PRINT ' ,[FieldNewValue] [varchar](8000) NULL'
PRINT ' ,[ModifiedBy] [varchar](75) NOT NULL'
PRINT ' ,[ModifiedDate] [datetime] NOT NULL'
PRINT ' ,CONSTRAINT [PK_AuditTable] PRIMARY KEY CLUSTERED ([AuditID] ASC) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]'
PRINT ' )'
PRINT 'ON [PRIMARY]'
PRINT 'GO'
DECLARE
@TableName VARCHAR(255)
,@KeyName VARCHAR(255)
,@Schema VARCHAR(255)
,@TriggerName VARCHAR(255)
,@FieldName VARCHAR(255)
DECLARE table_cursor CURSOR
FOR SELECT
KU.TABLE_NAME
,KU.COLUMN_NAME
,KU.CONSTRAINT_SCHEMA + '.'
FROM
INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS TC
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS KU
ON TC.CONSTRAINT_TYPE = 'PRIMARY KEY'
AND TC.CONSTRAINT_NAME = KU.CONSTRAINT_NAME
WHERE
--In the "NOT IN" is where you can list any tables you DON'T want to audit.
--Be sure to put at least the AuditTable in here.
KU.TABLE_NAME NOT IN ('AuditTable')
ORDER BY KU.TABLE_NAME
OPEN table_cursor
FETCH NEXT FROM table_cursor INTO @TableName, @KeyName, @Schema
WHILE @@FETCH_STATUS = 0
BEGIN
--The trigger will be the name of the table prefixed be "audittr_".
--This can be changed by setting @TriggerName to something different.
SET @TriggerName = @Schema + 'audittr_' + @TableName
DECLARE field_cursor CURSOR
FOR SELECT
c.name
FROM
sysobjects o
INNER JOIN syscolumns c
ON o.id = c.id
WHERE
o.name = @TableName
ORDER BY
o.name
,c.colorder
--If the trigger already exists, alter it instead of create.
IF OBJECT_ID((@TriggerName), 'TR') IS NOT NULL
PRINT 'ALTER TRIGGER ' + @TriggerName
ELSE
PRINT 'CREATE TRIGGER ' + @TriggerName
PRINT ' ON ' + @Schema + @TableName
PRINT ' AFTER UPDATE'
PRINT 'AS '
PRINT ''
PRINT ' INSERT INTO AuditTable'
OPEN field_cursor
--Get the first field name.
FETCH NEXT FROM field_cursor INTO @FieldName
PRINT ' SELECT ' + QUOTENAME(@TableName, '''') + ' AS TableName,'
PRINT ' ' + QUOTENAME(@KeyName, '''') + ' AS KeyName,'
PRINT ' INSERTED.' + @KeyName + ' AS KeyValue,'
PRINT ' ' + QUOTENAME(@FieldName, '''') + ' AS FieldName,'
PRINT ' CAST(DELETED.' + @FieldName + ' AS VARCHAR(MAX)) AS FieldOldValue,'
PRINT ' CAST(INSERTED.' + @FieldName + ' AS VARCHAR(MAX)) AS FieldNewValue,'
PRINT ' SYSTEM_USER AS ModifiedBy,'
PRINT ' getdate() AS ModifiedDate'
PRINT ' FROM INSERTED'
PRINT ' INNER JOIN DELETED'
PRINT ' ON INSERTED.' + @KeyName + ' = DELETED.' + @KeyName
PRINT ' WHERE CAST(DELETED.' + @FieldName + ' AS VARCHAR(MAX)) <> CAST(INSERTED.' + @FieldName + ' AS VARCHAR(MAX))'
--If there is another field (can't see why you'd want just one)
--get the next field name.
FETCH NEXT FROM field_cursor INTO @FieldName
WHILE @@FETCH_STATUS = 0
BEGIN
PRINT ' UNION ALL'
PRINT ' SELECT ' + QUOTENAME(@TableName, '''') + ','
PRINT ' ' + QUOTENAME(@KeyName, '''') + ','
PRINT ' INSERTED.' + @KeyName + ','
PRINT ' ' + QUOTENAME(@FieldName, '''') + ','
PRINT ' CAST(DELETED.' + @FieldName + ' AS VARCHAR(MAX)),'
PRINT ' CAST(INSERTED.' + @FieldName + ' AS VARCHAR(MAX)),'
PRINT ' SYSTEM_USER,'
PRINT ' getdate()'
PRINT ' FROM INSERTED'
PRINT ' INNER JOIN DELETED'
PRINT ' ON INSERTED.' + @KeyName + ' = DELETED.' + @KeyName
PRINT ' WHERE CAST(DELETED.' + @FieldName + ' AS VARCHAR(MAX)) <> CAST(INSERTED.' + @FieldName + ' AS VARCHAR(MAX))'
-- Get the next field.
FETCH NEXT FROM field_cursor INTO @FieldName
END
PRINT 'GO'
--Close and deallocate the field cursor for the next table.
CLOSE field_cursor
DEALLOCATE field_cursor
--Get the next table.
FETCH NEXT FROM table_cursor INTO @TableName, @KeyName, @Schema
END
--Close and deallocate the table cursor.
CLOSE table_cursor
DEALLOCATE table_cursor

Wednesday, March 12, 2008

Welcome

Welcome to MaxAffinity where youre programming affinity can be maximized through the use of code snippets and tips from some of the top developers in the country.

Actually most of that is complete bullshit, but there is going to be a lot of neat code snippets, hardware tips and tricks, and a lot more. The real big difference is that it's not from some of the top developers in the world, it's just me. Sorry to disappoint. Enjoy the blog.