How to obfuscate string constants? - c#

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.

Related

Protecting WPF application with self-made key algorithm

I need to find a way to lock a software product, so only customers who bought it can use it. I was thinking about implementing my own "CD-key" feature.
How it works:
I have a seperate program, that is used only for generating keys.
The program uses the same algorithm than the software being selled. The key is shipped with the program (on lets say the manuals) and entered in the program one time. After that the user can use it freely without ever entering it again(until reinstalling).
This looks pretty simple and doable to me, but the only problem is that the key can be reused on other devices, so I would need to implement a way, that the key is online marked as used and unused, when the program is getting uninstalled.
I would try asking this on https://softwareengineering.stackexchange.com/ instead of here - but I'd advice you to look into (non)-commercial products/API's to help you out (e.g. http://www.ssware.com/cryptolicensing/cryptolicensing_net.htm) in stead of reinventing the wheel. As it's not your core business, you'll likely have a less optimal solution (and thus weak and leaky solution) than what others might provide you with.
Some products you can look into:
free
QLicense (on CodeProject): https://www.codeproject.com/Articles/996001/A-Ready-To-Use-Software-Licensing-Solution-in-Csha
pay to use
SSWare's CryptoLicensing: http://www.ssware.com/cryptolicensing/cryptolicensing_net.htm
SORACO: https://soraco.co/quick-license-manager/?gclid=CjwKEAiAirXFBRCQyvL279Tnx1ESJAB-G-Qvy65J7uzmMUClDy0fltJKN7U9HtFex5akQ-H3r7YgFhoCa7nw_wcB
PS: if you would start implementing a licensing solution on your own, please drop implementing the same algorithm in both the deployed code as well as the generator - it's too easy to reverse engineer. Try to use some mathematical formulas that support public/private key mechanisms for example, or as I said try to rely on a library/api that's specialised in this domain.
Problem:
Since your code can be reverse-engineered, there is not real way to provide safe solution for your key storage. All your variables hard-coded into application, or in separate files, where they are encrypted using the same application are not safe. You need to treat them as publicly available.
Second even if you will provide way of server key authentication, again. Your code can be reverse-engineered. Hacker will remove authentication part, and will re-build your application, DRM free.
Third, even if you whole code, will be crypted, there are still ways to decode that and remove authentication (look denuvo latest failures).
If you will connect code crypting and server side key authentication depending on how many people will be involved in hacking you can delay them be finite amount of time.
Solution:
There are 100% secure ways to prevent your application to be hackable, you need to make it 100% web based. There are solutions like ASP.Net if you wish to use C# as server engine.

Can some hack my key license system by analysing my CLR DLLs?

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.

Secure network traffic c#

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.

Protecting XML file from editing

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.

How do you hide an encryption key in a .NET application?

I'm developing an intranet application (C#) that uses some data (local to the web server) that we'd like to keep private. This data is encrypted (AES) using a legacy data repository. We can't totally prevent physical access to the machine.
Clearly, we're never going to have perfect security here. However, we want to make it as hard as possible for anyone to gain unauthorized access to the data.
The question is how best to store the key. Encrypting it based on some machine specific ID is an option, but that information would be readily available to anyone running a diagnostic tool on the machine.
Encoding it in the application is an option (it's a one off application). However, .NET assemblies are pretty easy to decompile. So, would it be best to obfuscate it, use an encryption launcher, compile it?
Or is there an option I'm missing?
Just so we're clear, I know it's pretty much a lost cause if someone is determined, but we're looking to make it as hard as possible within the constraints.
Encryption is built into the .NET configuration system. You can encrypt chunks of your app/web.config file, including where you store your private key.
http://www.dotnetprofessional.com/blog/post/2008/03/03/Encrypt-sections-of-WebConfig-or-AppConfig.aspx
Speaking in obfuscation terminology, what you are after is called constant hiding, i.e. a means by which you transform a constant into, say, a number of functions and calculations that are executed at runtime to re-materialize said constant.
This still falls within the domain of obfuscation, however, and is susceptible to either code extraction, where the attacker simply maps out the code relevant to this constant, and runs it in a separate application to retrieve the value; or dumping the application's memory at the right point in order to scan it for the desired value.
There is another, slightly more advanced method of hiding crypto keys in particular, called White-box cryptography, which employs key-less ciphers through essentially generating a cipher function from a given key, baking them together. As the name suggests, this method has been devised to be resilient even in a white-box attack scenario (the attacker has access to the bytecode and is able to inspect and manipulate the executable at runtime).
These are both quite advanced methods of achieving security through obscurity, and it might be worth considering alternative models which do not force you to do this in the first place.
If somebody can just attach a debugger to your program, there is absolutely nothing you can do. They won't have to figure out your config, disassemble your app, etc. All they have to do is run the app - watch it use the key - bingo.
Obfuscation is of no help under those conditions.
The best defense is to use hardware to protect the key - which will do the crypto but not give out the key itself (and is sometimes hardened against attacks such as probing the wires, exposing the memory to low temperatures/radiation/other novel stuff). IBM do some appropriate stuff (google IBM-4764) but it's not cheap.

Categories