MaMoCrypt Ransomware Decryption Tool

We’re happy to announce the availability of a new decryptor for MaMoCrypt, a strain of ransomware that appeared in December last year.

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

If you don’t want to go through the technical analysis, you can jump straight to decryption by downloading the utility below:

Download the tool

Ransomware behavior

1. MaMoCrypt deletes shadow volumes, disables the firewall and UAC. These features are nothing unusual in the malware universe, and we will not go 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 ransom 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()); generate_key: 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

Continue reading

This post was originally published on this site