Olá pessoal,
Tudo bem com vocês ?

Neste post vou demonstrar como exportar o assembly de um CLR no SQL Server como DLL e fazer engenharia reversa para código-fonte C#. A primeira vez que precisei utilizar esse recurso foi quando existia um assembly já criado e compilado no banco e precisei alterar o código-fonte de uma procedure, mas a versão que estava no banco não parecia ser a mesma que estava no TFS (Team Foundation Server).

Como exportar o assembly de um CLR do banco para DLL

O primeiro passo para realizar essa atividade, é exportar o Assembly do banco de dados para DLL. Para isso, você precisará identificar o nome do assembly e executar um dos scripts abaixo.

Identificando o nome do assembly

Exportando o assembly para DLL com OLE Automation

Uma forma de exportar o Assembly para DLL é utilizando OLE Automation. Para isso, utilize o código abaixo:

-- Habilitando o OLE Automation (Se já está habilitando, não precisa executar)
EXECUTE SP_CONFIGURE 'show advanced options', 1
RECONFIGURE WITH OVERRIDE
GO

EXEC sp_configure 'Ole Automation Procedures', 1;
RECONFIGURE WITH OVERRIDE
GO

DECLARE @IMG_PATH VARBINARY(MAX)
DECLARE @ObjectToken INT

SELECT
    @IMG_PATH = A.content
FROM
    sys.assembly_files      A   WITH(NOLOCK)
    JOIN sys.assemblies     B   WITH(NOLOCK) ON A.assembly_id = B.assembly_id
WHERE
    A.file_id = 1
    AND B.name = 'tSQLtCLR' -- nome do assembly

EXEC sp_OACreate 'ADODB.Stream', @ObjectToken OUTPUT
EXEC sp_OASetProperty @ObjectToken, 'Type', 1
EXEC sp_OAMethod @ObjectToken, 'Open'
EXEC sp_OAMethod @ObjectToken, 'Write', NULL, @IMG_PATH
EXEC sp_OAMethod @ObjectToken, 'SaveToFile', NULL, 'C:\Teste\myassembly.dll', 2 -- Nome do seu assembly
EXEC sp_OAMethod @ObjectToken, 'Close'
EXEC sp_OADestroy @ObjectToken  

-- Desativando o OLE Automation (Execute apenas se não estava ativado antes)
EXEC sp_configure 'Ole Automation Procedures', 0;
RECONFIGURE WITH OVERRIDE
GO

EXECUTE SP_CONFIGURE 'show advanced options', 0
RECONFIGURE WITH OVERRIDE
GO

Exportando o assembly para DLL com CLR

Uma outra forma de exportar o Assembly para DLL é utilizando o próprio CLR.

using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using System.IO;

public partial class StoredProcedures
{
    [Microsoft.SqlServer.Server.SqlProcedure]
    public static void stpAssembly_Backup(SqlString Ds_Servidor, SqlString Ds_Database, SqlString Ds_Assembly, SqlString Ds_Diretorio_Destino)
    {
        
        var sql = "SELECT AF.content FROM " + Ds_Database.Value + @".[sys].assembly_files AF JOIN " + Ds_Database.Value + ".[sys].assemblies A ON AF.assembly_id = A.assembly_id where AF.file_id = 1 AND A.name = @assemblyname";

        using (var conn = new SqlConnection(Servidor.Localhost.Replace("LOCALHOST", Ds_Servidor.Value)))
        {

            conn.Open();

            using (var cmd = new SqlCommand(sql, conn))
            {

                var param = new SqlParameter("@assemblyname", SqlDbType.VarChar) { Value = Ds_Assembly.Value };
                cmd.Parameters.Add(param);

                using (var dr = cmd.ExecuteReader())
                {

                    dr.Read();

                    var bytes = dr.GetSqlBytes(0);
                    var nomeArquivo = Ds_Diretorio_Destino.Value + "/" + Ds_Assembly.Value + ((!Ds_Assembly.Value.ToLower().Contains(".dll")) ? ".dll" : "");

                    using (var bytestream = new FileStream(nomeArquivo, FileMode.CreateNew))
                    {
                        bytestream.Write(bytes.Value, 0, (int) bytes.Length);
                    }

                }
            }
        }
        
    }

}

Exemplo de uso:

EXEC CLR.dbo.stpAssembly_Backup 
    @Ds_Servidor = N'vm-dba', -- nvarchar(max)
    @Ds_Database = N'BI', -- nvarchar(max)
    @Ds_Assembly = N'tSQLtCLR', -- nvarchar(max)
    @Ds_Diretorio_Destino = N'C:\Teste\' -- nvarchar(max)

Resultado:

Como fazer engenharia reversa da DLL para código-fonte

Uma vez que você conseguiu exportar o assembly da sua biblioteca CLR para um arquivo DLL, você poderá fazer a engenharia reserva do código fonte. Para fazer isso, existem diversas ferramentas, mas sugiro a ferramenta JetBrains dotPeek.

Uma vez instalada, você poderá abrir a ferramenta dotPeek, clicar no menu e selecionar a opção “Open…”

Agora que a sua CLR vai aparecer na lista, basta clicar no botão destacado na imagem abaixo, ou clicar com o botão direito sobre a biblioteca e selecionar a opção “Export to Project” ou acessar o menu File > “Export to Project”.

Selecione onde você deseja salvar o código-fonte e pode deixar as opções padrão marcadas.

Pronto. O dotPeek fez a engenharia reversa da sua DLL e gerou novamente o código-fonte original, conforme exemplo abaixo:

Vale ressaltar que algumas formatações, espaçamentos e comentários não são recuperados através da engenharia reserva, uma vez que isso é perdido quando o código é compilado. Além disso, essa técnica só se aplica a DLL’s que não sofreram o processo de ofuscação (criptografia do código-fonte).

É isso aí, pessoal.
Espero que tenham gostado deste post.

Abraço!

SQL Server database como export save exportar o assembly de um CLR como DLL e fazer engenharia reversa para source code código-fonte C# csharp disassembly reverse engineering JetBrains dotPeek

SQL Server database como export save exportar o assembly de um CLR como DLL e fazer engenharia reversa para source code código-fonte C# csharp disassembly reverse engineering JetBrains dotPeek