today I'm gonna write a very quick analysis about an Happy Ransomware variant spotted in the wild on Jan 24 2019.
https://www.hybrid-analysis.com/sample/9da7d298691613a398e26ac3c4c4e4e9c93069d2162fa6639901dd7c62774ef5?environmentId=100
https://www.virustotal.com/en/file/9da7d298691613a398e26ac3c4c4e4e9c93069d2162fa6639901dd7c62774ef5/analysis/
sample hash details:
MD5 64f11aee7f21ec74a3f8f518e45c6d55
SHA1 1d06a6c7032c4ec4005a46ffe7c29135f26d3e15
SHA256 9da7d298691613a398e26ac3c4c4e4e9c93069d2162fa6639901dd7c62774ef5
This was a very easy ransomware, like many I've seen in the past it actually send an email with a PC screenshot, this.i (wich is the encrypted files counter) and some other stuffs... Actually the ransomware sends some of such informations also trough the UserAgent to a specific url but we dont care about that, we're focused to know how to get back our files.
In this ransomware a static analysis is enough to have an idea on how the sample works.
From the picture above, the circle number 1 is actually a search of all ("*") the files + all sub Directories of the following ones: ProgramFiles, PROGRAMFILES(X86), systemroot, appdata, tmp , Desktop and MyDocuments folder.
As you can see on the circle number 2or each file found, the encryption key string is composed by (this.i + 1) + "GbVjXehg"
The encryption function is called (2bis circle) and then the circle number 3 actually means this.i +=1;
This means that we have different key for each file encrypted in a keyspace which is contained into 1 up to the number of files encrypted. If we suppose to have 1000 encrypted files (wich we can enumerate by a search of "*.happy")
Minium key string is from "1"+"GbVjXehg" to "1000" +"GbVjXehg"
Each key is actually hashed (sha256Cng.Computehash(byte[] in) in the encrypt function), but this does not change the size of the keyspace because we have just one hash match for each key string.
Source code (its just a proof of concept), here:
using System;
using System.Security.Cryptography;
using System.Text;
using System.IO;
namespace proofofcode
{
class Program
{
public static void Main(string[] args)
{
var buffer = File.ReadAllBytes(@"c:\enc.happy");
int maxfiles= 1000; //We suppose to have just 1000 encrypted files.
int i=0;
MemoryStream mss = new MemoryStream();
for(;i<=maxfiles;i++){
if(Decrypt(i,buffer,out mss)==1) break;
}
File.WriteAllBytes(@"C:\Users\PC\dec.bin",mss.ToArray());
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}
public static int Decrypt(int i, byte[] buffer, out MemoryStream msi)
{
int ret=1;
try{
RijndaelManaged myRijndael = new RijndaelManaged();
myRijndael.Mode = CipherMode.ECB;
SHA256Cng asd = new SHA256Cng();
var rijndael = new RijndaelManaged
{
// "135GbVjXehg"
Key = asd.ComputeHash(Encoding.ASCII.GetBytes(i+"GbVjXehg")),
Mode = CipherMode.ECB
};
var transform = rijndael.CreateDecryptor();
string decrypted;
using (var ms = new MemoryStream())
{
using (var cs = new CryptoStream(ms, transform, CryptoStreamMode.Write))
{
cs.Write(buffer, 0, buffer.Length);
cs.FlushFinalBlock();
cs.Close();
// Console.Write("good key");
// File.WriteAllBytes(@"c:\dec.bin",ms.ToArray());
}
msi=ms;
ms.Close();
}
}catch(Exception e){Console.WriteLine("error key"+i);
Console.WriteLine("IOException source: {0}", e.Message);
msi=null;
ret=0;
}
return ret;
}
}}
Obviously the code can be optimized by for example, starting from rewriting my whole code LOL :)) plus, as we know each key is used once for one file, so to speedup the process excluding the used key helps a lot.
You can extend the use searching all the .happy files and automate the decryption for each file found.
Cheers,
RE Solver


Nessun commento:
Posta un commento