Comment prendre et voir les assemblys .NET dans SQL Server à l'aide de ICSharpCode.Decompiler

Bien sûr, vous pouvez utiliser des utilitaires tiers, par exemple, certains ILSpy open source, enregistrer l'assembly sur le disque, puis décompiler.

image

Mais je veux juste me connecter à la base de données et voir tous les assemblages et ce qu'il y a à l'intérieur.

Et en plus, il y a beaucoup de composants opensource de haute qualité pour tous les cas de vie de programmation, et l'écriture en C # est pratique et facile :)

Alors.

Pour cela, nous avons besoin d'un package Nuget

image

Lire tous les assemblages de la base de données


SqlDataReader, la requête SQL est triviale:

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

Initialiser l'assemblage


c'est-à-dire charger nos octets dans la classe AssemblyDefinition

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

rdr - voici juste SqlDataReader, mais vous pouvez lire tous les assemblys dans une liste, par exemple, une liste d'objets d'une classe aussi simple

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

Comme il existe généralement de nombreux assemblages, il est pratique de les afficher sous forme de liste ou de tablette, mais l'intérieur sous la forme d'un arbre, bien sûr!

Quelque chose comme ça sera la norme

image

Nous affichons


par exemple dans TreeView

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

Décompilation


Seulement trois lignes de code! (par exemple, je l'ai fait dans l'événement 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; 

La source elle-même, où tout est réuni

Cela ressemble à la fin

image

Un peu sur les pièges


Naturellement, les assemblys peuvent dépendre des assemblys, et tout cela peut se trouver dans la base de données SQL.

Ensuite, si vous décompilez "sur le front" - il y aura une erreur de décompilation.

L'éviter est facile (car il y a un AssemblyResolver dans ICSharpCode.Decompiler):

Écrivons notre résolveur en lui passant simplement tous les assemblys disponibles dans la base de données SQL analysée:

 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); } 

La variable _listItems n'est qu'une liste de tous les assemblys 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); 

Maintenant, lors de la décompilation, toutes les dépendances peuvent être résolues!

image

PS: Lily James a été utilisée pour attirer l'attention.

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


All Articles