Introduction
The previous paper showcased the essential configuration in terms of importing the external DLLs into the solution and NuGet package installation. As we have stated earlier, the process involves making the custom disassembly using several layers of a development cycle and we have already covered the user interface design, the obtaining of the assembly origin information and the decompiling of assembly members in the previous article. Now, we shall continue our voyage by explaining the process of obtaining the disassembled code in C# and the MSIL language.
The .NET CLR provisions several programming languages such as C#, VisualBasic.NET, F# and managed C++. Components written for example in VB.NET or C++, can easily be reprocessed in code written in another language, for instance C#. As we know, code from these high-level languages are compiled into a common Intermediate Language (IL) that runs in the Common Language Runtime (CLR). There are typically multiple reasons to disassemble code, ranging from interoperability purposes to recover lost source code or finding security vulnerabilities. Disassembling can assist in the audit of the implementation of security sensitive features such as authentication, authorization and encryption. Disassembling .NET clients for security purposes can also facilitate ensuring that the software does the expected tasks without hidden features such as spyware or adware.
UI Design recap

Getting Started
The moment the user uploads a .NET built assembly, the Treeview control is activated and shall produce the entire contents of the assembly in terms of modules and methods. As per the proposed functionality of this paper, we need to show the corresponding source code of an assembly in the form of C# of IL language. Here, we shall utilize the treeview control that streamlines our job in terms of when we select a specific method or the contents of the assembly. The equivalent original source code (C# and MSIL) will appear in the Rich Text Box located in the Tab control. Hence, we will create an AfterSelect event for the Treeview control and place the following code into it:
- private void tvMembers_AfterSelect(object sender, TreeViewEventArgs e)
- {
- try
- {
- populateCsharpCode();
- populateILCode();
- }
- catch
- {
- MessageBox.Show("Expand the Namespace");
- return;
- }
- }
C# Code Disassembling
In this section we shall express the process of yielding C# source code from a selected method in the Treeview control. We would have seen the process of generating the original source code earlier in erstwhile popular disassembles, for instance ILSpy, ILPeek and Reflector. We are, in fact, implementing the same functionality and features in our software.
Hence, the very first line of code in the populateCsharpCode(), reading an assembly from the text box control into a dynamic type variable and later by using this variable, we are enumerating the main modules residing in the assembly using a loop while loop construct as in the following:
- var assembly = AssemblyDefinition.ReadAssembly(txtURL.Text);
- IEnumerator enumerator = assembly.MainModule.Types.GetEnumerator();
- while (enumerator.MoveNext())
- {
- … ..
- }
- TypeDefinition td = (TypeDefinition)enumerator.Current;
- IEnumerator enumerator2 = td.Methods.GetEnumerator();
- while (enumerator2.MoveNext())
- {..}
- MethodDefinition method_definition = (MethodDefinition)enumerator2.Current;
- AstBuilder ast_Builder = null;
- foreach (var typeInAssembly in assembly.MainModule.Types)
- {
- ast_Builder = new AstBuilder(
- new ICSharpCode.Decompiler.DecompilerContext (assembly.MainModule) { CurrentType = typeInAssembly });
- foreach (var method in typeInAssembly.Methods)
- {
- if (method.Name == tvMembers.SelectedNode.Text)
- {
- ….
- }
- }
- }
- rtbCsharpCode.Clear();
- ast_Builder.AddMethod(method);
- StringWriter output = new StringWriter();
- ast_Builder.GenerateCode(new PlainTextOutput(output));
- string result = output.ToString();
- rtbCsharpCode.AppendText(result);
- output.Dispose();
- private void populateCsharpCode()
- {
- var assembly = AssemblyDefinition.ReadAssembly(txtURL.Text);
- IEnumerator enumerator = assembly.MainModule.Types.GetEnumerator();
- while (enumerator.MoveNext())
- {
- TypeDefinition td = (TypeDefinition)enumerator.Current;
- IEnumerator enumerator2 = td.Methods.GetEnumerator();
- while (enumerator2.MoveNext())
- {
- MethodDefinition method_definition = (MethodDefinition)enumerator2.Current;
- AstBuilder ast_Builder = null;
- foreach (var typeInAssembly in assembly.MainModule.Types)
- {
- ast_Builder = new AstBuilder(new ICSharpCode.Decompiler.DecompilerContext (assembly.MainModule) { CurrentType = typeInAssembly });
- foreach (var method in typeInAssembly.Methods)
- {
- if (method.Name == tvMembers.SelectedNode.Text)
- {
- rtbCsharpCode.Clear();
- ast_Builder.AddMethod(method);
- StringWriter output = new StringWriter();
- ast_Builder.GenerateCode(new PlainTextOutput(output));
- string result = output.ToString();
- rtbCsharpCode.AppendText(result);
- output.Dispose();
- }
- }
- }
- }
- }
- }
The previous demonstration of C# source code was pretty exhaustive rather than IL code producing. In this segment, we convert the produced MSIL code from the selected method of the current assembly module. It is, however, nearly the same process as in the earlier section implementation but this time we don't need to rely on or call on the AstBuilder class method in order to disassemble the code. Rather, just a couple of .NET Framework built-in classes such as ILProcessor is sufficient to produce the IL code as in the following:
- if (method_definition.Name == tvMembers.SelectedNode.Text && !method_definition.IsSetter && !method_definition.IsGetter)
- {
- rtbILCode.Clear();
- ILProcessor cilProcess = method_definition.Body.GetILProcessor();
- foreach (Instruction ins in cilProcess.Body.Instructions)
- {
- rtbILCode.AppendText(ins + Environment.NewLine);
- }
- }
- private void populateILCode()
- {
- var assembly = AssemblyDefinition.ReadAssembly(txtURL.Text);
- IEnumerator enumerator = assembly.MainModule.Types.GetEnumerator();
- while (enumerator.MoveNext())
- {
- TypeDefinition td = (TypeDefinition)enumerator.Current;
- if (td.Name == tvMembers.SelectedNode.Parent.Text)
- {
- IEnumerator enumerator2 = td.Methods.GetEnumerator();
- while (enumerator2.MoveNext())
- {
- MethodDefinition method_definition = (MethodDefinition)enumerator2.Current;
- if (method_definition.Name == tvMembers.SelectedNode.Text && !method_definition.IsSetter && !method_definition.IsGetter)
- {
- rtbILCode.Clear();
- ILProcessor cilProcess = method_definition.Body.GetILProcessor();
- foreach (Instruction ins in cilProcess.Body.Instructions)
- {
- rtbILCode.AppendText(ins + Environment.NewLine);
- }
- }
- }
- }
- }
- }
It is important to test both of the implementations that we have described earlier. We shall show the C# source generation process. In order to fulfill our goal, we need an exe or DLL file that has source code, we shall generate it using this software. The following DumySoftware.exe application is typically a login authentication mechanism and it restrains our way in the case of not entering a correct user name and password as in the following:

Hence, we open this application exe file into the Spyware Injector and Decompiler software. It will display the exe file contents with its origin information. The moment we expand the main modules of this assembly in the Tree View control and select a method, we will find its C# source code in the Tab control as in the following:

We can also view the MSIL code such as the code we saw using the ILDASM.exe utility. The process of MSIL code disassembly is similar to C# code de-compilation. We first need to select the method from the Tab control and switch on the IL code tab as in the following.
Final Note
This is the second part of “disassembler mechanized” providing additional features developed for the custom disassembler. The goal of this paper is to summarize the knowledge of, how to make a disassembler that produces code from a .NET assembly in both C# and IL format languages. We have observed the process of obtaining C# code in a step-by-step detailed manner along with the generation of MSIL code too. In the next part we shall present the development of a custom exe or code injection tactics in the form of both a message box and spyware.

Join the conversation! Your thoughts help the community grow.