2014-06-02
Abstract
Wapomi is a virus with trojan-like behaviour. It was originally detected as long as a couple of years ago, yet it is still very active in the wild. Raul Alvarez takes a look at some of the malware’s functionalities in an attempt to shed light on its persistence.
Copyright © 2014 Virus Bulletin
It is fairly common, these days, to find a cross-breed of malware, combining trojan-like functionalities and the file-infecting skills of a virus to make it more resilient to attack.
Wapomi is a virus with trojan-like behaviour. Its original variants were detected as long as a couple of years ago, yet it is still very active. In this article, we will discuss some of the malware’s functionalities that might shed light on why Wapomi is still so active.
When an infected file is executed, it will drop and run the main component of the malware, which contains the file infection routine among others.
Initially, Wapomi gathers the strings that make up the filename for the dropped file. The filename is randomized in nature (e.g. ‘rCgCYG.exe’), and is pre-generated by the previous infection process.
Once the strings for the filename have been gathered, Wapomi parses the PEB to get the ImageBase of kernel32.dll. There is no check to make sure it gets the right ImageBase. Afterwards, the malware parses the MZ/PE header of kernel32.dll (assuming that it is the right library) to get the location of the export table.
This is followed by parsing the function names within the export table, and comparing them against the following API names: GetModuleHandleA, GetTempPathA, lstrcat, WriteFile, CreateFileA, WinExec and CloseHandle.
Initially, the malware compares the first four characters of each API name against every function name in the export table. Once a match has been found for the first four characters, the rest of the characters are checked to make sure it is indeed the right API name. If the exact API name is found, the malware resolves the API address through the index used by the function name.
Most modern malware uses hash algorithms to hide the API names, but Wapomi uses none.
For the actual dropping of the file, Wapomi gets the temporary folder using the GetTempPathA API. Then it concatenates the filename to the folder name, using the lstrcat API and producing the pathname ‘%temp%\ rCgCYG.exe’. Afterwards, the file is created using the CreateFileA API.
Wapomi then parses the malware body to look for the executable image which will be used for the dropped file. It searches for the MZ header first. The image of the executable file is not encrypted or encoded in any way, it is just a plain embedded image.
The malware then writes the executable image to the ‘%temp%\ rCgCYG.exe’ file, using the WriteFile API. Then it closes it using the CloseHandle API.
Finally, Wapomi activates the dropped file using the WinExec API.
The dropped file, ‘%temp%\ rCgCYG.exe’, contains all the malicious functionalities of the malware and is packed with the compression utility ASPack.
After unpacking, it performs several steps of its preparation routine, which includes getting the %temp% folder name, the %system% folder name, and the module’s filename, using the GetTempPathA, GetSystemDirectoryA and GetModuleFileNameA APIs, respectively.
Next, the malware decrypts a block of 0x6CC (1,740) bytes of data, using the algorithm shown in Figure 1. Every DWORD passes through it.
(Click here to view a larger version of Figure 1.)
The algorithm works as follows: a given DWORD is rotated by a value in CL, which varies by a multiple of four. The result is then XORed using a key (0x1BC94E09) that has been generated from a previous infection. The value of the result is negated and added both to the key and to the next DWORD in the block.
Before we go further, let’s discuss the simple on-demand pseudorandom generator that the malware uses for most of its functionalities. The generated values can be used as randomized filenames or simply to determine the length of a given string. The following is a description of how the generator works:
Initially, the malware calls the GetSystemTimeAsFileTime API to get the current date and time of the system.
Then, the least significant WORD of LowDateTime is used as the seed to a call to the srand API. This is followed by calling the rand API to generate the first pseudorandom WORD.
The malware uses the most significant WORD of LowDateTime as a seed to another call to the srand API. Afterwards, another call to the rand API is used to generate the second pseudorandom WORD.
The final pseudorandom DWORD contains the first WORD as the most significant WORD, and the second WORD as the least significant.
After the decryption, Wapomi creates a new thread using the CreateThread API.
Within this thread, the malware uses the pseudorandom generator to produce a DWORD value such as 0x1C123A16. The random DWORD value serves as the filename, which is embedded in the string format ‘%s%.8X.exe’, using a call to the wsprintfA API. A pathname, such as ‘%temp%\1C123A16.exe’, is generated after the call to the wsprintfA API.
Another call to the wsprintfA API, with the string format ‘http://%s:%d/%s/%s’, produces a link such as ‘http://ddos.[REMOVED].net:799/cj//k1.rar’ (for safety, part of the domain name has been removed).
Using the two generated strings, Wapomi tries to download the file ‘k1.rar’ and save it as ‘1C123A16.exe’, using a call to the URLDownloadToFileA API. (At the time of writing this article, the link is no longer active.)
If the download has been successful, the malware will execute the downloaded file using the WinExec API.
Besides ‘k1.rar’, Wapomi will also try to download the following files: ‘k2.rar’, ‘k3.rar’, ‘k4.rar’ and ‘k5.rar’. For every download attempt, the malware calls the pseudorandom generator to produce a different filename.
This thread makes the malware an effective vehicle for running a different piece of malware from its server. The remote file (such as ‘k1.rar’) can be changed to any kind of malware – for example, FakeAV, Zeus, a different virus, or its own updated version – and the host machine will instantly be infected with it.
Meanwhile, in the main thread, the malware checks whether the dropped file ‘%temp%\ rCgCYG.exe’ still exists, using the PathFileExistsA API. If it does exist, the malware opens it using the CreateFileA API. Then a section of virtual memory is allocated with a size equivalent to the file’s size, using the VirtualAlloc API. Afterwards, the dropped file is copied into the newly allocated memory using the ReadFile API.
Then the second thread is created. Within the context of this thread, the malware initially determines the available drives in the system by calling the GetLogicalDriveStringsA API.
Wapomi skips drives A and B. It also skips any drive that has an invalid root path (DRIVE_NO_ROOT_DIR type), and CD-ROM drives (DRIVE_CDROM type), by determining the type of drive using the GetDriveTypeA API.
Once the drive has passed through the filtering, the malware creates a new thread to process it. A thread, similar to THREAD #3, is created to process every drive that the malware can use.
This thread is used to process the drive for infection.
Wapomi traverses each and every directory of a given drive looking for files to infect. It does this using the FindFirstFileA and FindNextFileA APIs. It checks for every occurrence of each folder name in the host system against the list of names shown in Table1. (Note that these folder names are part of the decrypted strings shown in Figure 1.) If a folder name matches any from the list, it will skip the infection routine.
Documents and Settings | MSN Gaming Zone |
Chinatelecom C+W | NetMeeting |
WINDOWS | Outlook Express |
WinNT | Windows Media Player |
System Volume Information | Windows NT |
RECYCLER | WindowsUpdate |
Common Files | Win RAR |
ComPlus Applications | Thunder |
InstallShield Installation Information | Thunder Network |
Internet Explorer | AppData |
Messenger | Local Settings |
microsoft | Tencent |
frontpage | Baidu |
Movie Maker |
Table 1. List of names
For any given victim file, the malware checks if it has the ‘.exe’ extension. If it does, it will proceed with the infection routine, otherwise, it will look for another file to infect.
To prepare the victim file for infection, the following series of routines is performed:
Initially, the malware looks for DWORD markers, such as: 0x11111111, 0x22222222, 0x33333333 and 0x44444444, and saves their location for later use.
This is followed by changing the attributes of the victim file to FILE_ATTRIBUTE_NORMAL using the SetFileAttributesA API. Then it opens it using the CreateFileA API.
Next, it gets the file’s timestamp using the GetFileTime API. This will be used later, after the file has been infected, to restore the original timestamp of the victim file. Restoring the timestamp minimizes the malware’s exposure – it would raise suspicion if every executable file in the system had the same timestamp.
The malware then maps the victim file into memory using a combination of the CreateFileMappingA and MapViewOfFile APIs. Any changes made in the mapped version of the file will be reflected in the physical file.
To make sure that the victim file is a valid executable, Wapomi checks that it has the proper MZ/PE header. It also checks that the file’s size is equivalent to the sum of PointerToRawData and SizeOfRawData of the last section of the file, to be sure that it is not corrupted.
Still within the mapped file, the malware calculates the location at which the additional section header will be placed. The new section header should be added straight after the last section header. The malware checks that the location of the new section header is free (it must contain zeros). If it is not free, the malware will skip the infection routine.
The malware tries to avoid overwriting the area of the new section header, as that might corrupt the executable file.
In continuation, the malware generates a pseudorandom value by rotating the value of the TimeDateStamp by 0x10, then XORing it to the value of the EntryPoint. This pseudorandom value serves as the first four bytes of the new section name. The next two bytes of the section name are a constant value (0x75A3), while the seventh byte is the result of XORing from the first to the sixth byte.
This is followed by calculating the necessary data for the new section header, which includes the VirtualSize, VirtualAddress, SizeOfRawData and PointerToRawData. The new section’s characteristics are set to 0xE0000020 (CODE|EXECUTE|READ|WRITE).
Finally, the malware increases the number of sections by one and updates the NumberOfSections field in the PE header.
After setting up all the information needed for the new section header, Wapomi unmaps the victim file from memory using a call to the UnmapViewOfFile API. Every modification to the mapped victim file is now reflected in the physical file.
As noted earlier, Wapomi drops a file with a randomized filename. The filename is pre-generated based on the previous infection. Every infected file contains a different pre-generated filename. Running them simultaneously will generate different copies of the same malware. The following is a description of how the randomized filename is generated (also see Figure 2):
(Click here to view a larger version of Figure 2.)
After unmapping the victim file, the malware generates a series of bytes in memory consisting of three sets of ‘a’ to ‘z’ characters, and three sets of ‘A’ to ‘Z’ characters.
Afterwards, the malware uses a simple algorithm to scramble the characters. It uses a random number, generated from a call to the rand API, to determine which characters are to be swapped.
This is followed by generating another randomized DWORD using the pseudorandom generator. The pseudorandom DWORD is ANDed with 0x0000000F, to determine the number of characters to be used from the newly scrambled bytes. These characters, such as ‘twzvXX’, concatenated with the string ‘.exe’, are used for the newly infected file. The length of the filename varies based on the pseudorandom DWORD.
The randomized filename, ‘twzvXX.exe’, is embedded into the malware code via markers, such as: 0x11111111, 0x22222222, 0x33333333 and 0x44444444, which were determined earlier.
The string ‘twzv’ overwrites 0x11111111; ‘XX.e’ overwrites 0x22222222; ‘xe’ overwrites 0x33333333; and finally, 0 overwrites 0x44444444 (see Figure 2).
After embedding the randomized filename, Wapomi expands the size of the file to accommodate the new section, using a combination of the SetFilePointer and SetEndOfFile APIs.
This is followed by writing 0x271 (625) bytes of malware code – which contains the embedded randomized filename – to the victim file, using the WriteFile API.
Afterwards, a copy of the original dropped file, which is in memory, is also written to the victim file using another call to the WriteFile API.
Then, Wapomi restores the victim file’s original timestamp using the SetFileTime API. The infection is finalized by closing the victim file using the CloseHandle API.
Once every file in every folder has been checked, Wapomi exits the execution of Thread #3 and transfers control to Thread #2 – the one that spawned the third thread. Thread #3 also exits after spawning the fourth thread.
Within the context of the fourth thread, the malware calls the SHGetFolderPathA API with the CSIDL_PROGRAM_FILES parameter to get the current program files folder. The standard installation is ‘C:\Program Files’. The string ‘\WinRAR\Rar.exe’ is concatenated with the generated string, producing the path name ‘C:\Program Files\WinRAR\Rar.exe’.
This is followed by generating a DWORD using the pseudorandom generator. A generated DWORD, such as 0x317A552F, is concatenated with the %temp% folder with the format ‘%s%.8x.exe’, using the wsprintfA API, producing ‘%temp%\317A552F.exe’.
Afterwards, the malware copies ‘C:\Program Files\WinRAR\Rar.exe’ to ‘%temp%\317A552F.exe’ using the CopyFileA API. After a successful copy operation, the file, such as ‘317A552F.exe’, in the %temp% folder, will look suspicious. Without analysis, we might assume that it is a malicious file that has been dropped by the malware.
Before the malware exits this thread, it deletes the ‘%temp%\317A552F.exe’ file using the DeleteFileA API.
If Rar.exe exists in the system, the malware checks if the ‘%system\% c_31892.nls’ file exists using the PathFileExistsA API. If it doesn’t exist, the malware creates the file using the CreateFileA API, but leaves the file empty.
After all the threads have been executed at least once, Wapomi generates another randomized DWORD, such as 0x6507656E, using the pseudorandom generator. It is formatted as ‘%s%.8x.bat’ using the wsprintfA API, producing the pathname ‘%temp%\6507656E.bat’.
The malware creates the batch file using the CreateFileA API, and fills it with the following data using the WriteFile API:
:DELFILE del ‘C:\Documents and Settings\[username]\Desktop\rCgCYG.exe’ if exist ‘C:\Documents and Settings\[username]\Desktop\rCgCYG.exe’ goto :DELFILE del ‘C:\DOCUME~1\[username]\LOCALS~1\Temp\6507656e.bat’
(Note: ‘[username]’ is the username of the infected system.)
Then, Wapomi runs the batch file using the ShellExecuteA API. Once executed, the batch file should be able to remove both rCgCYG.exe (the main malware component) and itself from the infected system.
This batch file is a cleanup routine that is commonly employed by malware in an attempt to remove traces of itself.
Note that removing the aforementioned files doesn’t rid the system of the malware.
Wapomi is commonly detected as a trojan or a worm due to its file-dropping functionality. It is easy for this kind of malware to be mistakenly identified as such.
This malware is careful enough to avoid infecting files that reside in common directories. It is also careful to avoid corrupting executable files by checking the feasibility of infection. But when we look at it closely, we can see that the malware is simple and doesn’t employ any complicated algorithms or techniques.
So the question still remains: why is Wapomi still in the wild? Is it because it cleans up after itself? Or is there another explanation for its persistence?