Home Obfuscar: Question on Local Variables
Post
Cancel

Obfuscar: Question on Local Variables

It is not a surprise that many people would like to try out Obfuscar, one of the most popular .NET obfuscation tools, and they have various questions on the obfuscation results. Thus, I might post from time to time on what you should expect from such a tool, and help you better understand C#, .NET, as well as Obfuscar.

Today, let’s start with a recent issue on GitHub regarding local variables in C# methods.

The Sample Code

So, we will use the simplest C# sample below as our test case,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
using System;
using System.Security.Cryptography.X509Certificates;

namespace C_
{
    class Program
    {
        static void Main(string[] args) 
        {
            var test = Int32.MinValue;
            Console.WriteLine(test);

            var test2 = new X509Certificate2();
            Console.WriteLine(test2);
        }
    }
}

If you use dotnet new console to create a test project and replace the content of Program.cs with the snippet above, you can then easily compile everything to an assembly, such as bin/Debug/net7.0/testconsole.dll.

If variable names are kept after compilation, we should be able to see them in MSIL format.

Disassembling MSIL

You might want to find a disassembler somewhere, and I just published a new global tool for .NET SDK here,

1
dotnet tool install --global dotnet-ildasm2

With this tool installed, you can easily run the following command to disassemble the Main method from the assembly,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
ildasm testconsole.dll -i Program::Main


.class private auto ansi beforefieldinit C_.Program extends [System.Runtime]System.Object
{

  .method private hidebysig static default void Main(string[] args) cil managed
  {
    // Method begins at Relative Virtual Address (RVA) 0x2050
    .entrypoint
    // Code size 28 (0x1C)
    .maxstack 1
    .locals init(int32 V_0, class [System.Security.Cryptography.X509Certificates]System.Security.Cryptography.X509Certificates.X509Certificate2 V_1)
    IL_0000: nop
    IL_0001: ldc.i4 -2147483648
    IL_0006: stloc.0
    IL_0007: ldloc.0
    IL_0008: call void class [System.Console]System.Console::WriteLine(int32)
    IL_000d: nop
    IL_000e: newobj instance void class [System.Security.Cryptography.X509Certificates]System.Security.Cryptography.X509Certificates.X509Certificate2::.ctor()
    IL_0013: stloc.1
    IL_0014: ldloc.1
    IL_0015: call void class [System.Console]System.Console::WriteLine([System.Runtime]System.Object)
    IL_001a: nop
    IL_001b: ret
  } // End of method System.Void C_.Program::Main(System.String[])
} // End of class C_.Program

As you can see, the original variable names test and test2 are nowhere to find. As we are currently working on a debug build assembly, we can see that C# compiler left hints for local variables in .locals. But even there names like V_0 and V_1 are not related to the original variable names.

If we disassemble the corresponding release build, we will see

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
.class private auto ansi beforefieldinit C_.Program extends [System.Runtime]System.Object
{

  .method private hidebysig static default void Main(string[] args) cil managed
  {
    // Method begins at Relative Virtual Address (RVA) 0x2050
    .entrypoint
    // Code size 21 (0x15)
    .maxstack 8
    IL_0000: ldc.i4 -2147483648
    IL_0005: call void class [System.Console]System.Console::WriteLine(int32)
    IL_000a: newobj instance void class [System.Security.Cryptography.X509Certificates]System.Security.Cryptography.X509Certificates.X509Certificate2::.ctor()
    IL_000f: call void class [System.Console]System.Console::WriteLine([System.Runtime]System.Object)
    IL_0014: ret
  } // End of method System.Void C_.Program::Main(System.String[])
} // End of class C_.Program

which does not even have .locals any more.

Conclusion

Thus, now you know that local variable names are lost during C# compilation, so that any obfuscation tool needn’t to perform anything else on them.

Stay tuned for more.

This post is licensed under CC BY 4.0 by the author.
Advertisement

The New Preview Engine from Bosch

History of This Blog

Comments powered by Disqus.