Author: Anandeshwar Unnikrishnan
Co-author: Aastha Mittal
Category:
Malware Intelligence |
Type/Family:
Ransomware |
Industry:
Multiple |
Region:
Global |
---|
What is BlueSky Ransomware?
BlueSky Ransomware is a modern malware using advanced techniques to evade security defences. It predominantly targets Windows hosts and utilizes the Windows multithreading model for fast encryption. It first emerged in late June 2022 and has been observed to spread via phishing emails, phishing websites, and trojanized downloads.
This deep-dive analysis of BlueSky Ransomware covers the following technical aspects:
- Procedure for privilege escalation
- Persistence
- Encryption mechanism
- Evasion techniques
Initial Phase
- The modules required for the ransomware are dynamically loaded and addresses of interesting functions are stored in an array for later use.
- The addresses of the following list of APIs are resolved:
APIs Stored | |||||
---|---|---|---|---|---|
ntdll.RtlAllocateHeap | kernel32.CreateFileW | kernel32.SetFilePointer | kernel32.CloseHandle | kernel32.lstCmpW | advapi32.CryptGenRandom |
ntdll.FreeHeap | kernel32.FindClose | kernel32.GetFileSizeEx | kernel32.SetFileAttributesW | kernel32.OpenProcess | shlwapi.PathCombineW |
kernel32.FindFirstFileExW | kernel32.ReadFile | kernel32.GetQueuedCompletionStatus | kernel32.MoveFileWithProgress | kernel32.TerminateProcess | shlwapi.PathRemoveExtensionW |
kernel32.FindNextFileW | kernel32.WriteFile | kernel32.PostQueuedCompletionStatus | kernel32.lstrCatW | kernel32.WaitForSingleObject |
- After loading the required libraries, the ransomware proceeds to perform the following tasks:
- Checks that the running process is 32 bit via kernel32.IsWow64Process
- Decrypts strings
- Adjust the privilege of the process to SE_DEBUG via ntdll.RtlAdjustPrivilege
- Retrieves the following:
- MachineGUID from SOFTWARE\\Microsoft\\Cryptography
- DigitalProductID and InstallDate from SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion
- Hides the main thread from debugger by calling ntdll.ZwSetInformationThread by passing ThreadHideFromDebugger (0x11) as ThreadInformationClass
- The ransomware updates the status as “Completed” after the initial phase and the user data is locked.
Mutex Generation
The ransomware creates a global mutex by calling kernel32.CreateMutexA API.
String Decoding
The ransomware decodes all the strings at runtime. Listed below are various extensions avoided while locking, user data extensions locked, and directory names for file enumeration.
Blacklisted Extensions
The ransomware leaves the files with the following blacklisted extensions from locking.
Blacklisted Extensions | |||||||
---|---|---|---|---|---|---|---|
“ldf” | “icl” | “bin” | “spl” | “diagcab” | “ini” | “theme” | “hta” |
“scr” | “386” | “hlp” | “ps1” | “ico” | “icns” | “rtp” | “diagpkg” |
“icl” | “cmd” | “shs” | “msu” | “lock” | “prf” | “msc” | “rtp” |
“386” | “ani” | “drv” | “ics” | “ocx” | “dll” | “sys” | “msstyles” |
“cmd” | “adv” | “wpx” | “key” | “mpa” | “bluesky” | “mod” | “cab” |
“ani” | “theme” | “bat” | “msp” | “cur” | “nomedia” | “msi” | “nls” |
“adv” | “msi” | “rom” | “com” | “cpl” | “idx” | “diagcfg” | “exe” |
“lnk” |
User Data Extensions
The files with the following user data extensions are specifically targeted.
User Data Extensions | ||||||
---|---|---|---|---|---|---|
“ckp” | “dbs” | “mrg” | “qry” | “wdb” | “sqlite3” | “dbc” |
“dwg” | “dbt” | “mwb” | “sdb” | “db” | “sqlitedb” | “mdf” |
“db3” | “dbv” | “myd” | “sql” | “sqlite” | “db-shm” | “dacpac” |
“dbf” | “frm” | “ndf” | “tmd” | “accdb” | “db-wal” |
Directory Names
The ransomware uses these directory names for file enumeration purpose.
Directory Names | ||||
---|---|---|---|---|
“$recycle.bin” | “boot” | “windows” | “perflogs” | “appdata” |
“program files” | “windows.old” | “all users” | ” users” | “programdata” |
“$windows.~ws” | “system volume information” | “$windows.~bt” | “program files (x86)” |
Pre-Encryption
Cryptographic Algorithm
Cryptographic context is a type of additional authenticated data consisting of non-secret arbitrary name-value pairs. During the initialization phase, the ransomware acquires cryptographic context from advapi32.CryptAcquireContext API. The cryptographic provider used by the malware is “Microsoft Enhanced Cryptographic Provider v1.0” and the encryption scheme selected is RSA.
Recovery Data
Before the execution of the encryption function, the ransomware writes data needed for the recovery of the locked files in the registry. The following data is written:
- RECOVERY BLOB
- X25519 public key
Ransom Note
If writing the decryption data fails, the ransomware will not execute the routine responsible for the encryption of user data. After a successful registry operation, the ransomware generates a ransom note as the initial task in the function that performs the locking.
The following steps are performed:
- A random and unique recovery ID for the victim is generated and stored in the heap buffer.
- The Bluesky ransomware creates ransom note in “.txt” and “.html” formats.
- Two blocks of 1000 (4096) bytes of heap memory are allocated to hold the final ransom notes.
- Two temporary buffers (txt_ransom_note_buffer and html_ransom_note_buffer) are allocated to hold encoded notes retrieved from the binary.
- A place format string specifier is used as a placeholder for the recovery ID generated in the initial step.
- The function “sub_2866E0” is responsible for formatting the note by replacing the “%s” with the recovery ID value which is 242 characters long.
- The result is then stored in memory, to be later used by the function responsible for writing the note to the filesystem.
Process Termination
After creating the ransom note, the ransomware enumerates the processes running on the compromised system. The ntdll.ZwQuerySystemInformation API is called by passing the SystemInformation class (0x5) to get the process list from the system. The list is used by the ransomware to selectively kill the processes.
The following steps are performed to terminate the running processes:
- The ransomware starts to analyze the process structure to retrieve the image name and uses shlwapi.PathRemoveExtensionW API to remove the extension (.exe) from the name.
- Once the name of the process without extension is retrieved, the ransomware calls sub_2869B0 to calculate the size of the process name.
- Next a call is made to sub_2868C0 to convert the characters to lowercase for uniformity.
- Finally, a custom byte encoding is used to convert the string to a hex value.
- The generated hex value is checked against an array of encoded values of processes to be terminated.
- At the initial phase the handle to “Shell_Traywnd”, which is obtained using user32.FindWindowA, is passed to the GetWindowThreadProcessId API in order to get the process ID of explorer.exe. (explorer.exe is responsible for creating “Shell_Traywnd”). The process ID is stored in the memory.
- If there is a match, the target process ID, obtained at the initial phase, is passed to sub_2910F0.
- The malware checks if the process ID is of its own process or of explorer.exe. After the check, a handle to process is retrieved via kernel32.OpenProcess API.
- Only “non-critical” processes are terminated to prevent bug check (Blue Screen of Death). If the passed process handle is not critical, it is terminated via kernel32.TerminateProcess.
- The ransomware calls ntdll.NtQueryInformationProcess by passing ProcessBreakOnTermination (0x1d) as the InformationClass to identify critical processes.
Empty Recycle Bin
Following the process termination, the ransomware empties the recycle bin by calling shell32.SHEmptyRecycleBinA.
Encryption
Threading Model: Windows IO Completion Ports in Nutshell
- The Bluesky ransomware performs the encryption by utilizing IO completion ports. I/O completion ports provide an efficient threading model for processing multiple asynchronous input-output (I/O) requests on a multiprocessor system.
- The main thread creates the IO completion port via CreateIOCompletionPort. The created port can be associated with many file handles. When the asynchronous IO operation on one of the file handles is completed, an IO completion packet is queued in FIFO order to the associated port.
- The worker thread performs a call to PostQueuedCompletionStatus to enqueue the associated data. In the case of ransomware, the data will be the absolute path of the user files waiting in the queue to get encrypted.
- Another worker thread performs GetQueuedCompletionStatus to dequeue the contents from the main queue. Usually, in ransomware, this thread is responsible for performing encryption and ransom note generation.
- The following section contains an depth description of each of the above-mentioned functions.
CreateIOCompletionPort
The call to CreateIOCompletionPort involves the following steps:
- The main thread retrieves the processor count from the PEB (Process Environment Block) structure.
- A call to CreateIoCompletionPort is made by passing processor count as NumberOfConcurrentThreads parameter value.
- Multiple worker threads are created by calling kernel32.CreateThread.
- For each thread, an affinity mask (a bit mask indicating what processor a thread should run on) is set by calling kernel32.SetThreadAffinityMask.
- The main thread performs basic drive enumeration and calls PostQueuedCompletionStatus.
Following APIs are used for drive enumeration on the system:
- kernel32.GetLogicalDriveStringsW
- kernel32.GetDriveTypeW
Further enumeration of files is performed by creating worker thread for PostQueuedCompletionStatus.
The main thread calls mpr.WNetOpenEnumW for enumerating network resources and creates a worker thread same as above that performs the PostQueuedCompletionStatus call.
Worker Thread: PostQueuedCompletionStatus
The newly created thread for PostQueuedCompletionStatus leads to the following:
- The files are enumerated via kernel32.FindFirstFileExW and kernel32.FindNextFileW.
- If it is a directory, the thread function is recursively called to perform the file enumeration.
- If it is a user file, then the absolute path is enqueued to the completion queue via PostQueuedCompletionStatus call.
- This worker thread is responsible for gathering the files for encryption.
Worker Thread: GetQueuedCompletionStatus
This worker thread is responsible for doing the actual locking of the user files. The ransomware hides this thread from the debugger via ntdll.ZwSetInformationThread by passing ThreadHideFromDebugger as the ThreadInformationClass.
The thread decodes the file extension “.bluesky” and proceeds to perform the encryption. The kernel32.GetQueuedCompletionStatus is called in an infinite loop to retrieve the absolute path of the user data.
The sub_288780 function is responsible for encrypting the data. The thread checks if the dequeued item is a directory or a file.
- If it is a file then it proceeds to encrypt the data by using the following APIs:
- kernel32.CreateFileW
- kernel32.SetFilePointer
- kernel32.ReadFile
- kernel32.WriteFile
- If the item is a directory then sub_28EDA0 is executed to dump the ransom note. The file name strings are decoded dynamically.
The note content generated by the ransomware is written on the disk by calling:
- kernel32.CreateFileW
- kernel32.WriteFile
Post Encryption
Once the user data is successfully locked, the ransomware performs the following operations:
- Releases the mutex created at the initial phase
- Sets the thread state to ES_Continous
- Destroys the allocated heap
- Exits the process via kernel32.ExitProcess
Indicators of Compromise(IoCs)
MD5 |
---|
961fa85207cdc4ef86a076bbff07a409 |
53c95a43491832f50e96327c1d23da40 |
5ef5cf7dd67af3650824cbc49ffa9999 |
efec04688a493077cea9786243c25656 |
d8a44d2ed34b5fee7c8e24d998f805d9 |
848974fba78de7f3f3a0bbec7dd502d4 |
Appendix