Modifying a Release-Mode .NET Assembly
Since IL is so simple, one way to achieve the same result without a debugger is to simply decompile the executable using ILDASM on a corresponding .NET release mode x64 executable using the following command line command:
"C:\Program Files (x86)\Microsoft SDKs\Windows\v8.1A\bin\NETFX 4.5.1 Tools\ildasm.exe" ApplicationTest.exe /out:Disassembly.asm
In the disassembly, you will see the following IL instructions under the
IL_000d: callvirt instance bool [mscorlib]System.String::Equals(string,
IL_0012: brfalse.s IL_0020
IL_0014: ldstr "You cannot proceed."
It's very verbose and looks almost identical to your original .NET code so it makes it really easy to find the location of your corresponding code. Modify the text
brfalse to be
brtrue, and compile it using ILASM:
The result will be an assembly named
Disassembly.exe which is nearly identical to the original assembly except that it has rerouted application logic. Now when you execute it, clicking the button will print
Well done, lad..
Note: You may need to download the Windows SDK or corresponding .NET Framework your .NET project is running in order to get access to ILDASM or ILASM. Also, these tools may not work if your .NET application uses a different version of the .NET framework than the .NET versions that the version of ILDASM or ILASM you are using target.
Debugging a Release-Mode .NET Assembly's MSIL Assembly Code Line-by-Line
To directly answer the question, you can debug release-mode .NET assemblies line by line. You first need to decompile any .NET assembly into IL code as I have shown above, using ildasm. Then, you can recompile your assembly in ilasm using the
/pdb flag (
ilasm Disassembly.asm /pdb) to create a debug database that will let you debug any .NET assembly line by line. Here is a simple demonstration of how to do that. Once you have compiled using
ilasm Disassembly.asm /pdb, launch the executable (
Disassembly.exe). In Visual Studio, go to
Tools -> Attach to process and attach the debugger to
Disassembly.exe. Once attached, go to
Debug -> Options and Settings -> Debugger -> Symbols and make sure you add the location of the folder hosting the
Disassembly.pdb file (it should be the same folder that
Disassembly.exe is in if you followed this guide correctly thus far. Hit the pause button in Visual Studio to freeze execution and go to
Debug -> Windows -> Threads and view your threads. Navigate through the threads by double clicking on them. You may need to disable
Just my code. If it prompts you, go ahead and do it, it should be a single click in the thread view. Eventually, you will see that one of your threads shows you the IL
Disassembly.asm. You can add breakpoints in and debug it line by line. Here is a screenshot:
Just a quick note, you may need to resume then freeze again after loading symbols so that Visual Studio synchronizes them. Also, for this to work, you will need the corresponding
Disassembly.asm file in the same directory as well.
Also, Visual Studio has a handy Disassembly View (
Debug -> Windows -> Disassembly) which shows you the machine instructions generated by JIT instead of IL instructions, but this window you cannot debug, presumably because JIT generates this stuff dynamically.