In April 2020, the systems of Portuguese multinational energy giant Energias de Portugal (EDP) were encrypted by RagnarLocker Ransomware . The operators of RagnarLocker demanded a ransom of 1580 Bitcoin ($10.9M) . Based on the ransom notes left on EDP’s systems (Figure 1) which directly mentioned the company, it’s clear that it was a targeted attack and the malware authors intended to infect EDP.
Figure 1: RagnarLocker Ransom note specifically mentioning EDP
In this blog post, we take a closer look at one of the samples used in the attack on EDP using a combination of static analysis and dynamic analysis through API monitoring .
One of the core capabilities of VMRay Analyzer is smart memory dumping of monitored processes. This makes unpacking and decryption of samples much easier while at the same time enhancing and accelerating static analysis with tools like IDA or Ghidra.
In this analysis, the smart memory dumps provide us with already decrypted strings/blacklists which are directly visible during static analysis. It also provides us with generated keys subsequently used as part of the encryption process.
View the VMRay Analyzer Report for RagnarLocker Ransomware
Before any malicious activity begins, the RagnarLocker checks the host’s locales and terminates if the locale is on the hardcoded list. From the list (Figure 2) we see that it’s covering the CIS countries with a few additions.
Figure 2: VMRay function log depicting the comparison of locales.
If it finds itself running on a machine not associated with this list it starts its malicious activity by creating a unique identifier for the host. To do it, the sample queries the computer name, user name, MachineGuid registry key, and the ProductName registry key. It concatenates the data together, encodes it and encodes each value individually. It is then printed into a buffer (Figure 3).
Figure 3: Algorithm to generate a unique id.
RagnarLocker first verifies whether it was started with a command-line argument. If that is not the case, the ransomware creates an event with the above mentioned unique ID (Figure 4). In case that the event already exists, for example, the ransomware has already infected the victim, the process is terminated without any further reinfection. The previously generated unique ID could potentially be used as a form of vaccination.
Figure 4: RagnarLocker uses the ID to create a unique event.
RagnarLocker makes sure to target as many drives and volumes as possible. Even disks marked as read-only or offline are not spared. It enumerates physical hard drives, opens a handle for reading and writing. If it’s successful it sets the disk device’s attributes by sending I/O control codes.
One of the control codes: IOCTL_DISK_SET_DISK_ATTRIBUTES takes a pointer to a buffer of type SET_DISK_ATTRIBUTES . A disk device can have its attributes changed by setting the Attributes member either to DISK_ATTRIBUTE_OFFLINE or DISK_ATTRIBUTE_READ_ONLY or a combination of the two. The AttributesMask member then specifies which attributes are to be changed (using the same flags as for the attributes).
RagnarLocker uses a combination DISK_ATTRIBUTE_OFFLINE and DISK_ATTRIBUTE_READ_ONLY masks to make sure it targets any offline and/or read-only disks it finds. By resetting the disk attributes for every disk device (i.e., making the Attributes member 0) it removes the offline and read-only flags (Figure 5). It will then be able to encrypt files on all disk devices it finds. Subsequently, it issues a IOCTL_DISK_UPDATE_PROPERTIES control code to synchronize the system view of each disk device it updated.
SET_DISK_ATTRIBUTES Structure
typedef struct _SET_DISK_ATTRIBUTES {
DWORD Version;
BOOLEAN Persist;
BYTE Reserved1[3];
DWORDLONG Attributes;
DWORDLONG AttributesMask;
DWORD Reserved2[4];
} SET_DISK_ATTRIBUTES, *PSET_DISK_ATTRIBUTES;
Figure 5: Sending IOCTL codes to reset disk attributes. The hex dump of the data sent
Afterward, RagnarLocker iterates over all volumes and retrieves the volume path names (i.e. drive letters and mounted folder paths). If there is no drive letter or mounted path associated with a volume it tries to mount this volume to the next available drive letter (Figure 6). This method is also used to make sure all volumes it finds can be targeted for encryption.
Figure 6: RagnarLocker verifying if all volumes are mounted.
Having verified that all available volumes are either mounted or have been mounted it generates symmetric encryption keys using the SHA512 algorithm (Figure 7) which are later used in the file encryption process. Steps it takes for key generation are as follows:
Generate a certain number X of bytes using the CryptGenRandom function.
Initialize SHA512 context.
Update SHA512 with 64 bytes of hardcoded data.
Update SHA512 with X bytes generated in step 1.
Finalize SHA512.
Figure 7: Key generation algorithm and key constant.
Following the key generation is the decryption of a list of blacklisted services and processes. The algorithm used for decryption is RC4 with a 64-byte key (Figure 8). After decrypting the lists, it iterates over all services, compares their names to its internal list (Figure 9). Then terminates them if a match is found and the service is currently running. To stop a running service and all dependent services it uses the ControlService function with the control code set to SERVICE_CONTROL_STOP .
Figure 8: RC4 key.
Figure 9: Look for blacklisted services.
List of services that RagnarLocker terminates:
Service List
sql
memtas
mepocs
sophos
veeam
backup
pulseway
logme
logmein
connectwise
splashtop
mysql
Dfs
In addition, all processes are enumerated and tested against the decrypted list. To achieve this, RagnarLocker loops over the list of processes, takes a snapshot of all processes each time and compares each process from the snapshot with one of the processes from the hardcoded list. If a match is found the process is terminated (Figure 10).
Figure 10: Function log showing process enumeration and comparison.
The following table includes a list of processes that the RagnarLocker is looking for:
Process List
sql
mysql
veeam
oracle
ocssd
dbsnmp
synctime
agntsvc
isqlplussvc
xfssvccon
mydesktopservice
ocautoupds
encsvc
firefox
tbirdconfig
mydesktopqos
ocomm
dbeng50
sqbcoreservice
excel
infopath
msaccess
mspub
onenote
outlook
powerpnt
steam
thebat
thunderbird
visio
winword
wordpad
EduLink2SIMS
bengine
benetns
beserver
pvlsvr
beremote
VxLockdownServer
postgres
fdhost
WSSADMIN
wsstracing
OWSTIMER
dfssvc.exe
dfsrs.exe
swc_service.exe
sophos
SAVAdminService
SavService.exe
Next, it makes sure to delete all shadow copies so that the files can’t be recovered. It first disables file system redirection then creates two new processes (wmic and vssadmin) which are responsible for the deletion of shadow copies (Figure 11) and re-enables the file system redirection.
Figure 11: Delete shadow copies.
At this point, RagnarLocker starts to decrypt its ransom note. In the beginning, it decrypts the threat actor’s public key (using RC4) which is wrapped in a CRT_PUBLIC_KEY_INFO structure. The algorithm identifier indicates it is an RSA key. It is later imported using the CryptImportPublicKeyInfo function. This key is used to encrypt the keys generated previously.
Next, it decrypts the content of the ransom note (using RC4), appends the public key which was converted to a string with CryptBinaryToStringA and writes it to a file (Figure 12). The file name is constructed from the string “RGNR_” concatenated with a value generated from the computer name.
Figure 12: RagnarLocker decrypts its ransom note and drops it to multiple directories.
The extensions used for encrypted files are generated using the same method as with the ransom note but instead of using “RGNR_” it uses “ragnar_” (Figure 13). To encrypt the files RagnarLocker starts from the last drive letter it can find and if it’s not a CD-ROM it starts encrypting. The encryption function iterates over all files in a given volume and compares them against a directory and file whitelist. If the current file/directory is on the whitelist it proceeds with the enumeration. If the file/directory is not on the list, the encryption function is recursively called on the new directory.
Figure 13: RagnarLocker encrypted file extension.
RagnarLocker also ignores certain files and extensions. Among the ignored files is also the previously dropped ransom note. A list of ignored directories, files and extensions can be seen in the table below:
Ignored Directories
Ignored Files
Ignored Extensions
“Windows”
“Windows.old”
“Tor browser”
“Internet Explorer”
“Google”
“Opera”
“Opera Software”
“Mozilla”
“Mozilla Firefox”
“$Recycle.Bin”
“ProgramData”
“All Users”
“autorun.inf”
“boot.ini”
“bootfont.bin”
“bootsect.bak”
“bootmgr”
“bootmgr.efi”
“bootmgfw.efi”
“desktop.ini”
“iconcache.db”
“ntldr”
“ntuser.dat”
“ntuser.dat.log”
“ntuser.ini”
“thumbs.db”
“.db”
“.sys”
“.dll”
“.lnk”
“.msi”
“.drv”
“.exe”
The encryption of the file also appends a file marker towards the end (Figure 14).
Figure 14: File marker appended to the end of an encrypted file.
The victim is given instructions for how to pay in the ransom note (Figure 15). They require to be contacted through their live chat and await further instructions.
It should be also noted that RagnarLocker is following the recent trend in ransomware by threatening to release a victim’s confidential information if the ransom is not paid. In the case of the attack on Energias de Portugal, the operators of RagnarLocker claimed to have stolen over 10 TB of sensitive company files and threatened to leak all the stolen data unless the ransom is paid.
Figure 15: Part of the RagnarLocker ransom note
IOCs
Sample:
c2bd70495630ed8279de0713a010e5e55f3da29323b59ef71401b12942ba52f6