Palo Alto Networks recently identified a new campaign targeting the transportation sector in Europe with ties to the Dark Seoul and Operation Troy campaigns that took place in 2013. This new campaign used updated instances of the Tdrop malware family discovered in the Operation Troy campaign. For more information on the new campaign discovered by Unit 42, please refer to our recent blog post.
In this attack, attackers embedded the TDrop2 malware inside a legitimate video software package hosted on the software distributor’s website. By doing this, they were able to target organizations that relied on the distributor’s security camera solution and infect their systems with malware. They created a true Trojan horse, which sneaks into a network as a gift, but when opened, the attacker’s army leaps out.
Trojanized Video Player (Stage 1)
The malware used for the attempted infection purported to be a legitimate video player, providing viewing software for security camera solutions. The following two unique file names were involved in the attack.
- [redacted]Player_full.exe
- [redacted]Player_light.exe
The difference between the files involves the specific video player that was dropped and executed during runtime. Each file would drop and execute the full or light version of the legitimate video player respective to the file name.
Both the legitimate copy of the video player, as well as a malicious executable were bundled into a single executable. These files were added to the end of the Trojan executable, as seen below.
When initially run, the malware checks to see if its parent process is either explorer.exe or cmd.exe. In the event the malware is not running in the context of either of these processes, it will exit. This check exists in a number of the subsequent processes/executables used by the TDrop2 malware variant.
Subsequently, the malware proceeds to extract both the video player and the embedded malware using a series of calls to CreateFile, CreateFileMapping, GetFileSize, and MapViewOfFile. Once extracted, the file writes it to a new file on disk prior to executing it. The video player is written to one of the following locations, based on the original filename:
- %TEMP%\[redacted]Player_full.exe
- %TEMP%\[redacted]Player_light.exe
The malware itself is written to the %TEMP% directory as well. The filename is derived by randomly choosing an executable name from the system32 directory. The randomly chosen executable must not contain any of the following strings:
- setup
- install
- update
Dropped Malware (Stage 2)
This dropped malware begins by performing the same parent process check witnessed in the original sample. In the event the malware is not running within the parent process of cmd.exe or explorer.exe, it will exit immediately. This malware sample will also dynamically load a number of functions and libraries. After the kernel32.dll and ntdll.dll libraries are loaded via calls to GetModuleHandle, the following process takes place:
- Create a char array containing the desired function name and store this array to a variable
- Load this library via a call to GetProcAddress
- Store this function offset in a global variable
- Free the memory containing the char array
In total, the following 14 functions are loaded during runtime:
|
|
After these functions are loaded, the malware will randomly select an executable from the system32 using the same routine witnessed in the earlier sample. The malware proceeds to spawn a new process of the selected executable and performs a technique called process hollowing to hide itself inside a legitimate executable. This leads us to the next stage of our malware
Injected Malware (Stage 3)
This particular stage of malware acts as a downloader. The parent process check is not used in this particular sample. The malware initially attempts to download a file from the following location:
- http://www.combra[.]eu/includes/images/logo.jpg
While the link above shows a file extension of an image, the transferred file is in fact a modified executable file.
The downloaded file has the first two bytes of the PE file format replaced with the characters ‘DW’, instead of the usual ‘MZ’. After the download occurs, the malware immediately corrects the first two bytes with the ‘MZ’ characters prior to writing the file to disk.
The downloaded file is dropped to the system32 folder. The malware selects a randomly chosen DLL from this directory. The base name of this DLL is used to write the downloaded file. As an example, in the event apcups.dll was selected, the malware would write the downloaded file to apcups.exe in the same folder. The downloader then proceeds to execute this downloaded file in a new process.
JPG Executable (Stage 4)
As we’ve seen in previous samples, this executable file begins by checking the parent process for the presence of ‘cmd.exe’ or ‘explorer.exe’. It proceeds to randomly select an executable file in the system32 folder, and performs process hollowing against it. The injected executable contains the last stage of the TDrop2 malware variant.
Final Payload (Stage 5)
Upon execution, we once again see the parent process check to determine if the malware is running within the ‘cmd.exe’ or ‘explorer.exe’ parent process. It continues to dynamically load a number of libraries and functions for later use. A feature that has yet to be seen is that of string encryption. Strings are encrypted using the following function, represented in Python:
1 2 3 4 5 6 7 8 |
def decrypt(data): length = len(data) c = 1 o = "" while c < length: o += chr(ord(data[0]) ^ ord(data[c])) c += 1 return o |
After dynamically loading functions and libraries, the malware iterates through the running processes and attempts to determine if the ‘V3lite.exe’ process is running. This process name is associated with the South Korean-based AhnLab security software provider. In the event this process is running, the malware will attempt to kill the process’ class window.
The final payload proceeds to generate the following mutex to ensure only one copy of the malware is running concurrently:
Global\SPPLMUTEX
The payload then spawns two threads—one to maintain persistence and another to gather victim information and perform command and control operations. Persistence is achieved by setting the following registry key:
HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
The name of the registry key in the above instances is derived from the basename of the supplied argument. In the event the supplied argument was C:\malware.exe, the registry key would be named ‘malware’, and the path for this key would be ‘C:\malware.exe’.
The persistence thread runs in a loop where the registry keys are set every 60 seconds, ensuring persistence even in the event an administrator manually deletes the registry keys.
The other thread begins by collecting information about the victim, such as the following:
- Computer Name
- IP Address
- Registered Owner
- Registered Organization
- Installation Date
These data points are used to generate a unique victim ID, which is stored in the following registry key:
HKCU\SOFTWARE\Microsoft\HY08A\Build
The malware will continue to decrypt and store embedded C2 URLs. The following URLs have been identified:
- http://mcm-yachtmanagement[.]com/installx/install_ok.php
- http://www.junfac[.]com/tires/skin/tires.php
The final payload proceeds to enter its command and control loop. It initially performs a DNS check against microsoft.com to ensure it has Internet connectivity. After this check is performed, it enters an infinite loop, with a sleep interval set at a default of 30 minutes. The malware will periodically poll the C2 server and determine if any commands are received. The initial POST request contains a unique victim identifier that was previously generated.
The optional response by the C2 server is both encoded and encrypted.
The data is first encrypted using an unidentified algorithm. The two keys used for this encryption are generated using another unidentified algorithm. The following Python script can be used to generate the keys. A default salt of ‘FFFFFFFF’ is used.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
def key_generation(rounds=8, buf="FFFFFFFF"): out = [0] out2 = [] for x in range(rounds): out2.append(0) c = 0 result = 0x616E6F6E while(c < rounds): result = (result + ((result >> 8) | ((result & 0xFFFFFF80 ^ 16 * (8 * result ^ (result ^ 2 * result) & 0xFFFFFFF8)) << 17))) & 0xFFFFFFFF out.append(chr(result & 0xFF)) print hex(result), hex(ord(out[-1])) c+=1 c = 0 while(c < len(buf)): result += ord(buf[c]) & 0xFFFFFFFF v7 = 32 while v7: result = (result + ((result >> 8) | ((result & 0xFFFFFF80 ^ 16 * (8 * result ^ (result ^ 2 * result) & 0xFFFFFFF8)) << 17))) & 0xFFFFFFFF v7-=1 if rounds > 0: while v7 < rounds: result = (result + ((result >> 8) | ((result & 0xFFFFFF80 ^ 16 * (8 * result ^ (result ^ 2 * result) & 0xFFFFFFF8)) << 17))) & 0xFFFFFFFF out[v7] = chr(ord(out[v7]) + result & 0xFF) v7 += 1 c+=1 key1 = pack(">I", unpack("I", ''.join(out[0:4]))[0]) key2 = pack(">I", unpack("I", ''.join(out[4:8]))[0]) return (key1, key2) |
Additionally, the following Python script can be used for encryption/decryption
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
def encrypt_decrypt(d, key1=0xBE095818, key2=0xD0D45242): ''' key1/key2 default values the result of using 'FFFFFFFF' in key_generation algorithm. ''' count = len(d) out_buffer = "" pos = 0 while True: slic3 = d[pos:pos+384] count = len(slic3) + 3 if slic3 == "": break v6 = key1 v7 = 0 v8 = 0x369CF result = 0x369CF v20 = [0x31, 0, 0, 0, 0, 0, 0, 0] u = 0 while count != 1: if u < len(slic3): v10 = v7 >> (result & 7) v11 = result >> 3 v12 = v10 & 1 v13 = v20[1] >> (v11 & 7) v11 = v11 >> 3 v14 = 2 * v12 | v13 & 1 v15 = v20[2] >> (v11 & 7) v11 = v11 >> 3 v16 = 2 * v14 | v15 & 1 v17 = v20[3] >> (v11 & 7) v11 = v11 >> 3 out_buffer += chr(((v20[7] >> ((v11 >> 9) & 7)) & 1 | 2 * (2 * (2 * (2 * (2 * v16 | v17 & 1) | (v20[4] >> (v11 & 7)) & 1) | (v20[5] >> ((v11 >> 3) & 7)) & 1) | (v20[6] >> ((v11 >> 6) & 7)) & 1)) ^ ord(slic3[u])) result = (v8 >> 1) & 0xFFFFFF | ((16 * (v8 & 1) ^ (v8 ^ (2 * (v8 ^ 4 * v8))) & 0x10) << 19) & 0xFFFFFFFF v8 = (v8 >> 1) & 0xFFFFFF | ((16 * (v8 & 1) ^ (v8 ^ (2 * (v8 ^ 4 * v8))) & 0x10) << 19) & 0xFFFFFFFF t = (key2 >> 1) | ((16 * v6 ^ (v6 ^ 2 * (v6 ^ 4 * v6)) & 0xFFFFFFF0) << 27) & 0xFFFFFFFF t1 = pack("I", t) v20[4] = ord(t1[0]) v20[5] = ord(t1[1]) v20[6] = ord(t1[2]) v20[7] = ord(t1[3]) t = (v6 >> 1) | (key2 << 31) & 0xFFFFFFFF t1 = pack("I", t) v20[0] = ord(t1[0]) v20[1] = ord(t1[1]) v20[2] = ord(t1[2]) v20[3] = ord(t1[3]) key2 = (key2 >> 1) | ((16 * v6 ^ (v6 ^ 2 * (v6 ^ 4 * v6)) & 0xFFFFFFF0) << 27) & 0xFFFFFFFF v6 = t v7 = v20[0] u += 1 count -= 1 pos += 384 return out_buffer |
After the data is encrypted, it is then base64-encoded using a custom alphabet. The following alphabet is used:
3bcd1fghijklmABCDEFGH-J+LMnopq4stuvwxyzNOPQ7STUVWXYZ0e2ar56R89K/
When the previously mentioned C2 response is both decoded and decrypted, we are presented with the following data:
1 2 3 |
tick 7880 systeminfo & net view & netstat -naop tcp & tasklist & dir /a "%userprofile%\AppData\Local\Microsoft\Outlook" & dir /a "%temp%\*.exe" & dir "%ProgramFiles%" & dir "%ProgramFiles%\Microsoft Office" 1018; 60 |
The command structure of the C2 response always begins with the string ‘tick’. The number following this string is most likely a unique command identifier. The malware will store these command identifiers in the following files:
- %TEMP%\MSI2001.LOG
- %TEMP%\MSI2002.LOG
In the event the number after the tick was previously witnessed, the command from the C2 will be ignored. The remaining lines are then parsed. The following commands are supported:
Command | Description |
1001 | Modify C2 URLs |
1003 | Download |
1013 | Download/execute malware in other process |
1018 | Modify wait interval time |
1025 | Download/execute and return response |
Default | Execute command and return results |
Once again, using the previous example, the malware will first ensure that the command was not previously parsed/executed. In the event it is new, it will proceed to execute the various reconnaissance commands found on line #2. The results of these commands are uploaded to the C2 server.
As we can see in the above network traffic, the malware attempts to disguise the data as a .gif image. Finally, the malware will parse the third line, which instructs the malware to modify the wait interval to a value of ‘60’. This interval value is set in the following registry key:
HKCU\Software\Microsoft\HY08A\Policy
Additionally, in the event the C2 response instructs the malware to update C2 URLs, it will be in the following format:
1001; [unique_identifier] [url]
The malware will encrypt the URL string with a 4-byte XOR key of “\x01\x02\x03\x04” and store this data in the following registry key:
HKCU\Software\Microsoft\HY08A\[unique_identifier]
Conclusion
The TDrop2 malware family that was witnessed in a recent attack against a European transportation company provided a minimal set of commands to the attackers. It was most likely used to establish a foothold, perform reconnaissance and deploy further malware into the victim’s network. While the malware lacked a large set of capabilities, it had a wealth of interesting and advanced features, such as the custom encryption/encoding witnessed in the network traffic, the use of process hollowing against a randomly selected Microsoft Windows binary, and the downloading component that attempted to bypass network security measures by modifying the executable header.
We created the AutoFocus tag TDrop2 to identify samples of this new variant and added known C2 domains and hash values to the Threat Prevention product set. At this time, WildFire is able to correctly identify the samples associated with this campaign as malicious.
Sample Identifiers
Stage 1
MD5 | 56C9BB7A7F3AF5F55F4E4FA94E8C6ACC |
SHA1 | 1B86A66A0A0D6A619D8F2CD1E2904EF7395B3F81 |
SHA256 | 43EB1B6BF1707E55A39E87985EDA455FB322AFAE3D2A57339C5E29054FB52042 |
Timestamp | 2015-05-20 14:27:55 UTC |
MD5 | 23637A57EA2F984AFAF991D4E90E3F4A |
SHA1 | 6270129B7EE49AEF969E8C18FAD584E7CB2E512E |
SHA256 | A02E1CB1EFBE8F3551CC3A4B452C2B7F93565860CDE44D26496AABD0D3296444 |
Timestamp | 2015-05-20 14:27:55 UTC |
Stage 2
MD5 | 285352CAD75DC32BAAE10ABF68005397 |
SHA1 | 01635C842F4CEE4E5A97FBA2341207B1372A4559 |
SHA256 | EE878A8ADEE367371242D624F79531FCB81850A25AF0A46B1F82CFB5975F1C89 |
Timestamp | 2005-09-13 08:15:56 UTC |
MD5 | F6F3D7264F7478B472894B90A66EA2A2 |
SHA1 | 8BB8E4193ED7A115B97046AFAA6CF371F237885F |
SHA256 | 3E9BFA7F4EFD3B5687872FEAE62138FAB14E4AF48E2A018C8113325C3D79D6CB |
Timestamp | 2015-07-30 23:45:41 UTC |
Stage 3
MD5 | 29289C19C414CF79E61E095C1500938A |
SHA1 | 25D283BEA4136F07C13FF3902821A207A9F67A7F |
SHA256 | 2356DB510C8C2D5F72945D3D0B9B826DA55AD93C4CD2461961888468EC2F1591 |
Timestamp | 2015-08-24 18:29:52 UTC |
MD5 | C89A97B99063A74EEEA8B7288196CB96 |
SHA1 | 6C53A43ACFB8F3A1C7B37EB614CBD89DD7E70DFE |
SHA256 | E64443E3F3D86D0AB86DAEB0B9E51D2ADA44B23CEBEE68AF9889C8AC72D2ED97 |
Timestamp | 2015-08-24 18:29:52 UTC |
Stage 4
MD5 | C89A97B99063A74EEEA8B7288196CB96 |
SHA1 | 7315E7FD14518B8A27750D5F717A9FA6BBA71880 |
SHA256 | A10CF8B278AF1BBC93E03E29908202197365792FCB0ADD8D02A1E0BDBF94121E |
Timestamp | 2015-05-24 09:33:48 UTC |
Stage 5
MD5 | B67638C91EAE7DB255E41F7CC0CCE46B |
SHA1 | 0EF3EC648B63BADADB6BA947E4F90F12C2C8B7E8 |
SHA256 | 49A665D51E0F17C6554F11BE7ABCDCC98B94A68F6041FD02A74291540FC05A79 |
Timestamp | 2015-09-14 17:53:14 UTC |