The title "Late Night Show" because, the attack origins at the end of 2018 and apparently the Show is very late.
I would like to thank @Manu_De_Lucia, for helping me when I need.
The group, also known as FancyBear, Sofacy Group, Sednit..., starts its activity in the mid-2000s. They target government, military and security organizations especially NATO-aligned states.
APT28 is a threat group that has been attributed to Russia's Main Intelligence Directorate of the Russian General Staff by a July 2018 U.S. Department of Justice indictment. This group reportedly compromised the Hillary Clinton campaign, the Democratic National Committee, and the Democratic Congressional Campaign Committee in 2016 in an attempt to interfere with the U.S. presidential election.
The analyzed sample's second stage, a DLL file, has a high code reusing ratio with the other known attacks by APT28. After detail analysis, I can say that the sample is a variation of SedUploader malware.
This variant initially uses beatguitar[.]com domain as C2 server. But, the DLL file has the capability to update C2 server. Whois information of the initial C2 server is:
The Attack Vector
Stage1: Phishing Document
The attack begins with a phishing document that mimics the brochure of the NATO STO (Science And Technology Organization) conference that organized in December 2018.
At the background, there is a VBA script that waits for permission in order to start its malicious activities. This script triggers with "AutoOpen" function.
The first action it takes is to extract the value of "HLinks" key inside XML Node of the document. The value which is Base64 string can be seen in the Exif Data.
When the string is decoded, it appears that it is structured as a PE executable.
The file utility verifies and identifies it as PE32 executable (DLL).
Then it creates 2 files:
With using WMI, "Uplist.dat" file at %APPDATA% folder is executed by rundll32 utility and the starting point of execution is Ordinal 1.
The last thing it does is to guarantee persistence on the machine, creates a registry key under "HKCU\Software\Microsoft\Windows\CurrentVersion\Run" path with the name "UIMgr" as:
At this point, it is clear that the purpose of the malicious document is to trigger the second stage of the attack vector, the DLL file that extracted within it.
Stage2: Extracted DLL File
DLL file contains lots of encrypted strings. When one of those strings is needed, it is decrypted dynamically. Decryption function is resides at 0x10002f3f and the encryption type is XOR.
The function takes encrypted string and the length as an argument. Then bytes of the string and hard-coded XOR key, XORed with each other one by one. Python implementation of the function is as follows:
Decryption function is called continuously for Mutex name, API calls, C2 addresses vs.
DLL uses a 35 bytes data structure very often while performing its activities. The data structure contains both required parameters and configuration values.
The 8th byte of the corresponding structure is for default C2 address. The 14th byte is for driver's Volume Serial Number. This number is calculated when the file system is created. The DLL uses this information while communicating with C2 server and sends it as 'id' parameter. Because of that, I believe VSN is used for identification purposes for various infected machines.
Communication with C2 server and the DLL file is based on HTTP. The file composes a string depending on the goal, XORs and Base64 encodes. Afterward, it sends encoded data to C2 server with HTTP POST request.
The string always follows a special pattern like starts with 'id=VSN&' and additional parameters comes to the end. An example of the pattern can be seen:
C2 server returns commands to live malware. But it is firstly be subject to a verification routine. The sequence is as:
- Base64 decodes,
- Decoded data's first 4 bytes are XORed with hard-coded value 0xaa7d756 and the result is stored to use it as XOR key for the rest of the routine,
- Decoded data apart of first 4 bytes is XORed,
- Separates first 2 bytes of the XORed data,
- Calculates 2 bytes checksum value of the XORed data apart of the first 2 bytes,
- Checks separated 2 bytes with calculated checksum, equivalence means verification.
With respect to the algorithm, I have written a Python script that produces data which can pass these verification process. So, I could continue my analysis in the intended way.
The execution of the DLL file starts from ordinal 1 of the export table.
At that function, it creates a thread that starts execution from 0x10002ca4. The thread is responsible for all the other actions.
First of all, it creates a Mutex object on the system and its name is 'qO4fU4DfMPBtLuikUd4cM4zVWu'. Then it enters a preparation block of the 35 bytes long data structure. Gets the hostname, and starts Winsock DLL. Any occurrence of an error, it sleeps for 10000 milliseconds and tries the same steps again.
Next one is connection test and for this purpose, it tries to connect google.com. It has 2 capabilities in order to connect the internet: WININET Library and Firefox code injection. It decides which capability is going to use during the connection test and updates configuration byte in the data structure.
In the first place, it makes HTTP request to google.com with WININET Library and expects returned status code like 200 or 404. According to the result, it searches Firefox information on the system. If it finds Firefox process on the system, with using NTDLL Library, it injects code to the process, and try to create a thread within it. When the connection is successful with this way, it updates 20th byte as 1 in the data structure. If it fails, sleeps 10000 milliseconds and the connection test reruns again.
Later successful internet connection, it starts to collect various system information like processes, network adapter information, disk information and Base64 encoded of the screenshot of that moment. Collected information is prepared in order to send to C2 server. The connection data starts with VSN and after that 'w' character is used for collected information. The end result is encoded with Base64 and send to C2 server.
As can be seen, system information has a 'build' variable. The value of this key is hard-coded inside DLL. Because of that reason, I believe it might be some kind of version indicator.
If the connection is failed, it sleeps and tries again to send the data to C2 server.
After this step, the DLL file enters a loop and it takes actions repeatedly. At the beginning of the loop, it gets hostname and checks the internet connection. If it fails, it sleeps 10000 milliseconds. Then it waits for command from C2 server.
When a command comes and it passes verification, the DLL replaces '\n' and '\r' characters on that with '\0' character. Thus, command data becomes one line and ready to parse.
For parser, it uses a new data structure and reflects extracted values to that structured accordingly. It searches for keywords:
Occurrence of '[file]', '[settings]', '[shell]' keywords, it creates sub data structures. For 'Execute', 'Delete', 'LoadLib', 'ReadFile' commands, it updates corresponding configuration bytes in data structure. '[/file]', '[/settings]' and '[/shell]' keywords means it is the end of parsing process.
Any non-matched values go to another parser function. This function searches:
It begins to take actions after a successful parsing process. The paths to follows are differentiated according to extracted data. The action routine is as follows:
- Existence of 'IP' information: The value of 'IP' key is encoded with Base64 and stored under 'HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Servers' path with the name 'Domain'. The DLL checks this registry value and in case of occurrence, it chooses that value as C2 address.
Additionally, it updates default C2 address inside 35 bytes long data structure with that value. After this point, for all C2 communication, the new address is used. When C2 address updated, the DLL enumerates the system(processes, network adapter information, etc.) again and sends it the same way. At the end, it makes a POST request to new C2 server with the same pattern and 'c=2'.
If 'IP' key does not exist, this means '[settings]' data structure does not exist. Therefore the control pass to '[file]' data structure
- Existence of 'ReadFile' information inside '[file]' data structure: The requested file is read and send to C2 server with the same pattern and '?='.
- Existence of 'Filename' information inside '[file]' data structure: The file name is send to C2 server as 'f=filename'. The response of this request is most probably the content of the file. Then, using 'PathToSave' value, it creates a folder and inside that folder, it creates a file with value of 'Filename' key. The response data is written to that file. At this point, it looks 3 configuration bytes in extracted data. First one is 'Execute' byte, and this means to execute the created file. Second on is 'Rundll' byte, this means to execute the created file with rundll32.exe. The last one is 'LoadLib' byte and this means to load the created file as a library. At the end of these controls, it checks 'Delete' byte and according to its value, it deletes the file.
- Existence of '[shell]' data structure: This data structure stores address of the shellcode that comes from C2 server. It creates a thread at that point of the memory.
As I said, these routine runs in a loop continuously.
- HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Servers\Domain