3

I have intellectual-property coded into .net 2.0 fully-trusted assemblies (.exe + DLLs) on an end-user machine, which I would like to protect from being hacked / reverse-engineered (WebService / Cloud-Computing solutions are not an option). Below is a list of techniques I gathered in order to reach this goal.

My questions are:

  1. Are my assumptions correct, or am I doing something wrong in one or more of the techniques?
  2. Will this list be sufficient in order to prevent a malicious attack, or are there other protections I should add?

Thanks in advance.

--

Suggested Techniques

  1. Sign all assemblies with the same strong-name key.
    This has two benefits:
    • A. Make sure any modification to an assembly will render it useless,
    • B. All assemblies will have the same public key, by which they can identify each other.
  2. Digitally sign the assemblies: Both let the users know that the executed code came from the correct source, and – add another identification component by which assemblies could identify each other.
  3. Enforce the above by crawling up the call-stack and verifying that all callers are inside the “community”.
    Possible leads:
  4. Use AOP (e.g. Spring.NET) to inject the call-stack crawling code into some/all methods.
    • This is mainly done because there’s no single entry point (like DllMain() for Win32 DLLs) in a .net assembly.
  5. Obfuscate all assemblies in order to hamper reverse-engineering and reflection-execution attempts (strong name signing will be performed after obfuscation, of course).
  6. Integrate a System.ComponentModel.LicenseProvider mechanism.
  7. Make use of the “InternalsVisibleTo” assembly-level attribute in order to expose internals among a pre-defined set of assemblies.
  8. Possibly use NGEN in order to convert the solution to native code.

Points to Consider

  • Implementing part or all of the above will most-likely introduce a performance penalty, so time-critical processing, for example, should be handled with care.
  • CAS seems to be irrelevant for this type of fully-trusted assemblies.
Community
  • 1
  • 1
AVIDeveloper
  • 2,954
  • 1
  • 25
  • 32
  • 5
    This is not a blog. Please follow the posting guidelines (excerpted from the FAQ): "You should only ask practical, answerable questions based on actual problems that you face. Chatty, open-ended questions diminish the usefulness of our site and push other questions off the front page." – Joe Feb 16 '12 at 19:19
  • "This is not a single/best answer type of article." Then StackOverflow is *not* the best place for this type of help. – Joe Feb 16 '12 at 23:54
  • Point taken, I'll rephrase the question. – AVIDeveloper Feb 17 '12 at 00:25
  • What's your focus? Make sure that no-one knows how your program does something? Make sure that no-one modifies the behavior (i.e. code changes within, or completely replace, an assembly)? – sisve Feb 17 '12 at 08:50
  • Both and more. I want to prevent any malicious attack on the code (e.g. 3rd party assembly disguising as one of mine); code tampering (modifying behavior); make sure no one can reference/execute the code; and seal the implementation from being reverse-engineered. In short - giving the assemblies maximum protection in all fronts. – AVIDeveloper Feb 17 '12 at 09:23

1 Answers1

2

I'm afraid you won't get all the security you want. You see, this is a problem with these languages/platforms that use an itermediate language. It must be in a format that all of the runtimes implementations can consume and then produce the native code.

I've seen some blog posts about tampering signed assemblies. I haven't tried yet, but I think it works. Besides that, the obfuscation tools will just make it harder, but not impossible to extract code (altough there are some pretty good tools that make it very hard). And NGEN is not for that. You still have do distribute the original assemblies.

I think that the most efective and secure way of protect your code, is to move it to a technology that you can't decompile, for example, move your sensitive code to unmanaged C++ and use DLLImport on your C# code.

It doesn't mean that you shouldn't try to protect your code, but you should have in mind that you won't be 100% protected. If you can't afford to rewrite your sensitive code in another language, go with obfuscation and signing. You can't get much more secure than that.

Fernando
  • 4,029
  • 1
  • 26
  • 35
  • +1 for writing sensitive code in unmanaged C++. What's your experience / thoughts regarding the code-execution prevention? – AVIDeveloper Feb 17 '12 at 19:28
  • Marking your types as internal and using InternalsVisibleTo can help you with that. If I'm not wrong, it will prevent from instantiating via reflection. If not, you could do something like this (warning smelly code!): class MyClass {public MyClass() { if (typeof(MyClass).Assembly.GetName().GetPublicKeyToken() != Assembly.GetEntryAssembly().GetName().GetPublicKeyToken()) { throw new Exception("sorry, dude");}}} but again, you will not be 100% secure. Although it will probably make it so hard to cheat that most people will give up. And a nice obfuscator will make the API hard to understand. – Fernando Feb 17 '12 at 21:01
  • That's the direction I was thinking about. Why is it smelly-code and what makes it not 100% secure? – AVIDeveloper Feb 17 '12 at 21:17
  • It is repetitive and ugly. You could make it a generic method, so it looks better. You could also use some tool like postsharp to insert this behavior at compile time. And remember that, altough it is quite difficult, it is not impossible to rewrite the obfuscated code. – Fernando Feb 21 '12 at 01:06
  • 1
    I totally agree with all you wrote. Basically, this is the direction I was heading (summarized in my question), and I'm happy to hear it's not off-track. Also, I do understand that nothing's unbreakable, but my goal is to make it as complex as possible to execute or reverse-engineer the code. Thanks for you time and your feedback. – AVIDeveloper Feb 21 '12 at 01:44
  • Why Microsoft not come with solution for this problem till now don't know. Developers putting efforts to develop stable application and due to this drawback another one can easily replicate the product. – Vishal Hatiskar Oct 06 '20 at 04:12