ransomware attack

MaMoCrypt Ransomware

is an unusual piece of ransomware, a variant of MZRevenge written in Delphi and packed using mpress.

Ransomware behavior

1. deletes shadow volumes, disables the firewall and UAC. These features are nothing unusual in the malware universe, and we will not into further details.

2. Using Delphi’s random generator (based on a linear congruential generator) and a DWORD seed based on time (using QueryPerformanceCounter or GetTickCount), it will generate two buffers which will be base64 encoded and prepended with MZRKEYPUBLIC / MZRKEYPRIVATE

3. Based on these two keys and a mask (see more details below), it will generate two encryption keys per file, which will be used for encryption. The content will be first encrypted with AES 128 CBC and then re-encrypted with Twofish 128 NOFB. The remainder % 16 from AES encryption will be encrypted using AES 128 CFB. All encrypted files will have their name appended with “.MZ173801”.

4. After encryption, the malware iterates the encrypted folders again to place the note in them. The note will also contain the 2 MZR keys.

Although the MZR keys will not be changed during key generation or encryption, the mask will be continuously updated. Their generation is based on a mix of SHA1, SHA512, and some custom computations. The AES and TWOFISH keys are computed by using SHA512 16 times for each key and XORing the bytes, using the result as the n-th byte of the key.

Mask and keys generation replication:

*(int*)mask_in = offset;
 for (int i = 0; i < 0x800; ++i) {
     SHA1(mask_in, 0x84, mask_out);
     *(int*)mask_in = i + 1 + offset;
     *(mask_in + 3 + (i & 0x7F) + 1) ^= mask_out[0];
     mask[i] = mask_out[1];
 offset += 0x800;
 aes_key = generate_key(mask, mzrkey_private.c_str(), 0x800, mzrkey_private.size());
 for (int i = 0; i < 0x200; ++i) {
 SHA1(mask_in, 0x84, mask_out);
     *(int*)mask_in = i + 1 + offset;
     *(mask_in + 3 + (i & 0x7F) + 1) ^= mask_out[0];
     mask[i] = mask_out[1];
 offset += 0x200;
 twofish_key = generate_key(mask, mzrkey_public.c_str(), 0x200, mzrkey_public.size());
 int mzrkey_size_bswap = _byteswap_ulong(mzrkey_len);
 int mask_size_bswap = _byteswap_ulong(mask_len);
 for (int i = 0; i < key_SIZE; ++i) {
   ((int*)in)[0] = _byteswap_ulong(i);
   for (int j = 0; j < i; ++j)
      in[j + 4] = key[j];
   *((int*)(in + 4 + i)) = _byteswap_ulong(1);
   *((int*)(in + 8 + i)) = mask_size_bswap;
   memcpy(in + 3 * sizeof(int) + i, mask, mask_len);
   memcpy(in + 3 * sizeof(int) + mask_len + i, &mzrkey_size_bswap, 4);
   memcpy(in + 3 * sizeof(int) + mask_len + 4 + i, mzrkey, mzrkey_len);
   SHA512(in, mask_len + mzrkey_len + 4 * sizeof(int) + i, out);
   for (int j = 0; j < SHA512_DIGEST_LENGTH; ++j)
       key[i] ^= out[j];

The IV for AES CBC will be generated using AES 128 ECB on a 16-byte buffer filled with 0xFF. Similarly, the IV for TWOFISH NOFB will be generated using TWOFISH 128 ECB on a 16-byte buffer filled with 0xFF. The initial contents of the mask are generated as follows:

memset(mask_in, MASK_IN_SZ, 0);
 memset(mask_out, MASK_OUT_SZ, 0);

 for (int i = 0; i < 0x80; ++i) {
   SHA1(mask_in, 0x84, mask_out);
   *(int*)mask_in = i + 1;
   *(mask_in + 3 + i + 1) = mask_out[0];

Apart from using an encryption scheme never seen in other ransomware, the binary will also not encrypt the entire system by merely iterating files, but it has a hardcoded list of folders and drives:

C:\Program Files\Steam
C:\Program Files (x86)\Steam
::{645FF040-5081-101B-9F08-00AA002F954E} (Recycle Bin)
C:\Users\%user%\AppData\Roaming\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar
C:\Users\%user%\AppData\Roaming\Microsoft\Windows\Start Menu
C:\ProgramData\Microsoft\Windows\Start Menu\

Because the mask/key generation uses an offset that is incremented at each file, the decryption process is heavily dependent on the files’ encryption order.

The ransomware will only encrypt files whose extension matches one of the below:











After encryption, the ransomware will iterate the folders in the same order, placing the note in them (named How Do I Recover My Files (Readme).txt):

recover my files