When it comes to cyber security, attackers seem to be classified as terrifying Advanced Persistent Threats (APTs) or trivialised as Script Kiddies. However, more often than not, the attackers that are actually faced lie somewhere in the middle; the not-so-advanced yet somewhat-persistent threat. Their attacks are often detected but can be difficult to unravel. Their Tactics, Techniques and Procedures do not include any zero-days, but still they manage to show ingenuity. They may not target a victim for years, but they can cause a stressful few weeks for IT managers. We witnessed such a campaign recently where one hospitality customer was targeted multiple times within a few days. Each attack was different, and yet there were distinct indicators that they were originating from the same adversary. Unravelling this attack series may be helpful in understanding the overall threat posed by these mid-tier adversaries.
Attack One: Office Dropper, Reflective Loading and Process Injection
This attack started simply: a user received a phishing email containing a malicious PowerPoint presentation titled “Copia Voucher.pptx”. However, the PowerPoint file could not be opened, even after the user had enabled editing and enabled macros. For the end user, this was the end of the story. However, ThreatSpike Wire identified the creation of an unusual scheduled task.
Though the file was corrupted, the embedded VBA macros were able to run successfully. It worked by piecing together a string from VBA UserForms and Tooltips that was passed as a command to Wscript.Shell().
Even though the PowerPoint never opened and the UserForms could not be seen, they still existed somewhere in the file and could be viewed by opening “Copia Voucher.pptx” with a text editor like notepad or using the Linux utility “strings”. This simple technique is often useful for finding hard-coded Ascii text within a binary file.
Piecing together the strings we identified the command used to create the scheduled task that was detected. The task was set up to run every hour and execute a secondary payload. Mshta is a commonly exploited Windows LoLBin (living-off-the-land binary) that allows users to execute HTML Application files (.hta). Therefore, in this particular case it is unusual to see an mp3 file as an argument to Mshta. When you open CDT.mp3 in a text editor, it becomes clear that it’s actually a .hta file containing an obfuscated VBScript. An extract of this script is shown below.
The commands executed by this script can easily be extracted by changing the lines that contain Run() to print the argument to the Run function.
Using this method of deobfuscation, two separate PowerShell commands were identified. The first copies the .hta file to the following path:
‘C:\Users\’ +‘[Environment]::UserName + \AppData\Roaming\Microsoft\Windows\Start Menu\Programs’
The final PowerShell command that is run is heavily obfuscated as is shown below. However, by breaking down the functions and reversing the process of obfuscation the actual command can be derived.
The steps used to deobfuscate the PowerShell command are displayed in the following screenshots.
In the final command that is run, ‘%rump%’ is replaced with the variable ‘ddd’ which is actually an executable that is obfuscated and encoded into a base64 string. The final PowerShell command reveals the underlying attack mechanism of the VBScript. The command clearly decodes the embedded base64 encoded executable into a byte array ($rOWg) and then reflectively loads it into memory using the .NET function [Reflection.Assemble]::Load(). It then invokes the ‘Run’ method of ‘ent.Class1’, passing a reversed URL hosting a .txt file as the argument.
At this point, the embedded executable can be written to the disk using the following command:
Analysis of the file shows that it isn’t widely detected.
As the embedded executable appears to be a .NET assembly it is fairly simple to decompile so that the code can be analysed. Doing so, the ‘ent.Class1’ code can be viewed to follow the payload delivery mechanism further.
Run(string s) function contains a do-while loop that runs the Thread.Sleep(1000) function 6 times resulting in the program doing nothing for 6 seconds before continuing on to the Run2(string s) function. This is presumably an attempt to evade dynamic detection. However, this technique is rarely successful anymore and AV emulators will skip the sleep function when it is encountered.
Run2(string s) function explains why the URL in the PowerShell command was reversed. The function StrReverse() is called twice. Once on the reversed version of https://paste[.]ee/r/ba6gI/0 and again on the string that was passed as the argument to the reflectively loaded function (reversed version of http://azulviagens[.]online/bolita.txt).
Using WebClient().DownloadString() these two additional files are downloaded and stored in strings and again these strings contain base64 encoded executables. The file from paste.ee is decoded and passed to the function AppDomain.CurrentDomain.Load() which reflectively loads the .NET assembly into memory once more. The
Run(string, byte) function from ‘ClassLibrary1.Class2’ is invoked and this time the argument is an object array containing two elements, “C:\Windows\Microsoft.NET\Framework\RegAsm.exe” and the decoded file as a byte array.
The next step is to decompile and analyse the code of the .NET assembly downloaded from paste.ee. It’s immediately obvious that
Run(string, byte) looks at the running processes and checks for the presence of the antivirus solutions Avast, AVG and “ekrn” which refers to an ESET executable. Again, the sleep function is called in an attempt at evading dynamic detection. The byte array storing the payload is reflectively loaded into memory once again and depending on the result of the if statements, either EntryPoint or Main() is invoked. At the end of the
Run(string, byte) function, the function
RunPE.Execute(ss, b) is also called.
Although both of these defenses failed at first, our client was not compromised. The email’s recipient never opened the attachment and instead flagged it as malicious. In taking such precautions, the recipient became an additional layer of defense and played a crucial role in the company’s security as a whole. In this case, the attacker’s target showed good security awareness, flagging a suspicious email even though its sender was a known partner.
RunPE.Execute(ss, b) it is immediately clear that it is loading Windows API functions that are often abused to carry out process injection.
The Execute() function uses process hollowing to inject the payload into the process that is passed as an argument. In this case, the process to be injected into is RegAsm.exe. This executable is a Windows utility that is used to read the metadata within an assembly and add the necessary entries to the registry allowing COM clients to create .NET Framework classes transparently.
Process hollowing works by unmapping the memory of a targeted process and injecting the malicious code as a replacement. This technique of evasion may bypass application whitelisting as the execution of the malicious code is proxied through a signed Windows executable.
The steps needed to perform process hollowing can be summarised as follows:
- The target process is created in a suspended state using the CreateProcess() function. The sixth argument to this function is the creation flags. In the code detailed below we see that an unsigned int of ‘134217732u’ which is equivalent to 0x8000004 is passed as the sixth argument. Referring to the Microsoft documentation reveals that this value has the CREATE_NO_WINDOW and CREATE_SUSPENDED flags set.
- GetThreadContext() is then used to obtain the Context of the target thread so that the target process’ base address can be found. The Context structure stores register data and is dependent on the process architecture. It is defined in winnt.h. In the code, the Context is stored in ‘array’ and ‘array’ refers to the EBX register of the target thread. The base address of the target process is stored at ‘array + 8’.
- The target process’ memory is then read from the base address into a buffer using ReadProcessMemory().
- ZwUnmapViewOfSection() is then used to unmap the virtual address space of the target process. Passing the process handle and the process’ base address as arguments.
- VirtualAllocEx() is used to allocate memory within the target process’ address space for the payload. The second argument specifies the starting address for the region of pages that is to be allocated. This function returns the base address of the allocated region if it is successful.
- WriteProcessMemory() is used to write the payload to the region of memory within the target process that was previously allocated.
- The process’ new Context is set using SetThreadContext() and the pointer to the updated Context structure is passed as an argument.
- Finally ResumeThread() is called with the target thread handle as an argument. This decrements the thread's suspend count and when the count is zero the execution of the thread is resumed.
So the payload delivery mechanism has been identified. The .NET assembly from paste.ee executes the payload by calling either the Main() function or the default entry point directly depending on which antivirus is detected. It then also injects the payload into RegAsm.exe using process hollowing.
The final step in analysing the attack chain is to reverse the payload executable which is found to be an open source RAT. The main() function ultimately calls
Client.Run() and this function, shown below, establishes a TCP socket connection in a new thread.
The code has a number of functions that are used to obtain information about the system. A few examples are string GetIp(), string GetHardDiskSerialNumber(), string GetCamera(), string GetSystem() and string GetAV(string product).
The Config class stores valuable information about the C2 server’s location. The ‘id’ variable also contains a base64 encoded string that decodes to ‘NyanCatRevenge’. This identifies the payload as a tool created by the GitHub account ‘NYAN-x-CAT’. This account has lots of different repositories for various .NET RATs. This particular RAT appears to be RevengeRat.
This incident has shown that a relatively simple attack vector of using an Office dropper can be greatly expanded on to create a more elaborate mechanism of delivery. In particular, using LolBins and native frameworks like .NET allow attackers to easily employ more complicated techniques such as reflective loading and process injection which ultimately increases the chance of bypassing endpoint solutions.
Attack Two: Recognition
A day later, another alert comes onto our radar, same company, different location:
This time, the detection flags up a suspicious connection rather than a scheduled task; however we still see Mshta connecting to a suspicious domain (URI: http://dreamakers3.hospedagemdesites.ws/dreamnovo/wp-includes/certificates/newgringo[.]mp3). A few things had to have happened before this alert. Firstly, an employee received and opened a phishing email with a malicious Word Document attached. This attachment immediately reaches out for a second Word document called 1.docx. While the original phishing email and attachment had been deleted, the logs still revealed this to be the likely scenario. The PCAP below shows the initial download of 1.docx as well as the registered user agent: MSOffice. Looking further at our logs, we see that WinWord.exe was the culprit indicating that the previous step in this attack involved a Word document with a download command.
The first investigative step was to search for macros in 1.docx, but none were found. Furthermore, if you open 1.docx, Excel pops up, followed briefly by a .hta file. A Word file opening an Excel file is a sequence that is likely enabled by the use of Object Linking and Embedding, a Windows mechanism that allows files to be linked together. Modern windows files (docx, xlsx, pptx etc.) can be thought of as archives which can bundle up the various file types used by the Office programs to render the desired document with the desired functionality. Unzipping the 1.docx archive using 7Zip reveals that Excel files have been embedded.
These .xlsm files didnt open correctly, but they still contained a macro which ran when 1.docx was opened:
This macro is recognizable, and at this point the attack is starting to look similar to Attack One. Again we go on the hunt for these UserForm objects and their associated metadata and we see another familiar artifact:
Again, this can be easily pieced together to reveal the command:
This is the command that caused the original alert. Again, Mshta is being used to run a web based mp3 file. As you may expect, newgringo.mp3 is actually a .hta file. If you opened it in a browser you would see this reservation confirmation.
As the target is a hospitality company, this reservation information, if real, would have been relevant to their business. It’s inclusion provides an early indication that the attack was targeted, at least to this industry. If you open newgringo.mp3 in a text editor, you see the image tag with the image above encoded in base64. Beneath the image tag, there is a slightly obfuscated VBScript script which uses PowerShell to download and run the next stage of the payload (async.crt). The script also closes WINWORD.exe. This is required because 1.docx runs on a loop; it does not close and continuously tries to run newgringo.mp3 until something kills the WINWORD.EXE process.
Upon inspection of async.crt, we see more recognisable techniques. async.crt is pulled down from the same domain that hosted CDT.mp3 in the previous attack. Additionally, async.crt is actually just a masqueraded text file with base64 encoded PowerShell commands, in that way, its contents are similar to CDT.mp3. async.crt contains 2 payloads; the first is a base64 encoded version of an open-source C# RAT tool called AsyncRat. It can be decoded using techniques described in Attack One. AsyncRAT’s github repo is managed by the same user as the RevengeRat tool used in the previous attack. The second payload in async.crt is an injector executable encoded in a byte array. This injector is very similar in behaviour to the injector downloaded off paste.ee in the first attack. Finally, like in the first attack, the injector is used to inject the RAT tool into the memory of a running process.
Between the first and second attack, we see many similarities but also some new developments. The level of obfuscation increased, connections with paste.ee were omitted and the injector and payload are both different code bases compared to the previous attack.
Attack Three: Repetition
A few days later, the client alerts us that yet another property has received a suspicious email with a suspicious attachment called “Voucher Cancelamento ao Hotel COVID-19.ppam”. Sure enough, if you look at the macros you see Mshta executing a web based .hta file “https://www.diamantesviagens[.]com.br/capi1.hta”
This can be decoded to show more instructions which use PowerShell to download the next stage of the attack a filed called "capi.jpg"
You can easily guess that “capi.jpg” is not an image, but is in fact a basic text file containing PowerShell commands. It serves a similar function to CDT.mp3 and async.crt from the first two attacks respectively, delivering and running the final payload.
capi.jpg contains 2 encoded binaries: a base64 encoded version of AsyncRat (again), and instructions for building and loading a byte array called “$elAs”. $elAs is decoded into a binary array which is then loaded using the obfuscated PowerShell command:
Lastly, AsyncRat (represented by the binary array $sTPO2) and RegSvc.exe are passed as parameters to an unknown function qw5f0:
To discover what that final command means, we first try to understand what $elAs does. To do this, the $elAs byte array is created using the PowerShell instruction
[Byte]$elAs=eaAQFJIL $xyYdUjPzB . The encoded string $xyYdUjPzB is decoded into a byte array using the function embedded deobfuscation
eaAQFJIL. This byte array can then be compiled into a executable using regular PowerShell Commands. We then decompile this executable back into C# code:
[rerup]::qw5f0('RegSvcs.exe',$sTPO2) begins to make more sense. It calls the “qw5f0” function in the “rerup” class of the elAs.exe binary which gets loaded into memory when the PowerShell script “capi.jpg” is run.
qw5f0 calls another function,
rOnAlDo.ChRiS; however if you search the codebase for references to “rOnAlDo.ChRiS”, nothing is found. We do see a namespace called Costura, a popular tool for embedding references as resources. Costura has a feature that allows developers to inject a new class into an assembly at runtime. This feature, in the hands of hackers, is a great evasion tactic. It makes sure suspicious elements in the code are only readable at runtime, which makes it harder for AVs to detect.
If you open elAs.exe using a .Net disassembler like ILSpy and inspect the resources, you would see a resource called “costura.management.inf.dll.zip”.
This zip file can be extracted from ILSpy and decompressed. Many tools exist to help decompress Costura Zip files; ILSpy comes with a plugin to do this, but it can also be done with tools like Fody-Costura-Decompress .The unzipped file contains an additional assembly called Managament.inf [sic]. We can then go looking for that r0nAlDo class and find it in the Managament.inf Root Namespace.
The total code contains multiple namespaces alongside rOnALDo:
The namespace C3, contains code which bears significant resemblance to RunPE , a memory injection script developed by NYAN-x-CAT. Furthermore, the Assembly Title is very revealing as it reads (without the additional spaces):
This exact process is carried out to inject AsyncRat.exe into RegSvc.exe in a fashion very similar to that described in Nyan-x-Cat’s RunPE code:
The chain of attack in this instance was as convoluted as the others. The use of open-source code (particularly those developed by Nyan-x-Cat), the obfuscation of function names and artifact extensions were all highly recognisable. The new addition was the use of Costura and PowerShell loading to hide functionalities and make reversing harder.
Speculating about our Adversary
The attacker is clearly creative and dynamic in their attacks. It appears that they are targeting hospitality providers; if you visit some of their attack servers you see:
Some of these sites appear to be compromised legitimate websites, while others appear to be fake or at least suspiciously new, complete with dummy emails and ad-lorem text. They all share the common theme of being in the hospitality industry. All the domains appear to have been registered or based in Brazil. Additionally, the names of the “Authors'' of the malicious Office documents (Copia Voucher.pptx and Voucher Cancelamento ao Hotel COVID-19.ppam) could be Brazillian names (e.g. “Juliana Passerani Zambon” and “Cavaleiro De Troia''). This may indicate the attacker has a significant footprint in Brazil.
On a technical level the attackers heavily leverage Living off the Land techniques meaning they rely on Windows executables and libraries to further their aims. This is shown repeatedly in their use of PowerShell and Mshta, the .Net RAT tools and Office document macros. The attackers also use Windows DLLs like kernel32.dll and reflective loading to run their malicious binaries in memory, making them harder to detect. These tactics are not very new, but can still be highly effective on unprepared systems with outdated AVs. The speed at which these attacks were generated indicates some organisation or coordination on the part of attackers and may indicate the work of a dedicated hacker or criminal organisation.
The series of attacks detected against this client contains many patterns that security analysts are familiar with by now. Things like memory injection, Living off the Land, packed code and C# RAT tools are commonly seen these days and often easy to detect with the correct tools. What makes this attack so remarkable is that an attacker was able to launch 3 slightly different attacks in the space of a few days. They were able to generate custom payloads, recompile binaries and send out multiple maldocs against the same target in a very short period of time. These attacks bear all the hallmarks of modern crimeware: the attackers are reusing off-the-shelf tools in novel ways, they are spending their time obfuscating existing code rather than building new payloads. The long chains of attack allows the adversary to swap out different domains and maldocs in a quick, semi-automated system which allows them to generate new attacks at pace while avoiding and mitigating the risk of detection. The first two attacks were at least partly successful, the payloads executed on the user’s computer; if the Target did not have advanced antivirus solutions at work, it is likely that the attackers would have gotten backdoors on the system. It is difficult to gauge how many companies this attacker has targeted, but it is clear that their methods are likely to have a high success rate.
Signature scanning any of the artifacts in any of the attacks would be futile as the contents were all slightly different: different names, different domains, different file extensions and different techniques. However, by looking at the behaviors it becomes clear that the artifacts are malicious. Defending against these types of attacks is usually easiest at the top of the attack chain, before the attacker starts gaining a foothold on your system. This makes anti-phishing controls and training paramount. Additionally, systems that are able to detect and block suspicious connections (e.g. from binaries like Mshta and PowerShell), are a must. Lastly, endpoint solutions such as EDR which which can detect malicious behaviours at runtime can be a big help in detecting the memory-injected payloads and packed resources.