Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does decompiled C# get reverse engineered from IL/MSIL?

Tags:

c#

When I open a tool like ILSpy or dotPeek, I have an option of viewing decompiled C# or the IL.

When you view the decompiled source, does the decompiler reverse engineer the IL into the decompiled C# equivalent?

If so then how would a decompiler infer such a case as the IL below? (do note that this is a trivial example of the first language construct that came to mind which couldn't easily be inferred from IL, as opposed to actual output from a decompiler):

IL_0000: nop                  // Do nothing (No operation)
IL_0001: ldstr "C"            // Push a string object for the literal string
IL_0006: stloc.0              // Pop a value from stack into local variable 0
IL_0007: ret    

Translate to:

public class C {
    public void M() {
        string foo = nameof(C);
    }
}
like image 679
Joseph Woodward Avatar asked Apr 12 '17 08:04

Joseph Woodward


2 Answers

Yes, the decompilation tools have to reverse engineer from the IL.

This is why the tools need to be updated for each version of C#/VB, if you want them to decompile newly introduced language features. Otherwise, if the tool is not updated, it will either give up on trying to decompile it or it will produce highly convoluted code that a maniac could have written in an earlier version of the language but most probably did not.

Some decompilation tools will also attempt to locate the actual source code (via PDBs and Source Servers), and if they're successful in this endeavour then you will see the actual source and of course no decompilation effort occurs in this case.

like image 95
Damien_The_Unbeliever Avatar answered Oct 05 '22 08:10

Damien_The_Unbeliever


Sure those tools will try to reverse engineer from MSIL, but speaking of your particular example - it is not possible to reverse engineer your MSIL to

public class C {
    public void M() {
        string foo = nameof(C);
    }
}

Without extenal guidance, like symbol (.pdb) files. Try to compile that statement above in a library, then delete ".pdb" file and put .dll into dotPeek. You will see that it will decompile it as expected:

public void M()
{
    string foo = "C";
}

Now put .pdb file back and you will see your nameof(C) expression back.

Now put .pbd file back, but change the location of source code you used to compile that .dll (for example, rename project folder, delete it completely, or just move .dll with .pdb to different machine). Load it again in dotPeek and you will see again string foo = "C";. That is because .pdb symbols might contain path to your actual source code (you might see those paths in exception stack traces for example), which is then used by decompiler tools to show it directly without any decompilation.

like image 36
Evk Avatar answered Oct 05 '22 06:10

Evk