0

I have created a little application in .NET that serves as a loader for my other applications.

Essentially, when opened, this app will get a list of available applications, and when an option is selected, it downloads the latest-version of the application in-memory and opens it up.

The application itself is obfuscated (although I doubt that matters) and does the following:

  1. Navigates to a hard-coded HTTP location
  2. Downloads a base-64 encoded string of an AES-256 encrypted message containing the list of available applications, their paths, dependencies, and decryption key.
  3. Once an application is selected, it downloads the encrypted binary file (and any dependencies) listed in the configuration, all in memory
  4. A basic set of simple string-manipulation functions are performed on the decryption key found in the config and a SecureString is generated
  5. This key is then used to AES decrypt, and then load the application (once again, all in memory).
  6. The key is immediately set for disposal

Security Concerns

  • I believe that the main entry point is the application itself. I believe, that although obfuscated, it can be easily analysed anyway.

    • Can you protect against this?
  • Using Fiddler / WireShark or other applications, one can easily determine where the configuration is being read from, and can possibly set up a a response, so for future calls, the app would be fed the same result (without actually retrieving it from the intended location).

    • Is there a way to actually verify that it has been downloaded from the intended destination?
  • The fact that the key to decrypt the binary files can be retrieved by a set of string-manipulation functions, I think can be easily reproduced, if the application is reverse-engineered.

    • Do you suggest an other way of dealing with the application-specific key?
  • How easy / likely is it, to save the state of an application running in memory so that it may be re-used without going through the loader application?

  • What other concerns would you consider?

Additional Info

The application currently checks whether a proxy is currently registered with the system, and tries to retrieve by bypassing the proxy, however to me this sounds like a hack rather than a security feature.

1

From what you described, it's not secure at all, for a bunch of reasons. The top two being:

  • You're downloading data over HTTP. Even if AES provides confidentiality, it doesn't provide message authenticity or integrity.
  • You're using hard-coded keys. Pulling those out would be trivial, even with obfuscation. This would mean I could MitM your traffic and send arbitrary binaries to take over the system.
  • You're relying upon obfuscation of the process for security, which is in violation of Kerckhoffs's principle.

The good news is that there is a proper way to do this, with asymmetric cryptography:

  • Generate an RSA key pair.
  • Store the public key components within your application.
  • Hash the assemblies on the server-side and sign that hash with the RSA private key.
  • Deliver the signed hash and assemblies over HTTPS to your application.
  • Hash the downloaded binary, then use the public key to verify the hash against the signature.
  • If the signature matches, you're safe to use the binaries.

You can do all of this with RSACryptoServiceProvider. I recommend using SHA256 for your hashes. I also recommend checking the strong name of the binaries even after you've verified their authenticity, just for peace of mind - you could extend this further by using Strong Name Signing.

A really simple verification routine might look like this:

bool VerifySignature(byte[] file, byte[] signature)
{
    using (var rsa = new RSACryptoServiceProvider())
    {
        rsa.ImportCspBlob(PublicKey);
        return rsa.VerifyData(file, CryptoConfig.MapNameToOID("SHA256"), signature);
    }
}

Where PublicKey is a byte array containing the data exported by rsa.ExportCspBlob(false) on the RSA instance that generated your key pair.

  • That is very well-explained. Aye, the HTTP part is my bad, mostly for lacking HTTPS support in my current environment. Thanks again for all the info :) – Zuiq Pazu Mar 20 '15 at 10:55
  • However, something that comes to mind is that, even if I implement all this, how feasible / easy is it to save the state of the decrypted application running in RAM? Because this would defeat the whole thing. – Zuiq Pazu Mar 20 '15 at 10:57
  • It's not as trivial as pulling it off the wire. Note that you can still encrypt the traffic inside HTTPS if you're trying to avoid the user getting access to the binaries. However, it seems you're trying to implement what amounts to a DRM system, which is inherently impossible: the user's machine is their own to do with as they wish, so they will get access if they want. In fact, all they need to do is write their own client that pulls down the binaries and saves them. You can't stop that - you can only make it a little harder. – Polynomial Mar 20 '15 at 11:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.