Photo by Collin Armstrong on Unsplash

Introduction

Albert Lamorisse invented Risk game in 1957. According to Wikipedia,

Risk is a strategy board game of diplomacy, conflict and conquest for two to six players. The standard version is played on a board depicting a political map of Earth, divided into forty-two territories, which are grouped into six continents. Turn rotates among players who control armies of playing pieces with which they attempt to capture territories from other players, with results determined by dice rolls. Players may form and dissolve alliances during the course of the game. The goal of the game is to occupy every territory on the board and in doing so, eliminate the other players.

During the early stages of the analysis of suspicious files, the abovementioned rules and goals of the game were observed. The code, the strings, the images all seem to form the digital version of the game.

Some strings about the game inside the files

At first glance, there was no malicious indicator at all. In contrast, on Virustotal, the files have a very bad reputation. After digging beneath the surface, the findings lead to a Github account and then a repository which is greatly matched with the files except for the sizes. The comparison results lighting up a complex attack vector that is constructed by various stages and also utilizes steganography-like technique in order to trigger the next step in one point of the execution. The attack vectors are ended with Agent-Tesla and Nano Core Client RATs. Agent-Tesla is a spyware that is active since 2014 and one Agent-Tesla variant in-depth analysis is available on https://r00tten.com/in-depth-analysis-rtf-file-drops-agent_tesla/.

Nano Core Client RAT

This particular remote access trojan has been discovered in 2013 and since then multiple versions have been all around and used by various threat actors. The capability of the malware is extended by the plugins. The analyzed sample's overall code quality takes attention especially when combines with exception handling and logging features.

The Attack Vector

Stage1: Risk

The analyzed samples are based on .Net Framework PE executable files. After glance their code, resources, and other contents, even all 7 files have various names about payment, booking offers, BRITISH PETROLEUM, etc. the thing is crystal clear that the files are about Risk board game. Code, strings that represent rules, image files in resources section all suggest this. These contents create an illusion for the analyst, it seems to be a game sample. And during the early stages of the dynamic analysis session, they don't reveal any [spoiler alert] malicious behavior [/spoiler alert]. On the other hand, during the early stages of the static analysis, the flow starts and continues to configure Forms. Later, dissecting the contents piece by piece, a string glance behind from the screen: the name that looks like the creator of the something.

The string that mentions a name as 'Creator'

By using this little information, a profile on Github and by then a repository is discovered. The name of the repository is Risk-Game. The language of the repository C#. Bingo!

Risk-Game project's repository on Github

This project has been added to the analysis, and all the signs that are observed apply to this file as well. The major differences are, on disk, the executable file of the project is much bigger than the suspicious samples.

Size differences

A plausible scenario is that the open-source project can be used to hide malicious behavior beneath the Risk board game. It also clarifies the size difference, reducing the size might be a plus by shrinking undesired parts. With this thought in mind, one of the suspicious files and the project file are compared side by side according to the flow and before long, during one of the Form sequences, an additional code block draws the attention.

Side-by-side comparison

At the basic level, the injected code block is loading a file named 'CassaPub2' ('CassaPub4' is also observed) that located in the resources section to the process by using 'Assembly.Load' function. Then it triggers this file with a parameter that it prepares by merging hard-coded Arabic strings dynamically.

The string of the one sample, that is going to be merged

The loaded file appears to be a DLL file, named GuitarLibX, based on .Net, and 'Hide_GuitarX' class is triggered.

GuitarLibX

Constructor of the Hide_GuitarX class takes the merged string as a parameter and using this value it reads a PNG file stored inside the resources section of the Risk-like file. Then the PNG file is subject to a decryption algorithm. The algorithm:

Reads pixel by pixel and filter out those RGBA(0, 0, 0, 0)

Separates R, G and B values and stores them in a new array

The first 16 values of the array used as XOR key array and the rest of the values XORed one by one

Decrypted data is loaded to the process and executed

A part of the routine that decrypts the image inside the resources section

GuitarLibX file triggers the next step of the attack vector by decrypting an image file located at the resources section. In order to hijack and grab the decrypted data, a new C# project is created by patching the code, instead of executing decrypted data, writes to the disk.

Bonus

The file GuitarLibX has an image file inside its resources.

The unused image inside GuitarLibX file

Corresponding image file is used by another code block that isn't triggered and the type of the code is Form. A new C# project has been created in order to run this code block as standalone.

The execution of the project that combines unused code and image

This image file and the code block have no responsibility on the attack vector.

Stage2: CyaX-Sharp

Basic Concepts

The decrypted data from the image file appears to be a PE file based on .Net. After a glance, it can be observed that this stage uses intense obfuscation techniques. One of them is Control Flow Flattening and the other one is that the symbols inside the file are obfuscated. All the 7 files that analyzed uses the abovementioned obfuscation techniques, but just one of them additionally keeps the strings in encrypted form and it resolves dynamically.

C# code is compiled into a special form, Intermediate Language (IL), and when executed Common Language Runtime (CLR) performs Just In Time (JIT) compilation to convert the IL code to native machine instructions. DnSpy is a tool that represents the IL in higher-level form. The other feature of this tool is to capable to modify the IL of a file. By using this feature, the suspicious file's IL is patched to decrypt encrypted strings and write to the disk. It can be much more plausible to pop up decrypted values one by one but required libraries don't available in this situation, so this isn't an option. Fortunately, writing disk is possible.

Patching the IL in order to reveal encrypted strings

The corresponding IL is as following:

0000 ldc.i4 -0x4E75C93B 0005 call !!0 [CssYlNN4An3ch7]'<Module>'::smethod_12<string>(uint32) 000A stsfld string [CssYlNN4An3ch7]Class8::string_0 000F nop 0010 nop 0011 ldstr "%path%" 0016 ldsfld string Class8::string_0 001B call void [mscorlib]System.IO.File::WriteAllText(string, string) 0020 nop 0021 ret

The Flow

The malware sleeps immediately after starting its execution, between 45 and 60 seconds long that it determines randomly. Then it begins to take actions according to the hard-coded configuration values inside it. Corresponding data comes as a string and it contains various configuration values separated by '||'. It dynamically splits this string.

One of the configuration string

The meaning of indexes of the array which is formed by splitting corresponding data, in sequence concerning the flow, is as follows:

9th value determines whether disables Microsoft Windows Defender protection

Code block that disables Microsoft Windows Defender protection

7th value determines whether stops the execution according to the artifacts of the virtualization software

Code block that searches virtualization software artifacts

8th value determines whether stops the execution according to the artifacts of the malware analysis

Code block that searches malware analysis artifacts

4th value determines whether downloads a file to '%temp%' from the internet and execute it

Code block that downloads and executes according to configuration values

5th value holds the file's URL to use according to 4th value

6th value holds a name to use as file's name while storing at '%temp%' path according to 4h value

1st value determines whether there is a file named match with hard-coded value inside the malware and if it doesn't find, copy the file the process launch from to '%appdata%' folder with the hard-coded name and schedule a task for the file in '%appdata%'

Code block that makes ready the file and schedules a task

0th value determines the way this step would trigger the next step. If the value is 4, then it triggers directly after decryption routine If the value is other than 4, then it does base64 decode and loads resultant data to the process and call the function 'Kurd' inside it. The path that is chosen according to 0th value and the file that was executed if the value was 4 passes as parameters.



2 function that triggered according to 0th value

4th value for all 7 analyzed samples is inactive so 5th and 6th values are empty. Also, for all 7 analyzed samples, there is a file as 'XML' stored inside the resources section. This is used as a scheduled task configuration file.

The XML file inside resources section

'[USERID]' and '[LOCATION]' fields are updated automatically by the malware.

Base64 encoded data that stored as 'CyaX-Sharp', when the 0th configuration value is other than 4, is decoded and loaded then the attack vector's execution continues from there. Decoded data is a DLL file named 'CyaX.dll' based on .Net. This file is the same for all of the analyzed samples. 'Kurd' function inside the Dll is triggered and it calls another function within it. The important thing; instead of using a dynamically chosen path concerning the 0th value, it passes the path of the file the process launch from, as a parameter. After this point, the malware creates a suspended process from the abovementioned path and then it injects the data block passes as a parameter to the process. After a successful injection routine, the execution passed to the injected data.

Totally 7 files are been analyzed. 6 of them try to inject 'Agent.Tesla' variant and only one sample try to inject 'Nano Core Client RAT'.

Stage3: Nano Core Client RAT

Basic Concepts

The analyzed sample of the NanoCore handles its execution according to configurations that they are stored as a dictionary object. It has a special class for these purposes. This class works like 'if the key exists then return its value, else return default value'. Additionally, with plugins, it can expend key-value storage. For the sample, configuration keys are as following:

BuildTime

Version

Mutex

DefaultGroup

PrimaryConnectionHost

BackupConnectionHost

ConnectionPort

RunOnStartup

RequestElevation

BypassUserAccountControl

BypassUserAccountControlData

ClearZoneIdentifier

ClearAccessControl

SetCriticalProcess

PreventSystemSleep

ActivateAwayMode

EnableDebugMode

RunDelay

ConnectDelay

RestartDelay

TimeoutInterval

KeepAliveTimeout

MutexTimeout

LanTimeout

WanTimeout

BufferSize

MaxPacketSize

GCThreshold

UseCustomDnsServer

PrimaryDnsServer

BackupDnsServer

ShowInstallationDialog

InstallationDialogTitle

InstallationDialogMessage

InstallationDialogIcon

KeyboardLogging

At the starting of execution, a file within the resources section is read and firstly the file used to initialize required components. The process can be summarized as:

Reads first 4 bytes and according to the value, it reads that amount of bytes

Takes GUID of the file

Applies Rijndael decryption to the bytes, uses GUID as Key and IV

Initialize DES algorithm, uses the decrypted data as Key and IV

Subsequently, including the rest of the data block of the file from the resources section, all plugins and configuration data are subject to the DES decryption routine firstly. Then the malware parses resultant data.

The malware uses custom data structures during the parsing routine.

public struct GStruct2 { public byte byte_0; public byte byte_1; public Guid guid_0; public object[] object_0; }

It begins assigning 'byte_0', 'byte_1' and 'guid_0' variables. Then a list object is used in the sequel and in the end it creates a new array from the list object and assigns it to the 'object_0' variable. The whole routine in detail is as:

Reads a byte and if it is true, reads 4 bytes and allocates that amount of bytes for a byte array and then decompress rest of the data and store it in the new array

Reads a byte and assigns to the 'byte_0'

Reads a byte and assigns to the 'byte_1'

Reads a byte and if it is true, reads 16 bytes and assigns to the 'guid_0'

From this byte to the last byte, it reads one by one and according to the value, a Case block is executed to form a list object

Creates a new array from the list (by calling list.ToArray) and assigns to the 'object_0'

According to 'EnableDebugMode' value, it tries to log to console, a file named 'client.log' at the location the process launched from, or to both of them. The logging is detailed and well structured. The corresponding value is actually 'false', but it is altered manually.

Friday, December 13, 2019 4:04 PM: Builder settings loaded.. 4:04 PM: KeyboardLogging = True 4:04 PM: BuildTime = 9/2/2019 6:55:15 AM 4:04 PM: Version = 1.2.2.0 4:04 PM: Mutex = fb03f1b7-c3cb-4a68-8d5a-68180ad51d86 4:04 PM: DefaultGroup = NewDNS 4:04 PM: PrimaryConnectionHost = newapa123.ddns.net 4:04 PM: BackupConnectionHost = newapa123.ddns.net 4:04 PM: ConnectionPort = 54900 4:04 PM: RunOnStartup = True 4:04 PM: RequestElevation = False 4:04 PM: BypassUserAccountControl = False 4:04 PM: ClearZoneIdentifier = True 4:05 PM: ClearAccessControl = False 4:05 PM: SetCriticalProcess = False 4:05 PM: PreventSystemSleep = True 4:05 PM: ActivateAwayMode = False 4:05 PM: EnableDebugMode = False 4:05 PM: RunDelay = 0 4:05 PM: ConnectDelay = 4000 4:05 PM: RestartDelay = 5000 4:05 PM: TimeoutInterval = 5000 4:05 PM: KeepAliveTimeout = 30000 4:05 PM: MutexTimeout = 5000 4:05 PM: LanTimeout = 2500 4:05 PM: WanTimeout = 8000 4:05 PM: BufferSize = 65535 4:05 PM: MaxPacketSize = 10485760 4:05 PM: GCThreshold = 10485760 4:06 PM: UseCustomDnsServer = True 4:06 PM: PrimaryDnsServer = 8.8.8.8 4:06 PM: BackupDnsServer = 8.8.4.4 4:13 PM: Reading client settings from 'settings.bin'.. 4:13 PM: 4:13 PM: Client Exception (LoadSettings): 4:13 PM: Settings file 'settings.bin' could not be found. at Class8.smethod_93(String string_4) 4:13 PM: 4:13 PM: Reading client settings from 'settings.bak'.. 4:13 PM: 4:13 PM: Client Exception (LoadSettings): 4:13 PM: Settings file 'settings.bak' could not be found. at Class8.smethod_93(String string_4) 4:13 PM: 4:13 PM: Initializing cached plugins.. 4:13 PM: Plugin: SurveillanceEx Plugin, Cache: True 4:13 PM: Rebuilding host cache.. 4:13 PM: Host: newapa123.ddns.net 4:14 PM: Connecting to newapa123.ddns.net:54900..

It relies on the 'PrimaryConnectionHost' configuration value for connection host. If the 'UseCustomDnsServer' value is 'True', then in order to obtain the IP address of the corresponding domain, it uses 'PrimaryDnsServer' and 'BackupDnsServer' values. In a situation that DNS check results as a failure for both of the servers, it uses the system's DNS server.

All the communication through the C&C server is DES encrypted. After successful connection; the GUID of the machine, the machine name + '' + username, 'DefaultGroup' configuration value and the version of the Nano Core Client is sent to the server.

Sending system's information

Then it beacons in certain intervals.

The Flow

The malware starts a routine at the beginning of the execution. First of all, it reads a file that is located inside the resources section. Then this data is decrypted and it separates these to 2 arrays as plugins and configuration variables. 'dictionary_1', used to track configuration values, is updated or, if the key does not exist, added according to configuration array. After parsing the other array, it is added to 'dictionary_0' which is used for plugins. At the end of this routine; configuration variables, plugins, and all the other required elements become ready to use.

After that, it takes action according to configuration values. For the analyzed sample, those actions are as follows:

Creates Mutex,

Creates a folder under '%appdata%' by using MachineGuid of the system,

Creates a file at '%appdata%' + GUID + '\run.data' in order to track first run time,

Adds an entry to the 'run keys'. According to the privilege level of the process, it chooses between 2 separate capabilities. If it is administrator: Adds an entry named 'NTFS Monitor' to the 'run keys' for HKLM and the file is at '%programfiles%\NTFS Monitor

tfsmon.exe', Checks the md5 of that file with itself, Deletes 'NTFS Monitor' at HKCU, if it exists, Deletes the file at '%appdata%' + GUID + '\NTFS Monitor

tfsmon.exe', if it exists,

If it is not administrator: Adds an entry named 'NTFS Monitor' to the 'run keys' for HKCU and the file is at '%appdata%' + GUID + '\NTFS Monitor

tfsmon.exe', Checks the md5 of that file with itself,

Clears zone identifiers of the file the process is launched from,

Creates a thread that calls SetThreadExecutionState in a certain interval,

Triggers SurveillanceEx plugin,

Connects to newapa123[.]ddns[.]net

SurveillanceEx

The plugin is designed to provide keylogging capability to the malware. It uses the 'RawInput' technique and besides that, it also intercepts Clipboard changes. The file for logging purpose is located at '%appdata%\Logs' + Username + '\KB_' + TickCount _ '.dat'. There is a data structure that defines data types. The logging process uses this structure to separate different types. It appends a byte corresponding to each type. It starts with Unix Timestamp, and also for each delay that is greater than 1 minute, it appends Timestamp again.

public enum KeyboardType : byte { Time, Window, Clipboard, Raw, Char, String }

A sample keylogger data:

Sample keylog data that contains logs of various kinds like Time, Window, Char and Clipboard

Conclusion

It is ironic that an attack vector is constructed as it will trigger from a point, a game, that at the core it is designed to bring fun. But when one look through the cyber dynamics of the decade, it isn't that much ironic though.

YARA

IOCs

newapa123[.]ddns[.]net

\BaseNamedObjects{fb03f1b7-c3cb-4a68-8d5a-68180ad51d86}

%appdata%\tDNlhP.exe

%appdata%\ImDdQPOzyrjI.exe

%appdata%\ZOxeRuBzJmpNJp.exe

%appdata%\JYBEcxnaL.exe

%appdata%\xaHinrL.exe

%appdata%\AFTppCr.exe

%appdata%\IZVyyrlfEctu.exe

%systemroot%\System32\Tasks\Updates\tDNlhP

%systemroot%\System32\Tasks\Updates\ImDdQPOzyrjI

%systemroot%\System32\Tasks\Updates\ZOxeRuBzJmpNJp

%systemroot%\System32\Tasks\Updates\JYBEcxnaL

%systemroot%\System32\Tasks\Updates\xaHinrL

%systemroot%\System32\Tasks\Updates\AFTppCr

%systemroot%\System32\Tasks\Updates\IZVyyrlfEctu

%appdata% + GUID + \run.dat

%appdata% + GUID + \Exceptions\1.2.2.0

%appdata% + GUID + \Logs\ + UserName + \KB_ + TickCount + .dat

%appdata% + GUID + \NTFS Monitor

tfsmon.exe

%programfiles%\NTFS Monitor

tfsmon.exe

c40d59f85e1b4bacf10643b535da804af2e99caba91ab860b221121e24a2a9bb

11455bc66548fd161362d300d24c6539c36c7b236aafd4f457d8ee2d8b6c9262

29659dd2cd05d0e3c97c2fd3687644a78622ad487178901cb67f14be314c168b

3c3b311505b8a3b280024d05017ff9edcb19e193c1760cac099d09fb165e93d7

6822a44b8ae526747479d59ea775b7dc5758880469f802caa9ad4ceade2218df

b0a8c2cb1e0afb0cdef74f983c4f16be2bcd87a93b3d3aa8cad21ec85d29153e

f7c2cd67d1a009454facf8ab9b0cbee0c9a53644cae7bbd4bc952917ec19522b

666bf6411729fa410c75bcdc6d09630c1b68c5b90827595b0fc7d022812aee8e

8d68e9e02e2289e0cc49f7b1dfe678a8b49ed4f02f31103907ec57ad3ecf59a1

283524aa6cfe0e44cc0010347157f218d929afe1ad2dc1377f8a00830f0c3c40

8c519c1a6be92305e2418b6bc477f0fd45c4371e16de8eaa726c6a818bb79fc1

277c66c0399e8da87d31461bde4229d69325d2bb5cba769be982228c213c3b2b

2565961dda75679a16247d7b56f85e1cf16c88ee4643e584b1902830deb4287e

References