Ryuk in 5 Hours
Intro
The Ryuk threat actors went from a phishing email to domain wide ransomware in 5 hours. They escalated privileges using Zerologon (CVE-2020-1472), less than 2 hours after the initial phish. They used tools such as Cobalt Strike, AdFind, WMI, and PowerShell to accomplish their objective.
Ryuk has been one of the most proficient ransomware gangs in the past few years, with the FBI claiming $61 million USD having been paid to the group as of February 2020. Earlier in the year, the group grew a little quiet, but that seems to have changed in the past few weeks, with incidents like what occurred at UHS hospitals.
Case Summary
In our previous Ryuk case, we saw the threat actors leverage access to an environment via the Bazar Loader malware. This time around, we saw them accomplish their objective faster, but the general tactics and techniques stayed similar between incidents.
Bazar was introduced to the environment again with the delivery via phishing emails. For an in depth breakdown on this loader, see this analysis by Roman Marshanski & Vitali Kremez. Bazar, once running, was seen again injecting into explorer.exe, svchost.exe, and spawning command shell processes.
From this loader we saw initial mapping of the domain, using built-in windows utilities such as Nltest. However, unlike the last case, the threat actors started at a lower privileged user and rather than proceed slowly or cautiously, they exploited the recently disclosed Zerologon vulnerability (CVE-2020-1472) to reset the machine password of the primary domain controller.
Lateral movement was initiated via SMB file transfers and WMI executions of Cobalt Strike Beacons. The network indicators align similarly to the prior campaign and were noted by Kyle Ehmke in response to our last post pivoting off the prior report’s intel. From memory analysis, we were also able to conclude the actors were using a trial version of Cobalt Strike with the EICAR string present in the network configuration for the beacon. Both portable executable and DLL beacons were used.
After moving laterally to the secondary domain controller, the threat actor started on more domain discovery via Net and the PowerShell Active Directory module. From there, the threat actors appeared to use the default named pipe privilege escalation module on the server. At this point, the threat actors used RDP to connect from the secondary domain controller, to the first domain controller, using the built in Administrator account.
Once on the main domain controller, another Cobalt Strike beacon was dropped and executed. Then more domain reconnaissance was performed using AdFind. Once this completed, at the four hour mark, the threat actors were ready for their final objective.
Four hours and 10 minutes in, the threat actors used the pivot from the primary domain controller to RDP into the Backup server. Backup servers were again targeted first for deployment of the ransomware executable, followed by servers and then workstations.The threat actors finished their objective by executing the ransomware on the primary domain controller, and at the 5 hour mark, the attack completed.
While last time we commented on the lead time between the first and second day to aid detection and response activity, this case goes to show that you can’t count on that kind of timescale. You need to be ready to act in less than an hour, to make sure you can effectively disrupt the threat actor.
Timeline
MITRE ATT&CK
Initial Access
Access was initiated by a phishing email leading to the Bazar Loader malware executable.
Execution
Bazar relies on user execution of an executable to run. This user was a Domain User and did not have any other permissions.
Privilege Escalation
CVE-2020-1472 was used to reset the credentials on one of the domain controllers in the environment. After resetting the password, the threat actors then targeted a different domain controller, potentially due to breaking services by use of their exploit.
Packet showing the zeroed out password.
On one of the domain controllers we saw use of the Cobalt Strike named pipe escalation.
C:\Windows\system32\cmd.exe /c echo 92d8cc45954 >; \\.\pipe\446b3c
Defense Evasion
On the first domain controller that the treat actors connected to after their initial connection, they dropped a DLL and executed it via rundll32.
C:\Windows\system32\cmd.exe /C rundll32 C:\Windows\system32\SQL.dll, StartW
Dropped via RDP and executed via rundll32 on the second domain controller.
rundll32 C:\PerfLogs\arti64.dll, rundll
Shortly after, the DLL was called again via regsrv32.
regsvr32 C:\PerfLogs\arti64.dll
Then a 2nd DLL was dropped and executed in a similar manner on the 2nd DC.
rundll32 C:\\PerfLogs\\socks64.dll, rundll
Discovery
Ran on the beachhead.
nltest /domain_trusts /all_trusts nltest /dclist:DOMAIN net group "Domain admins" /DOMAIN
Ran on a domain controller.
net group "enterprise admins" /domain nltest /domain_trusts /all_trusts nltest /dclist:"DOMAIN" ping DOMAINCONTROLLER cmd.exe /C time net user administrator /domain
Then they imported the PowerShell Active Directory module.
They then ran the following looking for host names, operating systems and last logon dates of all AD systems.
C:\Windows\system32\cmd.exe /C Get-ADComputer -Filter {enabled -eq $true} -properties *|select Name, DNSHostName, OperatingSystem, LastLogonDate | Export-CSV C:\Users\AllWindows.csv -NoTypeInformation -Encoding UTF8
After already completing the above discovery work and having already pivoted to their 2nd domain controller, the threat actors moved on to AdFind for further domain reconnaissance.
C:\Windows\Temp\adf\AdFind.exe C:\Windows\Temp\adf\adf.bat
adfind.exe -f "(objectcategory=person)" adfind.exe -f "objectcategory=computer" adfind.exe -f "(objectcategory=organizationalUnit)" adfind.exe -sc trustdmp adfind.exe -subnets -f (objectCategory=subnet) adfind.exe -f "(objectcategory=group)" adfind.exe -gcb -sc trustdmp
nltest /domain_trusts /all_trusts
Lateral Movement
The first lateral movement occurred to the domain controller not affected by the use of CVE-2020-1472. An executable was transferred to it via SMB using a domain administrator account.
After transferring the exe, the threat actors utilized WMI from the beachhead host to execute the file.
C:\Windows\system32\cmd.exe /C WMIC/node:"DC.DOMAIN.local" process call create "cmd /c C:\PerfLogs\servisess.exe\"
The presence of the EICAR strings point to the Cobalt Strike software being used as a trial version.
They accessed the GPO’s for the domain but none were modified or added.
mmc.exe" "C:\Windows\System32\gpedit.msc"
Shortly there after we saw a Cobalt Strike DLL transferred via the RDP connection.
RDP was used to pivot from the main domain controller and distribute the final ransomware payload enterprise wide.
Command and Control
After our previous report, @kyleehmke pivoted off of our prior Ryuk report and used the network data to link several of these domains which we saw in this case.
Bazar:
Report_Print.exe
3.137.182.114:443
cstr3.com
Cobalt Strike:
servisses.exe
Impact
Starting around 4.5 hours after the initial Bazar malware was executed, the Ryuk threat actors acted on their final objectives and initiated RDP connections from the domain controller previously exploited, to the rest of the environment. This time they initiated the ransomware first on the secondary domain controller (their 1st pivot) and transferred the Ryuk executable over the RDP connection.
Enjoy our report? Please consider donating $1 or more to the project using Patreon. Thank you for your support!
We also have pcaps, files, memory images, Kape and Redline packages available here.
IOCs
https://misppriv.circl.lu/events/view/80223 & https://otx.alienvault.com/pulse/5f8cce76f5614d9b220181b6
Network
3.137.182.114:443 cstr3.com 88.119.171.94:443 havemosts.com 5.2.64.174:443 quwasd.com
File
servisses.exe d971827d974effedaeaf7d62b619b1dd c3a846eb04e2fe765e56fa15a0d5c1eb650ccba3 1d8b7faf5f290465cc742e07abca78fac419135b191071cc77912263cd1dde1d socks64.dll 890206f0c506366d480e02fc9fed988a ba1542d9b55fff21bda9495ed884404b0436cff2 feb8c2bcb71da02dbbeecb999869e053cf96af8cce6f9705cadca4338133d3b5 SQL.dll 3785d87f6995b4b95d9b55f8d2556237 9b44a8f0bb2d65fb19e7ca7bbd85b36c176f3d60 d67461ba45a4edf3b2a69b3e64303fda8130bd1fc7a1173f35c1fe67b40c9639 arti64.dll 3785d87f6995b4b95d9b55f8d2556237 9b44a8f0bb2d65fb19e7ca7bbd85b36c176f3d60 d67461ba45a4edf3b2a69b3e64303fda8130bd1fc7a1173f35c1fe67b40c9639 xxx.exe 5b8b66ddbbf1fd67211e9a4bf78c1700 cdb042dd8e9dc17f677c991b386f4cd242f2628d ccde47a0d315dcd4740fccfe8e8110fbb1fd85bb305734fec409f52051790c98
Detections
Network
GPL NETBIOS SMB-DS IPC$ share access ET POLICY SMB2 NT Create AndX Request For a DLL File - Possible Lateral Movement ET POLICY SMB2 NT Create AndX Request For an Executable File
Sigma
https://github.com/Neo23x0/sigma/blob/master/rules/windows/malware/win_mal_ryuk.yml
https://github.com/Neo23x0/sigma/blob/master/rules/windows/process_creation/win_trust_discovery.yml
Detects AdFind usage from a past case:
title: AdFind Recon description: Threat Actor using AdFind for reconnaissance. author: The DFIR Report date: 2019/8/2 references: - https://thedfirreport.com/2020/08/03/dridex-from-word-to-domain-dominance/ tags: - attack.remote_system_discovery - attack.T1018 logsource: category: process_creation product: windows detection: selection_1: CommandLine|contains: - adfind -f objectcategory=computer selection_2: CommandLine|contains: - adfind -gcb -sc trustdmp condition: selection_1 or selection_2 falsepositives: - Legitimate Administrator using tool for Active Directory querying level: medium status: experimental
Yara
/* YARA Rule Set Author: The DFIR Report Date: 2020-10-13 Identifier: Case 1006 Ryuk Reference: https://thedfirreport.com */ /* Rule Set ----------------------------------------------------------------- */ import "pe" rule ryuk_1006_servisses_procdump { meta: description = "files - file servisses-procdump.exe" author = "The DFIR Report" reference = "https://thedfirreport.com" date = "2020-10-13" hash1 = "387894a0b404c67e722799308b12ff2be31d2e8ce798aa53d971f0c13805d54d" strings: $s1 = "c:/crossdev/src/winpthreads-svn6233/src/mutex.c" fullword ascii $s2 = "mutex_global_shmem" fullword ascii $s3 = "mutex_global_static_shmem" fullword ascii $s4 = "_pthread_key_dest_shmem" fullword ascii $s5 = "_pthread_key_sch_shmem" fullword ascii $s6 = "_pthread_key_max_shmem" fullword ascii $s7 = "_pthread_key_lock_shmem" fullword ascii $s8 = "cannot find name of executable" fullword ascii $s9 = "tiles32.png" fullword ascii $s10 = "GetModuleFileName: %s" fullword ascii $s11 = "IP_DEST_HOST_UNREACHABLE (11003)" fullword ascii $s12 = "This program requires Windows NT!" fullword ascii $s13 = "SNMP INVALID_SESSION" fullword ascii $s14 = "SNMP TRAP_ERRORS" fullword ascii $s15 = "SNMP SELECT_FDERRORS" fullword ascii $s16 = "Some different radices: %d %x %o %#x %#o " fullword ascii $s17 = "c:/crossdev/src/winpthreads-svn6233/src/rwlock.c" fullword ascii $s18 = "_pthread_tls_shmem" fullword ascii $s19 = "IP_DEST_PORT_UNREACHABLE (11005)" fullword ascii $s20 = "pthr_root_shmem" fullword ascii condition: uint16(0) == 0x5a4d and filesize < 2000KB and ( pe.imphash() == "a90d500745a1ce2417c01fecefbc2851" or 8 of them ) } rule ryuk_1006_files_socks64 { meta: description = "files - file socks64.dll" author = "The DFIR Report" reference = "https://thedfirreport.com" date = "2020-10-13" hash1 = "feb8c2bcb71da02dbbeecb999869e053cf96af8cce6f9705cadca4338133d3b5" strings: $x1 = "C:\\Users\\Izidu\\Desktop\\2019\\WindowsSDK7-Samples-master\\WindowsSDK7-Samples-master\\winui\\pictures\\acquisitionplugin\\x64" ascii $s2 = "C:\\Users\\Izidu\\Desktop\\2019\\WindowsSDK7-Samples-master\\WindowsSDK7-Samples-master\\winui\\pictures\\acquisitionplugin\\x64" ascii $s3 = "PluginSample.dll" fullword ascii $s4 = "AppPolicyGetProcessTerminationMethod" fullword ascii $s5 = "luginSample.pdb" fullword ascii $s6 = "rundll" fullword ascii $s7 = "AcquireSamplePlugin::DisplayConfigureDialog" fullword wide $s8 = "AppPolicyGetThreadInitializationType" fullword ascii $s9 = "`template-parameter-" fullword ascii $s10 = "operator<=>" fullword ascii $s11 = "operator co_await" fullword ascii $s12 = "AppPolicyGetWindowingModel" fullword ascii $s13 = "Transfer Completed Successfully!" fullword wide $s14 = "AppPolicyGetShowDeveloperDiagnostic" fullword ascii $s15 = "noexcept" fullword ascii $s16 = "Read-Only Photo Acquire Plugin" fullword wide $s17 = "api-ms-win-appmodel-runtime-l1-1-2" fullword wide $s18 = "Software\\Microsoft\\Windows\\CurrentVersion\\Photo Acquisition\\Plugins\\%ws" fullword wide $s19 = ".?AUIUserInputString@@" fullword ascii $s20 = "g0DVNrB\"Rtf#" fullword ascii condition: uint16(0) == 0x5a4d and filesize < 2000KB and ( pe.imphash() == "0fd22f187f22ab4ec2eb55f91ccefa7a" and ( pe.exports("SGeruIUrgVdfMaxMccIKRh") and pe.exports("rundll") ) or ( 1 of ($x*) and 4 of them ) ) } rule ryuk_1006_Report_Print { meta: description = "files - file Report_Print.exe" author = "The DFIR Report" reference = "https://thedfirreport.com" date = "2020-10-13" hash1 = "23ac461f9b5128841cafabb4282432252ea7b57874595cf6fe8457fc1ac65007" strings: $s1 = "kErNel32.Dll" fullword wide $s2 = "DOOKOL.exe" fullword ascii $s3 = "c:/crossdev/src/winpthreads-svn6233/src/mutex.c" fullword ascii $s4 = "hmutex" fullword ascii $s5 = "._FindPESectionExec" fullword ascii $s6 = "mutex_global_shmem" fullword ascii $s7 = "processthreadsapi.h" fullword ascii $s8 = "mutex_global_static_shmem" fullword ascii $s9 = "TargetIp" fullword ascii $s10 = "c:\\crossdev\\gccmaster\\build-tdm64\\gcc\\x86_64-w64-mingw32\\libgcc" fullword ascii $s11 = "h:\\crossdev\\gccmaster\\build-tdm64\\runtime\\mingw-w64-crt" fullword ascii $s12 = "J__mingw_winmain_lpCmdLine" fullword ascii $s13 = "GNU C 4.8.1 -mtune=generic -march=x86-64 -g -O2 -O2 -O2 -fbuilding-libgcc -fno-stack-protector" fullword ascii $s14 = "GNU C 4.8.1 -mtune=generic -march=x86-64 -g -O2 -O2 -O2 -fbuilding-libgcc -fno-stack-protector -fno-exceptions" fullword ascii $s15 = "GNU C 4.8.1 -m64 -mtune=generic -march=x86-64 -g -O2 -std=gnu99" fullword ascii $s16 = "GNU C 4.8.1 -mtune=generic -march=x86-64 -g -O2 -O2 -O2 -fbuilding-libgcc -fno-stack-protector -fexceptions" fullword ascii $s17 = "9lpszCommandLine" fullword ascii $s18 = "=__mingw_GetSectionForAddress" fullword ascii $s19 = "__mingw_winmain_lpCmdLine" fullword ascii $s20 = "%Target" fullword ascii condition: uint16(0) == 0x5a4d and filesize < 3000KB and ( pe.imphash() == "8f0088451a1156246379abc67514cacf" and pe.exports("CSBhvSWCvFRvfCfAoJdoFuAUmK") or 8 of them ) } rule ryuk_1006_files_xxx { meta: description = "files - file xxx.exe" author = "The DFIR Report" reference = "https://thedfirreport.com" date = "2020-10-13" hash1 = "ccde47a0d315dcd4740fccfe8e8110fbb1fd85bb305734fec409f52051790c98" strings: $s1 = "DOOKOL.exe" fullword ascii $s2 = "c:/crossdev/src/winpthreads-svn6233/src/mutex.c" fullword ascii $s3 = "hmutex" fullword ascii $s4 = "mutex_global_shmem" fullword ascii $s5 = "processthreadsapi.h" fullword ascii $s6 = "mutex_global_static_shmem" fullword ascii $s7 = "fake_get_output_format" fullword ascii $s8 = "&rvaTarget" fullword ascii $s9 = "h:\\crossdev\\gccmaster\\build-tdm64\\runtime\\mingw-w64-crt" fullword ascii $s10 = "c:\\crossdev\\gccmaster\\build-tdm64\\gcc\\x86_64-w64-mingw32\\32\\libgcc" fullword ascii $s11 = "E__mingw_winmain_lpCmdLine" fullword ascii $s12 = "GNU C 4.8.1 -m32 -mtune=generic -march=x86-64 -g -O2 -O2 -O2 -fbuilding-libgcc -fno-stack-protector" fullword ascii $s13 = "GNU C 4.8.1 -m32 -mtune=generic -march=x86-64 -g -O2 -O2 -O2 -fbuilding-libgcc -fno-stack-protector -fno-exceptions" fullword ascii $s14 = "GNU C 4.8.1 -m32 -mtune=generic -march=x86-64 -g -O2 -O2 -O2 -fbuilding-libgcc -fno-stack-protector -fexceptions" fullword ascii $s15 = "GNU C 4.8.1 -m32 -mtune=generic -march=x86-64 -g -O2 -std=gnu99" fullword ascii $s16 = "__mingw_winmain_lpCmdLine" fullword ascii $s17 = "Npthread_getspecific" fullword ascii $s18 = "__gthread_getspecific" fullword ascii $s19 = "=__mingw_GetSectionForAddress" fullword ascii $s20 = "4lpszCommandLine" fullword ascii condition: uint16(0) == 0x5a4d and filesize < 2000KB and ( pe.imphash() == "00f3261b5b33a9b1e8b6003f4056a885" and pe.exports("CSBhvSWCvFRvfCfAoJdoFuAUmK") or 8 of them ) } rule ryuk_1006_servisses { meta: description = "files - file servisses.exe" author = "The DFIR Report" reference = "https://thedfirreport.com" date = "2020-10-13" hash1 = "1d8b7faf5f290465cc742e07abca78fac419135b191071cc77912263cd1dde1d" strings: $s1 = "DOOKOL.exe" fullword ascii $s2 = "c:/crossdev/src/winpthreads-svn6233/src/mutex.c" fullword ascii $s3 = "mutex_global_shmem" fullword ascii $s4 = "mutex_global_static_shmem" fullword ascii $s5 = "_pthread_key_dest_shmem" fullword ascii $s6 = "_pthread_key_max_shmem" fullword ascii $s7 = "_pthread_key_sch_shmem" fullword ascii $s8 = "_pthread_key_lock_shmem" fullword ascii $s9 = "cannot find name of executable" fullword ascii $s10 = "tiles32.png" fullword ascii $s11 = "GetModuleFileName: %s" fullword ascii $s12 = "IP_DEST_HOST_UNREACHABLE (11003)" fullword ascii $s13 = "This program requires Windows NT!" fullword ascii $s14 = "SNMP INVALID_SESSION" fullword ascii $s15 = "SNMP TRAP_ERRORS" fullword ascii $s16 = "SNMP SELECT_FDERRORS" fullword ascii $s17 = "Some different radices: %d %x %o %#x %#o " fullword ascii $s18 = "c:/crossdev/src/winpthreads-svn6233/src/rwlock.c" fullword ascii $s19 = "_pthread_tls_shmem" fullword ascii $s20 = "IP_DEST_PORT_UNREACHABLE (11005)" fullword ascii condition: uint16(0) == 0x5a4d and filesize < 2000KB and ( pe.imphash() == "a90d500745a1ce2417c01fecefbc2851" and pe.exports("KADWEGAFSTWUATQFFFFkxcEEF") or 8 of them ) } rule ryuk_1006_files_SQL { meta: description = "files - file SQL.dll" author = "The DFIR Report" reference = "https://thedfirreport.com" date = "2020-10-13" hash1 = "d67461ba45a4edf3b2a69b3e64303fda8130bd1fc7a1173f35c1fe67b40c9639" strings: $s1 = ".data$_ZN12_GLOBAL__N_110fake_mutexE" fullword ascii $s2 = ".data$_ZZN12_GLOBAL__N_116get_static_mutexEvE4once" fullword ascii $s3 = "DOOKOL.dll" fullword ascii $s4 = "_ZN12_GLOBAL__N_110fake_mutexE" fullword ascii $s5 = "_ZZN12_GLOBAL__N_116get_static_mutexEvE4once" fullword ascii $s6 = ".data$_ZN12_GLOBAL__N_115emergency_mutexE" fullword ascii $s7 = ".data$_ZN12_GLOBAL__N_1L12static_mutexE" fullword ascii $s8 = "__shmem_winpthreads_grabber_mutex_global_shmem" fullword ascii $s9 = "__shmem_winpthreads_init_mutex_global_shmem" fullword ascii $s10 = "__shmem_winpthreads_ptr_mutex_global_shmem" fullword ascii $s11 = "c:/crossdev/src/winpthreads-svn6233/src/mutex.c" fullword ascii $s12 = "pthread_mutex_lock_intern" fullword ascii $s13 = "__shmem_winpthreads_init_mutex_global_static_shmem" fullword ascii $s14 = "__shmem_winpthreads_grabber_mutex_global_static_shmem" fullword ascii $s15 = "__shmem_winpthreads_ptr_mutex_global_static_shmem" fullword ascii $s16 = "_Z7ExecutePv" fullword ascii $s17 = "hmutex" fullword ascii $s18 = "._FindPESectionExec" fullword ascii $s19 = "_ZN9__gnu_cxx17__recursive_mutex6unlockEv" fullword ascii $s20 = ".text$_ZN9__gnu_cxx17__recursive_mutex6unlockEv" fullword ascii condition: uint16(0) == 0x5a4d and filesize < 2000KB and ( pe.imphash() == "d16819dafefb97404d0d0e42adb82e5c" and ( pe.exports("CSBhvSWCvFRvfCfAoJdoFuAUmK") and pe.exports("StartW") ) or 8 of them ) }
If you have detections you would like to add to this section, please contact us and we will credit you.
MITRE
(internal case 1006)