Summary
Turla is a Russian-based group that has impacted government, embassies, military, education, and research companies since 2004. Our analysis focuses on a backdoor called TinyTurla that was installed on an endpoint via a Windows Service. The list of C2 servers and a password used for authentication with the servers are stored in the Windows registry. The malware implements 12 different commands that include spawning and killing processes, creating and exfiltrating files, creating pipes for process communication, and modifying registry values used during the execution.
Analyst: @GeeksCyber
Technical analysis
SHA256: 030cbd1a51f8583ccfc3fa38a28a5550dc1c84c05d6c0f5eb887d13dedf1da01
The file is a 64-bit DLL that was installed as a service called “Microsoft Windows Time” (https://blog.talosintelligence.com/2021/09/tinyturla.html). We’ve manually created a service called “W64Time” and the corresponding registry keys/values by simulating the execution of the batch script mentioned in the Talos article:
Because we’re analyzing a 64-bit file, the calling convention is different, and the function arguments are passed to the RCX, RDX, R8, and R9 registers. Additional arguments are pushed onto the stack (right to left).
RegisterServiceCtrlHandlerW is utilized to register a function to handle service control requests:
The service status for the above service is set to 0x4 (SERVICE_RUNNING) via a function call to SetServiceStatus:
After the main function finishes, the service status is set to 0x1 (SERVICE_STOPPED).
The RegOpenKeyExW API is used to open the “SYSTEM\CurrentControlSet\Services\W64Time\Parameters” registry key (0x80000002 = HKEY_LOCAL_MACHINE, 0x20119 = KEY_READ | KEY_WOW64_64KEY):
The process extracts the following registry values using RegQueryValueExW:
- TimeLong – the number of milliseconds that the malware waits when the C2 servers are not responding
- TimeShort – the number of milliseconds between requesting different commands from the C2 server
- Security – password used to perform some sort of authentication
- Hosts – list of C2 domains and port numbers
The malware passes the C2 IPs and port numbers to the CommandLineToArgvW routine and extracts an array of pointers to them (the C2 server is randomly chosen for testing purposes):
We’ve emulated network connections using FakeNet.
The malicious process opens the “SOFTWARE\Microsoft\Cryptography” registry key using RegOpenKeyExW (0x80000002 = HKEY_LOCAL_MACHINE, 0x20019 = KEY_READ):
The “MachineGuid” value is extracted via a function call to RegQueryValueExW:
WinHttpOpen is utilized to initialize the use of WinHTTP functions:
The file initializes a connection to the C2 server by calling the WinHttpConnect API:
The WinHttpOpenRequest function is used to create a GET request handle (0x800000 = WINHTTP_FLAG_SECURE):
The process adds an HTTP request header called “Title” containing the Machine GUID to the HTTP request handle (0x20000000 = HTTP_ADDREQ_FLAG_ADD):
The security flags for the handle are set using WinHttpSetOption (0x1F = WINHTTP_OPTION_SECURITY_FLAGS, 0x3300 = WinHttpRequestOption_SslErrorIgnoreFlags):
The malicious file sends the request to the C2 server using the WinHttpSendRequest routine:
WinHttpReceiveResponse is used to receive the response to the GET request initiated above:
The binary obtains header information associated with the request by calling the WinHttpQueryHeaders API (0x26 = WINHTTP_QUERY_TITLE):
WinHttpQueryDataAvailable is utilized to extract the amount of data, in bytes, available to be read with WinHttpReadData:
The response from the server is copied to a buffer via a call to WinHttpReadData:
TinyTurla implements 12 different commands depending on the 1st byte received in the response. It uses a switch statement to execute a particular function:
1st byte = 0x00 – Authentication
The backdoor compares the “Security” value with a string starting from the 2nd byte in the response:
Whether the two strings are equal, the malware sends “00 00” to the C2 server. Otherwise, it sends “00 03”, indicating an unsuccessful “authentication”.
1st byte = 0x01 – create a process
The binary creates a process specified by the C2 server in the response (0x08000000 = CREATE_NO_WINDOW):
The WinHttpOpenRequest routine is used to create a POST request handle (0x800000 = WINHTTP_FLAG_SECURE):
The backdoor adds an HTTP request header called “Title” that contains the Machine GUID to the request handle (0x20000000 = HTTP_ADDREQ_FLAG_ADD):
The security flags for the handle are set using WinHttpSetOption (0x1F = WINHTTP_OPTION_SECURITY_FLAGS, 0x3300 = WinHttpRequestOption_SslErrorIgnoreFlags):
The malicious process sends the POST request to the C2 server by calling the WinHttpSendRequest API:
A confirmation message “01 00” is sent to the C2 server using WinHttpWriteData:
WinHttpReceiveResponse is utilized to halt the process until it receives the response to the HTTP request:
The backdoor sleeps for “TimeShort” milliseconds and waits for further instructions:
1st byte = 0x02 – create a process and exfiltrate its output
The malicious file creates an anonymous pipe and returns handles to the read/write ends of the pipe:
The write handle is set to be inherited by calling the SetHandleInformation routine (0x1 = HANDLE_FLAG_INHERIT):
A second anonymous pipe is created via a function call to CreatePipe:
The read handle is set to be inherited by calling the SetHandleInformation routine (0x1 = HANDLE_FLAG_INHERIT):
The malware creates a process mentioned by the C2 server in the response (0x08000000 = CREATE_NO_WINDOW):
WaitForSingleObject is used to wait until the above process is in the signaled state or 0xEA60 = 60000ms = 60 seconds have elapsed:
The output of the created process is copied from the anonymous pipe into a buffer by calling the PeekNamedPipe function:
The process reads data from the pipe using ReadFile:
The backdoor kills the process created above using the TerminateProcess routine:
The execution flow of creating a POST request (WinHttpOpenRequest -> WinHttpAddRequestHeaders -> WinHttpSetOption -> WinHttpSendRequest) is repeated and will not be detailed again. The process output is exfiltrated to the CnC server:
1st byte = 0x03 – create and populate a file
The backdoor creates a file specified by the C2 server using CreateFileW (0x40000000 = GENERIC_WRITE, 0x2 = CREATE_ALWAYS, 0x80 = FILE_ATTRIBUTE_NORMAL):
The WriteFile API is utilized to populate the file with data received from the server:
A confirmation message “03 00” is sent to the C2 server.
1st byte = 0x04 – exfiltrate a file to the C2 server
The process opens a file nominated by the server using CreateFileW (0x80000000 = GENERIC_READ, 0x3 = OPEN_EXISTING, 0x80 = FILE_ATTRIBUTE_NORMAL):
The size of the file is retrieved by calling the GetFileSize routine:
The file content is copied to a buffer via a function call to ReadFile:
The content extracted above is transmitted to the CnC server:
1st byte = 0x05 – spawn a new process
The malicious process creates an anonymous pipe using the CreatePipe API:
The write handle is set to be inherited by calling the SetHandleInformation routine (0x1 = HANDLE_FLAG_INHERIT):
A second anonymous pipe is created by the malware:
The read handle is set to be inherited by calling the SetHandleInformation routine (0x1 = HANDLE_FLAG_INHERIT):
CreateProcessW is used to create a process specified by the C2 server (0x08000000 = CREATE_NO_WINDOW):
A confirmation message “05 00” is sent to the C2 server.
1st byte = 0x06 – kill a process
The binary kills the process spawned in the above command by calling TerminateProcess:
A confirmation message “06 00” is sent to the C2 server.
1st byte = 0x07 – read/write to a pipe
The WriteFile API is utilized to write data transmitted by the CnC server to a pipe created earlier:
The process reads data that is available through the pipe using the PeekNamedPipe and ReadFile APIs:
The pipe content extracted above is exfiltrated to the C2 server.
1st byte = 0x08 – modify the “TimeLong” registry value
The malware opens the “SYSTEM\CurrentControlSet\Services\W64Time\Parameters” registry key by calling the RegOpenKeyExW routine (0x80000002 = HKEY_LOCAL_MACHINE, 0x20006 = KEY_WRITE):
The “TimeLong” value is modified to a number sent by the C2 server:
A confirmation message “08 00” is sent to the C2 server.
1st byte = 0x09 – modify the “TimeShort” registry value
This command is similar to the one from above. The “TimeShort” value is modified accordingly:
A confirmation message “09 00” is sent to the C2 server.
1st byte = 0x0A – modify the “Security” registry value
This command is similar to the one from above. The “Security” value used in the authentication process is changed by the backdoor:
A confirmation message “0A 00” is sent to the C2 server.
1st byte = 0x0B – modify the “Hosts” registry value
This command is similar to the one from above. The “Hosts” value that contains the list of C2 servers is changed by the malware:
CommandLineToArgvW is utilized to retrieve an array of pointers to the C2 server(s):
A confirmation message “0B 00” is sent to the C2 server.
References
MSDN: https://docs.microsoft.com/en-us/windows/win32/api/
Fakenet: https://github.com/fireeye/flare-fakenet-ng
VirusTotal: https://www.virustotal.com/gui/file/030cbd1a51f8583ccfc3fa38a28a5550dc1c84c05d6c0f5eb887d13dedf1da01
MalwareBazaar: https://bazaar.abuse.ch/sample/030cbd1a51f8583ccfc3fa38a28a5550dc1c84c05d6c0f5eb887d13dedf1da01/
Talos article: https://blog.talosintelligence.com/2021/09/tinyturla.html