Skip to main content
Splunk Lantern

Detecting DarkSide ransomware

DarkSide ransomware presents users on targeted machines with a customized URI that contains their leaked information. The payload leaves machines at a minimum level of operation, only enough to browse the attackers' websites to gather required information to make payment to the attackers.

You are an analyst responsible for your organization's overall security posture. You need to be able to detect and investigate unusual activities that might relate to DarkSide ransomware, and these searches help you to do that.

Required data

Endpoint data

How to use Splunk software for this use case

Searches using the endpoint data model

To run these searches, ensure that you should also ensure you are ingesting endpoint data that includes the name of the process responsible for the changes from your endpoints. Use this to populate the Endpoint data model in the Common Information Model (CIM). For information on installing and using the CIM, see the Common Information Model documentation. In addition, if you are using Sysmon, you must have at least version 6.0.4.

► Attempted credential dump from registry 

To run this search, your deployment needs to ingest endpoint data that tracks process activity, including parent-child relationships from your endpoints.

This search is designed to monitor for execution of reg.exe with parameters specifying an export of keys that contain hashed credentials that attackers might try to crack offline.

| tstats summariesonly=false allow_old_summaries=true count, min(_time) AS firstTime, max(_time) AS lastTime FROM datamodel=Endpoint.Processes WHERE (("Processes.process_name"=reg.exe OR "Processes.original_file_name"=reg.exe OR "Processes.process_name"=cmd.exe OR "Processes.original_file_name"=Cmd.Exe) "Processes.process"=*save* ("Processes.process"=*HKEY_LOCAL_MACHINE\\Security* OR "Processes.process"=*HKEY_LOCAL_MACHINE\\SAM* OR "Processes.process"=*HKEY_LOCAL_MACHINE\\System* OR "Processes.process"=*HKLM\\Security* OR "Processes.process"=*HKLM\\System* OR "Processes.process"=*HKLM\\SAM*)) BY "Processes.dest", "Processes.user", "Processes.parent_process", "Processes.process_name", "Processes.original_file_name", "Processes.process", "Processes.process_id", "Processes.parent_process_id" 
| rename "Processes.*" AS "*" 
| convert timeformat="%Y-%m-%dT%H:%M:%S" ctime(firstTime) 
| convert timeformat="%Y-%m-%dT%H:%M:%S" ctime(lastTime)
► BITSAdmin download file

This search identifies Microsoft Background Intelligent Transfer Service utility bitsadmin.exe using the transfer parameter to download a remote object.

In addition to running this search, you should also look for downloads or uploads on the command-line since the switches are not required to perform a transfer. Capture any files downloaded and review the reputation of the IP or domain used. Typically, after it is executed, a follow-on command is used to execute the dropped file. Network connection or file modification events related do not spawn or create from bitsadmin.exe, but the artifacts appear in a parallel process of svchost.exe with a command-line similar to svchost.exe -k netsvcs -s BITS.

It's important to review all parallel and child processes to capture any behaviors and artifacts. In some suspicious and malicious instances, BITS jobs are created. You can use bitsadmin /list /verbose to list out the jobs during investigation.

Limited false positives should occur from this search; However, you might need to filter based on parent process name or network connection.

| tstats summariesonly=false allow_old_summaries=true count, min(_time) AS firstTime, max(_time) AS lastTime FROM datamodel=Endpoint.Processes WHERE (("Processes.process_name"=bitsadmin.exe OR "Processes.original_file_name"=bitsadmin.exe) "Processes.process"=*transfer*) BY "Processes.dest", "Processes.user", "Processes.parent_process", "Processes.original_file_name", "Processes.process_name", "Processes.process", "Processes.process_id", "Processes.parent_process_id" 
| rename "Processes.*" AS "*" 
| convert timeformat="%Y-%m-%dT%H:%M:%S" ctime(firstTime) 
| convert timeformat="%Y-%m-%dT%H:%M:%S" ctime(lastTime)
► CertUtil download with URLCache and split arguments

Certutil.exe might download a file from a remote destination using -urlcache. This behavior requires a URL to be passed on the command-line. In addition, -f (force) and -split (split embedded ASN.1 elements, and save to files) are used. While certutil.exe can contact a public IP space, it is uncommon for certutil.exe to write files to world-writeable paths.

During triage, capture any files on disk and review them, and also review the reputation of the remote IP or domain in question. 

You should receive limited false positives from this search in most environments. You can tune as needed based on parent-child relationship or network connection.

| tstats summariesonly=false allow_old_summaries=true count, min(_time) AS firstTime, max(_time) AS lastTime FROM datamodel=Endpoint.Processes WHERE (("Processes.process_name"=certutil.exe OR "Processes.original_file_name"=CertUtil.exe) (("Processes.process"=*urlcache* "Processes.process"=*split*) OR "Processes.process"=*urlcache*)) BY "Processes.dest", "Processes.user", "Processes.parent_process", "Processes.process_name", "Processes.process", "Processes.process_id", "Processes.original_file_name", "Processes.parent_process_id" 
| rename "Processes.*" AS "*" 
| convert timeformat="%Y-%m-%dT%H:%M:%S" ctime(firstTime) 
| convert timeformat="%Y-%m-%dT%H:%M:%S" ctime(lastTime)
► CertUtil download with VerifyCtl and split arguments

Certutil.exe might download a file from a remote destination using -VerifyCtl. This behavior requires a URL to be passed on the command-line. In addition, -f (force) and -split (split embedded ASN.1 elements, and save to files) will be used. While certutil.exe can contact a public IP space, it is uncommon for certutil.exe to write files to world-writeable paths.

During triage, capture any files on disk and review. Review the reputation of the remote IP or domain in question. Using -VerifyCtl, the file is either written to the current working directory or %APPDATA%\..\LocalLow\Microsoft\CryptnetUrlCache\Content\<hash>.

You should receive limited false positives from this search in most environments. You can tune as needed based on parent-child relationship or network connection.

| tstats summariesonly=false allow_old_summaries=true count, min(_time) AS firstTime, max(_time) AS lastTime FROM datamodel=Endpoint.Processes WHERE (("Processes.process_name"=certutil.exe OR "Processes.original_file_name"=CertUtil.exe) (("Processes.process"=*verifyctl* "Processes.process"=*split*) OR "Processes.process"=*verifyctl*)) BY "Processes.dest", "Processes.user", "Processes.original_file_name", "Processes.parent_process", "Processes.process_name", "Processes.process", "Processes.process_id", "Processes.parent_process_id" 
| rename "Processes.*" AS "*" 
| convert timeformat="%Y-%m-%dT%H:%M:%S" ctime(firstTime) 
| convert timeformat="%Y-%m-%dT%H:%M:%S" ctime(lastTime)
► Detect PsExec with accepteula flag

To run this search, your deployment needs to ingest data that records process activity from your hosts.

This search looks for events where PsExec.exe is run with the accepteula flag in the command line.

PsExec is a built-in Windows utility that enables you to execute processes on other systems. It is fully interactive for console applications. This tool is widely used for launching interactive command prompts on remote systems, and threat actors use this extensively for executing code on compromised systems. If an attacker is running PsExec for the first time, they are prompted to accept the end-user license agreement (EULA), which can be passed as the argument accepteula within the command line.

False positives from this search might occur because administrators can use PsExec for accessing remote systems and might pass accepteula as an argument if they are running this tool for the first time. However, it is not likely that you will see multiple occurrences of this event on a machine.

| tstats summariesonly=false allow_old_summaries=true values("Processes.process") AS process, min(_time) AS firstTime, max(_time) AS lastTime FROM datamodel=Endpoint.Processes WHERE (("Processes.process_name"=psexec.exe OR "Processes.process_name"=psexec64.exe OR "Processes.original_file_name"=psexec.c) "Processes.process"=*accepteula*) BY "Processes.dest", "Processes.user", "Processes.parent_process_name", "Processes.process_name", "Processes.process", "Processes.process_id", "Processes.parent_process_id" 
| rename "Processes.*" AS "*" 
| convert timeformat="%Y-%m-%dT%H:%M:%S" ctime(firstTime) 
| convert timeformat="%Y-%m-%dT%H:%M:%S" ctime(lastTime)
► Detect RClone command line usage

This search identifies commonly used command-line arguments used by rclone.exe to initiate a file transfer.

At this stage of a ransomware event, exfiltration is about to occur or has already occurred. During triage, isolate the endpoint and continue investigating by reviewing file modifications and parallel processes.

False positives should be limited as this search is restricted to the Rclone process name. You can filter or tune the search as needed.

| tstats summariesonly=false allow_old_summaries=true count, min(_time) AS firstTime, max(_time) AS lastTime FROM datamodel=Endpoint.Processes WHERE (("Processes.original_file_name"=rclone.exe OR "Processes.process_name"=rclone.exe) ("Processes.process"="*copy*" OR "Processes.process"="*mega*" OR "Processes.process"="*pcloud*" OR "Processes.process"="*ftp*" OR "Processes.process"="*--config*" OR "Processes.process"="*--progress*" OR "Processes.process"="*--no-check-certificate*" OR "Processes.process"="*--ignore-existing*" OR "Processes.process"="*--auto-confirm*" OR "Processes.process"="*--transfers*" OR "Processes.process"="*--multi-thread-streams*")) BY "Processes.dest", "Processes.user", "Processes.parent_process", "Processes.process_name", "Processes.process", "Processes.process_id", "Processes.parent_process_id" 
| rename "Processes.*" AS "*" 
| convert timeformat="%Y-%m-%dT%H:%M:%S" ctime(firstTime) 
| convert timeformat="%Y-%m-%dT%H:%M:%S" ctime(lastTime)
► Detect renamed PSExec

This search identifies renamed instances of PsExec.exe being utilized on an endpoint.

During triage, validate this is the legitimate version of PsExec by reviewing the PE metadata. You should also review parallel processes for further suspicious behavior.

False positives from this search might occur since is possible some third party applications might use older versions of PsExec. You can filter or tune the search as needed.

| tstats summariesonly=false allow_old_summaries=true count, min(_time) AS firstTime, max(_time) AS lastTime FROM datamodel=Endpoint.Processes WHERE ("Processes.process_name"=psexec.exe OR "Processes.process_name"=psexec64.exe OR "Processes.original_file_name"=psexec.c) BY "Processes.dest", "Processes.user", "Processes.parent_process_name", "Processes.process_name", "Processes.process", "Processes.process_id", "Processes.parent_process_id", "Processes.original_file_name" 
| rename "Processes.*" AS "*" 
| convert timeformat="%Y-%m-%dT%H:%M:%S" ctime(firstTime) 
| convert timeformat="%Y-%m-%dT%H:%M:%S" ctime(lastTime)
► Detect renamed RClone

This search identifies the usage of a renamed rclone.exe used to exfiltrate data to a remote destination. RClone has been used by multiple ransomware groups to exfiltrate data. During triage, isolate the endpoint and begin to review parallel processes for additional behavior.

At this stage of a ransomware event, the adversary might have staged data to be exfiltrated.

False positives from this search should be limited as the search identifies renamed instances of rclone.exe, which rarely occurs in legitimate scenarios. You should filter as needed if there is a legitimate business use case.

| tstats summariesonly=false allow_old_summaries=true count, min(_time) AS firstTime, max(_time) AS lastTime FROM datamodel=Endpoint.Processes WHERE ("Processes.original_file_name"=rclone.exe "Processes.process_name"!=rclone.exe) BY "Processes.dest", "Processes.user", "Processes.parent_process_name", "Processes.process_name", "Processes.process", "Processes.process_id", "Processes.parent_process_id", "Processes.original_file_name" 
| rename "Processes.*" AS "*" 
| convert timeformat="%Y-%m-%dT%H:%M:%S" ctime(firstTime) 
| convert timeformat="%Y-%m-%dT%H:%M:%S" ctime(lastTime)
► Extraction of registry hives

This search identifies the use of reg.exe exporting Windows Registry hives containing credentials. Adversaries might use this technique to export registry hives for offline credential access attacks, which are usually executed from a untrusted process or script. Upon execution, a file is written to disk.

False positives from this search might occur because it is possible that some agent-based products generate false positives. You can filter or tune the search as needed.

| tstats summariesonly=false allow_old_summaries=true count, min(_time) AS firstTime, max(_time) AS lastTime FROM datamodel=Endpoint.Processes WHERE (("Processes.process_name"=reg.exe OR "Processes.original_file_name"=reg.exe) ("Processes.process"=*save* OR "Processes.process"=*export*) ("Processes.process"="*\sam *" OR "Processes.process"="*\system *" OR "Processes.process"="*\security *")) BY "Processes.dest", "Processes.user", "Processes.parent_process", "Processes.process_name", "Processes.process", "Processes.process_id", "Processes.parent_process_id" 
| rename "Processes.*" AS "*" 
| convert timeformat="%Y-%m-%dT%H:%M:%S" ctime(firstTime) 
| convert timeformat="%Y-%m-%dT%H:%M:%S" ctime(lastTime)
► SLUI RunAs elevated

This search identifies the Microsoft Software Licensing User Interface Tool, slui.exe, elevating access using the -verb RunAs function. This particular bypass utilizes a registry key/value. Identified by two sources, the registry keys are HKCU\Software\Classes\exefile\shell and HKCU\Software\Classes\launcher.Systemsettings\Shell\open\command. To simulate this behavior, multiple POCs are available.

Limited false positives should be present because this behavior is not commonly used by legitimate applications.

| tstats summariesonly=false allow_old_summaries=true count, min(_time) AS firstTime, max(_time) AS lastTime FROM datamodel=Endpoint.Processes WHERE ("Processes.process_name"=slui.exe "Processes.process"=*-verb* "Processes.process"=*runas*) BY "Processes.dest", "Processes.user", "Processes.parent_process", "Processes.process_name", "Processes.process", "Processes.process_id", "Processes.parent_process_id" 
| rename "Processes.*" AS "*" 
| convert timeformat="%Y-%m-%dT%H:%M:%S" ctime(firstTime) 
| convert timeformat="%Y-%m-%dT%H:%M:%S" ctime(lastTime)
► SLUI spawning a process

This search identifies the Microsoft Software Licensing User Interface Tool, slui.exe, spawning a child process. This behavior is associated with publicly known UAC bypass. Slui.exe is commonly associated with software updates and is most often spawned by svchost.exe. The slui.exe process should not have child processes, and any processes spawning from it run with elevated privileges.

During triage, review the child process and additional parallel processes. Identify any file modifications that might have lead to the bypass.

False positives from this search might occur since certain applications might spawn from slui.exe that are legitimate. Filter those out to ensure proper monitoring.

| tstats summariesonly=false allow_old_summaries=true count, min(_time) AS firstTime, max(_time) AS lastTime FROM datamodel=Endpoint.Processes WHERE "Processes.parent_process_name"=slui.exe BY "Processes.dest", "Processes.user", "Processes.parent_process", "Processes.process_name", "Processes.process", "Processes.process_id", "Processes.parent_process_id" 
| rename "Processes.*" AS "*" 
| convert timeformat="%Y-%m-%dT%H:%M:%S" ctime(firstTime) 
| convert timeformat="%Y-%m-%dT%H:%M:%S" ctime(lastTime)

Additional searches

Some commands, parameters, and field names in the searches below might need to be adjusted to match your environment. In addition, to optimize the searches shown below, you should specify an index and a time range when appropriate. In addition, if you are using Sysmon, you must have at least version 6.0.4.

 
► CMLUA or CMSTPLUA UAC bypass

This search detects a potential process using a COM object like CMLUA or CMSTPLUA to bypass UAC. This technique has been used by ransomware adversaries to gain administrative privileges to its running process.

| search (EventCode=7 NOT Image="*\\program files*" NOT Image="*\\windows\\*" NOT process_name="CMMGR32.exe" NOT process_name="CMSTP.exe" (ImageLoaded="*\\CMLUA.dll" OR ImageLoaded="*\\CMLUAUTIL.dll" OR ImageLoaded="*\\CMSTPLUA.dll") (source=Syslog:Linux-Sysmon/Operational OR source=XmlWinEventLog:Microsoft-Windows-Sysmon/Operational OR sourcetype=XmlWinEventLog:Microsoft-Windows-Sysmon/Operational)) 
| stats count min(_time) as firstTime max(_time) AS lastTime BY Image ImageLoaded process_name Computer EventCode Signed ProcessId 
| convert timeformat="%Y-%m-%dT%H:%M:%S" ctime(firstTime) 
| convert timeformat="%Y-%m-%dT%H:%M:%S" ctime(lastTime)
► Cobalt Strike named pipes

To successfully implement this search, your deployment needs to ingest logs with the process name and imageloaded executions from your endpoints. 

This search identifies the use of default or publicly known named pipes used with Cobalt Strike. A named pipe is a named, one-way or duplex pipe for communication between the pipe server and one or more pipe clients. Cobalt Strike uses named pipes in many ways and has default values used with the Artifact Kit and Malleable C2 Profiles.

Each EDR product presents named pipes differently. You can try taking the values and generating a search based on your product of choice.

Upon triage, review the process performing the named pipe. If it is explorer.exe, it is possible it was injected into by another process. Review recent parallel processes to identify suspicious patterns or behaviors. A parallel process might have a network connection, review and follow the connection back to identify any file modifications.

Adversaries use named pipes with Cobalt Strike to blend in. Because of this, some of the named pipes identified and added might cause false positives. Filter by process name or pipe name to reduce false positives.

| search ((EventID=17 OR EventID=18) (source=Syslog:Linux-Sysmon/Operational OR source=XmlWinEventLog:Microsoft-Windows-Sysmon/Operational OR sourcetype=XmlWinEventLog:Microsoft-Windows-Sysmon/Operational) (PipeName=\\DserNamePipe* OR PipeName=\\MSSE-* OR PipeName=\\UIA_PIPE* OR PipeName=\\mojo.* OR PipeName=\\msagent_* OR PipeName=\\ntsvcs* OR PipeName=\\postex_* OR PipeName=\\spoolss_* OR PipeName=\\srvsvc_* OR PipeName=\\status_* OR PipeName=\\win_svc* OR PipeName=\\winsock* OR PipeName=\\wkssvc*)) 
| stats count min(_time) AS firstTime max(_time) AS lastTime BY Computer, process_name, process_id process_path, PipeName 
| rename Computer AS dest 
| convert timeformat="%Y-%m-%dT%H:%M:%S" ctime(firstTime) 
| convert timeformat="%Y-%m-%dT%H:%M:%S" ctime(lastTime)
► Delete ShadowCopy with PowerShell 

To successfully implement this search, your deployment needs to ingest PowerShell logs from your endpoints.

This search is designed to detect a PowerShell command to delete a shadow copy using the WMIC PowerShell module. This technique is used to deploy DarkSide Ransomware, where it executes a child process of PowerShell to execute a hex encoded command to delete shadow copy. This hex encoded command can then be decrypted by PowerShell log.

| search (EventCode=4104 Message="*ShadowCopy*" (Message="*Delete*" OR Message="*Remove*") (source=WinEventLog:Microsoft-Windows-PowerShell/Operational OR source="XmlWinEventLog:Microsoft-Windows-PowerShell/Operational")) 
| stats count min(_time) AS firstTime max(_time) AS lastTime BY EventCode Message ComputerName User 
| convert timeformat="%Y-%m-%dT%H:%M:%S" ctime(firstTime) 
| convert timeformat="%Y-%m-%dT%H:%M:%S" ctime(lastTime)
► Bulk creation of ransomware notes
  • If you are using Sysmon to run this search, you need a Splunk Universal Forwarder on each endpoint from which you want to collect data.
  • Need more help with this search? Click here.

This search looks for instances where a large number of ransomware notes are files created in the infected machine. These notes often have file extensions of .txt, .html or .hta.

| search (EventCode=11 (source=XmlWinEventLog:Microsoft-Windows-Sysmon/Operational OR sourcetype=XmlWinEventLog:Microsoft-Windows-Sysmon/Operational) (file_name="*\.hta" OR file_name="*\.html" OR file_name="*\.txt"))
| stats min(_time) AS firstTime max(_time) AS lastTime dc(TargetFilename) AS unique_readme_path_count values(TargetFilename) AS list_of_readme_path BY Computer Image file_name
| where (unique_readme_path_count >= 50)
| convert timeformat="%Y-%m-%dT%H:%M:%S" ctime(firstTime)
| convert timeformat="%Y-%m-%dT%H:%M:%S" ctime(lastTime)
► Windows possible credential dumping

To successfully implement this search, your deployment needs to ingest logs with the process name, parent process, and command-line executions from your endpoints. 

This search identifies common GrantedAccess permission requests and CallTrace DLLs which you can use to detect credential dumping.

False positives from this search might occur based on GrantedAccess 0x1010 and 0x1400. You should filter based on source image as needed or remove them. Cobalt Strike usage of Mimikatz generates 0x1010 initially, but will later be caught.

| search (EventCode=10 TargetImage=*lsass.exe (CallTrace="*dbgcore.dll*" OR CallTrace="*dbghelp.dll*" OR CallTrace="*ntdll.dll*") (source=Syslog:Linux-Sysmon/Operational OR source=XmlWinEventLog:Microsoft-Windows-Sysmon/Operational OR sourcetype=XmlWinEventLog:Microsoft-Windows-Sysmon/Operational) (GrantedAccess="0x01000" OR GrantedAccess="0x1000" OR GrantedAccess="0x1010" OR GrantedAccess="0x1038" OR GrantedAccess="0x1400" OR GrantedAccess="0x1410" OR GrantedAccess="0x1438" OR GrantedAccess="0x143a" OR GrantedAccess="0x1fffff" OR GrantedAccess="0x40")) 
| stats count min(_time) AS firstTime max(_time) AS lastTime BY Computer, TargetImage, GrantedAccess, SourceImage, SourceProcessId, SourceUser, TargetUser 
| rename Computer AS dest 
| convert timeformat="%Y-%m-%dT%H:%M:%S" ctime(firstTime) 
| convert timeformat="%Y-%m-%dT%H:%M:%S" ctime(lastTime)

Next steps

The content in this article comes from Splunk Enterprise Security (ES). As a Splunk premium security solution, ES solves a wide range of security analytics and operations use cases including continuous security monitoring, advanced threat detection, compliance, incident investigation, forensics and incident response. Splunk ES delivers an end-to-end view of an organization's security posture with flexible investigations, unmatched performance, and the most flexible deployment options offered in the cloud, on-premises, or hybrid deployment models. If you have questions about this use case, see the Security Research team's support options on GitHub.

In addition, these Splunk resources might help you understand and implement this use case:Use case: Detecting ransomware attacks

Still need help with this use case? Most customers have OnDemand Services per their license support plan. Engage the ODS team at OnDemand-Inquires@splunk.com if you require assistance.