Disclaimer: I'm perfectly aware that a client-side program will never be safe from a dedicated reverse engineer.
Mostly out of personal curiosity, I've been learning about "obfuscation" techniques for C# applications. It seems that a popular technique is "string encryption", which appears to encrypt the string constants in the software and decrypt them for use later. This makes them not appear properly in decompilers like Reflector (please correct me if this is wrong).
If this is true, and you only see an encrypted version of the string in Reflector, what needs to be done (i.e. how difficult is it) to work around this and get the decrypted string? Obviously it must be possible or the application wouldn't be able to do it, but just how much of a deterrent would it be?
I don't have any experience with C# obfuscators, but the Java obfuscators I've looked at (Stringer, Allatori, Zelix Klassmaster, JFuscator) were pretty bad. Usually, I can reverse engineer the encryption algorithm after a day or two, and then I can deobfuscate all apps protected by the same obfuscator version and other versions usually only require a slight tweak.
Note that this is for purely static analysis, to figure out the algorithm and write a script that decrypts it without executing any code. If your goal is to just decrypt things quickly, it's a lot easier to simply execute the decryption function. The good obfuscators have a call context check so you can't do it directly, but it's a simple matter to find and edit out the check. This could potentially be done in only a couple minutes.
Obviously, there are ways to make reverse engineering much harder, but they aren't done in practice.
If you have the encrypted strings in your application, then you also have the decryption key embedded in your application.
So, a moderately determined person could use a debugger to step through the decryption code to retrieve the key, and then decrypt all other strings in your application with the flick of a wrist.
How much time it would need to understand manually
depends on the general obfuscation level,
ie. if there is a method decrypt which can be called just like that...
with compiling and all probably <1min
The other, simple way: Recompile with debug information, set a breakpoint,
execute the program and just read the string in VS
("simple" depends what is necessary to get to this code part)
I only recently learned about the secureString class. I am sure it is not a total solution, but in combination with other techniques, it might help.
http://msdn.microsoft.com/en-us/library/system.security.securestring%28v=vs.80%29.aspx
The value of an instance of SecureString is automatically encrypted when the instance is initialized or when the value is modified.
Note that SecureString has no members that inspect, compare, or convert the value of a SecureString. The absence of such members helps protect the value of the instance from accidental or malicious exposure.
Related
I am creating an application with the purpose of receiving an encrypted string, decrypting it and passing the clear text string as arguments to a PowerShell script.
The executable has to be self contained, cannot connect to things like a SQL DB or anything alike. The cipher will always be the same, which means that the password/salt can't really be random either.
I know that hardcoding the password/salt is not really a good idea, but I'm struggling with how store a password/salt that doesn't change in a secure way in a self-contained executable.
Right now what I'm doing is rather than having a static string as the password/hash, I create a password and salt based on the modified date of the executable itself (with a few more things done to it). If the executable changes I'll have to recreate the cipher as the previous one cannot be decoded anymore, but at least I'm not really hardcoding a password and/or salt.
Still, I'm not sure just how secure this is and am sure there has to be a better way.
Any suggestions?
EDIT
The only place where this will be used is inside a task sequence running inside SCCM, which means that users won't be able to interact with the computer at all during the time that the task sequence is running (assuming that debug mode is not enabled, else there's also far worse things to worry about).
So I could potentially pass it in clear text to the script as no one would be able to read it since they can't interact with the PC, but then SCCM would automatically output it to logs, which obviously I don't want. I could write it on the script which would avoid having it on the logs, but if someone gets a hold of the script, bearing in mind it's a script and not compiled code, they'd know the password.
Remember the password/salt are not actually hardcoded strings as it is, they are generated during runtime, so they will not be visible using a disassembler.
This article can help you to decide how you need to design password storage
http://flagdefenders.blogspot.in/2012/12/how-to-save-password-securely.html
I've got a question regarding C#.
I am currently working on a medical software product, and one of the important things is to make sure that the patient's data is encrypted. I got two questions regarding this:
1.) How secure is the Microsoft .NET implementation of AES (Rijndael) from System.Security.Cryptography? Does it have any known security flaws, or am I fine just using the MS implementation? (note, I know the basic background of how these algorithms work, but I am not really that deep into it to get an idea of how it works).
2.) Since the data is stored on the same PC as the application, how hard is it to get information from a C# application? Assuming I have somewhere in the code
string encrypPassword = "ThisIsMyPassword";
string encryptedString = EncryptString(ClearString, encrypPassword);
// save encryptedString to harddrive
I know that an attacker could just go down to the assemble code, and at that point there is nothing at all I can do against this (the system has to be able to encrypt / decrypt the data), but is there like a shortcut for C# to get the encrypPassword, since it is managed, or does something like this still require you to go down to the assemble code?
If you have a fixed password compiled into your app, then you don't need to care about the security of AES and known security faults because your data is simply not secure. A sufficiently knowledgable person with access to the PC will be able to decrypt all the data.
And locating a fixed password usually doesn't require any programming knowledge. A good hex editor will do in most case. You don't even need to know what programming language was used.
If your data is used by a single user, then you can tie the password for the patient data to his or her Windows password (or account). Windows provides some specific functions for that. See http://msdn.microsoft.com/en-us/library/aa302402.aspx for how to access it from .NET.
In answer to the first part of your original question - the native Windows implementation of AES is NIST certified to be FIPS 140-2 compliant. Access to the certified implementation is limited to:
Using the Windows Crypto API
Using the CAPICOM com wrapper to the Windows Crypto API
Using the .Net AesCryptoServiceProvider class in the System.Security.Cryptography namespace (this class did not become available until .Net Framework 3.5)
That being said, the implementation in the RijndaelManaged class is the same, it just has not been thru the NIST certification process (this process is very long and very expensive).
The Aes algorithm is very secure (military grade encryption - especially the 256 bit key variant).
The biggest concern (agreeing with the posters above) is keeping your encryption password embedded in the application in plain text.
To store your password data you could use SecureString class from System.Security namespace.
Most decent obfuscators will encrypt the strings from your code before storing them in the assembly's strings section, and inject a method to decrypt them before use. These techniques have also long since been reverse engineered by disassemblers.
Realistically, there is almost no way to really safely store a string in any programming language. Someone can pretty much always either find the string, or reverse engineer your logic used to build it. The best thing you can do is stow down the attacker long enough to make it not worth their time and effort.
In your case, I would probably store the password encrypted in the app (as in, encrypt it yourself manually outside your app, and copy/paste it in). Possibly split it into parts so it isn't stored as a single string. Then put it back together and unencrypt it at runtime, then at runtime store it in a SecureString. Also invest in a good obfuscator, as it will help mask your unencryption logic (which will become the weak link in the security).
In fact, private methods are implemented in C# that can still be searched with Reflection.
What I am going to do is to write public string Encrypt(string data) and private string Decrypt(string cipher) methods to perform encryption and decryption.
Unfortunately, if someone knows .NET framework, he can use Reflection to find Decrypt methods and it decrypt everything that is encrypted.
It seems that is not that secure. So I want to make Decrypt method to truly private method.
But how to do that?
Updated 09 Jan 2012 10:52PM Sydney Time
bdares provides the technical explanation of this question
Eric Lippert provides the political explanation of this question
Thanks both experts!
You can't. If the attacker has access to your code, compiled or source, he can trace your program and find where it's being encrypted or decrypted.
You can add a layer of security by storing the key in a separate location, but generally if the attacker is executing code on your server, you're already screwed.
(You're only worried about this if the attacker is executing code on your server, because otherwise it doesn't matter whether or not the method is private. Also, he can't use reflection to find method names unless he's executing code on your server. In short: you're worrying about the wrong thing here.)
Your fundamental problem is that you've got the trust model wrong. If someone can use reflection then they are the user. You are the software provider. You work for them. Trust flows from them, not from you. They are the person who has to trust you, not you them.
If you don't trust the user then do not sell them your software in the first place. Don't sell weapons to people who you believe plan to attack you.
I believe you are referring to obfuscation, which is an attempt to hide/disguise code from being read by humans when opened in program such as Reflector.
Supplied within Visual Studio is a community use license for PreEmptive Solutions dotfuscator which will provide this functionality on small projects, and also for Windows Phone projects (if you download the add-on). There are also commercial platforms available too, from the same vendor and others .
This blog post explains a little more.
If you're creating your own encryption method, you're doing it wrong. People who know way more about encryption than you or I have already come up with excellent methods for encryption, and MS has implemented most of them already.
For good encryption, it's the keys, not the method, that makes encryption secure. Keep the keys safe and the algorithm can (and should) be published for all to see.
If you're trying to distribute both content and keep it encrypted, aka DRM, you're most probably doomed to failure unless you can keep the keys very well hidden in hardware, and even that will only buy you some time -- maybe months, maybe years.
I am not sure about your exact application. But if you are selling a product to a customer who will be doing both the Encryption and Decryption on their own system, then there is no way to keep the encryption secret from them. But you can instead allow them to generate a new Private Key for their own use. In this way each customer's data is 'secure' in regards to other customers; though obviously still not so secure within the same customer's site. In other situations where you control the encrypted content you can also look into creating a private master key to be generated on your side and only allow the customer to have a public key.
I have a bunch of AES256-encrypted ZIP containers (using DotNetZip), and I am writing a program to help the user understand what is inside them. I would ship the "Launcher" program with XML doc which I am also encrypting the "metadata" so to speak in AES256 as well. I was considering encrypting the password to the various (1-10+ zip files) in a strong AES256 string within the XML document for convenience (so the user only has to enter it once). It unsettles me, but what little "usability" tests we have done has shown people don't want to enter a password 7 times.
So, assuming the string is fully encrypted within the XML/dat/whatever file, how much do I detour the other "factors" within my program? I would have to hard-code the decryption/IV/salt/etc (or at least pass it to a deypcrtion method) no?
I've been trying to understand what things like DotNetCrack (http://www.dotnetcrack.com/) can easily get from my program. I know that nothing is perfect and memory dumping is a huge problem, but I want to at least detour the really easy "script kiddie" sort of stuff.
I've looked at secure-string, but it seems like a silly solution in-so-far you have to decrypt eventually anyways.
EDIT for clarity -- The ZIP files are self-extractors, e.g. just zip files wrapped into the EXE. They may be zips, either way it doesn't matter. My program is just to help somebody extract all the contents without having to click each one AND help them navigate through the ZIPs which may be confusing to a novice user.
All my program is doing is reading the XML file with "data" about each zip (e.g. zip001 is "information from john smith etc etc" -- but the zip file name is something like BOBSMITH_INFO_001.EXE (.zip).
how much do I detour ?! that's the question. when we talk about obfuscation e battle between cracker and programer never ends so basically as much as you can. to stop a script kiddie the basic technics like hardcoding an encrypted version of key and decrypting it before use should work but then again that depends on how motivated your script kiddie is!
that said you can check Reflector and ILDASM (in vs tools) to see that any hardcoded string is found in few seconds! you should also know that the .net is compiled to IL which is a very high level and hence easy to read intermidiate language. so a very simple obfuscation like XOR ing the key and hardcoding it is easy to track even by a script kidie.
As for the solution, use multi levels of encryption. keep the key splited in multiple places encrypted. and even better try write an algorithm that generates the key in runtime. after you did all that, Use an Obfuscator to complicate the thing even further.
Good luck.
I'm not asking for a tutorial with code, I'm trying to do the research, but I want to make sure I'm asking the right questions.
What's the best form of encryption I can use out of the box with .NET?
Public/Private key, where do I store these things securely?
What tools should I have in order to do this properly?
I started off with an AESCryptoServiceProvider, encrypted a string I passed in, I was happy. Tested that if I called it twice it would come out with the same value. Then realized I hadn't provided any form of key, so a second run of the app yielded different results. So I began reading up, seeing RSA Public/Private keys etc. etc. And just want make sure I'm going down the right path with the reading I'm doing. There's tons of examples out there, few mention where you put these keys or where you even get them from.
There's a lot of cryptological functions in System.Security.Cryptography.
They have hashes, crypts, streams, and a lot more.
The RSA provider is a good one. And about storing the constants securely. I can only suggest storing them crypted in the solution.
You shouldn't be able to read them from the source, so there needs to be some kind of security after the assembly has build. Maybe obfuscation, maybe something else.
About the generating of the key, do not use your own system, or any development system I guess.
EDIT:
To generate keys you better use either user input, for example, just create a little application, that calculated the time it takes to type a certain piece of text, per letter.
Or use a HRNG/TRNG, Hardware Random Number Generator (uses input from the actual world, retrieved through sensors). Or True Random Number Generator, basically also HRNG, but mostly with other forms of input, very advanced.
RANDOM.ORG should be able to help you out.
If it's not that extreme important, just go smack your head against your keyboard, and see the results :).
Go for AES. Stack Overflow already has a wonderful implementation of AES Algorithm as an answer.
Regarding "Public/Private key, where do I store these things securely?", I recommend that you do not re-invent the wheel. Microsoft has already spent a great deal of effort to build, and is actively maintaining and (hopefully) improving, infrastructure to store private keys: https://msdn.microsoft.com/en-us/library/windows/desktop/bb204778%28v=vs.85%29.aspx. You can use the native key storage.