views:

136

answers:

3

I am struggling with this problem since last one week. I have obfuscated exe of my application. Our application is offline tool for online web application. Client will install this application and connect once to internet, application will download relevant information and store in xml file on client machine for further display. for security purpose we are encrypting these xml files. Unfortunately we have one method GetCryptXML inside exe which will read encrypted settings.xml on client machine and return it after decrypting. this setting.xml contain encryption key for other xml as well.

Problem I am facing here is, even after obfuscation, person can invoke GetCryptXML method by passing obfuscated name.

Is there any way to solve this problem?

This is my idea to solve problem but I am not sure how to implement.

My idea: Only way to invoke my function is through reflection by using InvokeMember() function. before one can call this function he/she needs to load assembly by using this.

Assembly.LoadFrom("myapplication.exe")

If code inside myapplication.exe can identify which application is trying to load me then we can restrict them to load if it is not intended application. I dont know how can I solve.

Any help is greatly appreciated.

Thanks.

+1  A: 

If something can be called through Reflection, it has to be callable (somehow) through regular code.

I would suggest against this (as there is no way to fully thwart somebody that is adamant about executing code they shouldn't).

If you're truly interested in doing something like this, you could break the OO Principals of C# and make all of your methods private. That way only code executing from inside your class could call them regularly. Everybody else would have to call them via Reflection (and calling private members via Reflection is considered bad practice more often than not).

Oddly enough, the more I think about it, the method should probably be marked as private anyway since you don't want everybody to be able to call it. Callers should have to call through a public facade which would determine if you're allowed to call the method or not...and only allow authorized calls.

Justin Niessner
+6  A: 

Obfuscation doesn't change the underpinnings of .net or your application - in the end, all it does is make it much harder to read, and tries to add cases that decompilation tools cannot handle... but either way the IL is still there. If you give them the encrypted text (the xml) and the key (sent over the wire or hidden in your code), they can decrypt it. All you are doing is making it harder, not impossible.

One thing you can do is strong name your assemblies, and verify that the caller of your type is from a specific strongly-named assembly with the StrongNameIdentityPermission attribute. Note that KeeperOfTheSoul is correct- full trust assemblies can bypass this in versions of .net prior to 4.0 (it is my understanding that in 4.0 this attribute no longer uses the identity permission and only succeeds if the correct evidence is there).

You can also write code to get the call stack via System.Diagnostics.StackTrace, and check the calling methods to verify that it is one of the expected callers. This means a bit slower execution and more code, but you would have control of it.

EDIT See here for a walkthrough of using the StrongNameIdentityPermission. And here is an article on inspecting the stack trace. Again, note that neither of these is a silver bullet, but can add one more hurdle to the attacker, if you think it's worth your time. (Remember that in the day of the internet, it only takes one successful attacker for any number of people to google the result)

Philip Rieck
But an application running with full trust can make any changes to the runtime environment including asserting strong named identities so the check will always pass.
KeeperOfTheSoul
@KeeperOfTheSoul Added a note about .net4 and this permission... I believe you are correct up *until* 4.0, but in 4 it no longer uses the identity permission. I will have to come back and test this.
Philip Rieck
Could you please give me example for strong name and how can I validate strongNameidentityPermission? Thanks.
Akie
Maybe, but StackTrace is also flawed, as a stack trace can be faked (since you don't control the runtime environment), and also due to method inlining by the JIT the stack trace isn't always what one would expect.
KeeperOfTheSoul
Could you please give any idea how do I solve?
Akie
@KeeperOfTheSoul also correct. in reality it is a tuatology that when you give the code to someone, they have it (even if you compile and obfuscate it). Really this is about multiple layers of protection, and how much work is it worth to the developer and attacker to protect/crack the system. As I say, "all you are doing is making it harder, not impossible"
Philip Rieck
A: 

If you want to restrict access to a method to a particular assembly you could do the following:

    private void RestrictedMethod() {
        Assembly calling = Assembly.GetCallingAssembly();
        if(calling.FullName != "myapplication, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null") {
            throw new InvalidOperationException();
        }
        // Do method work...
        return;
    }

One of the advantages of this approach is that if someone used reflection from an unauthorized assembly the call would fail.

Steve Ellinger
Unless I fake the calling assembly, which I can do if I control the runtime (i.e. any application running in full-trust). At which point I can make Assembly.GetCallingAssembly return any value I like.
KeeperOfTheSoul
That may be true. And perhaps my answer in that respect was incomplete. The function in question seems to be in an .exe file and the implication of the question is that some code external to the exe (in other words, a .dll) can call this method. Which means part of the solution is that any such code cannot be running full-trust, which should be controllable by an exe, such as running the dll code in another AppDomain.
Steve Ellinger