"Sophisticated" and "Genius" Shamoon 2.0 Malware Analysis

  • Posted on: 3 December 2016
  • By: siteadm

After reading headlines like this, I decided to take a look at this "most damaging cyberweapon the world has ever seen". Seriously CNN?

Seems like this not-sophisticated-at-all malware called Shamoon 2.0/Disttrack caused lots of damage across multiple government networks in Saudi Arabia. I don't have a saying on the network breach and the initial breach method since I never had chance to analyze the evidence files. But I decided to take a look at the malware itself and dissect its components and classify skills of the attackers behind it, rest is already done by other analysts and they've published their findings online. Executive summary of my findings points to only one thing, that the developers behind it definitely are not skilled C++ developers and (highly likely) they don't have any experience in windows kernel development. They also lack basic understanding of C++ data-types. In addition to that (possibly intentionally) hackers left some clues in resources section, pointing to Yemen. As I said multiple times before, these signatures are too easy to manipulate and anyone with a little bit of Googling skills can alter the language identifier of the resources in PE files. But definitely "Yemen" is left there as political message to Saudi Arabia. Go figure.

 

0x00 Basic Malware Info

The malware have multiple components and each component have x32 and x64 versions. Main malware component is compiled using Microsoft Visual C++ 10 compiler.

The malware have a kernel driver which it uses to have raw access to disk. The developers didn't write any code for such access, instead they just decided to use a driver from Eldos RawDisk tool. Fortunately for malware authors, this driver comes in with a signature. So they didn't have to do any kernel development and find a novel method to bypass windows driver signature enforment.

x64 kernel driver hash: 5a826b4fa10891cf63aae832fc645ce680a483b915c608ca26cedbb173b1b80a

x32 kernel driver hash: 4744df6ac02ff0a3f9ad0bf47b15854bbebb73c936dd02f7c79293a2828406f6

Here is a screenshot of driver's signature:

Malware authors intentionally left a "Yemen - Arabic" language identifier in the resources section of the malware:

As you can see langID is 9217 (0x2401) which translates to SUBLANG_ARABIC_YEMEN

 

0x01 Main Malware Code

As mentioned earlier, I believe malware authors were not skilled C++ developers. They've done multiple things wrong and they have very bad coding practices. For instance, they have "encoded" strings used in the malware. Decoding is basically just adding a const value to each character. For this purpose, you can basically do the addition in place for a char/wchar array in C++. But instead, the "expert" malware authors behind it, wrote a decoder function that calculates the length of the string, then allocates a new wchar_t array dynamically which is (unnecessarily) double of the needed size, copies encoded string to newly allocated location, decodes the string in the allocated array and returns the pointer to this dynamically allocated wchar_t array and they never free the allocated memory. Smart move.

Code graph above will translate into this C++ code:

wchar_t *StringDecoder(wchar_t *EncodedStr, int Key)
{
	int len = wcslen(EncodedStr);
	wchar_t NewBuffer = new wchar_t[(2 * (len + 1))];
	wcsncpy(NewBuffer, EncodedStr, len + 1);
	int Counter = 0;
	if ( len )
	{
		do
			v3[Counter++] += Key;
		while ( Counter < len );
	}
	return NewBuffer;
}

Noticed the multiplication in new wchar_t allocation? It shows their skill in C++ data types and memory management. So "WCHAR* t = new WCHAR[wcslen(s)+1];" is apparently wrong, you need to multiply it by two.

You might argue that who needs memory management in a disk wiper malware? Well, once you are a good C++ developer, you just write proper code. It doesn't matter you are writing a malware or a data parsing library.

Anyway, the malware drops and installs a kernel driver (x64 or x32 based on the architecture), communication and wiper components.

You want to see another piece of this "sophisticated" and "most destructive cyber weapon ever"? Well, here it is...

The main dropper component uses a rather "novel" method to determine if the current OS is 64-bit or 32-bit. Well, as you may know this is an extremely difficult problem to solve. How can you tell that current OS is 64bit or 32bit? How? If you think you can do it with IsWow64Process and GetCurrentProcess, you are wrong... But at least now you can learn from Shamoon 2 author(s):

To identify 64Bit OS, first you open "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" using RegOpenKey API. Then by calling RegQueryValue API you read "PROCESSOR_ARCHITECTURE" value inside. Now using wcscmp function, you once compare it to "amd64" once and with another wcscmp call, you compare it against "AMD64" string. So for this purpose you store "amd64" and "AMD64" strings separately in the code, encrypt them separately with separate keys, decrypt each one individually in runtime and use all these information and around 7 function and API calls to identify 64 bit OS. Because as old C++ saying goes, "never trust wcsicmp as case-insensitive string compare, it doesn't work". Here is the genius code snippet:

char Detect64BitOSNovelMethod()
{
  char v0; // bl@1
  unsigned int v1; // esi@3
  DWORD Type; // [sp+4h] [bp-DCh]@2
  DWORD cbData; // [sp+8h] [bp-D8h]@2
  HKEY phkResult; // [sp+Ch] [bp-D4h]@1
  BYTE Data; // [sp+10h] [bp-D0h]@2
  __int16 v7[52]; // [sp+74h] [bp-6Ch]@4

  v0 = 0;
  if ( !RegOpenKeyExW(HKEY_LOCAL_MACHINE, EnvironmentRegPath, 0, 0x20019u, &phkResult) )
  {
    Type = 0;
    cbData = 100;
    if ( !RegQueryValueExW(phkResult, PROCESSOR_ARCHITECTURE_STR, 0, &Type, &Data, &cbData) )
    {
      v1 = cbData;
      if ( cbData > 0 )
      {
        memcpy_0(v7, &Data, cbData);
        v7[v1 >> 1] = 0;
        if ( !wcscmp((const unsigned __int16 *)AMD64_STR, (const unsigned __int16 *)v7)
          || !wcscmp((const unsigned __int16 *)amd64_lower_str, (const unsigned __int16 *)v7) )
        {
          v0 = 1;
        }
      }
    }
    RegCloseKey(phkResult);
  }
  return v0;
}

 

 

I want to thank authors of this malware for teaching me this novel method for just identifying 64Bit OS.

So if you go to the registry location above and change "AMD64" string to "amD64", malware will assume that your running a 32bit OS. *facepalm*

 

0x02 Wiper component

Wiper component also have encoded strings and API calls. I decrypted all the strings and analyzed it. Here is what happens:

Main function checks for month & year and if today's date matches defined month and year, it sets the day to a random value and starts wiping. (what?) Here is pseudo code for date checking:

HANDLE __cdecl CheckWipeDate(void *Filename, DWORD dwDesiredAccess)
{
  HANDLE result; // eax@2
  HANDLE v3; // ST0C_4@6
  struct _SYSTEMTIME SystemTime; // [sp+4h] [bp-24h]@3
  SYSTEMTIME v5; // [sp+14h] [bp-14h]@3

  if ( Filename )
  {
    EnterCriticalSection(&CriticalSection);
    GetSystemTime(&SystemTime);
    v5 = SystemTime;
    v5.wDay = rand() % WipeDay + 1;
    v5.wMonth = WipeMonth;
    v5.wYear = WipeYear;
    if ( SystemTime.wYear != (unsigned __int16)WipeYear || SystemTime.wMonth != v5.wMonth )
      SetSystemTime(&v5);
    v3 = ElRawDiskOpenCall(Filename, dwDesiredAccess, NotUsedAppendStr);
    LeaveCriticalSection(&CriticalSection);
    result = v3;
  }
  else
  {
    result = (HANDLE)-1;
  }
  return result;
}

 

Next, based on the command received, if "E" command/config is there, it fills the disk with random data, otherwise wiping process is done by fills the disk with the photo of the famous Syrian refugee boy. Here is the pseudo code from OverwriteMBR fuction:

...
...
...
  hFile = (HANDLE)CheckWipeDate(HarddiskPartition0Str, 0xC0000000);
  if ( hFile == (HANDLE)-1 )
  {
    result = 0;
  }
  else
  {
    v6 = 1;
    if ( CommandByte == 'E' )
    {
      NumberOfBytesRead = 0;
      if ( ReadFile(hFile, &Buffer, 0x200u, &NumberOfBytesRead, 0) )
      {
        if ( NumberOfBytesRead == 512 && CorruptTheBuffer((int)&Buffer, 512, (int)&unk_358330, 100) )
          v6 = 0;
      }
    }
    if ( CommandByte != 69 || v6 )
    {
      if ( (signed int)nNumberOfBytesToRead >= 512 )
      {
        qmemcpy(&Buffer, ThePhotoBuffer, 0x200u);
...
...
...

As you can see above, if command/config is "E", it reads the data from the location its going to overwrite, then calls a function which uses an XOR table (which changes constantly and randomly) to corrupt the data and then finally writes it back to the location where it read the original data from.

After corrupting the first 512 byte of each drive, it uses combination of NtFsControlFile, QueryDosDeviceW and CreateFile APIs to get handle to drives.

Here is the pseudo code for corrupting data in each drive:

 if ( CommandStr == 'E' )
            {
              if ( ReadFile(hFile, lpBuffer, nNumberOfBytesToRead, &NumberOfBytesRead, 0) && NumberOfBytesRead )
              {
                if ( NumberOfBytesRead )
                {
                  if ( SetFilePointer(hFile, -NumberOfBytesRead, 0, 1u) == -1 )
                  {
                    GetLastError();
                  }
                  else
                  {
                    v10 = CorruptTheBuffer((int)lpBuffer, nNumberOfBytesToRead, (int)&unk_358330, 0x64);
                  }
                }
              }
              
            NumberOfBytesWritten = 0;
            if ( v10 )
              v9 = WriteFile(hFile, lpBuffer, nNumberOfBytesToRead, &NumberOfBytesWritten, 0);
            else
              v9 = WriteFile(hFile, ThePhotoBuffer, nNumberOfBytesToRead, &NumberOfBytesWritten, 0);
            
            FlushFileBuffers(hFile);

So it either reads data to temp buffer, corrupts the buffer and writes it back or it just fills the disk with Syrian refugee boy's photo.

Here is the screenshot of photo buffer post decryption:

To identify the system boot disk, it reads REG_SZ value of SystemBootDevice in HKLM\SYSTEM\CurrentControlSet, then it looks for "rdisk(" and "partition(" string in it and reads the numbers next to it to build string to call for opening and overwriting MBR using the driver. Best and most sophisticated method. Read from registry, do strstr, read next char, append to \Device\Hardisk\ and start wiping. Very efficent, wow!

 

0x03 Driver

As developers of this "most destructive cyberweapon ever" didn't have time, they just used a driver from another tool. If you think they had other reasons such as constant BSOD during kernel development, you're wrong. Nothing special here AT ALL.

 

0x04 Communication Piece

This piece is also full of genius coding practices. For instance it uses system function call to create a directory. But not that easily. It first uses sprintf to format and set the arguments. So final thing looks like this:

sprintf(&v40, "mkdir %s%s > nul 2>&1", &v28, &v39);
system_call(&v40);

The system_call will create a cmd.exe process by appending "/c" and arguments passed to it by the code. All this, just to create a folder. Probably because CreateDirectory API needs two arguments and figuring out second optional argument (LPSECURITY_ATTRIBUTES) is not easy. Instead we use cmd.exe and mkdir command.

Another fantastic feature of this component is the User Agent string. Usually malware needs to blend in and hide its presence and its activities. For example this network component was there to check for the start date for wiping operation. So out of all possible user agent strings to choose from, author decided to build and use most fake and unique user agent string where when you Google it, only Shamoon 2 related articles pop up. Here is the genius user agent string: "Mozilla/5.0 (MSIE 7.1; Windows NT 6.0)".

 

At this point I just gave up. Judging by the malware, I'm going to take a wild guess on initial entry point to the network by saying a web vulnerability scanner like ZAP probably found an easy to exploit vulnerability (SQLi) and that's how they initially breach to the network happened. Second phase probably was just guessing/cracking/finding the credentials. Also at this point as everyone have the sample and it's over, I think it's OK to share this.

Main malware component have an embedded username and password for the network administrator. Username is gacadmin15 and the password is typing "Allah-u Akbar" in Arabic keyboard plus 1122. So basically gacadmin15's password was Allah-u Akbar1122 but just in Arabic keyboard. I figured this out by using online Arabic keyboard and Google translate. Original password string is: "hggiH;fv1122"

Here is the screenshot of the password:

 

So dear CNN and other bloggers, please do more research before panicking and calling vulnerabilities or a piece of malware big names. "Most destructive cyberweapon" takes much more skill...

Comments

Everything in this post was new to me and I read anaysis and blog posts of all big anti virus companies. Totally different view. Thanks for sharing

Everyone loves it when individuals come together and share thoughts.

Great website, keep it up!

Its like you read my mind! You seem to know a lot about this, like you wrote the <br><br>
book in it or something. I think that you can do with a <br><br>
few pics to drive the message home a little bit, but instead <br><br>
of that, this is great blog. An excellent read. I will definitely be <br><br>
back.<br><br>
<br><br>
First time replying. I have shared this to my Tumblr.

Nice analysis. I can't tell by your review, is it nice malware or not? haha thanks for sharing. "The Most destructive malware ever!" ha

I really need to practice my self, and i'll be appreciated for you if help me to find it.

T.Q.

Add new comment

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
CAPTCHA
This question is for testing whether or not you are a human visitor and to prevent automated spam submissions.
Image CAPTCHA
Enter the characters shown in the image.