terça-feira, 3 de janeiro de 2012

Beware of stress. Don't (.Net) suppress.

.Net disassembly protection or not?

Since ILdasm.exe version 1 was born it has become one of the best tools for reversing .Net assemblies. As ILdasm is provided by Microsoft I would like to say: thank you, Microsoft. But somewhere along the way, Microsoft must have reflected on the dangers that posed for their clients (and perhaps for the framework usage) having a tool (built by Microsoft itself) lying around that empowered the user with the ability to reverse .NET code. So ILdasm.exe version 2.0 appeared. In version 2 Microsoft decided that some kind of protection was in order, so they armored ILdasm with a safety protection to limit its usage. Yet, it is the software author that, if he wants it to be protected from disassembly, needs to enforce this protective policy on his code. The protection is added with a simple assembly attribute:

using System;
using System.Runtime.CompilerServices;

[assembly: SuppressIldasmAttribute()]
namespace HelloWorld {
       class Hello {
              static void Main(string[] args) {
                     Console.WriteLine("Hello World!");
              }
       }
}

The corresponding MSIL is:

.assembly sample
{
  .custom instance void [mscorlib]System.Runtime.CompilerServices.SuppressIldasmAttribute::.ctor() = ( 01 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 0:0:0:0
}

Compile this code and then try to visualize it in ILdasm 2.0. You'll get the following error:

Now comes the funny part. If you use the ILdasm version 1, this is useless as it is only enforced by ILdasm code in version 2, as seen here:

So, this is easily bypassed. You can use any other IL decompiler like ILdasm version 1. You can edit the binary file, look for the key ascii string “SuppressIldasmAttribute”, like in the following picture, and replace its content by NULL bytes.

Before edit

After edit

If editing the application isn’t your thing and you really, really, really want to use ILdasm 2.0, fear not, you can patch the “call HasSuppressingAttribute” by a “xor eax, eax” and all will be well again.

But wait, there’s yet another bypass provided by Microsoft. In their documented SuppressIldasmAttribute Class  (http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.suppressildasmattribute.aspx) they state the following: “This attribute does not prevent an assembly from being viewed using reflection.”.

In conclusion, as I still keep seeing some people relying exclusively on this to protect their Intellectual property, I’d like to say to them: please don’t use this on your protection schemes. It will save us all time.