Question

I have an interface which implementing classes export via MEF in my application. The implementing classes are in separate assemblies and aren't known about at compile-time (think plug-ins).

The interface basically consists of a call which says 'here is a bunch of key-value pairs, now initialise your licensing state'. I.e.

public LicensingInfo InitialiseLicense(IEnumerable<KeyValuePair<string, string>> keys)

What I would like to know is - is there any way of protecting that interface from a 'middle man' implementation? I.e. one that receives the call from my application, then calls the same method on the plug-in assembly with a different bunch of key-value pairs, basically saying 'yes - here you go - have everything'.

I did try and think of it a different way, in that the application would call the plug-in assembly and pass in an object which could be queried. That method might look something like this:

public LicensingInfo InitialiseLicense(ILicenseQueryProvider provider)

However, again with this method I think that an intercepting object could just simply give a different provider to the library.

So, is there a way I could prevent such interface interception, or should I refactor it such that the plug-in assembly is entirely responsible for licence loading etc within it's own code? Or is there another way, perhaps, that I could refactor it that I haven't considered?

Was it helpful?

Solution

I believe you can make it harder to break, but not with an interface.

Here's what you do:

You need 2 + n projects: one for the exe (let's call it program.exe), one for the contracts (contracts.dll), and one for each of your n plugins (plugin.dll).

program.exe has a hard reference to contracts.dll, as does plugin.dll.

Sign all of them with a strong name key. See http://msdn.microsoft.com/en-us/library/xc31ft41.aspx

Instead of an interface ILicenceQueryProvider, create a sealed class LicenceQueryProvider in contracts.dll. Make sure it has no public constructors, only an internal one, and no methods to modify the object (initialized on construction, immutable and with readonly fields).

Mark contracts.dll with an InternalsVisibleToAttribute, granting program.exe access to the internal constructor. See http://msdn.microsoft.com/en-us/library/System.Runtime.CompilerServices.InternalsVisibleToAttribute.aspx

This way, program.exe can call the constructor on this object, and plugin.dll can read from it.

plugin.dll "knows" the object class has not been modified because of the strong name signature. And because it's sealed, a man in the middle cannot substitute in another implementation.

Now remember I said you can make it much harder to break, but it is not impossible and will never be, especially if you're using managed code.

For example, a man in the middle can use reflection to instantiate the object with the internal constructor.

Even worse, in your plugin there is code that reads from this object, and makes a decision based on licence information. A hacker can decompile your plugin.dll to IL, and replace that code with code that always grants all privileges.

Obfuscation would help just a little bit, but not against the reflection attack. Native code would make it somewhat more difficult, but native code can be patched too.

Ultimately, the code is on the hacker's machine, and the hacker can do what he wants. He can even run it under a debugger, and modify the data in memory. This is the problem that all copy protection and licencing mechanisms face. In my opinion, licences make it harder on your clients to use your software, and will not stop a determined hacker. Do you (or your company) want to make it hard on your clients to use your software?

Now this doesn't mean there is no solution. In fact there is: a hacker cannot modify code that is not on his machine. Have the code run on a server under your control. The client app accesses it through a web service. The web service authenticates the user (not the calling code, that is impossible). Knowing the user, the service can validate the user's licence. This is the only solution.

UPDATE

Just to be clear: such a service needs to run the actual code that has value for the user, not just a licence check. In the latter case, a hacker could modify the client to simply not mke the call, or even substitute a fake licence server. However, the assumption is that a licence is cheaper than it is to recreate the actual logic living in the service. In that case, even hackers will prefer to buy over recreating the code.

OTHER TIPS

There isn't a bullet proof way to secure your software.

We once used (advertisements ahead) Safenet Inc's Sentinel hardware keys, dotfuscator pro and smart assembly to protected some of our applications.

The hardware keys can used to store licenses (i.e. each feature/plugin has its own license that can be enabled on the hardware key and queried by the application). Optionally their product can be used to encrypt your application - the application gets encrypted and can then only be in-memory-decrypted and started when the right hardware key is attached to the system. There are anti-debugging mechanisms in place to make it harder for someone to use a debugger, waiting for the application to get decrypted in memory and then copying it.

Dotfuscator and smart assembly can be used to "obfuscate" the code of applications to make decompiling using tools like Reflector harder.

Neither of these tools are bullet proof though. But "really really painful to achieve/steal"? I'd say so, but that comes at a price... you sure can throw a lot of money at these tools.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top