How do I protect my C# code against reverse engineering?

One of the questions that comes up often – usually after somebody comes across one of the C# decompilers, such as RemoteSoft’s Salamander or Lutz Roeder’s Reflector – is “how do I keep somebody from reverse-engineering my assemblies and stealing my code?”.

While reverse engineering of code has been around for a long time, the combination of IL and rich metadata in systems such as Java and .NET make it easier. Reverse engineering optimized x86 code is harder, but it’s still quite feasible, as many companies that used copy protection back in the 80s found out.

One way to think about securing your code is to consider how you secure your house or business. There are some possessions that are not protected, some that are secured with simple locks, some are put in safes, and some warrant a vault with a 24-hour guard. I think it depends upon how valuable a specific piece of software is, and that obviously is something you’ll have to decide for yourself.

As for protection, there are a number of different schemes that customers have told me about.

  1. No protection. Some companies sell products that either ship with source code or have source code that can be bought separately, or have chosen not to protect certain parts of their application that have little IP.

  2. Some companies use the obfuscator that ships with VS 7.1 (a “Community Edition“ of PreEmptive Solution’s Dotfuscator)

  3. Some companies use one of the commercial obfuscators out there. There’s a list on the C# Developer Center on MSDN.

  4. Some companies write the sensitive parts of their code in C++, compile that to an unmanaged DLL, and then use interop to call into the unmanaged DLL.

I should also point out that there are some products that claim to use encryption-based approaches to prevent reverse-engineering, but I don’t have any credentials to evaluate such schemes, so I won’t venture an opinion.

If you know of any other schemes, please add them in the comments

Comments (27)

  1. Brad More says:

    The follow-up question is, of course, how does MS protect their code? With many of the new server (and I suspect client) applications coming out of managed code, how does the mothership protect her young?

  2. damien morton says:

    Id like to chime in that Reflector has proven invaluable for learning the windows forms framework.

  3. Eric Wilson says:

    Right up their with this question is the question: How do I prevent people from running my code without a license? I’ve yet to come up with a good answer for this one (anything that I could do to prevent it I could just as easily circumvent by decompling, removing the check, and recompling).

  4. Reverse engineering isn’t going anywhere. Be it compiled Win32 code or .NET assemblies or whatever else. Ten years ago there were even InstallShield script decompilers and a host of other decompilers.

    I appreciate the fact that Microsoft’s .NET code is not obfuscated because being a hacker (in a good sense) by nature I love to dig deep into the internals. To me Reflector has been a source of much learning by way of poking around .NET assemblies (again, in a good way).

    I truly think anyone with a strong agenda can get to your code mo matter how hard you obfuscate it or whatever other word we may use for it. We don’t need to go to extremes or it’ll start hurting us in the first place.

  5. Ferris Beuller says:

    Reverse Engineering is LEGAL in the EU according to directives in order to promote interoperation and competition.

  6. Ferris Beuller says:

    Let me further qualify the previous.

    If I want to know how some closed protocol works (say Yahoo YMSG10 or whatever) and I request the information ( and I have done and I get silence) I can now reverse engineer it for such information in order for my product to work.

    If there is an application that I want to add features to, I request information, i get the usual BS reply, I can now reverse engineer it (like K++ for kazaa hacks).

    All perfectly legal.

  7. Ferris Beuller says:

    I could make a business model out of legally providing a reverse engineering service to those companies in countries that prevent it.

    $$$ ka ching.

  8. Ferris Beuller says:

    Btw, if you think charging for such information (FAT32 file system licensing) forget it, I can still reversen engineer it as that information is not FREELY available.

    Yer screwed 😀

  9. Ferris Beuller says:

    Btw, if you think charging for such information (FAT32 file system licensing) forget it, I can still reversen engineer it as that information is not FREELY available.

    Yer screwed 😀

  10. Nic Wise says:

    How does MSFT do it? I really hope they DONT – there is no other way to workout how things work under the hood, at the moment (yes, releasing a source block for the framework, like Sun does with java, would be lovely)

    As for obfuscation – I’d love to find one that works on the Compact Framework. 90% of our code, which could get into "nasty" people’s hands, is on a small device, not on a desktop…. And with Smartphone and over the air deployment being pushed, maybe…. just maybe….. :)

  11. Ferris Beuller says:

    They dont, run reflector on the System.* etc librariy modules. All there to see.

  12. Putting sensitive code into a C++ assembly is normally a bad idea. The reason is that you isolate your sensitive code and stick a big red flag out that says "Crackers: look here.".

    A few other notes: Many obfuscators boast about generating verifiable code. This is nice if you need to run in a sandbox. However, generating verifiable code means that the obfuscation is weaker. In our obfuscator, we can even obfuscate calls to mscorlib and type info at the call site (example: a call to System.Console.WriteLine looks like it could be taking a NullArgumentException as a param). As well, verifiable code is round-trippable through ILDASM/ASM. If we use unverified (and rename everything to "X"), then we can break ILDASM/ASM roundtripping.

    Also, a good obfuscator can throw in opcodes that have no meaning in C# and VB.NET, like cpblk, calli, and tailcalls.

    Remember, the point of obfuscation is to make the code as screwed up as possible. Stopping half way defeats the idea.

    As well, encrypted loaders can help. The encryption is almost NEVER the weak point. Our obfuscator links assemblies together, performs obfuscation on them, then encrypts the whole thing and emits a loader. This raises the bar even more, since now an attacker has to get the IL out of memory instead of from the disk. If anyone is interested in this, email me. The thing to remember is that someone can modify the CLR and make it do their bidding. There’s no way around that.

    I also recommend manually obfuscating your critical code, if that’s an option. (Hint, no one cares how you load your plugins or create you menu items, no matter how clever you think it is). I’m talking about a key-generation section. It’s temping to do it in 5 lines of code (encrypt their serial number or whatnot). However, even in x86, that’s going to be easy to see through. Using multiple threads, adding extra unused data, etc. can make it hard to tell what’s going on, even if you have the source (remember to comment). This kind of code is much harder to crack (if you’re Microsoft or Adobe, don’t even bother since it’s going to be cracked no matter what you do).

    BTW, the site for our obfuscator is, in case anyone wants to join the beta.

  13. Personally, I think it is wrong to obfuscate your shipping product, especially for platform venders like Microsoft. People will be scared by the closeness nature of obsuscation. In the long run, obfuscation hurts your business more than helps it.

  14. Stephane Rodriguez says:

    "The follow-up question is, of course, how does MS protect their code?".

    MS Reporting services, the first real .NET app I am aware of (and reportedly written with C#), is protected with dotfuscator.

  15. Catatonic says:

    I think you just have to live with this problem, unless your product is a web service (or otherwise is exposed to the world without shipping any code to them).

  16. Catatonic, there are many cases were you’re shipping to a very narrow market (from inhouse to extremely verticle). In those cases, you might have a very good reason to protect code. I know of a particular case (software for a company and only their partners), had the programmers been more careful, the cost of an eletronic attack against their code would have exceeded the cost of a physical attack. Obfuscation techniques (in code and via tools) would have raised the cost + risk for the attack high enought that it would not have been a success.

  17. Louis Parks says:

    Seems to me the first real .NET app from Microsoft was the .NET Framework itself. Next would include the ASP.NET runtime (with only a small amount of unmanaged code for the ISAPI wrapper), several utilities in Windows Server 2003, and Office 2003 BCM.

  18. What about using a #pragma unmanaged section inside a C++ Managed assembly?

  19. Bart Jacobs says:

    I have one word: NGSCB

  20. Anonymous says:

    Just so you know: Reflector is really cool. It would have taken me twice as long to learn the .NET Framework without Reflector. It is also by far the best managed code app I’ve seen so far. Reflector doesn’t exposes the evil "write to disk" option like Salamander does so it is not rally useful for "stealing code". OTOH, even this is valuable for source translation between languages. So I guess the answer is obfuscate, obfuscate, obfuscate. I was wondering why Microsoft never added a /obfuscate switch to the C# compiler?

  21. Jason Lewis says:

    Like what has been said before, if someone wants your code bad enough they will crack it. Most crackers and elite groups will crack your software just to show they can. Want a testament to that, try to think of a heavy duty piece of software and type <software name> crack in google and see what happens. I guess the only true way to keep people from cracking your software….Release it Open Source 😉

  22. White Rabbit says:

    Wy don’t use Net Reactor by Eziriz or Net Protector by Remotesoft. But remember: