• subscribe
July 19, 2007 12:00 AM

Decrypt SQL Server Objects

A simple T-SQL script unlocks encryption
SQL Server Pro
InstantDoc ID #95728
Downloads
95728.zip

When users create stored procedures, functions, and other SQL Server objects, the text body of those objects is immediately available to anyone who has sufficient (often minimal) permissions. You can see how easy it is to expose object content by creating a stored procedure and scripting its content in Query Analyzer, SQL Server Management Studio (SSMS), Windows PowerShell, or a third-party scripting tool. In many cases, developers and software vendors want to obscure the underlying schema of their products to protect intellectual property and confidential information. A common way to achieve this goal is by specifying the WITH ENCRYPTION clause inside the CREATE or ALTER statement for each object deployed. However, although the WITH ENCRYPTION option makes object accessibility and readability more difficult, it doesn't prevent advanced users from accessing the code. (See the sidebar "A Brief Background on Encoding and Encryption".) By doing so, users can extract, troubleshoot, and examine code that might otherwise not be easily available. The simple do-it-yourself T-SQL algorithm in this article lets you decode the content of encrypted database objects.

SQL Server 2000 stores the content of text-based objects (i.e., stored procedures, functions, views, triggers) in a system table called syscomments. This table contains an id column that holds the object id and a text column of type NVARCHAR(4000) that stores the CREATE statement in clear text (possibly over multiple rows). In addition, the ctext column is the hexadecimal representation of the corresponding text column entry, which is needed for the decryption process outlined below.

With SQL Server 2005, the text content of each object is available in the system table sys.sql_modules. Here, object_id is the identifier of each object and the definition column captures the object text. Interestingly enough, the hex stream needed for the decryption isn't found in sys.sql_modules. However, SQL Server 2005 offers the syscomments system table as a backward compatible system view (which contains the ctext varbinary column). The inclusion of this view implies that the binary (or the equivalent hex) representation of the DDL is stored somewhere in the database. To track it down and find the binary data source, follow these steps.

Step 1
Log in to a user database in SQL Server 2000 and create a test object by running the following script:

CREATE PROC dbo.uspMyProc 
  AS SELECT 1 AS MyCol

Step 2

Get the hex representation of the object by executing on the same database the following query:

SELECT ctext 
FROM syscomments WHERE id = object_id(‘dbo. uspMyProc')

At this point, we have the hex format of the object text. We'll use this information to determine and verify the data source in SQL Server 2005.

Step 3
Log in to a user database in SQL Server 2005 in dedicated administrator connection (DAC) mode, which gives you access to and lets you query system tables and views. Open SSMS, start a new query, type ADMIN:<ServerName> as your server name in the connection dialog box, and enter the sa credentials to log in.

Step 4
Take a snapshot of database tables and their row-counts by executing the following code:

SELECT OBJECT_NAME(id), rows
  FROM sysindexes 
  WHERE indid IN (0, 1)
  ORDER BY OBJECT_NAME(id)

You can store the results; an Excel spreadsheet works well. This query returns the name and number of rows in each database table, information that we'll use in upcoming steps for comparison purposes.

Step 5
Create the same object as you did in Step 1, this time in SQL Server 2005 on the database you selected in Step 3. Log in to the database in normal (not DAC) mode and run the following command:

CREATE PROC dbo.uspMyProc 
AS SELECT 1 AS MyCol

Step 6
Repeat Step 4 and compare the query results to the results you recorded earlier. It should appear that a new row was added to a table called sys.sysobjvalues, which has a binary column called imageval. Therefore, it's likely that the sys.sysobjvalues table might be the sought-after source of data. This assumption is validated in the next step.

Step 7
Using the DAC connection, get and compare the SQL Server 2005 hex value from sys.sysobjvalues to the hex value you recorded in Step 2 for SQL Server 2000. You can get the value by running the following query:

SELECT imageval 
FROM sys.sysobjvalues
WHERE objid = object_id(‘dbo. uspMyProc')

Voila The result of the query in Step 7 is identical to the ctext column value we captured in Step 2, which proves that the sys.sysobjvalues table indeed contains the hex sequence we want.

To continue, it's important to understand how SQL Server treats the text body of objects that are created WITH ENCRYPTION. The next steps reveal that treatment.



ARTICLE TOOLS

Comments
  • infante@gigasrl.it
    4 years ago
    Aug 11, 2008

    The procedure works for procedure but with my instance (SQL2005 SP2) doesn't with views.
    Everytime i receive the error
    Syntax not correct near 'AS'

  • Michael
    5 years ago
    Aug 13, 2007

    I found a bug in the 2005 version: The line that reads

    PRINT(SUBSTRING(@ContentOfDecryptedObject, 1 + 2000*@i, 2000*(@i + 1)))

    should read

    PRINT(SUBSTRING(@ContentOfDecryptedObject, 1 + 2000*@i, 2000))

    because the third parameter to the subsctring is length not position

  • Peter
    5 years ago
    Jul 25, 2007

    Disregard the above, I fat fingered.

  • Peter
    5 years ago
    Jul 25, 2007

    The code does not work. It only returns Null when using the 2000 code on a 2000 machine.

You must log on before posting a comment.

Are you a new visitor? Register Here