ESET researchers receive and analyze thousands of new malware samples every day. Earlier this year, one of them caught our attention because it was not an ordinary executable file, but a preference file used by a specific program. Further analysis quickly revealed the file actually is malicious and exploited a vulnerability in the software in order to execute code while it is parsed.

This article will take a deep dive into how the exploit works and briefly describe the final payload.

Exploit overview

The exploit takes advantage of a buffer overflow vulnerability in the demo version of a program called Uploader!. Developed by ksoftUploader! allows its user to upload files to the internet via FTP. Preferences such as the FTP hostname and username are stored in a file named uploadpref.dat. ESET researchers analyzed a preference file that was used to compromise the system when Uploader! is launched.

A proof of concept exploit has been available online since March 2014.

The vulnerability

Uploader!’s preference file consists of a set of line-separated strings such as the username and the hostname of the server to which to upload files. The application uses the standard C++ input stream (std::ifstream) to parse the uploadpref.dat file from the disk. While reading strings from the file, all fields are correctly checked for their size by using in_stream.get(buffer, sizeof(buffer), '\n'). However, the last field containing the encrypted password uses the following line of code: in_stream >> buffer, where buffer is on the stack. If in_stream.width(…​) isn’t called, in_stream >> buffer will result in copying the content of the file to the stack until a white space or the End Of File is reached.

opgtgt_call

Figure 1 - Problematic call to in_stream >> encrypted_password

ESET has contacted Ksoft about the issue and a new version of Uploader! (3.6) was released within 24 hours of notification.

How code execution is triggered

In the case of the exploit we have analyzed, the content of the file is copied onto the stack, beyond the buffer variable, which has a fixed size of 80 bytes. The Structured Exception Handler (SEH) is overwritten and the first shell code is copied. The copy is stopped by an exception when the destination has reach the end of the stack, raising a page violation while trying to write at an invalid address. The exception handler controlled by the attacker will be called. It is set to a pop ecx; pop ecx; ret gadget inside Uploader!’s address space. Finally, the gadget will enable the execution of the first shell code on the stack.

SE_Handler_olly

Figure 2 - View in the debugger once the exception is raised

SEH-based exploits are not new. If you are interested in the details, Corelan Team has a very good article on this subject on their website. Structured Exception Handling Overwrite Protection (SEHOP) prevents the execution of such an exploit, but it is not enabled in the Uploader! application and is enabled system-wide only on Windows Server. It is possible to change this setting in EMET’s user interface.

The exploit was likely based on the proof-of-concept exploit mentioned above: although there are 178 pop; pop; ret gadgets in the code, this exploit uses the exact same one found at 0x0040bf38. The other parts such as the shellcode and the next stages were added by the malware author.

Figure 3 - uploadpref.dat heading taken from the PoC

Figure 3 - uploadpref.dat heading taken from the PoC

Figure 4 - uploadpref.dat header taken from the malicious preference file

Figure 4 - uploadpref.dat header taken from the malicious preference file

Stages

The exploit has multiple stages before the final payload is executed. This section briefly describe each of these steps.

Stage 0

As we said before, the SEH handler points to a pop ecx; pop ecx; ret gadget that will pass the control flow to our first shell code.

These first few instructions unpack the next stage, which we call shell_code_1. It computes a one-byte value out of a two-byte word and writes it at the same memory location. This method allows Stage 1 to be encoded with only uppercase letters in the file.

Figure 5 - Unpacking function for the first shellcode

Figure 5 - Unpacking function for the first shellcode

Stage 1

At the end of this stage the whole content of the uploadpref.dat file is read to memory. It is not obvious at first, because the code searches for Windows API functions in the PEB by using hashes of the DLL names and functions. It calculates the sum of each individual hexadecimal representation of the lowercased characters forming the name of the function and multiplies it by two.

Here is a Python version of the hashing algorithm:

def hash_name(name):
    result = 0
for c in name:
result = 2 * (result + (ord(c) | 0x60))
return result

Interestingly, this hashing algorithm is the same that is used as an example in a book by Chris Anley and John Heasman titled "The Shellcoder’s Handbook: Discovering and Exploiting Security Holes". The C implementation is at page 145 of the 2nd edition.

After the API calls are resolved, shell_code_1 allocates two buffers of the same size as the uploadpref.dat file. The whole content of the file is copied into the first, and the second is left untouched. Then it jumps into the first block at offset 0x10, where the next stage is. Here is a summary in pseudo-C:

HANDLE f = CreateFileA("uploadpref.dat", GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
DWORD uploadpref_size = GetFileSize(f, 0);
char * memblock1 = VirtualAlloc(NULL, uploadpref_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
char * memblock2 = VirtualAlloc(NULL, uploadpref_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
ReadFile(f, memblock1, uploadpref_size);
stage_2 = &memblock1[0x10];
stage_2(&memblock1[0x650], memblock2);
// memblock2 is also pushed so that returning from stage_2 will jump at offset 0 in memblock2

Stage 2

The function decompresses a buffer at 0x650 into the previously allocated buffer memblock2 with a somewhat inefficient algorithm. Inflated, this buffer is 3,632 bytes long. After this is done, control flow is redirected to the beginning of memblock2, which now contains stage 3.

Stage 3

This stage reopens uploadpref.dat and decompresses a PE file from it, starting at offset 0x1600, into a newly allocated buffer. The decompression algorithm is the same as that used in stage 2.

Then, it creates a new process in suspended mode, and injects and runs the new executable.

The PE file extracted from uploadpref.dat is 56,832 bytes long, and downloads and executes a malicious remote access tool.

Malicious uploadpref.dat file overview

To summarize, here is the whole content of the malicious uploadpref.dat file relative to the different stages of execution.

Table 1. uploadpref.dat exploit file layout
Offset Size (in bytes) Description
0x0 11 First field
0x0B 4 "1\n", meaning the file contains a password (to trigger the vulnerability)
0x0F 1 A' (padding)
0x10 138 Stage 2
0x9A 326 Null bytes (padding)
0x1E0 12 A' (padding)
0x1EC 4 Jump to Stage 0
0x1F0 4 Pointer to a pop pop ret gadget
0x1F4 66 Stage 0
0x236 832 Packed Stage 1 with ending marker (0xFFFF)
0x576 218 Null bytes (padding)
0x650 3952 Compressed stage 3
0x15C0 64 Null bytes (padding)
0x1600 870912 Compressed PE file

Malicious payload

Upon successful exploitation, a new process is created with the PE file embedded in the uploadpref.dat file. This new process downloads and executes the final stage: a Remote Administration Tool (RAT) based on Gh0st RAT.

First stage downloader

Persistence

This module maintains persistence on the system by copying the original exploit file and the Upload 3.5!.exe as msfeedssync.exe into the user’s Application Data directory. Then, it adds a shortcut to the executable file inside the the Start menu’s Startup folder. On reboot, the exploit will be triggered again and all the steps will be repeated.

The following files are installed to maintain persistence:

Files dropped Path Hashes
uploadpref.dat C:\Documents and Settings\%USER%\Application Data\ 16d842b8746944cd29cea6237e210be2d185cbe2
msfeedssync.exe C:\Documents and Settings\%USER%\Application Data\ e2fc91f82b7db3221502d2582ac3be7a5b663498 (itself)
msfeedssync.lnk C:\Documents and Settings\All Users\Start Menu\Programs\Startup\ 0fff6640f72115021f0e5d0514921eb856948f30

shortcutTarget

Figure 6 - Shortcut installed in Startup folder on the infected computer

Downloading the payload

Once the persistence of the code is ensured, the executable will fetch the malicious payload via HTTP. Two threads are started at 30-minute intervals. Based on the HTTP user-agent each thread uses, we call the first thread Alan_function and the second one BFunction.

Each thread tries to download the payload from different URLs using the same domain name. Once the downloaded file is decompressed, the two functions will launch the code differently:

  • Alan_function expects an executable PE file and will simply launch it.
  • BFunction expects a DLL file which it will load and call the TestFunction exported function.

URL User-Agent Content SHA-1 (As of March 2015) Detection name
http://biless.com/alan/19437192.txt Alan_Function e440eea118d1701ad7886af6c93ef7102326d4c8 Win32/Farfli.PZ
http://biless.com/alan/Alan.txt BFunction Unknown

We have only observed the first method of distribution being used in March 2015. The downloaded executable file we have seen is tightly linked to this first stage downloader because its obfuscation method includes the unpacking of a DLL file with an exported function called TestFunction. This DLL could have been delivered to the BFunction thread directly to achieve the same results.

The final payload is a trojan based on Gh0st RAT.

The trojan

The last stage is to drop a variant of remote spying malware based on Gh0st RAT. Gh0st RAT has been thoroughly analyzed and documented by various researchers in the past. If you are interested, links to relevant research are included in the references section below.

Gh0st RAT’s network protocol includes a five-character string to identify the campaign. This Gh0st RAT variant uses the campaign code A1CEA. It is unclear if the A1CEA campaign is specific to a group. We found a few references online related to A1CEA:

The C&C server in the sample is www.phw2015.com on TCP port 2015. At the time of writing, the domain resolves to 112.67.10.110.

Other minor modifications to the Gh0st RAT source include:

  • Presence of a function that harvests the computer specifications.
  • Presence of the exported "TestFunction" that loads the malicious components.

All of Gh0st RAT’s functionalities are present and we have confirmed that the keylogger was enabled.

Conclusion

This exploit is curious because Uploader! is not a massively-deployed application. We are missing some context to understand clearly what happened. Was this exploit used to fool a specific target? The initial attack vector is also unclear: did they use social engineering to persuade the user to replace the preference file with this "special" file? Did they only use this technique as a way to hide the malware’s persistence?

Acknowledgment

Thanks to Hugo Genesse for his help on this analysis.

References

Michael G. Spohn (McAfee), Know Your Digital Enemy: Anatomy of a Gh0st RAT, http://www.mcafee.com/ca/resources/white-papers/foundstone/wp-know-your-digital-enemy.pdf, 2012

Snorre Fagerland (Norman), The many faces of Gh0st Rat, http://download01.norman.no/documents/ThemanyfacesofGh0stRat.pdf, 2012

IoCs

Samples

SHA-1 Type ESET Detection name
16d842b8746944cd29cea6237e210be2d185cbe2 DAT file Win32/Exploit.Ksoft
e2fc91f82b7db3221502d2582ac3be7a5b663498 Win32 PE Win32/TrojanDownloader.Agent.BGF
e440eea118d1701ad7886af6c93ef7102326d4c8 Win32 PE Win32/Farfli.PZ
d7d65d44657af68ddeba821b4adee6285bcdb418 Win32 PE Win32/Farfli.PZ
6b5095fcd9b230a34f9e51120c36a19908ef3885 Win32 PE Win32/Farfli.PZ

Other

Mutex www.phw2015.comwww.phw2015.comwww.phw2015.com

Network

Host Port Description
www.phw2015.com 2015 Gh0stRAT C&C server
www.biless.com 80 Used to dowload the Gh0st RAT payload

See also:

  • Emerging Threat’s snort rule

2809928 - ETPRO TROJAN PCRat/Gh0st CnC Beacon Request (A1CEA) (trojan.rules)