Analyzing SilentMoon — Turla Trojan!

Static and Dynamic Analysis

In this particular I’m going to reflect light on Russian APT group Turla Operating backdoor/trojan “SilentMoon”. Turla APT group is operational to conduct hijack satellite communication for hacking into governments, private sectors , APT as they are moreover like cyber espionage operational APT group for nearly past two decades ( around 2004 ).

[ Source: Kaspersky ] Command and Control in the Sky: Turla Hijacking SATCOM for conducting hacking operations.

Analysis

Signature Overview

Signature Overview of SilentMoon Trojan.

File Information

“SilentMoon” Hash analyzed in this report is EC2CA1E96997E6146F9C148D3607E7A53607C21F31FF03894266D27CB29F082D.

Information Gathering on SilentMoon Trojan using PEStudio.

Fire-ing up IDA for starting-off with the exports present in the SilentMoon backdoor.

exports in Turla APT “SilentMoon” backdoor.

Since the main entry function is start, we can start our reversing journey of “SilentMoon” with that.

start function:

In this module of “SilentMoon” Turla Developers had written this module for calling-up another module “active_dir_ops_func” function in the end of the “start” module , after performing some command line operations.

Call Graph and Reversed Code of “start” function.

Moving on to the next module in “SilentMoon” Turla backdoor.

active_dir_ops_func function:

After gathering information on victim system environment using following functions:

..:- GetProcessHeap()

..:- GetModuleHandleW()

..:- GetProcAddress()

..:- GetCurrentProcess()

Reversed Code & Call graph of “active_dir_ops_func” module.

and using “gather_env_info()” .

Reversed Code of “gather_env_info” module.

In this module “active_dir_ops_func” does is that it calls the module named as “ServiceMain” after “gather_env_info” module. Then in the end of this module Turla developers had written a call to OpenServiceW function is being made which opens existing service ADSInternal under then if statement which as a whole passed to v22 and just after that by making call to the function ChangeServiceConfig2W & ChangeServiceConfigW optional parameters and parameters of service are being respectively modified for the service ADSInternal addressed to v22 and lastly in this module by calling CloseServiceHandle() service control handles v22 and v21 are being closed.

ServiceMain function:

In this function, after declarations of required variables of the module, RegisterServiceCtrlHandlerExA() function is used to return the status of the ADSInternal which is the Active Directory Scheme service and it is passed in the v1 variable and just after that v1 is passed to the handle hServiceStatus which is the handle to the ADSInternal service status information structure.

Reversed Code & Call graph of “ServiceMain” module.

Moving further in the module, SetServiceStatus is used to set the status of the ADSInternal service and then the event object is created with use of CreateEventW. Moving on in the module handle to the Event hEvent is being passed in the if statement. Then after some parameters setting in the nested if statement under the parameters of if statement get_keycontainer_info() module is being called for fetching crypto key container values. Moving further in the module by executing allocation of several heap using functions like heap_and_alloc_ops() , HeapAlloc() & setting the version info using set_version_info. Then after that calling map_malw_info_in_sys() module the version and type info is being written in the compromised victim system.

Reversed Code of “map_malw_info_in_sys()” module.

Then soon after that the call to write_malw_info_in_sys() is being made which is being developed by Turla developers for writing malware information in the system.

Reversed Code of “write_malw_info_in_sys()” module.

Moving further in this module , what we find is that some Registry Key Operations which is done by calling following function twice:

reg_create_and_set_query_ops() function:

In this module, firstly inside the conditional if statement key is being specified for enabling SMB server which is being created under the HKEY_LOCAL_MACHINE “SYSTEM\\CurrentControlSet\\Services\\lanmanserver\\parameters”.

Reversed Code of “reg_create_and_set_query_ops()” module.

Then calling the RegCloseKey() key handle is being closed after querying RegQueryValueExW() several times and setting registry values by calling RegSetValueExW() inside the “query_reg_ops” module which is passed into the v1. After that in the if statement parameters using RegCreateKeyExW() for the compromised victim system HKEY_LOCAL_MACHINE setting up the LSA Protection registry KeySYSTEM\\CurrentControlSet\\Control\\LSA”. Then after calling “reg_create_query_ops” creating registry key as “SYSTEM\\CurrentControlSet\\Services\\lanmanserver\\parameters” for SMB Server and then after RegQueryValueExW() several times and setting registry values by calling RegSetValueExW() inside the “query_reg_ops_1”

Reversed Code of “query_reg_ops” & “query_reg_ops_1” module are similar.

Then as we move further in the reversed module we can see that that the thread is being created for SilentMoon trojan to make communications with the command and control server (C2/C&C) by passing the function C2_comm_and_fetch_payload_write_ops as parameter in the CreateThread function. Then soon after that the using the handles to the event as the parameter in the if stmt the thread which was created in this module is being closed by calling TerminateThread() and then in the ending the handles for the event created is being closed by making call to the CloseHandle() after passing hEvent as parameter to the CloseHandle() function and calling it in if stmt where condition is hEvent. And lastly the using the SetServiceStatus() function status of the service is being set.

C2_comm_and_fetch_payload_write_ops function:

In this module, using function CreateNamedPipeW() pipe server is being created then after as passing the ConnectNamedPipe() as parameter the connection to the Command and control server is being checked for satisfying if the connection is up or not , if it is the next following stmt inside if is being executed which is the used for creating thread CreateThread that carries out the operations of connecting to the command and control server ( C2/C&C) and fetching the additional plugins (payloads) from C2 and write them in the memory of infected system or else handle is being closed and after that execution of if and else stmt , all the Processes and threads is being exited by calling ExitProcess() function.

Reversed Code & Call Graph of “C2_comm_and_fetch_payload_write_ops” module.

connect_C2_get_paylaod_write_ops_in_temp function:

What’s happening in this module is that is helps SlientMoon instance to connect to C2 and fetch additional plugins( payloads) from C2.

Call Graph of “connect_C2_get_paylaod_write_ops_in_temp” module.
Reverse Code of “connect_C2_get_paylaod_write_ops_in_temp” module.

After that this module writes those plugins in the temp directory of infected victim system using write_additional_payload_in_temp module.

Reverse Code of “write_additional_payload_in_temp” module.

And lastly the memory is being freed & victim system is being disconnected from the command and control server (C2/C&C).

For basic dynamic analysis you can run SilentMoon Backdoor on VirusTotal or Any.Run or Intezer Sandbox.

Dynamic Analysis on VirusTotal.

For dynamic analysis, we are going set few breakpoints in the disassembly viewed in IDA view. Setting breakpoints at following locations:-

Note: Set some breakpoints in the disassembly of function in the starting just to confirm that our windows debugger had dropped in following function.

In start function :

:- GetStartupInfoA()

:- active_dir_ops_func()

In active_dir_ops_func() function:

:- GetProcessHeap()

:- ServiceMain()

:- StartServiceCtrlDispatcherW()

:- OpenSCManagerW()

:- OpenServiceW()

:- ChangeServiceConfig2W()

:- ChangeServiceConfigW()

:- StartServiceW()

In ServiceMain() function:

:- get_keycontainer_info()

:- reg_create_and_set_query_ops()

:- reg_create_and_set_query_ops() (at loc_40838B location)

:- C2_comm_and_fetch_payload_write_ops()

:- CreateThread()

:- TerminateThread()

:- CloseHandle()

In reg_create_and_set_query_ops function:

:- RegCreateKeyExW()

:- query_reg_ops()

:- RegCloseKey()

:- RegCreateKeyExW()

:- reg_create_query_ops()

:- RegSetValueExW()

In C2_comm_and_fetch_payload_write_ops function:

:- CreateNamedPipeW

:- CreateThread()

:- ConnectNamedPipe()

:- CloseHandle()

:- connect_C2_get_paylaod_write_ops_in_temp()

:- CreateThread()

:- CreateNamedPipeW()

:- ExitProcess()

In connect_C2_get_paylaod_write_ops_in_temp() function:

:- ReadFile()

:- crypto_and_key_ops()

:- CreateFileA()

:- WriteFile()

:- GetTempPathW()

:- GetTempFileNameW()

:- write_additional_payload_in_temp()

:- DisconnectNamedPipe()

:- CloseHandle()

Let’s fun begins, when we start debugging the SilentMoon in IDA it hits it’s first breakpoint at inside start function at GetStartupInfoA.

Dbg hitting at the breakpoint inside “start” function.

Then after running the debugger at the next breakpoint hitting is the active_dir_ops_func module which start the service ADSInternal.

Dbg hitting at the breakpoint “active_dir_ops_func” module while debugging in IDA.

Debugger now drops at the location inside active_dir_ops_fun module at location GetProcessHeap function( random bp) and soon after that our debugger hits at the ServiceMain module which is developed by Turla developers for creating service for communicating with command and control server (C2).

Dbg hitting at the breakpoint “ServiceMain” module while debugging in IDA.

After hitting some random breakpoints on following debugging further:

Debugger hitting at random set breakpoints set by us.

Debugger hits at the breakpoint where the “OpenSCManagerW” exists in active_dir_ops_func module which establishes a connection to the service control manager on the victim system.

Dbg hitting at the breakpoint “OpenSCManagerW module while debugging in IDA.

Then the debugger opens the service using OpenServiceW module which opens the service.

Dbg hitting at the breakpoint “OpenServiceW module while debugging in IDA.

Debugger hits at the ChangeServiceConfig2W & ChangeServiceConfigW functions where config for the service is being altered.

Dbg hitting at the breakpoint “ChangeServiceConfig2W module while debugging in IDA.
Dbg hitting at the breakpoint “ChangeServiceConfigW” module while debugging in IDA.

Now debugger hitting at the StartServiceW function to start service.

Dbg hitting at the breakpoint “StartServiceW” module while debugging in IDA.

Indicators of Compromise (IOCs) & Detection

Attack IDs

T1486: Data Encrypted for Impact

T1573: Encrypted Channel

T1560: Archive Collected Data

T1056: Input Capture

T1082: System Information Discovery

T1518.001: Security Software Discovery

T1027: Obfuscated Files or Information

T1055: Process Injection

T1543.003: Windows Service

T1569.002: Service Execution

T1059: Command and Scripting Interpreter

Mitre Attack Matrix

Mitre Att&ck Matrix from Joe Sandbox.

Sample from Report

MD5: 9233b0492ec15c34dd89dc448d4a2de6

SHA1: fe1c0a43fa1f379e4f9703ea040790fb7f2fee27

SHA-256: ec2ca1e96997e6146f9c148d3607e7a53607c21f31ff03894266d27cb29f082d

YARA Signature

/*
YARA Rule Set
Author: 0xthreatintel
Date: 2021–07–17
Identifier: Turla_SilentMoon
Reference: 0xthreatintel Blog https://0xthreatintel.medium.com/fc34b49fe726?source=friends_link&sk=f14964b7491d766d90810ce108d00917
*/

/* Rule Set — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — */

rule silentmoon_trojan {
meta:
description = “Turla_SilentMoon — file silentmoon_trojan.bin”
author = “0xthreatintel”
reference = “0xthreatintel Blog https://0xthreatintel.medium.com/fc34b49fe726?source=friends_link&sk=f14964b7491d766d90810ce108d00917"
date = “2021–07–17”
hash1 = “ec2ca1e96997e6146f9c148d3607e7a53607c21f31ff03894266d27cb29f082d”
strings:
$s1 = “NetworkService.exe” fullword ascii
$s2 = “c:\\laQhpE2NDgx.exe” fullword wide
$s3 = “ADSInternal.exe” fullword wide
$s4 = “\\\\.\\Global\\PIPE\\” fullword wide
$s5 = “ <requestedExecutionLevel level=\”asInvoker\” uiAccess=\”false\”></requestedExecutionLevel>” fullword ascii
$s6 = “ (www.memtest86.com). At the time of writing it is free (GPLd).” fullword ascii
$s7 = “ problem — without which I will be unable to investigate it.” fullword ascii
$s8 = “REMOTE:ERROR:%d” fullword ascii
$s9 = “REMOTE_NS:ERROR:%d” fullword ascii
$s10 = “ points in compression, you may have a flaky memory system.” fullword ascii
$s11 = “mddviphw.inf” fullword wide
$s12 = “adsintrpc” fullword wide
$s13 = “ bytes: mapping %d, “ fullword ascii
$s14 = “ pass %d: size is %d, grp uses are “ fullword ascii
$s15 = “ block %d: crc = 0x%08x, combined CRC = 0x%08x, size = %d” fullword ascii
$s16 = “ERROR:%d” fullword ascii
$s17 = “ power-on test, and may find failures that the BIOS doesn’t.” fullword ascii
$s18 = “ %d blocks, %d sorted, %d scanned” fullword ascii
$s19 = “?ServiceMain@@YAXKPAPA_W@Z” fullword ascii
$s20 = “ <trustInfo xmlns=\”urn:schemas-microsoft-com:asm.v3\”>” fullword ascii
condition:
uint16(0) == 0x5a4d and filesize < 200KB and
8 of them
}

Thanks for reading.

Honey. Malware Analyst. I write blogs related to threat intelligence , malware analysis, APTs , network intrusions and incident responding.