HackDig : Dig high-quality web security articles for hackers

Same Zeus, Different Features

2014-08-10 19:51


This article originally appeared in Virus Bulletin

](http://www.virusbtn.com/virusbulletin/archive/2013/10/vb201310-Zeus)We have seen hundreds, if not thousands, of variations of Zeus in the wild. The main goal of the malware does not vary, yet different functionalities have been added to its different iterations over time. This article discusses some of Zbot's functionalities in detail, such as: dropping a copy of itself and its components using random fi lenames, generating the registry key and some of its mutexes, and injecting codes with an anti-anti-malware trick. These functionalities are common in malware, but we will look into the details of how Zeus does things slightly differently.


We will not discuss the details of the malware's initial decryption algorithm, since several existing write-ups focus on them. However, we will look at some of the decryption algorithms that the malware uses while performing its malicious activities.

Zbot starts preparing the path and folders for its fi le manipulation functionalities using the SHGetFolderPathW API. The malware gets the Windows folder name using the SHGetFolderPathW API with the parameter (0x24) CSIDL_WINDOWS, also known as the 'FOLDERID_ Windows' parameter. CSIDL_WINDOWS generates the name of the Windows directory or SYSROOT, also known as %windir% or %SYSTEMROOT%, respectively. Then it uses the PathAddBackslashW API to add a backslash () to the resulting Windows path name.

This is followed by getting the volume GUID (globally unique identifier) path of the Windows folder using the GetVolumeNameForVolumeMountPointW API.

If a call to the GetVolumeNameForVolumeMountPointW API fails, the malware will remove the backslash from the Windows folder name using a deprecated PathRemoveBackslashW API. It also removes the last element of the Windows path name using the PathRemoveFileSpecW API, producing just the root folder, e.g. 'c:'. Then it makes another call to the GetVolumeNameForVolumeMountPointW API using the root folder.

If a call to the GetVolumeNameForVolumeMountPointW API fails, the malware will remove the backslashfrom the Windows folder name using a deprecated PathRemoveBackslashW API. It also removes thelast element of the Windows path name using the PathRemoveFileSpecW API, producing just the rootfolder, e.g. 'c:'. Then it makes another call to the GetVolumeNameForVolumeMountPointW API using theroot folder.

A successful call to the GetVolumeNameForVolumeMountPointW API will yield a result such as ' ? V o l u m e { 3 e a 9 a 7 c 1 - 3 4 5 3 - 11 a a - a 0 a d - 8 0 6 d 6 1 7 2 6 9 6 a } ', where the CLSID has been extracted using a call to the CLSIDFromString API. To obtain the path that contains application-specifi c data, Zbot once again uses the SHGetFolderPathW API with the parameter CSIDL_APPDATA (FOLDERID_RoamingAppData), which typically yields 'C:Documents and Settings{username}Application Data'. In order to remove any excess backslash symbol(s), the malware calls the PathRemoveBackslashW API.


After setting up the required paths and folders, Zbot looks for the '.reloc' section of the current decrypted module by parsing the section names from the PE header. Figure 1 Zbot copies (0x504) 1,284 bytes of encrypted code to the stack memory and uses a simple XOR decryption algorithm. Each byte is XORed using another byte taken from a different memory block. It masks the whole 1,284 bytes of encrypted code using another 1,284 bytes of key code (see Figure 1).

The .reloc section contains some information needed by Zbot for some of its malicious activities.


Figure 1: Partial view of the .reloc section



Before we go any further, let's discuss the random generator used by Zbot to produce the random fi lename, folder name and registry keys.

The seed value for the random generation algorithm is taken from the result of calling the GetTickCount API. There are two different sets of instructions that generate a list of random values.

The first set of instructions, let's call it 'Randomize 1', is as follows:

There is no complicated instruction in the above algorithm. Initially, EAX will contain the seed value, which is moved to EDX and copied to ESI. This is followed by SHR, XOR, IMUL and ADD instructions. The final value of ESI is then copied to the memory location [EAX + 4].

EAX is increased by four (EAX + 4), then checked to see whether it is equal to 0x00440EE4. If it isn't, it goes back to the start of the loop and performs the same set of instructions until EAX reaches 0x00440EE4.

Since the initial value of EAX is 0x00440528, the number of iterations it takes to complete the algorithm is approximately (0x270) 624. Randomize 1 will generate 624 random DWORD values in memory, then call the second set of instructions, 'Randomize 2'.

The second set of instructions uses the 624 random values generated by Randomize 1, and the last GetTickCount value.

Within the Randomize 2 algorithm, Zbot uses a combination of a series of XOR, AND and SHR instructions to generate another list of random values, which are stored in the same memory locations as used by Randomize 1.

The final DWORD is the returned value of the random generator function.


Zbot gets the fi le attributes of the %appdata% folder using the GetFileAttributesW API. This is followed by generating a random folder name to be added to the %appdata% folder's path.

The random folder name is generated as follows:

Initially, the malware calls the random generator to determine the length of the folder name to be generated. This is followed by another call to the random generator to produce the index pointer to either 'bcdfghklmnpqrstvwxz' or 'aeiouy'. Then, it stores the selected character to the stack memory and adds a zero byte to produce a Unicode version of the string. It will keep repeating these steps until it reaches the number of characters needed for the folder name.

Once the random folder name is generated, Zbot converts the fi rst character to upper case using the CharUpperW API. Then, it adds the random folder name to the appdata path using the PathCombineW API, e.g. 'C:Documents and Settings{username}Application DataHoyqub'. This is followed by a check as to whether the folder already exists, which is done by calling the GetFileAttributesW API.

To actually create the new folder, a call to CreateDirectoryW API fi nishes the job.


After creating a new folder, Zbot creates a new file within it.

First, it generates a random name using the same steps as it used to create a random folder name. Then it attaches that random fi lename to '%appdata%{random folder name}', with the extension name '.exe'.

The format of the generated executable fi le is '%appdata% [random folder name][random fi lename].exe'. For example:

C:Documents and Settings{username}Application Data Hoyqubvigon.exe This is followed by a check as to whether the fi le already exists by using the GetFileAttributesW API. If it doesn't already exist, a new file will be created using the CreateFileW API with GENERIC_READ|GENERIC_ WRITE access.

The content of this file will be discussed later.


After creating the fi rst fi le, Zbot creates two more fi les with random fi lenames and random extension names. The new files are placed under two separate folders with random folder names.

  • %appdata%[random folder name 1][random filename 1].[random extension name 1]
  • %appdata%[random folder name 2][random filename 2].[random extension name 2]

For example:

  • C:Documents and Settings{username}Application DataCoyvenbi.ifo
  • C:Documents and Settings{username}Application DataMoekiexhya.weo

The contents of these files are created after all the code injections have been performed.


After the new folders and fi les have been created, Zbot opens the registry key HKEY_CURRENT_USERSoftware Microsoft using the RegCreateKeyExW API. This is followed by creating a random Unicode string using the same random generator as used in creating fi lenames. Then it creates a new subkey using the RegCreateKeyExW API, e.g. 'HKEY_CURRENT_USERSoftwareMicrosoft Gafamu'.

Three more subkeys are generated under 'HKEY_CURRENT_USERSoftwareMicrosoftGafamu' with random names, e.g. 'Empyutso', 'Laukerr' and 'Sida' (see Figure 2). These keys contain information gathered from the infected system.


After the registry keys have been generated, Zbot gets the computer name and the current version of the operating system using the GetComputerNameW and GetVersionExW APIs, respectively. This is followed by opening the registry key 'HKEY_LOCAL_MACHINESOFTWAREMicrosoft Windows NTCurrentVersion' and querying the values of 'InstallDate' and 'DigitalProductId'. Zbot encrypts this information to be added to the overlay area of the original Zbot file.

After gathering the information above, Zbot gets the path name of the original module using a combination of the GetCommandLineW and CommandLineToArgvW APIs.

Zbot loads the original fi le into memory and decrypts the file's overlay area. The decryption algorithm is similar to the decryption of the last section, as discussed earlier. Then, the malware updates the overlay area with the new information, and encrypts it again.

Afterwards, Zbot sets the file attributes of the fi rst dropped fi le, e.g. 'C:Documents and Settings{username} Application DataHoyqubvigon.exe', to FILE_ATTRIBUTE_ARCHIVE. (Note that 'vigon' is a randomly generated filename.)

Then, Zbot opens 'vigon.exe' using the CreateFileW API with GENERIC_WRITE access, and copies the contents of the memory to the fi le using the WriteFile API. The memory contains a copy of the original Zbot plus the modified version of the overlay area.

Then, Zbot executes the dropped EXE file, 'vigon.exe', using the CreateProcessW API.


The binary for Zbot's code injection is already visible in the decrypted code within the execution of the original process, but it is only activated within the 'vigon.exe' process. (Note that 'vigon.exe' is spawned from the original process and it uses a randomly generated fi lename - 'vigon.exe' is not always the filename used.)

Within the vigon.exe execution, Zbot parses the process list using a standard call to the CreateToolhelp32Snapshot, Process32FirstW and Process32NextW APIs.

After a call to the CreateToolhelp32Snapshot API, Zbot checks for the value of the PID (processID) and skips both system processes and its own process for code injection.

The malware prepares the binaries for code injection by decrypting some of the code using a simple maskingtechnique, as discussed in the 'Last section' part of this article. After getting the necessary information from the decrypted content, it combines the bits and bytes of information to generate a possible mutex value, 'BaseNamedObjects{883D274C-A605-1AD2-7045-FE06EA6D7800}', relative to the currently parsed process.

After creating the mutex using the CreateMutexW API, itopens the currently parsed process using the OpenProcessAPI. It follows this by opening the access token by callingthe OpenProcessToken API with TOKEN_QUERY as theparameter. If the token is not accessible, Zbot will parseanother process from the list.

If the token of the currently parsed process is accessible, itgets the length of the SID (security identifi er) of the tokeninformation using the GetLengthSid API. If it is not equal to0x1c, Zbot will skip the parsed process.

If the SID length is equal to 0x1c, Zbot will open theprocess using OpenProcess, but this time with PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION| PROCESS_VM_READ | PROCESS_VM_WRITE| PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION access mode. Zbot ascertains that it hascomplete access to the process. After successfully openingthe parsed process, it performs its anti-anti-malware trick(discussed in the following section) to determine if theparsed process can be injected with its code.

If the executable fi le is not used by an anti-malwareapplication on the list, Zbot will allocate a remote memorylocation within the parsed process using the VirtualAllocExAPI and write the decrypted code to the newly allocatedremote memory using the WriteProcessMemory API.

Then, Zbot passes the handle of the mutex createdearlier to the parsed process using the DuplicateHandleAPI. The parsed process now has access to the mutex,'BaseNamedObjects{883D274C-A605-1AD2-7045-FE06EA6D7800}'.

After everything is in place, Zbot will activate the remotecode using a call to the CreateRemoteThread API and willrelease the parsed process by calling the CloseHandle API.

Before calling the next process, the generated mutex,'BaseNamedObjects{883D274C-A605-1AD2-7045-FE06EA6D7800}', is removed using the CloseHandle API.

Zbot will perform this code injection routine on allprocesses running in the system if they satisfy all thespecified conditions.


A standard trick used by malware to avoid injecting itscode into anti-malware applications is to check the processlist for anti-malware names or check for the services usedby anti-malware applications. This variant of Zbot does itdifferently.

Before Zbot injects itself into a process, it opensthe process and gets the ProcessImageFileName bycalling the ZwQueryInformationProcess API. (TheProcessImageFileName will be used later after getting theright device name.)

Then, the malware obtains a list of valid drives in thesystem using the GetLogicalDriveStringsW API and it gets information about each device using the QueryDosDeviceWAPI. Zbot uses the resulting device type and compares itagainst the ProcessImageFileName to determine the exactpath of the executable fi le of the currently parsed process.

Once Zbot knows the exact path of the equivalentexecutable fi le of the parsed process, it starts gatheringinformation by calling the GetFileVersionInfoSizeW API todetermine if the fi le contains version information. If thereis no version information available for the executable fi le,Zbot will skip this part of the routine.

This is followed by actually getting the fi le versioninformation using a call to the GetFileVersionInfoW API.Then, the malware uses the VerQueryValueW API with'VarFileInfoTranslation' as the parameter, to get thepointer to the translation array from the version-informationresource. It uses the resulting array of language and codepage identifi ers to determine the '{lang-codepage}' valuefor the next call to the VerQueryValueW API.

Finally, Zbot gets the 'Product Name' of the executablefi le using another call to the VerQueryValueW API with anlpSubBlock parameter of 'StringFileInfo{lang-codepage}ProductName'.

After getting the 'Product Name' of the executable fi le,Zbot checks it against specifi c strings found in someanti-malware applications (see Figure 3).

If the executable fi le's 'Product Name' contains substringsof an anti-malware name, Zbot will not perform the codeinjection for the executable's process.


We all know that Zbot is a well-coded piece of malware.It uses a non-standard way of doing things compared withother malware. Instead of using the GetWindowsDirectoryAPI to get the %windir% folder, it uses the newerSHGetFolderPathW API. Instead of checking the processnames for anti-malware strings, it looks for the productname of the actual fi le in the disk. And generating 624random DWORD values a few times just to generate asingle DWORD is probably a little excessive.

Zbot is one of the main players in the malware underground.Its structure is as well coded as it is designed. It has lots offunctionalities and capabilities, and this article only toucheson a small percentage of them.

As we have seen so far, there is always room forenhancements and upgrades pertaining to its code. We arelikely to see further adaptation of Zbot to its ecosystem andits environment in the near future.

As always, we will be there to keep you up to date.

To download this and other great articles, please visit Virus Bulletin

Source: serutaef-tnereffid-suez-emas/tsop/moc.tenitrof.golb

Read:3080 | Comments:0 | Tags:No Tag

“Same Zeus, Different Features”0 Comments

Submit A Comment



Blog :

Verification Code: