Featured

Incident response case study featuring Ryuk and Trickbot (part 2)





This is part 2 of our recent incident response study encountering a Trickbot infection.

Initial compromise

Right after tricking a user into running the malicious Office macro on their machine, thus gaining code execution, the first stage Trickbot executable is downloaded and executed. The first stage payload is responsible for three things:
  • First, Trickbot tries to disable Windows Defender by running these commands:
    cmd.exe /c sc stop WinDefend
    cmd.exe /c sc delete WinDefend
    cmd.exe /c powershell Set-MpPreference -DisableRealtimeMonitoring $true
  • The next step is to unpack itself to all users' AppData/Roaming directory under a less-than-suspicious folder name (such as WinDefrag, WinSocket, GPUDriver, msnet, etc.).
  • Last, but not least, it creates persistence. As we have already mentioned in the first part of this series, Trickbot does not need advanced persistence mechanisms; creating Scheduled task, installing a Service or even a simple Run registry persistence is sufficient. Beside the abovementioned methods to evade detection, Trickbot has several layers of code packing in order to hide the main payload and make detection harder. See Figure 1 for one such example of code decrypting and unpacking.
Figure 1

This concludes stage 1, and usually this is the point where automated dynamic sandbox analyses stop. Trickbot applies several sandbox detection methods, but the main things that prevent automatic analyses from discovering Trickbot's functionalities are the extensive use of Sleep (or NtDelayExecution in a deeper level), restarting the process itself after further delay and the use of reflective dll injection.

In its working state, Trickbot is running disguised as an svchost.exe process, spawning multiple subprocesses from time to time. In the filesystem one can observe the usual Trickbot structure. Next to the main executable there is an initialization file and a folder named 'Data'. The initialization file contains several configuration settings and the unique key used for encrypting the contents of the 'Data' directory. The configurations themselves are obfuscated using a custom base64 alphabet and also appended with junk data. The downloaded Trickbot modules are placed inside the 'Data' folder and each module has a corresponding subdirectory containing its configs. All configs and modules are encrypted with a key derived from the botkey. Interestingly, the module names were not really changed to hide their purpose (i.e. wormDll64 makes Trickbot wormable or systeminfo64 gathers basic information about the compromised system).

One core module of Trickbot is injectDll32/injectDll64 (at least this is the name of the module in the filesystem, but in development, it is WebInject according to a pdb path left in the code: 'F:\Projects\WebInject\bin\x86\Release_nologs\payload32.pdb'). This module is responsible for conducting Trickbot's original mission to be a banking trojan malware. The way it does that is continuously scanning the process list of the compromised host (even to the point of crashing itself because it uses up all possible handle values to processes without closing them properly) and searching for browser executable names in the process list. Once a browser process is started, injectDll writes malicious content into the target browser process' memory and executes the codes it copied as threads. If the user visits one of the banking websites Trickbot has in its injectDll config, the injected code will dump the contents of the input fields and eventually steal banking credentials.
The host Trickbot process creates a named pipe to communicate with the implant injected into the browser. The name of this pipe object is distinguishable, so it can be used for detection. The common name of this pipe object is '\\.\pipe\pidplacesomepipe', but the 'pid' part is replaced with the target process' PID in runtime. However, this placeholder is of size three, so if the target process has a four-digit PID, then the pipe's name will be somewhat bodged, i.e. '\\.\pipe\1892lacesomepipe'.

ReflectiveDLLInjection


Trickbot's extensive use of reflective dll injection has been observed for a long time. The method has three key components: the injection code running in the context of the malware process, the reflective loader that is the first snippet of code running in the host process, and finally the injected payload, which is a dll in this case. In our example, the loader is an exported function of the payload dll. The function ReflectiveLoader is implemented to be position independent and therefore shows resemblance to shellcodes.
    • Injection code: Its task is to allocate space in the host process' memory, make the allocated page executable, copy the loader and the payload and 'call' ReflectiveLoader export function by executing a thread with the function pointer (i.e with CreateRemoteThread).
    • ReflectiveLoader: This implements the core concept of reflective loading. Since it has to be position independent, it has to start with finding its own offset in the host process' virtual memory, then parse the host process' PEB to find the address of kernel32.dll and the offsets of three functions: LoadLibraryA, GetProcAddress and VirtualAlloc. These are standard methods for shellcodes to be able to use the operating system's resources. With these functions, it is then able to load arbitrary functions. To circumvent the Windows PE loader, this component implements a tiny, but fully functioning PE parser. This is when the offset of VirtualAlloc comes in handy; PE files loaded in memory look quite different than in the filesystem, so the custom PE loader has to do the same work the Windows loader would: for example, separate sections go to separate memory pages, import table and import address table has to be completed and relocations has to be done. The final step is to call DllMain of the payload.
    • Payload: This is the injected payload that is run within the context of the host process as a thread.
    What makes reflective dll (or in general, PE) injection unique is that a payload injected this way has no entry in the list of loaded dll's in the host process, because the Windows loader was not used for the loading of the library. Also, the nature of the method allows payloads to be injected directly from memory. In case of Trickbot, the modules are stored encrypted in the filesystem only because of persistence. They are decrypted in memory and injected into the desired process.

    Detection

    Regarding Trickbot, we would like to highlight some ideas, which could serve as indicators of compromise in EDR systems. Ideally, we would like to catch Trickbot at its very first stage, as a malspam. Email protection or spam filtering could definitely help but bear in mind that Trickbot authors come up with new weaponized attachments daily, so it can be hard to track their techniques and also integrate it into the defence systems within hours. Not to mention that Trickbot infections can happen indirectly, for example, deployed by Emotet.

    If we can't grab the snake by its head, try to grab by its tail. The other end of the kill chain is C2 communication and exfiltration of harvested credentials and other data. Trickbot uses https and its GET and POST requests follow a detectable pattern (https://<C2 host>:<port>/<campaign ID>/<workstation name>_<OS version>.<unique ID>/<C2 command>/spk/...), but the pattern is recognizable only from the workstation names and the OS versions, which could be tedious to incorporate in IDS rules.

    There are some in-between steps where one might catch Trickbot on an endpoint. In the filesystem, a signature-based antivirus software could find the main Trickbot executable, but just as Trickbot disables the Windows Defender, it could also do that with other endpoint protection software, as all of them can be stopped with the sufficient privileges.

    Figure 2
    We could try to look for loaded libraries in memory, but with reflective injection, there will be no trace of malicious dll-s in the import lists of processes.

    Let us show a couple of techniques to detect a running Trickbot sample:
    • The named pipe used for communicating between Trickbot and the injectDll module in a browser process ('\\.\pipe\<3-digit PID>placesomepipe', or '\\.\pipe\<4-digit PID>lacesomepipe').
    • In process list, look for suspicious 'svchost.exe' processes. A benign svchost.exe has services.exe as parent process, has 'C:\Windows\system32' as current directory and is a service process running as SYSTEM. When Trickbot uses svchost.exe, it is a standard process running as the current user, has 'C:\Users\<user>\AppData\Roaming\<Trickbot folder>' as current directory and often an orphan process as its parent exited after launching Trickbot (see Figure 2).
    • To check that such process is, in fact, Trickbot, try to find valid PE files in the process memory of svchost.exe. In this quick example we have found three executables for which there is no entry in the import list of the process and has some relevant strings indicating reflective injection. Two of them has an export named ReflectiveLoader and begin execution by checking if they are being run in the context of a browser process. They are the modified, x86 and x64 versions of ReflectiveDLLInjection's ReflectiveLoader component. For reference, let's compile the original ReflectiveLoader written by Stephen Fewer, and compare them with the dumped PE files. The modified version has one additional section, more code has been added and the signature of the exported ReflectiveLoader function is also different (see Figure 3).
      Figure
        Finally, the third PE file dumped from svchost.exe is almost identical to the injectDll64 module. We can verify this similarly to the two previous files, the section tables are identical (see Figure 4). But if this is not enough, we can try to diff them function by function. We used diaphora for this, but there are other useful tools out there (such as BinDiff). Out of the dumped PE file's 1470 functions 974 were 100% identical, while several of them were almost identical, which is more than enough to deduce that Trickbot authors had used ReflectiveDLLInjection's source code.


    Figure 4

    References






    Comments