Packer: absent
Compilation date:
11.01.2018 12:16:21 (x86 version)
SHA1 hash :
- 7797107eb4a9a9e4359413c15999603fa27714b3
Description
A multifunctional backdoor trojan for 32-bit and 64-bit Microsoft Windows operating systems. It represents an executable library written in C++. It uses vector classes and strings from the STL library (Standard Template Library). The main function of the trojan is to obtain unauthorized access to infected computers and perform malicious actions at attackers’ commands.
Operating routine
The library contains the following exporting functions:
ServiceMain
mymain
The mymain carries the main functionality of the trojan.
mymain function
When called, this function uses GetTempFileNameW to generate the name of the temporary file with the rar prefix and opens it for writing. This file is used as a journal. Writing to the journal is performed in the following format:
[%d-%02d-%02d %02d:%02d:%02d] %d %d\n%s\n\n" => "[YYYY-MM-DD HH:MM:SS] <rec_id>
<error_code>\n<record>\n\n
where:
- rec_id — is a record type ID;
- error_code — error code (in most cases, it has a 0) value; if an error occurs during execution, the GetLastError() or WSAGetLastError() value is written;
- record — additional data.
Before it is added to the journal, the written data is encoded with the XOR operation, using the 0x31 byte. The rec_id table of ID values is listed at the end of this description.
Next, the trojan collects the following information about the infected system:
struct sysinfo
{
DWORD dword_0;
DWORD is_VMWare;
WCHAR str_test[8]; //возможно ID
DWORD dword_1;
BYTE user_name[64];
BYTE gap_0[64];
WCHAR host_IP[20];
DWORD osver_Major;
DWORD osver_Minor;
DWORD uiANSI_CP;
DWORD uiOEM_CP;
WCHAR host_name[15];
BYTE gap_1[98];
BYTE user_SID[128]; //string SID
DWORD osver_ProductType;
BYTE is_Wow64process;
BYTE mac_address[12];
BYTE gap_2[3];
DWORD number_of_processors;
DWORD total_phys_mem_MBytes;
};
It then checks that the library runs inside the VMWare virtual machine environment. If it detects a virtual machine, the corresponding information is added to the collected system data, while the trojan continues to run.
There is a list of several C&C server addresses encoded inside the source code of the BackDoor.Logtu.1. They are encrypted with the XOR, using the 0x11 byte. However, only the first address from that list is used to control the backdoor. See this list below:
104.194.215[.]199;
192.168.1[.]115;
www.test[.]com.
Moreover, the trojan stores an array of ports within which each element corresponds to one of the servers above:
443, 443, 80
BackDoor.Logtu.1 has an option to use a proxy server, but the analyzed sample lacks such an address. If the proxy server address is present, it is also encoded byte by byte with the XOR operation, using the 0x11 byte.
After the initial preparation, the trojan launches the cycle of connections to the C&C server through the TCP socket. Within the first connection, BackDoor.Logtu.1 tries to directly connect to the server. If it fails, it uses an HTTP proxy server if its address is encoded into the body of the trojan. If it wasn’t successful, the trojan extracts the proxy server parameters from the HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ProxyServer registry key and tries to establish the connection. . In case of another failure, the backdoor tries to obtain the proxy server information through the WinHTTP API, sending the google[.]com request via the WinHttpGetProxyForUrl function. If this attempt has also failed, BackDoor.Logtu.1 tries to extract the corresponding settings from the HKU\<session_user_SID>\...\ProxyServer registry key. . This cycle repeats until the trojan is successfully connected to the server.
After successfully connecting, BackDoor.Logtu.1 sends the information about the infected system to the server. The data transfer and response receipt is divided into two stages:
- sending the packet with the length of the payload;
- sending the payload itself.
The value of the packet with the length of 4 bytes equals <payload_len>+4. This is because the packet with the payload contains a 4 bytes prefix, which in turn, contains the payload ID. Consequently, the payload has the format as shown below:
struct payload
{
DWORD payload_id;
BYTE payload[payload_len];
}
The data transferred from the trojan to the server, as well as its response, are encrypted with the RC4 algorithm. The encryption key is stored inside the trojan body as a separate string, but calculates using the following algorithm:
from hashlib import md5
password = "123456"
salt = md5("").hexdigest()
key = md5(password + salt).hexdigest()
The ID of the packet with the system information has a value of 0.
After the system information is sent and the trojan receives the response from the server, it launches a thread that sends heartbeats every minute. Their ID has a value of 1 and the payload length has a value of 0. After 10 packets are sent, the server connection closes and reestablishes again.
The backdoor waits for the server reply with the packet with the length value that should not exceed 0x1F40. Next, it waits for the packet itself, which contains the command as a payload. After this packet is decrypted, it checks the value of the first DWORD, which is the command ID. The ID value should not exceed 0x34.
In some cases, the command contains additional parameters presented in the form of the strings split with the | symbol. The structure of this command has the form of the "param_0"|"param_1"|...|"param_n".
The list of commands that the trojan can receive and execute is shown in the table below:
Command ID | Command description |
---|---|
0x00 | NOP |
0x01 | Calls GetTickCount(), writes the result into the global variable. |
0x02 | In this command, two parameters separated with the | symbol, are received: The first one is the path to the file. The trojan uses it to form two new paths:
Next, the trojan checks if the file with the original name, specified in the command, exists. If it exists, the trojan sends the response <param_1>|01 to the server. If it does not exist, it checks if the <param_0>.tu is present. If this file exists, the trojan sends its size as a <param_1>|<size>. If the <param_0>.tu file does not exist, the trojan creates the file <param_0>tut, writes the string, which consists of 32 zeros, into it and deletes the file. Depending on the command execution results, the trojan can send various types of responses to the server. In cases of failure at any given step of the command execution, the trojan sends <param_1>|<code>, where code can have a value from 01 to 05. |
0x03 | Creates an application process with the <param_0> name and <param_1> command line parameters. |
0x04 | Runs a separate thread that lists the processes and sends the information about them to the C&C server one by one. Before the listing, the packet with the 0x17 ID and a DWORD 0x47 payload is sent to the server. It is sent as follows:
Herewith, self_module_path is only sent when the process is running in the WOW64 environment. Otherwise, this string is filled with 0 values. |
0x05 | Launches the cmd.exe thread. It creates the cmd.exe process with the input-output redirection into the pipes. After the process is created, it sends a packet with the 0x17 ID and a 0x3D payload in case of a successful connection, or 0x3E in case of a failure. Herewith, the trojan receives the input parameters of the command line from the message using the GetMessage function. The results are sent with the 0x06 ID. |
0x06 | Input of the parameters for the cmd.exe. Using PostThreadMessage, it sends the message 0x464 to the cmd.exe thread and puts the data from the command into lParam. |
0x08 | Ends the connection, sending a packet with the 0x17 packet ID and a DWORD 0x3E payload prior, then deletes its service and executable file. |
0x09 | Opens the file for writing from the end and writes the buffer received in the command into it. Command’s parameters:
It adds a param_0 extension to .tu, opens (or creates) the resulting file for writing, places the pointer to the end of the file and writes a param_4 buffer. If param_3 equals 1, then it deletes the param_0 file and renames the file <param_0>.tu into param_0. |
0x14 | Gets the size of the file specified in the command. |
0x15 | Reads the 0x1000 bytes from the param_0 file, starting with param_2, and sends the results with the 0x15 ID to the server. |
0x16 | Deletes the specified file. If successful, it sends a packet with the 0x17 ID and a DWORD 0x1F payload to the server; in case of an error, a packet with the 0x20 ID is sent instead. |
0x17 | If the first DWORD of the command’s body equals 1, the trojan goes to sleep for 1 second; if it equals 2 the trojan closes the file handle. |
0x18 | Ends the process with PID specified in the command. In return, the C&C server sends the packet with the 0x17 ID. If successful, DWORD 0x0B is sent along with this ID. If failed, 0x0C will be sent. |
0x19 | Gets information about disks. Upon receiving this command, the trojan checks all the disks available from the letter A to the Z and sends information about each of them to the C&C server.
The disk information is sent as a the following structure:
Herewith, if the disk found has a DRIVE_REMOVABLE type or a DRIVE_CDROM type, the trojan indicates the value 1 in the cdrom_or_removable parameter. Prior to listing the disks, the trojan sends the disk_info structure with the dword_1 value, which equals 1, as well as other parameters, which are equal to 0. |
0x20 | Gets the file list in the specified folder. The list is formed as lines of the <file_name>;<file_size>;<last_write_time(YYYY-MM-DD hh:mm:ss)>;<is_dir> format, which are separated by the | symbol.
If the object represents the directory, the <is_dir> value is indicated as 1; if the object represents a file, the 0 value is indicated. |
0x22 | Creates the TCP tunnel. This command has the host parameters to connect to. The parameters come as the following structure:
Where index is the tunnel index. After connecting to the host, the trojan receives a block with the size of 0x400 bytes and sends it to the C&C server as the following structure:
After the last block is sent, the trojan sends the index with the 0x24 ID. |
0x23 | Sends the data to the tunnel. The C&C server sends the structure tunnel_data, and the trojan sends the data into the tunnel with the tunnel_data.index index. |
0x24 | This command contains tunnel index that needs to be closed. |
0x25 | This command contains the structure tunnel_host. The trojan creates a TCP socket, binds the port to tunnel_host.port, and awaits for the incoming connection.
Upon receiving the incoming connection, the trojan sends a zero-length packet without a payload and 0x25 to the C&C server. After that, it receives the data from the new connection, along with the 0x26 ID and sends them to the C&C server. |
0x26 | The command contains a tunnel_data structure. Upon receiving this command, the trojan sends the data to the connection it received in the 0x25 command. |
0x28 | Ends the thread sending the heartbeats. |
0x29 | Moves the file from param_0 to the param_1. |
0x31 | Creates a desktop screenshot. |
0x33 | Gets the list of running services as strings <service_name>;<service_display_name>;<current_state>, separated with the | symbol. |
0x34 | Services management command.
If param_0 has a 0 value, the trojan stops the param_1 service; If param_0 has a 1 value, the trojan launches the param_1 service. |
Upon receiving the command with the 0x17 ID, the trojan closes the file handler, which is stored in the global variable. This file is used only twice: once upon receiving the command, specified earlier, and once in the journal writing function.
File handler closing:
Writing to the journal (logging):
Table of the identifiers of the log entries types
rec_id identifier | Error code | Log entry type | Description |
---|---|---|---|
0x01 | 0 | No entry | Written at the beginning of the execution. |
0x0E | 0 | The name of the C&C server | |
0x0F | WSAGetLastError() | No entry | Added upon C&C server connection error. |
0x07 | 0 | Proxy server name | |
0x08 | 0 | No entry | Added before connecting to the proxy server. |
0x09 | GetLastError() | No entry | Added upon proxy server connection failure. |
0x0A | 0 | CONNECT <proxy_addr>:<proxy_port>
HTTP/1.1\r\nProxy-Authorization: Basic <proxy_auth>\r\n\r\n
or CONNECT <proxy_addr>:<proxy_port> HTTP/1.1\r\n\r\n, if proxy server authorization parameters are missing |
HTTP-proxy connection string. |
0x0B | GetLastError() | No entry | Added if there is a proxy server connection error. |
0x0C | GetLastError() | No entry | Added upon receiving an empty reply from a proxy server. |
0x0D | 0 | Proxy server response | Added upon successfully connecting to the proxy server. |
0x05 | GetLastError() | No entry | Added when a HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings registry key opening failed. |
0x06 | 0 | A not find proxy address string which is encoded inside the body of the trojan. | Added if ProxyServer registry parameter value receiving failed. |
0x03 | 0 | No entry | Added when a system information packet is sent through the proxy server, whose address is encoded inside the trojan body. |
0x04 | 0 1 2 |
No entry No entry No entry |
Added when system information is sent through the proxy server:
from the registry section HKCU; received using WinHTTP API; from the HKU\<session_user_SID> registry section |
0x02 | 0 | No entry | Added when system information is sent directly to the server. |
0 | No entry | Added after system information is sent to the server and before a thread with heartbeats is launched |