views:

1335

answers:

14

I have an assembly which should not be used by any application other than the designated executable. Please give me some instructions to do so.

+1  A: 

You might be able to set this in the Code Access Security policies on the assembly.

Charles Graham
+2  A: 

You should be able to make everything internally scoped, and then use the InternalsVisibleTo Attribute to grant only that one assembly access to the internal methods.

bdukes
can it beat reflection?
cathy
+9  A: 

In .Net 2.0 or better, make everything internal, and then use Friend Assemblies

http://msdn.microsoft.com/en-us/library/0tke9fxk.aspx

This will not stop reflection. I want to incorporate some of the information from below. If you absolutely need to stop anyone from calling, probably the best solution is:

  1. ILMerge the .exe and .dll
  2. obfuscate the final .exe

You could also check up the call stack and get the assembly for each caller and make sure that they are all signed with the same key as the assembly.

Lou Franco
will this beat reflection?
cathy
No, to beat reflection you need to obfuscate.
Rick Minerich
A: 

If the assembly was a web service for example, you could ensure the designated executable passes a secret value in the SOAP message.

Dr Zimmerman
+2  A: 

Check w/ Assembly.GetEntryAssembly()

Darren Kopp
but others can use the same entry assembly to hack it..
cathy
+1  A: 

You can use obfuscation.

That will turn:

int MySecretPrimeDetectionAlgorithm(int lastPrimeNumber);

Into something unreadable like:

int Asdfasdfasdfasdfasdfasdfasdf(int qwerqwerqwerqwerqwerqwer);

Others will still be able to use your assembly, but it will be difficult to make any sensible.

Hallgrim
+9  A: 

100% completely impossible without jumping through some hoops.

One of the perks of using the .NET is the ability to use reflection, that is load up an assembly and inspect it, dynamically call methods, etc. This is what makes interop between VB.NET and F# possible.

However, since your code is in a managed assembly that means that anybody can add a reference to your code and invoke its public methods or load it using reflection and call private methods. Even if you 'obfuscate' your code, people will still be able to use reflection and invoke your code. However, since all the names will be masked doing anything is prohibitavely difficult.

If you must ship your .NET code in a fashion that prevents other people from executing it, you might be able to NGEN your binary (compile it to x86) and ship those binaries.

I don't know the specifics of your situation, but obfuscation should be good enough.

Chris Smith
i am not sure how that will help me..whether it is a .net assembly or a native assembly, anybody should be able to load it right..
cathy
Yes, you can dynamically load an unmanaged DLL and execute that too - however then you have to know: the memory address of the code, the number / type of parameters, how to marshall those parameters, etc. Calling into unmanaged code to do things is practically impossible without having the source.
Chris Smith
+2  A: 

The Code Access Security attribute that @Charles Graham mentions is StrongNameIdentityPermissionAttribute

bdukes
from that link - In the .NET Framework version 2.0 and later, demands for identity permissions are ineffective if the calling assembly has full trust.
cathy
+1  A: 

As some people have mentioned, use the InternalsVisibleTo attribute and mark everything as internal. This of course won't guard against reflection.

One thing that hasnt been mentioned is to ilmerge your assemblies into your main .exe/.dll/whatever, this will up the barrier for entry a bit (people won't be able to see your assemby sitting on its own asking to be referenced), but wont stop the reflection route..

UPDATE: Also, IIRC, ilmerge has a feature where it can automaticaly internalise the merged assemblies, which would mean you don't need to use InternalsVisibleTo at all

spmason
ironically, this same assembly is being loaded on demand using reflection. i guess there is no foolproof way to prevent this.
cathy
+9  A: 

You can sign the assembly and the executable with the same key and then put a check in the constructor of the classes you want to protect:

public class NotForAnyoneElse {
  public NotForAnyoneElse() {
    if (typeof(NotForAnyoneElse).Assembly.GetName().GetPublicKeyToken() != Assembly.GetEntryAssembly().GetName().GetPublicKeyToken()) {
      throw new SomeException(...);
    }
  }
}
Hallgrim
I think the InternalsVisibleTo option mentioned below is better. It is the same thing as this answer, without the coding. You need to sign the assemblies for InternalsVisibleTo to work. With both techniques, other users can see the methods and call them using reflection; but both techniques will fail if the calling assembly does not have the same key.
Rob Kraft
+2  A: 

You could also look at using the Netz executable packer and compressor.

This takes your assemblies and your .exe file and packs them into a single executable so they're not visible to the outside world without a bit of digging around.

My guess is that this is sufficient to prevent access for most .net programmers.

A big benefit of the .netz approach is that it does not require you to change your code. Another benefit is that it really simplifies your installation process.

Mark Smith
+1  A: 

It sounds like you are looking for a protection or obfuscation tool. While there isn't a silver bullet, the protection tool I recommend is smartassembly. Some alternatives are Salamander Obfuscator, dotfuscator, and Xenocode.

Unfortunately, if you give your bytes to someone to be read... if they have enough time and effort, they can find way to load and call your code. To preemptively answer a comment I see you ask frequently: Salamander will prevent your code from being loaded directly into the Reflector tool, but I've had better (ie: more reliable) experiences with smartassembly.

Hope this helps. :)

Jeffrey LeCours
+1  A: 

I'm not sure if this is an available avenue for you, but perhaps you can host the assembly using WCF or ASP.NET web services and use some sort of authentication scheme (LDAP, public/rpivate key pairs, etc.) to ensure only allowed clients connect. This would keep your assembly physically out of anyone else's hands and you can control who connects to it. Just a thought.

Jesse C. Slicer
A: 

Just require a pass code to be sent in using a function call and if it hasn't been authorized then nothing works, like .setAuthorizeCode('123456') then in every single place that can be used have it check if authorizeCode != 123456 then throw error or just exit out... It doesn't sound like a good answer for re-usability but that is exactly the point.

The only time it could be used is by you and when you hard code the authorize code into the program.

Just a thought, could be what you are looking for or could inspire you to something better.

shogun