[This question has nothing to do with login credentials, or the user/player inputting any kind of pass-phrase, etc; thank you and keep reading.]
First off, my question has already sort of been asked, here and here. My question is different than either of these though, because I am not connecting through the internet to get data or concerned with any type of "logging in". To put this as simply as I can, I am making a game, and my games resources are all encrypted into a proprietary format, which takes a single password to decrypt the data. I have to hide that password in the source code. I can't think of any other way than to keep the password within the application itself. Encrypting the password within another file would still take a password, and that just starts this endless circle of where to hide that password, and so on.
This got me wondering, how do modern games handle their resource decryption passwords? Think of games like Call of Duty, Elder Scrolls, Grand Theft Auto, etc. They encrypt their data, right? So that means that they need a password/salt/etc to decrypt it. Such a password would also need to be within the executable, too. So where do they hide it? How do they obfuscate it?
I considered one option, which seems like it would actually be pretty good. Basically, I would construct a method which would run through some bizzare gauntlet of mathmatical computations, construct a string, and return the data to serve as the password. Someone could just rip the method out of the code and then launch it in their own private app, but at least it wouldnt be so blatant as:
public const string ResourceDecryptionPassword = "MY_AWESOME_DECRYPTION_PASSWORD";
Also, I considered just keeping the password as a large hardcoded array of bytes, which I could convert back to a string during application start.
Can anyone suggest any other solutions to this problem?
Also, and I forgot to mention: the source code of my game will be obufsicated. This is a no brainer, so it will already make it difficult to visually walk through the code. I just need a good solution for how to hide the password for my encrypted resources.
Based on the comments you received, you already know that "hiding" a security key in the code is NOT a good practice. It's Security through obscurity and it's not efficient.
For games, it was used long time ago. Then with the advance of world wide web, games required an online connection to register/activate the game.
However, these games were so popular they ended cracked whatsoever (by replacing the online activation by a dummy check). That's why a big part of the modern games content (if not all) is now only available when connected to the game servers.
Anyway some games retains parts of the old scheme and use DRM while others (Pillars of Eternity) don't have any.
The common principle is all DRM is to make the reverse engineering of the key (or the debugging of the whole program) difficult: Easy to compute, difficult to debug.
Like a hundred or so embedded encryption/decryption (with hundreds of keys).
Another example is this DRM software that process the code into a VM.
Call unmanaged code to decrypt the data.
Detect any debugger and kills it.
Generate decryption unmanaged code, compile it and run it.
Anything sufficiently complex will do.
I've even seen some financial well known console that refused to launch when VNC is run on the machine... Others complained about Process Explorer.
However, such a hiding job is complex and if you're saying the code will be obfuscated, it should be handled already by the obfuscation software.
By the way, you shouldn't miss windbg if your intent is to play games.
Related
My software (written in C#/.NET) have a simple key license system to activate certain resources. The way it works is: it creates a unique code based on the running computer's hardware, then mix this value with the client's activated licenses to create a password that will, on that specific computer, liberate access to the determinated resources. The key given to the client is a file with the password.
The way it verifies this is even simpler: the software calculates the expected password, and then matches with the password stored on the file. If it matches, the resources are liberated.
So, since the software itself calculates the correct password, I wonder if it's possible to someone take the software's DLLs and hack them to discover the calculation method.
Yes, and if you don't put effort in to obfuscating your code it is trivial to do.
There will always be ways to get around any protection you put in place, the only thing you can do is make it difficult enough that any attacker will get too frustrated and declare it is not worth his time to try and reverse engeneer your software. It is just a matter of how much time/money is it worth it to you to keep that one extra person from trying.
I wrote a fairly extensive answer to a similar question here that goes over what steps you can do to mitigate the problem, but there is nothing you can do to stop it.
I'm developing a program in C#.
It connects to the internet to see if this copy is valid.
Currently I'm just sending the licence key and getting a response (0 or 1) if the key is valid.
The problem is that some users just fake the data with some packet capturing tool and replay it.
So the application is very easy to crack. How can I prevent this?
Here is what I essentially want to prevent:
Network replay attacks
Authentication "emulators"
It should be impossible to find out what data is sent.
Maybe I should add the current time and then encrypt the packet ?
So it's always different ?
Attention: Please don't warn me that it's easy to crack the application itself by modifying it. I know that. This question is only about the network part.
If you use SSL or HTTPS then you don't have to worry about users cracking the data packets. This is easy because the libraries already exist and are easy to implement. With C# and IIs for example it is just a matter of installing the certs and changing a few configuration items. (Maybe a recompile with some slight code changes).
Assuming you actually want to prevent license abuse there are far better ways to do this. The "phone home" approach is easy to roll yourself, but as you've noticed it's full of holes.
Disclaimer: I work for a company that makes commercial tools to solve these license management and copy-protection issues. There are other similar products available from a variety of vendors.
This isn't that different from thinking about how to do setup for your application. Choices are roll your own or buy an existing 3rd party toolset. Rolling your own at first blush make seem cheaper, but that's perhaps only because you haven't really discovered all the true requirements to create something robust and reliable. The 3rd party tool vendor needs to charge for their products, but they've spent years discovering all the issues with particular problem set and have solved the problems. So that eliminates work for you and leaves you free to focus on where your application can add value.
The difference is if you get setup wrong your users will be irritated; if you get copy protection wrong your product will be pirated.
In any event, reducing license validation checking to a binary "either/or" condition is extremely easy to crack--doing that check over the net makes it 10 times easier (record playback attack). Modern approaches encrypt the executable and the license is contained in the key to decrypt it (this is an oversimplification since the actual methodology includes a lot more complexity to make it virtually impossible to get around). Only by having a valid license can the executable be decrypted on program load and run.
If you want to do it the way you've described, consider this:
Have the app use a predictable, changing value (such as a lookup from a table of random numbers coupled with some external value like time) to create some kind of hash. Have the server implement the same code. The server sends the hash to the app, which compares it to its own hash. If they match, the app is allowed to run. If they don't, it errors out. Since the hash is different on ever startup attempt, recording it over the network won't allow the user to get it to run the next time it tries to start.
I love c# for programming applications (I consider myself intermediate with c#, and a bit less with C/C++, but am only learning, nothing real yet in the arena), and I used to like it until i discovered "anyone" who understand MSIL (not an easy task to learn neither) could decompile my code. I don’t really care about someone decompiling my code, but my utter concern is the security for my eventual program users. I know obfuscators exist, and I even know of one or two that are really good, I hear (even if they only delay a decompiling).
For example, if I want to decrypt something using c#, some where in the code the key should be, making it a danger for anyone who use my program (someone who know someone who encrypted the file using my program could decrypt it by researching on my MSIL code, finding my key). Then, the developing of massive applications that encrypt/decrypt stuff (or OpenSSL) is insane with c#, I think, for this reason.
I mean, most users won’t know what language was used to make that exe, but a bunch of people are able to program n c#, and an elite of this people can read MSIL, and a minority of this elite would like to hack what ever is possible to hack. Of those people who like to hack, some of them can do it with perverse intentions (in a value-less world where we live that shouldn’t surprise anyone).
So, if I want to make a program that download a file from the internet, someone could interfere the transmission and do some evil, even if I use OpenSSL with c#, because somewhere in the c# file is the key. I know avoiding hacking is probably impossible, but it looks like c# is a very unsecure way.
Does it happen with Java? (Java has the same “interpreting” and “decompile” structure as C#); I mean, the fact that the key is visible in Java (with some educated eye) some where in the building file? Or does Java use some C/C++ based API that makes it harder (way harder) to decompile the file where the key is and so making it hard to get the key?
Is my only option to write my program with c/c++? Because if so, my only option is C++Builder, since its a hell to even try to watch (and less to learn) MFC/OWL code; I mean: I cant hardly think of someone who could like MFC/OWL programming. In fact, I suppose Assembly could be of more interest in the today programming world.
So, here I am, wanting to find someone who could explain me better a way to store securely crypto keys for encrypting/decrypting or to use OpenSSL with c#. Or even with Java. I would like to confirm that C/C++ is the only way of really using these features with some security for decompiling reasons (as other compiled programming languages, i.e. Delphi).
If anyone knows a site where I can find precise information about the subtle reasoning I suppose I have done (specially one that shows am wrong in my analysis), please tell me. If any one can confirm my analysis, please confirm. If anyone find any hole in my analysis, again, please tell me, and where to find more information that rule me to get a better understanding of all this.
Am sorry for making this philosophical computer programming question that long.
Thank you,
McNaddy
Could I hide the encryption key of a c# exe securely (in a way that can't be decompiled in any known way), as in C/C++?
No. You can't do that in any language.
The .NET security system is designed to protect benign users from hostile code. You are trying to protect benign code from hostile users. You simply cannot do that, so don't even try. If you have a secret, do not share it with anyone.
The purpose of crypto is to leverage the secrecy of some private key into the secrecy of a text. If that is not the security problem you face, crypto is the wrong tool. Explain the security problem you actually have and someone here can help you solve it.
So, if I want to make a program that download a file from the internet, someone could interfere the transmission and do some evil, even if I use OpenSSL with c#, because somewhere in the c# file is the key.
You don't need to store a secret key in the program just to download a file safely.
If you want to ensure that the file you downloaded is authentic and hasn't been modified in transit, you use a digital signature. The private key used to make the signature doesn't have to be (and shouldn't be) distributed with the program; all the program needs is the corresponding public key, which you don't have to hide.
If you want to prevent eavesdroppers from reading the file as it's downloaded, then you need to encrypt it, but that can be done with a temporary session key generated randomly for each download; it doesn't have to be stored anywhere. If you use HTTPS for your download, it'll do this for you.
The choice you've mentioned (embed key into executable) is bad irrespective of language you choose - it is not too hard to extract data from C/C++ and slightly easier for C#/Java.
As Jordão said - you need to figure out your story of distributing key outside the binaries. You also need to figure out what you actually trying to protect and understand possible exploits. Just using encryption of some sort in an application does not make it more secure.
You should not store cryptographic keys inside assemblies; they should normally be provided from outside, e.g. from a key-store, or derived from a secret known to a user.
You can also generate a key from a password(this means the key is no more stronger than the password though). So each time the user runs the program, they are prompted for a password, and that password is then used to generate a key. Depending on your requirements you could employ this in a variety of ways.
When the user needs to access the encrypted data, the password can be provided again and this generates the key for use during that session. Once the program is closed the key is discarded(there are techniques/APIs in C# to help ensure that sensitive data is only present in memory as short a time as possible).
For example, this is essentially what many password storing programs like Keepass or Roboform do. The user can upload and download the encrypted data to and from servers. No keys are ever stores, and instead generated on demand as the user supplies their password for that session.
With a service like Dropbox, when you register with their site, they generate the private key on their server and keep a copy there. So the user's machine and client software never store the key, but the server has a copy stored. Dropbox does this so that they can decrypt user data for many purposes, such as compression, de-duplication, compliance with law enforcement, etc.
We have an application which contains sensitive information and I'm trying my best to secure it. The sensitive information includes:
The main algorithm
The keys for an encryption/decryption algorithm
I've been looking at Obfuscating the code but it doesn't seem to help much as I can still decompile it. However, my biggest concern is that the keys used for encryption of serial numbers etc are clearly visible when you decompile the code, even when it's Obfuscated.
Can anyone suggest how I can secure these strings?
I realise one of the methods might be to remove any decryption from the application itself, while this may be possible in part, there are some features which have to use encryption/decryption - mainly to save a config file and to pass an 'authorisation' token to a DLL to perform a calculation.
There are ways to do what you want, but it isn't cheap and it isn't easy.
Is it worth it?
When looking at whether to protect software, we first have to answer a number of questions:
How likely is this to happen?
What is the value to someone else of your algorithm and data?
What is the cost to them of buying a license to use your software?
What is the cost to them of replicating your algorithm and data?
What is the cost to them of reverse engineering your algorithm and data?
What is the cost to you of protecting your algorithm and data?
If these produce a significant economic imperative to protect your algorithm/data then you should look into doing it. For instance if the value of the service and cost to customers are both high, but the cost of reverse engineering your code is much lower than the cost of developing it themselves, then people may attempt it.
So, this leads on to your question
How do you secure your algorithm and data?
Discouragement
Obfuscation
The option you suggest, obfuscating the code, messes with the economics above - it tries to significantly increase the cost to them (5 above) without increasing the cost to you (6) very much. The research by the Center for Encrypted Functionalities has done some interesting research on this. The problem is that as with DVD encryption it is doomed to failure if there is enough of a differential between 3, 4 and 5 then eventually someone will do it.
Detection
Another option might be a form of Steganography, which allows you to identify who decrypted your data and started distributing it. For instance, if you have 100 different float values as part of your data, and a 1bit error in the LSB of each of those values wouldn't cause a problem with your application, encode a unique (to each customer) identifier into those bits. The problem is, if someone has access to multiple copies of your application data, it would be obvious that it differs, making it easier to identify the hidden message.
Protection
SaaS - Software as a Service
A more secure option might be to provide the critical part of your software as a service, rather than include it in your application.
Conceptually, your application would collect up all of the data required to run your algorithm, package it up as a request to a server (controlled by you) in the cloud, your service would then calculate your results and pass it back to the client, which would display it.
This keeps all of your proprietary, confidential data and algorithms within a domain that you control completely, and removes any possibility of a client extracting either.
The obvious downside is that clients are tied into your service provision, are at the mercy of your servers and their internet connection. Unfortunately many people object to SaaS for exactly these reasons. On the plus side, they are always up to date with bug fixes, and your compute cluster is likely to be higher performance than the PC they are running the user interface on.
This would be a huge step to take though, and could have a huge cost 6 above, but is one of the few ways to keep your algorithm and data completely secure.
Software Protection Dongles
Although traditional Software Protection Dongles would protect from software piracy, they wouldn't protect against algorithms and data in your code being extracted.
Newer Code Porting dongles (such as SenseLock†) appear to be able to do what you want though. With these devices, you take code out of your application and port it to the secure dongle processor. As with SaaS, your application would bundle up the data, pass it to the dongle (probably a USB device attached to your computer) and read back the results.
Unlike SaaS, data bandwidth would be unlikely to be an issue, but performance of your application may be limited by the performance of your SDP.
† This was the first example I could find with a google search.
Trusted platform
Another option, which may become viable in the future is to use a Trusted Platform Module and Trusted Execution Technology to secure critical areas of the code. Whenever a customer installs your software, they would provide you with a fingerprint of their hardware and you would provide them with a unlock key for that specific system.
This key would would then allow the code to be decrypted and executed within the trusted environment, where the encrypted code and data would be inaccessible outside of the trusted platform. If anything at all about the trusted environment changed, it would invalidate the key and that functionality would be lost.
For the customer this has the advantage that their data stays local, and they don't need to buy a new dongle to improve performance, but it has the potential to create an ongoing support requirement and the likelihood that your customers would become frustrated with the hoops they had to jump through to use software they have bought and paid for - losing you good will.
Conclusion
What you want to do is not simple or cheap. It could require a big investment in software, infrastructure or both. You need to know that it is worth the investment before you start along this road.
All efforts will be futile if someone is motivated enough to break it. No one has managed to figure this out yet, even the biggest software companies.
I'm trying my best to secure it
I'm not saying this as a scathing criticism, just you need to be aware of what your trying to achieve is currently assumed to be impossible.
Obfuscation is security through obscurity, it does have some benefit as it will deter the most incompetent of hacker attempts, but largely it is wasted effort that could perhaps be better spent in other areas of development.
In answer to your original question, you are going to run into problems with intelligent compilers, they might automatically piece together the string into the compiled application removing some of your obfuscation efforts as a compilation optimisations. It would be hard to maintain as well, so I would reconsider your risk analysis model and perhaps resign yourself to the fact it can be cracked and if it has any value probably will be.
I recently read a very simple solution to OP.
Simple declare your constants as readonly string, not const string. That simple. Apparently const variables get written to a stack area in the binary but written as plain text whereas readonly strings get added to the constructor and written as a byte array instead of text.
I.e. If you search for it, you won't find it.
That was the question, right?
Using a custom algorithm (security through obscurity?), combined with storing the key inside the application, is simply not secure.
If you are storing some kind of a password, then you can use a one-way hashing function to ensure that decrypted data is unavailable anywhere in your code.
If you need to use a symmetric encryption algorithm, use a well known and tested one, like AES-256. But the key obviously cannot be stored inside your code.
[Edit]
Since you mentioned encryption of serial numbers, I believe you a one-way hashing function (like SHA-256) would really suit your needs better.
The idea is to hash your serial numbers during build time into their hashed representations, which cannot be reversed (SHA-256 is considered to be a pretty safe algorithm, compared to, say, MD5). During run time, you only need to apply the same hash function to the user input, and compare hashed values only. This way none of the actual serial numbers are available to the attacker.
#Tom Gullen have given a proper answer.
I merely got some suggestions on how you can make it harder for the users to access your keys and algorithm.
As for the algorithm: Do not compile your algorithm at compile time, but at runtime. To be able to do this you need to specify an interface which contains the methods for the algorithm. The interface is used to run it. Then add the source code for the algorithm as an encrypted string (embedded resource). Decrypt it at runtime and use CodeDom to compile it into a .NET class.
Keys: The usual way is to store spread parts of your key in different places in the application. Store each part as byte[] instead of string to make it a bit harder to find them.
If all your users have an internet connection: Fetch the algorithm source code and the keys using SSL instead.
Note that everything will be pieced together at runtime, anyone with a bit of more knowledge can inspect/debug your application to find everything.
i dont think you can easily obfuscate string constants, so if possible, dont use them :) you can use assembly resources instead, those you can encrypt however you want.
Depends what you're trying to do but can you use asymmetric encryption? That way you only need to store public keys with no need to obfuscate them.
We have around 60 MB of device configuration implemented in at least 1000 xml files.
Now we are releasing the software to the customers. But our requirement is not to allow the user to view and edit the xml configuration files. XML configuration files contains a lot of secret of the device information which can be easily hacked if it is readable.
Now we need to encrypt the xml files. Are there any recommended method to encrypt the xml file and it can be decrypted at run time?
This is a problem known from DRM applications - you want to make the data available to the user agent of your choice but not to the user operating the user agent. But, since the user agent is usually on the user's side, as Jon and Oded point out, a determined hacker will find a way to break the encryption. It's a cat and mouse game. You are trying to find a solution to exactly the same problem that people implementing DRM want to solve. Software-only user agents are easier to hack than hardware-assisted user agents, but in either case time works for the hackers. The latest development is the latter - embedding all the cryptography in hardware - like the HDMI's HDCP method (High-bandwith Digital Content protection Path) where they have essentially made the decrypted digital signal inaccessible to the user by letting it pass along black-box hardware from its point of decryption until it is made so available, but at the intended destination - TV screen. The key for HDCP to succeed however was implementing it in hardware. Most hackers have learned to deal with software. But since I would say there is 1 good hardware hacker per 100 good software hackers these days, the mouse hopes no cat will be around to catch it. Sorry for too much theory, it is essential to your problem though, I believe. If you are still willing to play the game, encrypt your XML files and make sure the decryption key is not available to potential hackers on a silver plate - i.e. obfuscate it, can't do much else.
How determined are you expecting the "hackers" to be? If all the information required to decrypt the information has to be present on the system anyway, then a determined attacker is going to be able to get at it anyway.
You can use the classes in the Cryptography namespace.
Most of the encryption classes will allow you to encrypt and decrypt streams, so are good for your purpose.
However, you will still need to hold the encryption keys somewhere, even if it is in the assembly.
As Jon points out, a determined hacker will find a way to break any encryption.
As others explained, you won't get it absolutely secure without a trusted device which stores the key and does the decryption without granting access to the key under any circumstances. Computers aren't "trusted devices"...
My employer sells such technology and if your data is really money worth, you should possibly take such a solution into account.
If an additional USB-Dongle is not acceptable (or too expensive) at least use public-key (asymmetic) cryptography (see System.Security.Cryptography).
Asymmetric cryptography has the advantage that the key used to decrypt your data can't be used to encrypt the data.
Your application has to store the decryption key and the hacker can determine it with more or less effort. He then can decrypt all your data but he can't not encrpyt the changed data again. So he can't use your application with the changed data.
If you want to prevent him from doing this, you have to obfuscate your application and use anti-debugging techniques (static and runtime). If you go this way buying an existing solution is probably cheaper.
Watch out: Hackers can see all functions in .net generated executables and dll's!
If you make a decription algorithm in your .net project like DecryptXML(string Path), it is very easy for a hacker to call this instruction. So be sure to dotfuscate your project.