Como apenas pegar e ver assemblies .NET no SQL Server usando ICSharpCode.Decompiler

Obviamente, você pode usar utilitários de terceiros, por exemplo, algum ILSpy de código aberto, salvar o assembly em disco e descompilar.

imagem

Mas eu só quero conectar ao banco de dados e ver todos os assemblies e o que há dentro.

Além disso, existem muitos componentes Opensource de alta qualidade para todos os casos de vida de programação, e escrever em C # é conveniente e fácil :)

Então

Para isso, precisamos de um pacote Nuget

imagem

Leia todos os assemblies do banco de dados


SqlDataReader, consulta SQL é trivial:

SELECT af.name, af.content FROM sys.assemblies a INNER JOIN sys.assembly_files af ON a.assembly_id = af.assembly_id 

Inicializar montagem


ou seja, carregue nossos bytes na classe AssemblyDefinition

 var _assemblyDefinition = Mono.Cecil.AssemblyDefinition.ReadAssembly(new MemoryStream(rdr.GetSqlBytes(1).Value), pars); 

rdr - aqui está apenas SqlDataReader, mas você pode ler todos os assemblies em uma lista, por exemplo, uma lista de objetos de uma classe tão simples

 public class SqlAssemblyObject { public string AssemblyName { get; set; } public SqlBytes Data { get; set; } } 

Como geralmente existem muitas montagens, é conveniente exibi-las na forma de uma lista ou tablet, mas o interior na forma de uma árvore, é claro!

Algo assim será a norma

imagem

Nós exibimos


por exemplo, no TreeView

 foreach (var typeInAssembly in _assemblyDefinition.MainModule.Types) { if (typeInAssembly.IsPublic) { var node = new TreeNode(typeInAssembly.FullName); node.Tag = typeInAssembly; } treeView1.Nodes.Add(node); } 

Descompilação


Apenas três linhas de código! (por exemplo, fiz no evento treeView1_AfterSelect )

 var decompiler = new ICSharpCode.Decompiler.CSharp.CSharpDecompiler(_assemblyDefinition.MainModule, new DecompilerSettings()); var str = decompiler.DecompileAsString(e.Node.Tag as IMemberDefinition); textbox1.Text = str; 

A fonte em si, onde tudo é reunido

Parece que isso no final

imagem

Um pouco sobre as armadilhas


Naturalmente, os assemblies podem depender de assemblies, e tudo isso pode estar no banco de dados SQL.

Então, se você descompilar "na testa" - haverá um erro de descompilação.

Evitar isso é fácil (porque existe um AssemblyResolver no ICSharpCode.Decompiler):

Vamos escrever nosso resolvedor simplesmente passando todos os assemblies disponíveis no banco de dados SQL analisado:

 public class DatabaseAssemblyResolver : IAssemblyResolver { List<SqlAssemblyObject> _databaseLibs; DefaultAssemblyResolver _resolver; public DatabaseAssemblyResolver(List<SqlAssemblyObject> dlls) { _databaseLibs = dlls; _resolver = new DefaultAssemblyResolver(); } public void Dispose() { //throw new NotImplementedException(); } public AssemblyDefinition Resolve(AssemblyNameReference name) { foreach (var item in _databaseLibs) { if(item.AssemblyName.Contains(name.Name)) { return AssemblyDefinition.ReadAssembly(new MemoryStream(item.Data.Value)); } } return _resolver.Resolve(name); } public AssemblyDefinition Resolve(AssemblyNameReference name, ReaderParameters parameters) { foreach (var item in _databaseLibs) { if (item.AssemblyName.Contains(name.Name)) { return AssemblyDefinition.ReadAssembly(new MemoryStream(item.Data.Value)); } } return _resolver.Resolve(name, parameters); } 

A variável _listItems é apenas uma lista de todos os assemblies de sys.assembly_files

 var pars = new ReaderParameters(); pars.AssemblyResolver = new DatabaseAssemblyResolver(_listItems); _assemblyDefinition = Mono.Cecil.AssemblyDefinition.ReadAssembly(new MemoryStream(_listItems[idx].Data.Value), pars); 

Agora, ao descompilar, todas as dependências podem ser resolvidas!

imagem

PS: Lily James foi usada para atrair atenção.

Source: https://habr.com/ru/post/pt425799/


All Articles