I'm a developer of a game in c#, and I have a security feature in which my server dynamically creates a DLL with some secret keys in it and uploads this DLL to amazon s3, and then pushes out challenges to people are random. When the clients receive this challenge they have 30 seconds to respond.
The clients download the DLL from amazon s3, and using reflection call a method, which takes in a key sent to them by the server.
The dll then takes the key passed into the function, the secret key randomly built into the dll, and a crc hash of the GetCallingAssembly() and hashes them together. This result is returned to the client and the client pushes the response back to the server.
Back to the question... We have a hacker who has somehow found a way to fake GetCallingAssembly and to better understand this, so that I may find a way to prevent it or use something a little harder to fake, I would like to replicate what he did.
From what I've gained its an application he is using, he did NOT use code to do this. But i have found NOTHING in regards to this. Any help with be greatly appreciated so that i can remove this guys security hole.
There are a variety of techniques that could be used for this. For example, the Moles framework allows one to replace the implementation of even static methods on BCL assemblies. It accomplishes this via use of a CLR profiler, which may or may not be what your hacker has done.
It seems like the only thing you'd have to do in order to trick GetCallingAssembly would be to create a new assembly with the same name. Now the chain is broken. I can't point to how he did it, but I can provide a suggestion to make it more difficult to crack...
Client downloads DLL from S3
Client invokes method in the DLL
DLL gets the calling assembly, and invokes a method on the client. This method takes in some salt (preferably one of the unique keys in the DLL or a datetime), appends it to a secret string (stored in the client), hashes the result, and returns this hash to the DLL.
Once the client provides the correct result, then the DLL answers the server correctly.
It's always possible to break in, but the more encryption-related steps in-between, the more difficult you make it for them. And this step wouldn't take much effort to add.
Related
I have Created a C# Desktop Windows form Application and I have created a setup for that. In the C:\Programs files app folder I have a JSON file. I need to protect it from accessing by anyone (I need to protect the data). What should I do?
You can't. If the intruder have access to the computer with the Administrator rights (or even more - a physical access to the hardware), then any protection will be useless.
You can use some kind of encryption, code obfuscation and some anti-debugging techniques to make it harder to retrieve the data, but qualified intruder with the appropriate access level will be able to access the data in the moment when you will decrypt it.
The only working way is to completely remove the secret data from the client's computer and move it to the your secure server alongside with the processing of such a data. So, client sends the inputs to your server, the server performs the processing using the secret data and sends back ready-to-use results.
First of all: it's impossible to make it un-breakable - I won't argue on this. Then you can simply encrypt it with a simple Blowfish algorithm and keep the key hardcoded.
You can use a more secure algorithm if you want so.
Easiest solution is to use a binary serialization format instead of json. This will make it much harder to understand and decode. Or just hardcode the data instead. Most people lack the knowledge to do anything meaningfull with a binary chunk of data, or an assembly for that matter.
A more complicated solution would be to sign the data, as this would allow you to only hardcode the key. A related alternative is Encryption. Encryption is sufficient but not necessary for ensuring the integrity of the data, but is not really more difficult to apply, see encrypting data.
Whatever you do you cannot really prevent a sufficiently determined and knowledgeable attacker. It is possible to decompile the program and extract or replace any secrets therein. The only truly secure way would be to prevent access to the files in the first place, by moving it to the web for example.
I had a similar requirement and decided to encrypt the data.
I used the package "AuthenticatedEncryption" (available from NuGet ) and could hard-code the key in my code.
NuGet: https://www.nuget.org/packages/AuthenticatedEncryption/
Guthub: https://github.com/trustpilot/nuget-authenticated-encryption
I can do this, as my main purpose is more to make the data unreadable to users and I don't expect it to be unbreakable.
Even so, I change the key every few releases.
For my ~70Kb JSON file I only load it once at the start of the program, so performance is not a problem. Not that I anyway notice anything!
I have a dll with an "authentication" method in it that checks if a password is valid, like this:
public static void AuthenticationExample(string password)
{
if (PasswordIsValid(password))
this.locked = false;
}
To prevent the password from being "cracked" by a loop, I want the method to crash the entire application if authentication fails, like this:
public static void AuthenticationExample(string password)
{
if (PasswordIsValid(password))
this.locked = false;
else
Crash();
}
Is there a way of doing this?
Alternatively, what is a better way of protecting a dll?
CLOSING WPF:
You can just call the main window and close it or throw a custom exception.
PASSWORD PROTECTION:
I had same issue. Finally, understood that whatever you do, it can be cracked. Nothing is fail proof. If your license verification is done on the cloud, like sending some info to a server and receiving back response, it can be managed to an extent.
Just because everything can be hacked, doesn't mean that you have to leave your product wide open for cracking. You can add some barriers so that it is little hard for the crackers. If the product is worth the effort, eventually someone will hack it.
For my applications, I have 2 or 3 licensing steps (which can slow down a hacker but not stop him/her)
A dll (say, DLL-A) with cryptography methods for verifying a license. DLL-A will be placed in working directory. Along with that, a copy of this dll (say, DLL-B) will also be placed as an embedded resource.
During runtime, when the DLL-A is about to be loaded, the DLL-B will be extracted and hash for both will be compared. This is to ensure that DLL-A is not tampered with. In case, DLL-A is tampered, the DLL-B will replaced DLL-A.
Along with that dll method, a XML-Signed file will also be used. This will be verified somewhere in the code.
A C++ native library, with different cryptography methods. This will also be used similar to DLL-A /DLL-B procedure (steps 1,2).
Thus, in my application, i generally use 3 to 4 different license verification scheme. All are independent. Even though everything can be hacked and broken, the hacker will have to be fed up trying to hack all the 4. And with every year, I change my licensing methods and update the new app. So, this means that for every year, hacker has to spend hard time to hack it. (Which should eventually make them feel frustrated).
Above all, I also have cloud based verification for my apps (the ones which store credentials in cloud DB). But, there are still some clients who expect their app to run without connection to internet (due to some security reasons).
Note: Eventually everything is hackable. Point is you just make it hard for hackers.
This is probably coming off as a REALLY broad question.
But is there a way to have my applications code (or some of it) stored on a server, and download it and execute it securely?
I've been seeing ASP.net everywhere but I don't fully understand it. Is this basically exactly what im looking for, or is it some kind of C# Website Hosting, like xampp?
Either way, what im looking to do, is to be able to download some C# methods, not an entire namespace and be able to reference code like, System.*, Program, Form1 and such from those methods.
I managed to get CSHarpCodeProvider working and with System references using its CSharpParameter but it uses a direct namespace, essentially asking for an entire full valid .cs file, whereas I want to load in methods only and not have it secluded but to be interactable with all existing code.
This is probably a lot to ask and probably doesn't exist.
Here's my formula:
Make a request to website.com/api/login.php?e=email#domain.ext&p=Pass123, returns obfuscated C# code along with the first line of text being an MD5 hash of the C# code, Email, Password and random generated strings/numbers/symbols.
Generate the verification hash on the C# Client Side, send the returned hash back to the website on a different php script, That script will verify if it's correct and will return a session token even if it's an incorrect hash (meaning the request was tampered with).
The C# returned from the first request, This seems good to go, Everything matches up. Replace the placeholder garbtext like <!!TOKEN!!> with the token from request 2 without doing verification checks at all.
Execute the finalized C# code.
The finalized C# code will do stuff like create methods that would be used throughout the application including a private bool x() that returns if the application is licenced/purchased.
Use application as normal using the methods created.
Notes:
Having some unixtime checks in the hash and inside bool x() and such would be a good idea to further prevent un-licenced intrusion.
Pros:
The application is theoretically almost impossible to "Crack". To crack it, you would have to manually replace all the functions. Obfuscate the code on server-side before returning to the C# client and it will be extremely hard to do and would be very time consuming.
Can be auto-updated and you wouldn't need to update the .exe unless you did vast changes.
Cons:
Will require a lot more server power depending on the size of your userbase.
Costs you and makes profit a lot smaller if your selling an application licence.
Internet connection needed no-matter-what!
Startup time would be slower.
Downtime can seriously impact your application.
I have a DLL file (cf.dll) in my project.
It has some methods for encrypting and decrypting a string To/From a file.
My "cf.dll" have some methods for:
write "mystring" ---to-->> new encrypted dll
and
read encrypted dll ---to--->> "mystring"
Now i want publish my project, but if end user use my dll in his/her visual studio (by reference to dll), he/she can decrypt my encrypted files.
Another hand i need this dll in my published project because my project use theirs methods some times.
Now my question is:
How can i change this published dll (cf.dll) to a none-reference dll, for prevent any hack by it.
Edit (more details):
What i want to do:
I want encrypt some connection strings (as a DataTable) to a file and read this file agin.
I have a dll file for doing this work. it is cf.dll. it has some methods for encrypting and decrypting.
Encryption workflow>
DatatTable ------to------>> Xml as String ------by cf.dll methods to------>> enc.dll
Decryption workflow
enc.dll ------by cf.dll methods to------>> Xml as String ------to------>> DataTable
Everything is working properly and encrypted file (enc.dll) is created.
But if the end user use my magic DLL (cf.dll) in a new project in the visual studio (by reference to it), he/she can decrypt my encrypted file (enc.dll) and hack my program.
So, i want to prevent this hack by changing my DLL (cf.dll) to a none-reference DLL OR use another safe solution.
Edit:
My Table Columns for keeping connection string data:
Server DbName DbUser DbPass FileName
But may i ask save another DataTable by this encryption mechanism. so please help me by a solution for saving any string, not only a ConnectionString.
I want a very secure encrypted file from any data. in my solution i conver each object to a string then use my dll methods for save it as a encrypted file (i can do it nice, my problem described above).
You cannot make your dll "non-reference dll", but you can hide all your classes/methods with "internal" keyword (instead of public). This means that this classes/methods can be used only inside of current dll or in DLL/EXE which were specified with InternalVisibleTo attribute. So nobody can use them directly, but you should know that this is managed code, so anybody can take a look inside of your DLL and extract your keys for decryption and write the same code as you have in your dll.
Surprisingly you can not archieve your goal by using a .NET Assembly.
You could even obfuscate your code and it would still be decompilable and reusable.
There's nothing which can prevent that. You can rise the bar, but someone - if she want's - will be able to get the information you are trying to hide.
(Have you seen copy-protection mechanisms that really work besides doing something crucial online?)
Always think of the following:
If you want to hide information from a user DO NOT DELIVER that information. Everything else is just protection through obfuscation, wich can be cracked with more or less effort.
That's a really nice question RAM.
Some solutions to your problem:
1) Don't make a separate assembly (DLL), but put the code of your DLL in your EXE and make the encryption/decryption function of your DLL "internal" (so that no-one can use it from outside the EXE). Then use a free tool like Eazfuscator to obfuscate your EXE (because, if you don't, your code will be easy to decompile and read).
2) You could put the DLL in your EXE's resources (perhaps encrypted too). Then perhaps you can find a way to get it from there and load it into memory for your app to use. But this is quite complex thing to do if you are a beginner and I'm not 100% sure if it's doable in .NET (I haven't done it myself). However, I think it's doable.
3) The fact is that, if your code executes on the client's machine, there's not much you can do to prevent people from analysing it. The best you can do is to make it a little (or much) difficult for them to do it. E.g. you can add a lock mechanism in your DLL that requires the caller to respond to a random question. If he responds correctly, you execute the decryption. If not, throw an exception, return null or, even better, return a wrong output. The random question could be an integer that your DLL will generate on initialization and the EXE should process this integer to generate a new integer based on some "secret" algorithm. Then the EXE will "feed" this into the DLL somehow and it's functionality would be "unlocked".
4) Perhaps you could use reflection to analyse the caller assembly in order to find characteristics or even the author signature (if you put one in your EXE). That way, you could execute the decryption if the EXE is signed by your private key and the signature is valid. But that's a bit complex too.
5) I think there are tools called "EXE packers" that pack your EXE and DLLs into one EXE file and protect them at some degree. I haven't used one of those yet.
6) You can move the encryption/decryption process on a web site that will ask for authentication in a complex manner, similar to the one described in (3) for the DLL. This may keep your encryption algorithm safe, but the authentication process could still be analysed and hacked.
I would suggest the 3rd solution since it's the most easy to implement. The 4th (using signed code) is the most secure one but it takes a lot of knowledge to implement it (knowledge that even I don't have right now).
Have a nice coding! :)
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.