tags:

views:

136

answers:

5

How hard would it be to retrieve embedded resources from a .NET application, from outside the application itself? Even if the resources are compressed and trivially encrypted, how difficult is it to retrieve them using a tool? (I am not concerned with the protection of the data per se, just the methods of retrieval of the resource itself)


EDIT:

I think my question was misunderstood, it was less about the encryption and more about the retrieval, other than reflector, what else can be used?

+4  A: 

If you encrypt the resources with a key that is embedded in the application, then it will be easy to retrieve the key, and therefore the resources, with a bit of reverse engineering.

If you encrypt them using a secure algorithm and ask the user to enter the password, then without the password it won't be possible to extract the resources. But I guess that's not what you want. I guess you want to prevent the user from using your resources outside the application?

If so the short answer is: resources in .NET are not secure.

Mark Byers
I upvoted you; however, resources in ANYTHING is not secure. It doesn't matter what language you use, if the encryption key is embedded in the application itself, then it can be yanked out.
Chris Lively
+5  A: 

It is trivial to retrieve resources from a compiled .NET DLL using tools like the .NET Reflector or .NET Resourcer.

Paul Williams
Is there any other way that you are aware of? I will test Resourcer, but Reflector is currently not a problem.
Kyle Rozendo
Well, you could write a wee bit of code. Assembly.GetManifestResourceStream().
Hans Passant
Also, try opening the assembly in Visual Studio. Just curious, did you find that Reflector can't extract them?
Paul Williams
Well, I currently obfuscate, so reflector is pretty harmless to anyone undetermined :)
Kyle Rozendo
+1  A: 

If I show you a safe with a million dollars in it, then walk away, you will eventually get into that safe. There is no technology that will protect that money, your ownly real barrier is time.

It is the same for software. The only way to protect resources is to not place them where someone can, given enough time, get to them. The most effective option I know is storing the critial resources on a server that you control.

Of course many people get this wrong. One way or another, they allow the secure resource to be temporarily copied to the user's computer. At which point, the game is lost. This means you can only truly secure resources that have a natually temporary clone. For example, a security token that expires or the results of calcuation that don't reveal how the calculation was made.

Jonathan Allen
+2  A: 

The problem is less about .NET resources and more about security in general. You could rephrase the question as "my client application stores secrets that I don't want reverse-engineered" and not change the intent.

What is in your resource files, and why does it need to be secured? Have you considered a design in which you don't store those secrets on the client at all? If you're banking on keeping client-side secrets secure, I think you'll be disappointed.

Gabriel Isenberg
+1  A: 

Here is some quick code to get resources out of Assemblies. You decide how easy and secure it is...

class Program
{
    static void Main(string[] args)
    {
        var assemblies = from file in args
                         let assembly = TryLoad(file)
                         where assembly != null
                         from rName in assembly.GetManifestResourceNames()
                         select new { assembly, rName };

        foreach (var item in assemblies)
            using (var rs = item.assembly
                                .GetManifestResourceStream(item.rName))
                SaveTo(rs, item.rName);

    }

    static void SaveTo(Stream stream, string name)
    {
        var buffer = new byte[32*1024];
        var bufferLen = 1;
        using (var fs = new FileStream(name, FileMode.Create))
            while (bufferLen > 0)
                if ((bufferLen = stream.Read(buffer, 0, buffer.Length)) > 0)
                    fs.Write(buffer, 0, bufferLen);
    }

    static Assembly TryLoad(string filename)
    {
        if (string.IsNullOrEmpty(filename) ||
            !File.Exists(filename))
            return null;
        try
        {
            var fullName = Path.GetFullPath(filename);
            return Assembly.LoadFile(fullName);
        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex);
            return null;
        }
    }
}
Matthew Whited