Integrating Microsoft Code Protector
September 5, 2008
In the last post I wrote about how I came to use Microsoft Code Protector for preventing tampering with my .NET licensing scheme. Here I’ll go though how I use it, including how I design my code to get the best out of it.
To protect an application you configure a project using the SLP Code Protector GUI. Select the assemblies and methods to protect and then run. The IL in the assemblies will be manipulated and the method bodies will now be just calls to the Code Protector runtime which uses the unique ‘permutation’ you get issued.
The GUI is a little bit clunky in terms of selecting methods and there is the issue of keeping the Code Protector project file in sync with the code as methods are added and renamed. A nice trick is to use type name filtering by working with the project file directly – it is not supported in the gui.
<Rule>
<Filter>
<CodeEntityFilters>
<Assembly>
<Name>MyAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=e4d4e46e5e55655d</Name>
</Assembly>
<Namespace>
<Name>DW.Licensing</Name>
</Namespace>
<Type>
<Name>DW.Licensing.LicenseManager</Name>
</Type>
<Method />
<Property />
<Field />
</CodeEntityFilters>
</Filter>
<RuleParams>
<UnlockingFeature>Execute</UnlockingFeature>
</RuleParams>
</Rule>
Note that you might get the occasional IL op code that can’t be translated with a message along the lines of
Warning Failed to transform method DW.LicenseManager.ActivationState:ProcessKey(string). Unsupported OpCode found in “IL_0018 starg.s 1″. Method was automatically excluded from the transformation.
In this case was a simple aString = aString.Replace("-", String.Empty); to blame (Reflexil was useful here), which can easily be worked around.
The protection process can be run from the command line for automated builds and assemblies can be resigned but not with a key container.
There aren’t really any settings to tweak about the code protection itself apart from selecting ‘Cloaking’ method calls to increase security. Details in the manual! However architecture and implementation should be tweaked to get the most out of Code Protector.
So protection is method based and it is not designed to protect every method. It’s slow, you lose stack traces and debugging, and there are restrictions on what it can protect such as no generics. In this case I want to prevent the licensing code being tampered with, or bypassed altogether, so I:
- Protect the method containing the call to check the license, and all of the licensing code itself.
- Place the call to check the license in a method that is vital to the operation of the application. In this case initialisation code. This will stop the application working in the case of an upstream unprotected method call being removed to bypass the licensing check.
Code Protected methods may be slow, but in this case because they are all in the initialisation it didn’t really matter. The only effect was to increase start up time by a few seconds.
I like to distribute pdb files so that there are line numbers in the stack traces in the error log. Using Code Protector will mangle the stack traces much like an obfuscator does and this is to be expected. But it also seems to stop line numbers being displayed for the whole assembly, and there is the issue of the pdb containing information about protected methods. Because of this isolating the protected initialisation in a separate assembly (in addition to putting the licensing code in another assembly) seems like a good idea. Moving all the initialisation methods of an important class into a sub class in a new assembly does the trick with a bit of help from InternalsVisibleTo.
It can also be seen that exceptions thrown from unprotected code have their stack traces mangled when passing through the protected code. Calling out to unprotected methods by wrapping them in a delegate passed to the following method sorts that:
// usage: CallOut(delegate() { <code goes here> }); public void CallOut(ThreadStart toCall) { try { toCall(); } catch (Exception ex) { TraceHelper.WriteException(ex, "License Manager Logging Stack Trace"); throw; } }
So we can consider anything happening in protected methods safe, statically in terms of IL and also at runtime in terms of memory. Whereas fields are not protected and are vulnerable, to reading secrets from the IL, and to malicious manipulation at runtime. This is not a big deal as we can design the class to take advantage of the method centric protection. Any inline initialisers should be put in constructors instead where they can be protected (.NET will do this anyway for instance members, at least when I looked, but not static members). Taking things further — note that I’m not a cracker and don’t know how much these measures really help, just a developer using his imagination and deferring to the defensive option — we can work to minimise any state, preferring to calculate it instead. For example instead of caching a boolean isLicenseOk the whole license checking code should be run through to calculate this instead. If a state must be stored it can be done as an encrypted byte array (see the code at the bottom to do this). Minimising its lifetime probably helps too. Am I getting paranoid?
All in all I was glad to find Code Protector as it completed my licensing system by protecting the licensing system itself. Working out how best, or at least better, to use it was a bit of a step into the unknown.
Code for storing encrypted members:
Byte[] Store(String info) {
if (info == null)
return null;
SymmetricAlgorithm symmetricAlgorithm = GetSymmetricAlgorithm();
MemoryStream underlying = new MemoryStream();
byte[] iv = symmetricAlgorithm.IV;
underlying.Write(iv, 0, iv.Length);
// We don't use 'using' as CryptoStream.Dispose does not close underlying Stream but
// Close does.
TextWriter writer = null;
try {
ICryptoTransform encryptor = symmetricAlgorithm.CreateEncryptor();
Stream crypto = new CryptoStream(underlying, encryptor, CryptoStreamMode.Write);
writer = new StreamWriter(crypto);
writer.Write(info);
} finally {
// StreamWriter.Close and CryptoStream.Close close their wrapped streams.
writer.Close();
}
return underlying.ToArray();
}
String Retrieve(Byte[] bytes) {
if (bytes == null)
return null;
SymmetricAlgorithm symmetricAlgorithm = GetSymmetricAlgorithm();
// We dont use 'using' as CryptoStream.Dispose does not close underlying Stream but
// Close does.
MemoryStream underlying = new MemoryStream(bytes);
byte[] iv = symmetricAlgorithm.IV;
IOUtils.ReadByteBlock(underlying, iv, iv.Length);
symmetricAlgorithm.IV = iv;
TextReader reader = null;
try {
ICryptoTransform decryptor = symmetricAlgorithm.CreateDecryptor();
Stream crypto = new CryptoStream(underlying, decryptor, CryptoStreamMode.Read);
reader = new StreamReader(crypto);
return reader.ReadToEnd();
} finally {
// StreamReader.Close and CryptoStream.Close close their wrapped streams.
reader.Close();
}
}
// We generate the SymmetricAlgorithm just as we try to minimise state elsewhere.
SymmetricAlgorithm GetSymmetricAlgorithm() {
// Add your own tricks for hiding keys here!
byte[] key =
new Byte[] {69, 100, 103, 345, 67, 746, 736, 162, 463, ...
SymmetricAlgorithm symmetricAlgorithm = new RijndaelManaged();
symmetricAlgorithm.Key = key;
return symmetricAlgorithm;
}
Protecting .Net software, and Microsoft SLP Code Protector
August 29, 2008
I’ve been working on the protection of a .Net application recently. Protection against the application being distributed or used by a third party without paying for it that is. There are a few aspects to this but in this post I’d like to talk about preventing tampering, and the solution I arrived at, Microsoft SLP Code Protector.
Once you have a licensing system in place you need to make it difficult for someone to bypass that licensing system by modifying the IL. If you haven’t heard of Reflexil take a look at it and you’ll see that modifying the IL is fairly trivial. What about strong naming? Strong naming does not prevent tampering as it is easily removed. If you didn’t know that try the tool here to remove strong naming from your application in a couple of minutes (there are many others also). Note that strong naming can also be removed by round tripping the IL using ildasm.exe and ilasm.exe, or cecil. So strong naming does not prevent tampering.
One approach is to use an obfuscator to make it difficult to find the IL that needs to be changed to bypass the license system. However I came to the conclusion that this is not a great approach as it doesn’t seem like it would make it that hard. Licensing systems tend to have to display messages to the user when they fail and that would be a good place to start hunting for the modification. Obfuscators seem better suited to protect the secrets of algorithms or prevent large bodies of code being adopted by other parties via decompilation. However I would like to recommend Eazfuscator, the best free obfuscator I came across while working on this.
Another technique used for example by Salamander Protector (costing $1900) is compiling the IL to native code and then distributing that instead. However you are losing a lot of benefits when you move from a managed application back to native. And it intuitively seems well, a bit hairy, the sort of thing you can imagine causing problems. In addition remember that native apps are cracked. Another technique likely used by some code protection products is runtime code injection. There are a couple of articles about this here and here, including techniques that can be used to defeat it. These articles are pretty interesting, a tour de force of .Net innards!
In the process of finding a decent solution poking around the reversing (not necessarily cracking!) communities at http://www.reteam.org and http://www.woodmann.com/forum/ was invaluable in getting an idea of what I was up against. There are recommendations on which protection products are best although most have claims that they have been broken. I found no such claims about the Microsoft Code Protector (although this could be because the Microsoft lawyers are a more ‘tenacious’ than the rest!).
So Microsoft Code Protector, formerly the product SecureLM from Secured Dimensions, part of their SLP product. The approach used is to remove selected method implementations from MSIL into a ‘Secure Virtual Machine Language’ that is executed on a ‘Secure Virtual Machine’ outside of the CLR.
If you look in reflector you’ll see that the body of any protected methods has been removed and replaced with something like that shown here:
private OleDbConnection GetDBConnection()
object[] args = new object[0];
object obj2 =
SLMRuntime.ExecMethod(
null, "DS9FvZGluZyAvV2luQW5zaUVuY29kaW5A0vQmXZ“, args);
return (OLEDBConnection) obj2;
}
Every SLP customer is given a unique of the SVM and SVML reducing the chance of a global crack. There is a white paper (pdf). There isn’t too much information to be found about the details of the security, however in theory it sounds stronger than the other approaches I came across, browsing the reversing communities loosely supports this, and also it is from Microsoft themselves which in this case seems a good thing.
Code Protector is one part of Microsoft SLP which includes everything you need to license an application including hosted management and distribution of licenses (msdn, forum, blog, home page). However I was interested in only the Code Protector component, providing protection against tampering as it does. I wasn’t ready to surrender the licensing aspect of the product to Microsoft SLP as I wanted control over licensing and aspects such as hardware locking, needed something that would work on a machine without internet access, and was sceptical it would be as trouble free and easy to use as my custom solution which required only a subset of the SLP behaviour.
Code Protector is freely downloadable to try out. To get a unique permutation that is valid for redistribution and that can be used to protect an unlimited number of methods you must subscribe to the standard service at $10 per month through a Microsoft reseller (GreyMatter sell it in the UK). There are no further costs for using the Code Protector. According to forum posts if you can cancel this subscription you will still be able to use the Code Protector. Up until a few months ago it cost around $5000 dollars to get access to it, so it is possible we will see it become more widely known about and used in the future.
I’ll talk more about the nitty gritty of using Code Protector and integrating it with the application next time.