reflection is possible on obfuscation

2019-02-20 00:24发布

问题:

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:

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.



回答2:

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)



回答3:

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.