domenica 27 gennaio 2019

Free decryption tool: .Happy Ransomware variant spotted in the wild

Hello everybody,
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

mercoledì 16 gennaio 2019

Free decryptor tool: Unpacking, Analysis and solution for the JobCrypter ransomware

Hello everybody!




sha256: 37e28559fba615aee1204eebf551dc588f7dc5b8a7e11893a1602da40b03f4fb
https://www.virustotal.com/en/file/37e28559fba615aee1204eebf551dc588f7dc5b8a7e11893a1602da40b03f4fb/analysis/1547612281/
sample url - be carefully! - http://axens[-]archi[.]com/5.exe

Today I saw a Tweet from MalwareHunterTeam talking about a JobCrypter ransomware, everything was set up to have fun :)


Once I got the sample, I've started the analysis by using dnSpy... yet another eazfuscator exe

I did not want to spent time trying to deobfuscate and devirtualize the malware, so....the easiest was to infect myself with it :)
A couple of exe has been created in %Appdata% and no obfuscation at all....(LOL)

Digging inside the "nlo.exe" in %Appdata% I found something very very very funny:


His email credentials in plaintex. Username and password. I couldn't resist to login.....


Lovely <3 ....but go back work.
(I do not change the password, is not up to me.)

If you have no Avast (Avastsvc process), notepad opened (yes...notepad.exe.... dont ask me why! :) ) and/or the email can't be sent correctly, the ransomware wont start his job.

Oh, I forgot to say: into the email, the owner will get also a nice screenshot of your pc (stored in %Temp% path) and the key to decrypt your data with the "VolumeSerialNumber" of C: and other stuffs.


Well, is pretty easy to guess what the Password variable is and what does it contain.... ;)

Here we are in the encryption core where the string_1 parameter is our RegKey data named "MOI" stored in "Computer\HKEY_CURRENT_USER\Software"
Such ransomware provide also another class which is named as "DecodeFiles"...and do what it say...!!!
After a check with the awesome CryptoTester tool made by @demonslay335 I've made a very quick "copy and past" and here is the decryptor POC (no proper args[] checks, and drive scan...do it yourself if needed):

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace FranceRansomwareDecryptor
{
 class Program
 {
  public static void Main(string[] args)
  {
   Console.WriteLine("Hello World!");
   // Computer\HKEY_CURRENT_USER\Software
   //MOI 6914262016XXXXXXX8153754XXXXXXX01007XX69574184XXXXXXX34846XX0245058
   //1 1
   
   Decode_File(args[0], args[1]);
   
   Console.Write("Press any key to continue . . . ");
   Console.ReadKey(true);
  }
  public static void Decode_File(string string_0, string password)
  {
   try
   {
    string string_ = File.ReadAllText(string_0);
    string s = tdsDecode(GetStrings(string_), password, false);
    byte[] array = Convert.FromBase64String(s);
    string path = string_0.Replace(".css", "");
    FileStream fileStream = new FileStream(path, FileMode.Create);
    fileStream.Write(array, 0, array.Length);
    fileStream.Close();
    //File.Delete(string_0);
   }
   catch (Exception ex)
   {
   }
  }
   public static string tdsDecode(string string_0, string string_1, bool bool_0 = false)
{
 TripleDESCryptoServiceProvider tripleDESCryptoServiceProvider = new TripleDESCryptoServiceProvider();
 MD5CryptoServiceProvider md5CryptoServiceProvider = new MD5CryptoServiceProvider();
 tripleDESCryptoServiceProvider.Key = md5CryptoServiceProvider.ComputeHash(Encoding.ASCII.GetBytes(string_1));
 tripleDESCryptoServiceProvider.Mode = CipherMode.ECB;
 ICryptoTransform cryptoTransform = tripleDESCryptoServiceProvider.CreateDecryptor();
 byte[] array = Convert.FromBase64String(string_0);
 return Encoding.ASCII.GetString(cryptoTransform.TransformFinalBlock(array, 0, array.Length));
}
   public static string GetStrings(string string_0)
{
 int num = 0;
 string result = "";
 string[] array = string_0.Split(new char[]
 {
  ';'
 });
 checked
 {
  int num2 = array.Length - 1;
  for (int i = 0; i <= num2; i++)
  {
   if (num == 0)
   {
    num = 1;
   }
   else if (num == 1)
   {
    result = array[i];
   }
  }
  return result;
 }
}
 }
}



Do it works? Let's test :)



Victory! :)

You can compile the decryptor by your own or download it from here (zip password: 123 ): https://ufile.io/als52

Cheers!
RE Solver

martedì 15 gennaio 2019

A crypto-defeat story of a malware labeled as: Backdoor.MSIL.Agent - NanoCore Client

Hello Everybody,
on 14/01/2019 just another RAT has been seen in the wild.

https://www.hybrid-analysis.com/sample/38cba78c3d1650f2ad347c0254837f376fd4434904096451faee82ec31ed829a

Such sample born as obfuscated .net PE. The first step has been obviously to deobfuscate the executable, de4dot was my swiss knife.


From the entry point you can follow the calls and arrive easly to an interesting part...
Class8.smethod_16(), by using WIN APIs calls, allows the malware retrive encrypted data from the only resource it has named "1". A common story of many malwares. :)
Ok, take a look at it and keep it in mind:
Following the code, and focus at
byte[] byte_ = binaryReader.ReadBytes(binaryReader.ReadInt32());
our binaryReader is already filled with the resource and the first step is to read an int32  wich means that the our memory pointer is moved forward of 4 bytes. That is also means that the byte_ array wich have size of the first bytes ( we read "10 00 00 00" --> 0x10) is also filled with the following first 10 bytes of the resource starting after the first 4 bytes.
[spoiler]This will be important because the item will be our DES-perate decryption item! :)  [/spoiler]


Going back on dnSpy we're on the line 366 (see few pictures up) "Class8.byte_2 = Class8.smethod_19(byte_, guid_);"
Let's follow the Class8.smethod_19 method:
Very nice, the parameters byte_ and guid_ are used to prepare the Rijndael keys.
byte_ is written in the resource, and guid_ is just the guid of the exe (see at the method smethod_18 in the last picture).

Stepping back on:
 On the line 367 we have a call to a function, and you can guess what such function does...

public static void smethod_0(byte[] byte_0)
 {
  DESCryptoServiceProvider descryptoServiceProvider = new DESCryptoServiceProvider();
  descryptoServiceProvider.BlockSize = 64;
  descryptoServiceProvider.Key = byte_0;
  descryptoServiceProvider.IV = byte_0;
  Class22.icryptoTransform_0 = descryptoServiceProvider.CreateEncryptor();
  Class22.icryptoTransform_1 = descryptoServiceProvider.CreateDecryptor();
 }

Yes, DES algo with same key and same IV related to the Class8.smethod_19(byte_, guid_) we seen before. We can put it togheter by writing a tiny (super dirty) c# console aplication here is the source:

using System;
using System.Security.Cryptography;

using System.Reflection;

using System.Runtime.InteropServices;


namespace testz
{
 class Program
 {
  public static void Main(string[] args)
  

      byte[] byte_3 ={ 0x39 ,0x5C ,0x38 ,0xAC ,0x45 ,0x65 ,0x1A ,0xEB ,0x26 ,0x5C ,0x00 ,0xC0 ,0xC9 ,0xA1 ,0xD2 ,0x03};
   
   Assembly assembly_1 = Assembly.LoadFile(args[0]);
          Guid guid_0 = new Guid(((GuidAttribute)assembly_1.GetCustomAttributes(typeof(GuidAttribute), false)[0]).Value);
  
   Console.WriteLine("Hello World!");
   Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(guid_0.ToByteArray(), guid_0.ToByteArray(), 8);
   
   byte[] IV;
   
   
   
   RijndaelManaged asddd = new RijndaelManaged{ IV = rfc2898DeriveBytes.GetBytes(16),Key = rfc2898DeriveBytes.GetBytes(16)  };
   byte[] test= new byte[64];
   
          ICryptoTransform asdsss= asddd.CreateDecryptor();
   test= asdsss.TransformFinalBlock(byte_3, 0, byte_3.Length);
   
   DESCryptoServiceProvider descryptoServiceProvider = new DESCryptoServiceProvider();
  descryptoServiceProvider.BlockSize = 64;
  descryptoServiceProvider.Key = test;
  descryptoServiceProvider.IV = descryptoServiceProvider.Key;
  Console.Writeln(String.Concat(Array.ConvertAll(test, x => x.ToString("X2"))));
   
   
   Console.Write("Press any key to continue . . . ");
   
   Console.ReadKey(true);
  }
 }
}

And here we are! Yayyy!! We have the DES key: 0x72 0x20 0x18 0x78 0x8C 0x29 0x48 0x97
But the question is: what binary data do we decrypt with it? Let's step back to the resource we were.
our reader pointer were at 0x14 position of the resource.

Once again, another array of 4 bytes int32 dimension, so we have an array size of 0x15fa0 filled by the following resource starting from 0x18.

Let's check our theory by using CryptoTester as below:


Decryption succeded! ....but, i was expecting a more readible data then 01 9B DE 01 00 ED BD...no magic numbers, no blob data, is that a fail? Go back and take a look on the dnSpy and follow the smethod_13() on line 369. the array3 which will contain our decrypted data is filled by the Class22.smethod_2 method.
Following we'll land here:


And here we are! the decrypted data is just a compressed data (deflate). We did the right things, any doubt?! :P
The resource file contains the client settings (keylogger:bool, persistance:bool, hostaddress:string and a lot of others informations) togheter with another MZ  file which is the clientplugin.dll referenced, but not "contained", in the original sample.

I think that the same decryption is valid for most of NanoCore client versions/variants maybe, so feel free to use my code.

I wanna thank Michael Gillespie for his amazing CryptoTester ("saving my soul from hell").
Huge thanks also to Karsten Hahn (without knowing, he inspired me to share things).

Cheers!
Re Solver






venerdì 11 gennaio 2019

Perfect Keylogger - Not a so perfect protection itself. An old infected keygen story.

Hello everybody,
everything has started by watching this video on youtube made by some user "St.Bandera" https://www.youtube.com/watch?v=xv1WbTQbXzY

His "nasty dirty trick" used to crack the software has triggered my anger and I wanted to write this post. :)


Some time before I was also interested to take a look into the same commercial keylogger which is packed with Themida protector. 

Themida has always been a nightmare. 

My goal was to unpack it and analyze the keylogger deeply to know what does it really do...until now :)

In my pc I have an older version with an infected keygen and I'm focusing on it.

Virustotal scores it as 51/67.
https://www.virustotal.com/#/file/c5b81e4f47aae5c7b74b6c4257bb98e6d07c05b5d6ab04bb5727a7509f0419f2/detection



After first unpacking I dumped a second exe which is also (probably) a malware... https://www.virustotal.com/#/file/d7da3cebe33476fe10f088cec3220f6b6be00cac70bb25a258be97f0cc991952/detection
what do you expect from a keygen?! :)

In this case I won't dig about what such malware do, I focus myself into the keygen routine. IDA-Pro static analysis helps us:


Basically, each char of the key (which is always 16 char long as the lenght of the secret key) is generated by simple operations in a pseudo routine like this: 
// PSEUDO CODE
result = xor ( hex(A[0]), hex(k[i]) );
final_Char= result % 0x19;
final_Char+= 0x41;

Where the "A" array is just our "user name" of 16 char lengh and the "k" array is the secret key which changes on each version of the "Perfect keylogger" (and works until the owner does not change the registration routine).
Since we're starting from an old keygen which contains an invalid key for this keylogger newer version, now the question is: where do we find the key?

The keylogger, even if its packed by Themida protector, is not propelly fully protected and we can steal the key from the dump and we dont even need to do that by using ollydbg...we can just use a HXD!!!! LOL
Anyway, we're lazy...aren't we? :)
In the youtube video, there is the secret key showed up into the strings list. :)))

A quick snippet of code in .net do the job.

// hex rapresetation of the secret key - i wrote an invalid one -
   char[] secretkey =new char[]{   (char)0x90, (char)0x90, (char)0x46, (char)0x90,
           (char)0x90, (char)0x90, (char)0x90, (char)0x90, 
           (char)0x90, (char)0x78, (char)0x90, (char)0x25,
       (char)0x90, (char)0x90,(char) 0x90, (char)0x21};
   string hex ="A";
   
   
   
   int result=0x0;
   string key="";
   int A;
   int k;
   for(int i=0;i<=15;i++)
   {
    A=(int)Convert.ToChar(hex);                 
    k=Convert.ToInt32(secretkey[i]);
    result=( k ^ A);                 
    result= result % 0x19;
    result+=0x41;
    if(i==4 || i==8||i==12) key+="-";
    key+= ((char) result).ToString();
   }
   
   Console.WriteLine(key);
   Console.Write("Press any key to continue . . . ");
   Console.ReadKey(true);

Most of people are used to download crack on internet without considering the risks of infection.
In my experience, almost all of keygens (even the ones who do the job) are malware. 
Be aware of them and - for fun - always write it by your own!

Feel free to comment below.
Cheers!
RE Solver