This article is the second of a two series of articles about the .NET Framework internals and the protections available for .NET assemblies. This article analyzes more in depth the .NET internals. Thus, the reader should be familiar with the past article, otherwise certain paragraphs of this article may seem obscure. As the JIT inner workings haven’t been analyzed yet, .NET protections are quite naïve nowadays. This situation will rapidly change as soon as the reverse engineering community will focus its attention on this technology. These two articles are aimed to raise the consciousness about the current state of .NET protections and what is possible to achieve but hasn’t been done yet. In particular, the past article about .NET code injection represents, let’s say, the present, whereas the current one about .NET native compiling represents the future. What I’m presenting in these two articles is new at the time I’m writing it, but I expect it to become obsolete in less than a year. Of course, this is obvious as I’m moving the first steps out from current .NET protections in the direction of better ones. But this article isn’t really about protections: exploring the .NET Framework internals can be useful for many purposes. So, talking about protections is just a means to an end.
What is Native Compiling?
Strictly speaking it means converting the MSIL code of a .NET assembly to native machine code and then removing the MSIL code from that assembly, making it impossible to decompile it in a straightforward way. The only existing tool to native compile .NET assemblies is the Salamander.NET linker which relies on native images to do its job. The “native images” (which in this article I called “Native Framework Deployment”) technique is quite distant from .NET internals: one doesn’t need a good knowledge of .NET internals to implement it. But, as the topic is, I might say, quite popular, I’m going to show to the reader how to write his Native Framework Deployment tool if he wishes to. However, the article will go further than that by introducing Native Injection, which means nothing else than taking the JIT’s place. Even though this is not useful for commercial protections (or whatever), it’s a good way to play with JIT internals. I’m also going to introduce Native Decompiling, which is the result of an understanding of .NET internals. I’m also trying to address another topic: .NET Virtual Machine Protections.
The internal format of native images is yet undocumented. It also would be quite hard documenting it as it constantly changes. For instance, it completely changed from version 1 to version 2 of the .NET framework. And, as the new framework 3.5 SP1 has been released a few days ago, it changed another time. I’m not sure on what extent it changed in the last version, but one change can be noticed immediately. The original MetaData is now directly available without changing the entry in the .NET directory to the MetaData RVA found in the Native Header. If you do that action, you’ll end up with the native image MetaData which isn’t much interesting. Also, in earlier native images (previous to 3.5 SP1 framework) to obtain the original MSIL code of a method, one had to add the RVA found in the MethodDef table to the Original MSIL Code RVA entry in the native header. This is no longer necessary as the MethodDef RVA entry now points directly to the method’s MSIL code.
.method public hidebysig virtual instance void
B(class ['Microsoft.Licensing.Utils2.0']Microsoft.Licensing.Utils.Xml.IXmlDataNode A_0) cil managed
// Code size 33 (0x21)
IL_0002: ldstr "ps:IncludeRules"
IL_0008: call instance void class Microsoft1Licensing1Runtime210GE<!--A-->::A(class ['Microsoft.Licensing.Utils2.0']Microsoft.Licensing.Utils.Xml.IXmlDataNode,
IL_000f: ldstr "ps:ExcludeRules"
IL_0015: call instance void class Microsoft1Licensing1Runtime210GE<!--A-->::A(class ['Microsoft.Licensing.Utils2.0']Microsoft.Licensing.Utils.Xml.IXmlDataNode,
IL_001b: call instance void class Microsoft1Licensing1Runtime210GE<!--A-->::E()
} // end of method Microsoft1Licensing1Runtime210GE::B
Native Framework Deployment
The name I gave to this sort of protection may appear a bit strange, but it will appear quite obvious as soon as I have explained how it actually works. As already said, there’s no protection system other than the Salamander Linker which removes the MSIL and ships only native machine code. And, in order to do that, the Salamander Linker relies on native images generated by ngen. The Salamander Linker offers a downloadable demonstration on its home page and we will take a look at that without, of course, analyzing its code, as I don’t intend to violate any licensing terms it may imply. In this paragraph I’m going to show how it is technically quite easy to write a Native Framework Deployment tool, but I doubt that the reader will want to write one after reading this. Don’t get me wrong, the Salamander Linker absolutely holds its promise and actually removes the MSIL code from one’s application, but the method used faces many problems and in my opinion is not a real solution.