My library

+ Add to library

Contact us
24/7 Tech support | Rules regarding submitting

Send a message

Your tickets


Back to the news list

The Mac.BackDoor.iWorm threat in detail

September 29, 2014

Doctor Web's security researchers have dissected the complex malicious program Mac.BackDoor.iWorm, a threat affecting computers running Mac OS X. As of September 29, 2014, 18,519 unique IP addresses were used by infected computers to connect the botnet created by hackers using this backdoor.

The backdoor is unpacked into the directory /Library/Application Support/JavaW. Furthermore, using a specially generated p-list file, it disguises itself as the application com.JavaW and sets itself to autostart via /Library/LaunchDaemons/.

Mac.BackDoor.iWorm uses encryption extensively. When launched, the backdoor initialises the context (to be used later for encryption) and writes two bytes at zero offset which will later be used as a key for decrypting strings. Strings are decrypted using the following routine:

void DecryptStrings(unsigned __int8* Data, size_t size)
    for(int i = 0; i < size; i++)
        if (Data[i])
            Data[i] -= 'Z';
            Data[i] ^= 'M';

After that the backdoor attempts to acquire information about the contents of the /Library directory. If successful, it acquires the value of MD5 hash for the names of all of its subdirectories. The MD5 hash values are used to detect which of the installed software programs the malware won't be interacting with. The following routine is used to discover installed applications:

  challenge[5] = 0;
  challenge[4] = 0;
  challenge[0] = 0x67452301;
  challenge[1] = 0xEFCDAB89;
  challenge[2] = 0x98BADCFE;
  challenge[3] = 0x10325476;
  szDir = (const char *)&dir-&qt;d_seekoff;
  szDir_len = strlen(szDir);
  MD5_Update(szDir, challenge, szDir_len);
  MD5_Final((char *)&MD5OfDir, challenge);
  z = 0;
    if ( z &qt; 2 )
      dir = readdir(hLib);
      if ( !dir )
        goto banned_dir_not_found;
      goto find_banned_dir;
    BannedFoldersMD5 = pBannedFoldersMD5[z++];
  while ( MD5OfDir != _byteswap_ulong(BannedFoldersMD5) );

If application directories are not detected, the bot uses the getuid and gepwuid routines to determine the home folder for the account it is running under and checks whether the folder contains the file %pw_dir%/.JavaW (this file is created when the backdoor is first launched). The port number is generated upon the first launch too (later the port data is acquired from the configuration file):

r1 = TwisterGenRnd();;  //????????? ?????????? ?????
r2 = 0xFFFF0400 * (random_value / 0xFC00);
port = (WORD)(r1 + r2 + 1024);

The acquired port value is used to generate the backdoor_param data structure. Once encryption is complete, it will be written into the configuration file. All entries added into the file follow the template below:

struct backdoor_param
    char szParam[];
    char szValue[];

Generated using the values %param_name% and %param_value%, the structure is encrypted with the cipher AES-256. The encrypted structure is registered in the configuration file. After that the backdoor runs three threads that perform the following functions:

  • Open a port and await an inbound connection.
  • Send a query to a web server and acquire the addresses of the command and control (C&C) servers.
  • Connect to a C&C server and receive instructions.

To acquire the addresses of the C&C servers, Mac.BackDoor.iWorm determines the current date and calculates its value in days as follows:

time_t timee;
struct tm *tm;
tm = gmtime(&timee);
dwDays = tm->tm_yday + 365 * tm->tm_year;

The backdoor applies the MD5 hash function to the value and sends a query to The query template is as follows:<MD5_hash_first8>

Here MD5_hash_first8 is the value of the first 8 bytes of the MD5 hash value from the current date. The search returns a web page containing the list of botnet C&C servers and ports published by criminals in comments to the post minecraftserverlists under the account vtnhiaovyd. The server list is retrieved repeatedly at five-minute intervals.

The backdoor uses the following routine to choose a server to connect to:

rnd = TwisterGenRnd(); //????????? ?????????? ?????
szIP = GetAddressByIndex(pCSrvList, rnd % (pSrvList_size >> 2) % (pSrvList_size >> 2));

In fact, the bot picks a random server from the first 29 addresses on the list and sends queries to each of them. Once a connection is established, Mac.BackDoor.iWorm checks whether the site is on the exceptions list:

i = 0;
while ( 1 )
  BanListSize = (pBanListEnd - pBanListBeg) >> 2;
  if ( i >= BanListSize )
  pszBannedIP = GetAddressByIndex(pCBanList, i++);
  if ( CompareAddresses(pszBannedIP, szIP) ) 
    shutdown(this->socket, SHUT_WR);
    goto func_exit;

The backdoor exchanges data with the server and uses that data in tandem with specific routines to authenticate the remote host. If successful, the backdoor sends the server information about an open port on the infected machine and its unique ID and awaits directives. The transmitted data is encrypted with the cipher AES-256. The following routine is used to transfer the packets:

void SendPacket(char packet_signature, struct st_node *pNode, unsigned __int16 packet_size, char *pPacketData)
    WORD ps = 0;
    SendData(&packet_signature, pNode->pCSocket, 1u);
    ps = BYTE(packet_size) << 8;
    SendData((char *)&ps, pNode_->pCSocket, 2u);
    SendData(pPacketData, pNode_->pCSocket, packet_size);

The backdoor also supports Lua which enables it to process instructions received from the server. Depending on the type of data received, the bot can execute separate commands or Lua-scripts. An example of such a Lua-script is shown below:

if platform() == "OSX" and get("d") ~= "3" then
set("d", "3");

Basic backdoor commands for Lua-scripts can be used to perform the following actions:

  • Get the OS type.
  • Get the bot version.
  • Get the bot UID.
  • Get a value from the configuration file.
  • Set a parameter value in the configuration file.
  • Remove all parameters from the configuration file.
  • Get the bot uptime.
  • Send a GET query.
  • Download a file.
  • Open a socket for an inbound connection and then execute the commands received.
  • Execute a system instruction.
  • Sleep.
  • Ban a node by IP.
  • Clear the list of banned nodes.
  • Get the node list.
  • Get a node IP.
  • Get node type.
  • Get node port.
  • Execute a nested Lua-script.

Currently, the following features (in addition to executing functions performed with Lua-scripts) are available:

  • Send the UID.
  • Send information about the open port.
  • Add new bots (those that are actually connected as well as those whose addresses are received with commands) onto the node list.
  • Relay traffic (data received via one socket is relayed to another socket without any alterations).
  • Connect to the host specified by the command.
  • Execute Lua-scripts.

News post about this threat

Tell us what you think

To ask Doctor Web’s site administration about a news item, enter @admin at the beginning of your comment. If your question is for the author of one of the comments, put @ before their names.

Other comments