Visual Studio’s Out-of-the-Box Low-Level Debugging Tools: An IL Disassembler and IL Assembler How-To

Ildasm.exe (IL Disassembler) is an out-of-the box disassembler packaged with Visual Studio, and Ilasm.exe (IL Assembler) is an out-of-the-box assembler packaged with Visual Studio. Let’s try using Ildasm.exe and Ilasm.exe to disassemble and then re-assemble a portable executable from a C# Console Application. Take the following C# Console Application for example:

using System;

namespace PrintSomething
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Started the console application. Press any key to exit.");
            Console.ReadLine();
        }
    }
}

Build this code in Debug mode and run it. Figure out where the code was built and copy the path to your executable for this C# Console Application. Then do a search on your computer for the VS2012 x86 Native Tools Command Prompt and open it up (it will help us run the IL Assembler and Disassembler more easily). Try to change the directory somewhere where you have permissions…for me, the desktop is an alright place so the first command I ran was this:

cd "C:\Users\YourUserAccountName\Desktop"

Here comes the sweet stuff. To disassemble your executable, run this command on it (PrintSomething.exe is the name of the Console Application I’ve shown the code for above, but you can paste whatever path you have copied to your own executable):

ildasm "C:\PathToYourExecutable\PrintSomething.exe" /out:"Disassembly.asm"

You can inspect the assembly code in Disassembly.asm now by opening it up in your favourite text editor (you will find Disassembly.asm in your working directory, which I changed to be my desktop earlier):


//  Microsoft (R) .NET Framework IL Disassembler.  Version 4.0.30319.18020
//  Copyright (c) Microsoft Corporation.  All rights reserved.



// Metadata version: v4.0.30319
.assembly extern mscorlib
{
  .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )                         // .z\V.4..
  .ver 4:0:0:0
}
.assembly PrintSomething
{
  .custom instance void [mscorlib]System.Runtime.Versioning.TargetFrameworkAttribute::.ctor(string) = ( 01 00 1C 2E 4E 45 54 46 72 61 6D 65 77 6F 72 6B   // ....NETFramework
                                                                                                        2C 56 65 72 73 69 6F 6E 3D 76 34 2E 35 2E 31 01   // ,Version=v4.5.1.
                                                                                                        00 54 0E 14 46 72 61 6D 65 77 6F 72 6B 44 69 73   // .T..FrameworkDis
                                                                                                        70 6C 61 79 4E 61 6D 65 14 2E 4E 45 54 20 46 72   // playName..NET Fr
                                                                                                        61 6D 65 77 6F 72 6B 20 34 2E 35 2E 31 )          // amework 4.5.1
  .custom instance void [mscorlib]System.Reflection.AssemblyTitleAttribute::.ctor(string) = ( 01 00 0E 50 72 69 6E 74 53 6F 6D 65 74 68 69 6E   // ...PrintSomethin
                                                                                              67 00 00 )                                        // g..
  .custom instance void [mscorlib]System.Reflection.AssemblyDescriptionAttribute::.ctor(string) = ( 01 00 00 00 00 ) 
  .custom instance void [mscorlib]System.Reflection.AssemblyConfigurationAttribute::.ctor(string) = ( 01 00 00 00 00 ) 
  .custom instance void [mscorlib]System.Reflection.AssemblyCompanyAttribute::.ctor(string) = ( 01 00 00 00 00 ) 
  .custom instance void [mscorlib]System.Reflection.AssemblyProductAttribute::.ctor(string) = ( 01 00 0E 50 72 69 6E 74 53 6F 6D 65 74 68 69 6E   // ...PrintSomethin
                                                                                                67 00 00 )                                        // g..
  .custom instance void [mscorlib]System.Reflection.AssemblyCopyrightAttribute::.ctor(string) = ( 01 00 12 43 6F 70 79 72 69 67 68 74 20 C2 A9 20   // ...Copyright .. 
                                                                                                  20 32 30 31 34 00 00 )                            //  2014..
  .custom instance void [mscorlib]System.Reflection.AssemblyTrademarkAttribute::.ctor(string) = ( 01 00 00 00 00 ) 
  .custom instance void [mscorlib]System.Runtime.InteropServices.ComVisibleAttribute::.ctor(bool) = ( 01 00 00 00 00 ) 
  .custom instance void [mscorlib]System.Runtime.InteropServices.GuidAttribute::.ctor(string) = ( 01 00 24 36 37 36 65 36 33 32 34 2D 38 65 62 34   // ..$676e6324-8eb4
                                                                                                  2D 34 33 33 33 2D 39 33 37 37 2D 39 61 65 37 39   // -4333-9377-9ae79
                                                                                                  38 62 33 31 61 30 39 00 00 )                      // 8b31a09..
  .custom instance void [mscorlib]System.Reflection.AssemblyFileVersionAttribute::.ctor(string) = ( 01 00 07 31 2E 30 2E 30 2E 30 00 00 )             // ...1.0.0.0..

  // --- The following custom attribute is added automatically, do not uncomment -------
  //  .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 07 01 00 00 00 00 ) 

  .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 ) 
  .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78   // ....T..WrapNonEx
                                                                                                             63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 )       // ceptionThrows.
  .hash algorithm 0x00008004
  .ver 1:0:0:0
}
.module PrintSomething.exe
// MVID: {5750456D-A154-4CDE-A849-0BC5414E34EE}
.imagebase 0x00400000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003       // WINDOWS_CUI
.corflags 0x00020003    //  ILONLY 32BITPREFERRED
// Image base: 0x009C0000


// =============== CLASS MEMBERS DECLARATION ===================

.class private auto ansi beforefieldinit PrintSomething.Program
       extends [mscorlib]System.Object
{
  .method private hidebysig static void  Main(string[] args) cil managed
  {
    .entrypoint
    // Code size       19 (0x13)
    .maxstack  8
    IL_0000:  nop
    IL_0001:  ldstr      "Started the console application. Press any key to "
    + "exit."
    IL_0006:  call       void [mscorlib]System.Console::WriteLine(string)
    IL_000b:  nop
    IL_000c:  call       string [mscorlib]System.Console::ReadLine()
    IL_0011:  pop
    IL_0012:  ret
  } // end of method Program::Main

  .method public hidebysig specialname rtspecialname 
          instance void  .ctor() cil managed
  {
    // Code size       7 (0x7)
    .maxstack  8
    IL_0000:  ldarg.0
    IL_0001:  call       instance void [mscorlib]System.Object::.ctor()
    IL_0006:  ret
  } // end of method Program::.ctor

} // end of class PrintSomething.Program


// =============================================================

// *********** DISASSEMBLY COMPLETE ***********************
// WARNING: Created Win32 resource file Disassembly.res

Try changing the text in this file. For example, change this line:

IL_0001:  ldstr      "Started the console application. Press any key to "
    + "exit."

To this line:

IL_0001:  ldstr      "That just happened."

Now assemble the code with the following command:

ilasm "Disassembly.asm"

You should see a new executable pop out of this file in your current working directory (for me, its the desktop as I’ve shown before): Disassembly.exe. Run it, and voila, you’ll see that the assembler compiled your assembly (and included any changes you’ve made). Pretty nice for touching up some very low-level code in Visual Studio applications, or even for dynamically changing your application’s manifest information.

Alexandru

"To avoid criticism, say nothing, do nothing, be nothing." - Aristotle

"It is wise to direct your anger towards problems - not people; to focus your energies on answers - not excuses." - William Arthur Ward

"Science does not know its debt to imagination." - Ralph Waldo Emerson

"Money was never a big motivation for me, except as a way to keep score. The real excitement is playing the game." - Donald Trump

"All our dreams can come true, if we have the courage to pursue them." - Walt Disney

"Mitch flashes back to a basketball game held in the Brandeis University gymnasium in 1979. The team is doing well and chants, 'We're number one!' Morrie stands and shouts, 'What's wrong with being number two?' The students fall silent." - Tuesdays with Morrie

I'm not entirely sure what makes me successful in general programming or development, but to any newcomers to this blood-sport, my best guess would be that success in programming comes from some strange combination of interest, persistence, patience, instincts (for example, someone might tell you that something can't be done, or that it can't be done a certain way, but you just know that can't be true, or you look at a piece of code and know something doesn't seem right with it at first glance, but you can't quite put your finger on it until you think it through some more), fearlessness of tinkering, and an ability to take advice because you should be humble. Its okay to be wrong or to have a bad approach, realize it, and try to find a better one, and even better to be wrong and find a better approach to solve something than to have had a bad approach to begin with. I hope that whatever fragments of information I sprinkle across here help those who hit the same roadblocks.

Leave a Reply

Your email address will not be published. Required fields are marked *