views:

463

answers:

5

I need to write a "kill switch" into my C# application for licensing/billing purposes. What is the best way to do that?

The requirements are as follows (its actually 2 kill switches):

1 - "passive kill switch" - If a particular user does not log into the application in X days then the application stops working.

2 - "active kill switch" - A user can log in and set a date in the future when the application will stop working.

I can think of various ways to do this with a database but users might be able to bypass that. Is there a way I can use an encrypted database or something of the sort? Or maybe a secured file that can contain this data?

+7  A: 

No matter what you come up with, there will be a way to crack it. How much time and effort are you going to spend fighting your users instead of writing features that they would want? Just storing the time in plain text in the registry will be enough to prevent most ordinary users from messing with it. If advanced users want to pirate your program they will no matter what you do. I'd say don't waste your time trying to prevent this and give them something that would make them want to pay for your product instead.

Mark Byers
I appreciate your answers. With all due respect, your outlook is much too naive. Companies stiff each other on licensing all the time, no matter how wonderful the product. It's nice to think about the utopia you mentioned, but in the real world, invoices go unpaid (intentional or otherwise) and it's prudent business to protect against that.
Jim Beam
@Jim Beam: You're missing the point. There is a certain percentage of users that will never pay for your software -- and **nothing** you do will force them to pay. So while you can implement some measures to make it difficult for them, you end up chasing diminishing returns, and you quickly reach a point where attracting new users (by developing new features) is more profitable than trying to prevent users from stealing your work.
Daniel Pryden
I understand what you're saying. But I'm not looking to write the worlds greatest kill switch and do nothing else in my application code :). The features will be there, but that doesn't mean that investing some time in protecting our work is not a worthwhile endeavor.
Jim Beam
+1  A: 

It will always be possible for a sufficiently talented user to defeat your "kill switch" functionality.

The best you can hope for is to generate a public/private key pair, and embed the public key in your application. Then make it periodically "phone home" to a server that has the private key, which will respond with an authenticated message as to whether the application needs to shut down or not.

However, a malicious user can still modify your executable directly to disable the "phone home" routine (always making it return true, for example). As long as the end user has an executable on his/her own computer, there is no way to prevent this.

Daniel Pryden
If you sign the assembly, there isn't much fear from modification to your executable.
Martinho Fernandes
@Martinho: Well, it's still possible, it's just considerably more difficult. Good point though.
Daniel Pryden
Won't work: you can remove the signature quite easily. http://www.nirsoft.net/dot_net_tools/strong_name_remove.html
Mark Byers
@Mark Byers: Wow. I knew it was possible to defeat an assembly signature, but that's downright trivial. Thanks for the link.
Daniel Pryden
yeah, it's always good to sign the assembly, but its not failsafe. Nothing is. You just want to try and keep the most people out you can in exchange for a reasonable amount of time to spend on it.
Jeremy Morgan
I should have mentioned that one of the requirements is that the application can't "phone home". We can remote into it, but we can't always rely on the connection being there. I suppose we could write something where a failure to dial home causes the licensing to stop too . . .
Jim Beam
@Jim Beam: If you can't phone home then you're really out of luck. Best to just stick a value in the registry and hope for the best. It's just like locks on doors: there to keep honest people honest, not to actually keep a determined attacker out.
Daniel Pryden
@Daniel Pryden: That isn't really "defeating" a signature - just removing the fact that the assembly is signed. Signed assemblies exist to protect users (not vendors) from software that is masquerading as something it is not - if the user wants to remove the signature and screw with the assembly, presumably that's their own problem.
Nick Bastin
A: 

If humans made it, humans can break it, that's the inevitable truth. But if you want to put something that will slow down the average user, here is what I would do.

Create a script with basic windows authentication, and then a second set of authentication that is programmatic. The basic windows auth never changes, but the authentication on the page does. (Create an account for each person). Make that page return some XML with a random string in it.

On your desktop application, during startup send a request with:

the windows auth info 
the random string

And, if the user is current, they will authenticate, get the random string from the server, match it with the randomized string from the app (use an algorithm to generate it) and if they match, let the app work. If they don't match, post some sort of notification.

This way, when you need to kill switch an application, you simply delete or disable their account. Then they can't log in, or match the string.

Of course this could be defeated too by a hex editor or clever internal webserver, but if they're that smart, and that determined they will get the application no matter what.

Hope this helps.

Jeremy Morgan
That's definitely getting closer, but I can't assume that I will have access to the AD level of the OS. I can only assume that I will have control of my application.
Jim Beam
'If humans made it, humans can break it, that's the inevitable truth.' - mostly, but if this were strictly true, the whole RSA encryption scheme would be out the window!
echo
@justin: yeah, humans are fundamentally flawed when it comes to brute-force cracking: they die to soon.
Martinho Fernandes
+1  A: 

1 - "passive kill switch" - If a particular user does not log into the application in X days then the application stops working.

2 - "active kill switch" - A user can log in and set a date in the future when the application will stop working.

To implement either of these, you will need to reliably store state information for your application. Your options for where it's possible to store state are straightforward: in the filesystem, in a database (SQL Server, Access, Active Directory, etc), in the registry, or in some remote store.

For the filesystem option, you can store it directly as a file, or as an NTFS stream attached to a file. Streams are nice because they don't appear in a simple DIR list, and because they will follow the associated file if it's copied somewhere. For example, you might put the data in "file.exe:key".

The most secure approach is probably to use multiple locations, and to check for discrepancies as part of your validation process. You can use encryption to prevent one user being able to copy the validation data from one machine to another -- perhaps by creating a key that includes the local machine's MAC address.

You might also consider using the DPAPI to store any encryption keys you use; that keeps them more secure than just using a file in the filesystem.

RickNZ
A: 

You could always try DotFuscator that ships with Visual Studio, personally I've never got round to trying it myself but in terms of security it might work.

Hope I'm on the same lines as you anyway.

http://www.preemptive.com/products/dotfuscator/overview

Jamie Keeling
Why the downvote? The poster states he wishes to to be handled within the application itself. DotFuscator can be used to protect it and has been mentioned in several posts of a similar nature.
Jamie Keeling