Spelunking DOTNET : Microsoft .NET Framework is a new platform for building integrated, service oriented applications to meet the needs of today's Internet business, applications that gather information from & interact with a wide variety of sources regardless of the platforms or language in use. This is still Beta 1, we will have more targets in the future.

Understanding the Framework of .NET (in short) : Microsoft Intermediate Language (MSIL), the Common Language Runtime (CLR) & JIT (Just in Time compilers). MSIL is a CPU - independent intermediate language created by MS. It means the PE file containing MSIL can run on any CPU platform as long as the OS running on that CPU platform hosts the .NET common language runtime engine.

In simple when you compile a source under .NET the compiler produces an exe/dll file along with MSIL code. The MSIL code/instructions cannot be executed directly by CPU, so the common language runtime engine must first compile the MSIL instructions into native CPU instructions and than the CPU starts executing .NET programs.

Tools Used :
ILdasm.exe :
Intermediate Language Disassembler comes along with .NET SDK.
ILasm.exe : Intermediate Language Assembler comes along with .NET SDK.
.NET SDK tools Required to Compile the Source Code.

Target : No Target specifically. A small piece of code coded by me (source included along with this "pass.zip" file). It ask the user to give the password. If correct then show a Message Box "Correct Password ... have fun Cheers :-)" or "Wrong Password". There is an Exit Button to quit from the program. I was very much interested in the IL code hence did some work on it. Consider this tutorial as small findings only, it is just a begin. I assume you would have downloaded .NET SDK. Just run the compile.bat to produce the pass.exe. Now lets disassemble "pass.exe". So its time to use ildasm.exe, give the command below :-

ildasm /bytes /out=pa.il   pass.exe

This will produce a file "pa.il" the parameter /bytes shows the bytes code /out instruction produces the output to the file "pa.il". Lets open this file in your favourite text editor. What you see is the below MSIL code. I will try to show the important part which I have understood.

.method family hidebysig instance void 
        button1_Click(class System.Object sender,
                      class [mscorlib]System.EventArgs e) il managed

// Method begins at RVA 0x2290
// Code size       52 (0x34)
.maxstack  2
.locals ([0] class System.String chkvalue)
IL_0000:  /* 02   |            */ ldarg.0
IL_0001:  /* 7B   | (04)000004 */ ldfld      class [System.WinForms]System.WinForms.TextBox 
IL_0006:  /* 6F   | (0A)00001A */ callvirt   instance class System.String [System.WinForms]
IL_000b:  /* 0A   |            */ stloc.0
IL_000c:  /* 06   |            */ ldloc.0

IL_000d:  /* 72   | (70)00005F */ ldstr      "jack"   // Load the Correct String
IL_0012:  /* 28   | (0A)00001B */ call       bool [mscorlib]System.String::Equals
                                             (class System.String, class System.String)
IL_0017:  /* 2D   | 0D         */ brtrue.s   IL_0026  // If Correct Jmp to IL_0026

IL_0019:  /* 72   | (70)000069 */ ldstr      "Wrong Password"  // Nag
IL_001e:  /* 28   | (0A)00001C */ call       value class [System.WinForms]System.WinForms.
                                             DialogResult [System.WinForms]System.WinForms.
                                             MessageBox::Show(class System.String)
IL_0023:  /* 26   |            */ pop
IL_0024:  /* 2B   | 0D         */ br.s       IL_0033

IL_0026:  /* 72   | (70)000089 */ ldstr      "Correct Password ... have fun Cheers :-)"
IL_002b:  /* 28   | (0A)00001C */ call       value class [System.WinForms]System.WinForms.
                                             DialogResult [System.WinForms]System.WinForms.
                                             MessageBox::Show(class System.String)
IL_0030:  /* 26   |            */ pop
IL_0031:  /* 2B   | 00         */ br.s       IL_0033

IL_0033:  /* 2A   |            */ ret

} // end of method Win32Form1::button1_Click

We can see from the Disassembly real pass is "jack" being loaded at IL_000d. So if we type jack at the input box we get a Good Message. We can change the "jack" to "xyz" & recompile it with ilasm.exe giving the command below :-

ilasm pa.il

This will compile the file & will create a file named "pa.exe" on your hard-disk. Execute it & then give the pass "xyz".

We can change the code at IL_0017 from :-

      IL_0017:  /* 2D   | 0D        */ brtrue.s   IL_0026  // If Correct Jmp to IL_0026 
      IL_0017:  /* 2D   | 0D        */ brfalse.s   IL_0026  // If Not Correct Jmp to IL_0026

Know if we compile it back with the above change now you type anything & it will accept it.
We can also make it JMP to IL_0033 & there will be no MessageBox. Here the below change for no MessageBox :-

       IL_0017:  /* 2D   | 0D       */ brfalse.s   IL_0033  // If Not Correct Jmp to IL_0033

Lets insert our small code of MessageBox to the Exit Button. So that when the user Clicks the Exit Button it will show our MessageBox & then Quit. Below is the original code for Exit Button :-

.method family hidebysig instance void 
            Exit_Click(class System.Object sender,
                       class [mscorlib]System.EventArgs e) il managed
    // SIG: 11 F2 13 1C 21 A1
      // Method begins at RVA 0x2287
      // Code size       7 (0x7)
      .maxstack  8
      IL_0000:  /* 02   |                  */ ldarg.0
      IL_0001:  /* 28   | (0A)000019       */ call       instance void [System.
      IL_0006:  /* 2A   |                  */ ret
    } // end of method Win32Form1::Exit_Click

Lets Insert Our NEW CODE For Exit_Click Button

.method family hidebysig instance void 
            Exit_Click(class System.Object sender,
                       class [mscorlib]System.EventArgs e) il managed
    // SIG: 11 F2 13 1C 21 A1
      IL_0000:  /* 72   | (70)000027       */ ldstr     "Press OK to Exit Now ... 
                                                        Inserted MessageBox Code"
      IL_0005:  /* 28   | (0A)000013       */ call      value class [System.WinForms]System.
                                                        WinForms.DialogResult [System.
                                                        ::Show(class System.String)
      IL_000a:  /* 26   |                  */ pop
      IL_000b:  /* 02   |                  */ ldarg.0
      IL_000c:  /* 28   | (0A)000019       */ call      instance void [System.WinForms]System.
      IL_0011:  /* 2A   |                  */ ret
    } // end of method Win32Form1::Exit_Click

Using the ildasm /bytes option we know how many bytes are occupied by the instruction. We have to calculate the necessary bytes for our code & accordingly change the IL numbering instruction.

Some More Findings

There is an undocumented command /adv which can be used with ildasm.exe to show some new options in our disassembler View option.

(a) Statistics
(b) MetaData Info. (Ctrl+M) shortcut

How did I find about it. Well open ildasm.exe in your favourite hex editor & search for "adv", you will see majority of the options lined up together. Infact an anonymous person forced me to do this stuff when I read about .NET at _m forum. Click the link for more information.


There is a tool called "prejit.exe" that can compile an entire assembly listing to native code and save the result on disk. Also note if you search for it on your hard-disk you want find it why ? I guess it does not get extracted by default & I don't remember from which file I extracted it. If anybody requires it please drop me an e-mail.

prejit /v pass.exe (Verbose on)

I had fired filemon.exe before executing the above command & here the result.

This will create 2 file "zap.man" & "pass.exe" in your global cache directory.

If you try to look for this file through explorer you won't find it. We will have to go to the command prompt & search for it. I did try disassembling this prejited ver. of pass.exe inside IDA but its .... experts might help if useful or not. Also the prejited ver. of the file pass.exe does not execute. Why ? because it lacks the main entry point or something else, still digging :-).


While recompiling the disassembled file in our case "pa.il" we can use an option /OWNER switch which protects the resulting file against disassembling. Owner will be required to disassemble the file. e.g. ilasm /OWNER=some1 pa.il ... This will create pa.exe which cannot be decompiled with ildasm.exe if proper /OWNER is not given.

Note: There is no guarantee that all your files when decompiled with ildasm.exe & recompiling it with ilasm.exe will execute perfectly.

Tools to look Forward

Reflector for .NET ... by Lutz Roeder's Programming.net

Greetings Fly out to

Christoph Gabler, Bardia, Unforgiven, CrackZ, MaV3RiCk, Cadlink, ExeLord, Foxcy, Cbol, LBran, etc... &
to you to for reading :-). zenloren available at usa.net.

Dotnet.zip available here (1k).