Behavioral Summary
LockBit 3.0 seems to love the spotlight. Also known as LockBit Black, this ransomware family announced itself in July 2022 stating that it would now offer the data of its nonpaying victims online in a freely available easy-to-use searchable form. Then in July, it introduced a bug bounty program to find defects in its ransomware. The group even offered money to people willing to get the LockBit logo tattooed on their bodies. Regardless of the public spotlight LockBit continues its rise to the top of the ransomware ecosystem and, according to The Record, is currently the most prevalent ransomware strain.
LockBit 3.0 is a challenge for security researchers because each instance of the malware requires a unique password to run without which analysis is extremely difficult or impossible. Additionally, the malware is heavily protected against analysis and makes use of a substantial number of undocumented kernel level Windows functions.
However, in September 2022 Twitter user @3xp0rtblog announced that the builder for the ransomware was leaked by @ali_qushji and available for download from GitHub.
Figure 1: LockBit 3.0 Builder Leaked on Twitter
This leaked source allows for complete and unhindered analysis, but unfortunately also means that many new groups are emerging, using the same or modified versions of LockBit 3.0 originating from this builder.
Figure 2: LockBit 3.0 Builder
The builder, once extracted, contains the files shown in Figure 2, with the Build directory empty. Running the Build.bat file, which includes the contents shown in Figure 3, automates the build process and populates the Build directory with a unique instance of the ransomware. The resulting files are shown in Figure 4.
Build.bat
Figure 3: Content of Build.bat
The commands that make up Build.bat, clear the Build directory, and then call keygen to generate the public and private encryption keys. The next lines that start with “builder”, generate the different variations of the LockBit 3.0 ransomware by supplying the builder with different command line options.
Figure 4: LockBit 3.0 File Listing after Build
Description of Generated Files
- DECRYPTION_ID.txt – Text file containing a 16-character victim ID made from the first eight hex bytes of the public key that is used to uniquely identify a victim
- LB3.exe – Compiled ransomware, which doesn’t require a password
- LB3Decryptor.exe – Decryptor for the ransomware, which works with all the variations here
- LB3_pass.exe – Same as LB3.exe however requires a password to run. The password and instructions are found in Password_exe.txt in this directory
- LB3_RelectiveDLL_DLLMain.dll – Version of the ransomware that is meant to be reflectively loaded and executed in memory
- LB3_Rundll32.dll – DLL version of ransomware, which doesn’t require a password.
- LB3_Rundll32_pass.dll – DLL version of ransomware, which requires the password found in the Password_dll.txt file
- Password_dll.txt – Contains password and instructions for using LB3_Rundll32_pass.dll
- Password_exe.txt – Contains password and instructions for using LB3_pass.exe
- priv.key – A private encryption key unique to this build that is used to encrypt victim files
- pub.key – A public encryption key unique to this build that is used generate various strings that tie this instance of the ransomware to a victim.
keygen.exe
The first executable called in Build.bat is keygen.exe. It generates a unique public-private key pair for each build as well as the decryption ID. Keygen appears to rely heavily on MIRACL, which according to its own description is, “…a C software library that is widely regarded by developers as the gold standard open-source SDK for elliptic curve cryptography.” The generated keys are base64 encoded and saved to files priv.key and pub.key. Then the unencoded first eight bytes of the public key are converted to their hex values and saved to the DECRYPTION_ID.txt file, which acts as a unique victim identification number.
builder.exe
As shown earlier in Figure 4, the builder.exe file creates two executables, three dynamic link libraries, and two text files. In order to complete this, it requires the existing config.json (Figure 2), and the priv.key/pub.key files generated in the previous step by keygen.exe and shown in Figure 4. The builder.exe file itself also holds essentials. In its resource section are four executable template files. Each of these are used to construct the DLL and EXE encryptors as well as the program used for decryption.
Figure 5: Builder.exe Resources
Description of each resource by its ID:
- 100 – decryptor template file
- 101 – executable template file
- 103 – DLL template file
- 106 – DLL template file that enables reflective loading
The configuration file, config.json, contains options commonly associated with ransomware including targeted folders, files to avoid, and processes that should be killed. As shown in Figure 6, it also contains settings options to tune the behavior of the ransomware, those shown below were found by default in the builder.
Figure 6: Configuration Options
This builder configuration allows the resultant ransomware to be tuned for a specific target environment. In addition to these configurations there are options for
- Hosts, files, folders and file extension to exclude
- Process and services to stop and remove
- List of command and control domains, URLs, or IPs
- List of usernames and passwords to try on affected systems
Since this ransomware is highly configurable there are many different code paths possible. For the sake of simplicity, the analysis here will focus on running the ransomware in the default case, without command line configuration options. However, to explain full functionality these options will be mentioned in relevant code sections.
Inside the LockBit Black Box
The initial set of code, decompiled for readability, within the program is shown in Figure 7. This code shows that the executable contains a substantial amount of unused GUI related code listed after a call to exit the process, highlighted as kernel32.ExitProcess(). All the ransom functionality occurs in the three functions that occur immediately before the call to ExitProcess. The main function contains the largest part of the ransomware functionality. The implementation of unused code is not new to malware development, but it is also not very common. A technique like this helps obscure the true purpose of the malware from researchers, and can help make malware seem legitimate.
Figure 7: Entry Function
Typical applications call DLL functions directly, or perform simple calls to get the process address of functions from the DLL file. The LockBit builder has a different and more obscure method to discover and use external functions. The function we’ve named “prepare_address_table_lookups”, shown in Figure 7, contains a table of hashes pre-generated from a set of function calls. Each entry in this set includes the lowercase library and function names separated by a dot (i.e. ntdll.findfirstfileexw). LockBit 3.0 manually finds the DLLs it needs in the Windows System32 folder, and then manually loads each function, laboriously hashing and matching each functions library and name combination to create the address table. Once the table of hashed libraries and functions is created, the malware is careful to release and clear all memory to inhibit analysis. It should be noted that this is only a subset of the functions called, as more functions are retrieved and called from the Windows kernel during runtime.
As shown in Figure 7, the “check_priv_elevate_if_needed” function does what the name implies. Privilege escalation is achieved by duplicating access tokens to gain membership in privileged groups. To understand this it is helpful to have a high-level understanding of Windows privileges. In life Windows privilege is roughly equivalent to a large ring of keys that provide access to otherwise restricted areas. In Windows these keys are called access tokens and each access token can contain one or more privilege constants. Each privilege constant defines a specific action or set of actions that can be restricted in the operating system. For example, one privilege constant almost everyone has is called SeShutdownPrivilege, which allows a local user to shutdown the operating system. Without this privilege constant in the access token, Windows would not allow the shutdown. Just like in real life where a physical key ring can hold numerous keys, numerous privilege constants can belong to single access token.
Essential for understanding is that processes and services started by the user or on the user’s behalf are endowed with or inherit their privileges from the user. However, not all processes and services on a system belong to the user, some belong to the operating system. These operating system processes and services will by necessity have different privileges. Simply put, LockBit 3.0 duplicates an access token from a system process to use in a user process to allow functionality that would otherwise be prohibited.
To duplicate tokens LockBit 3.0 does several things. Initially it will check if it already has sufficient privilege by specifically checking for membership in the Domain Admin group. If this is not found, it attempts to grant itself a predetermined list of fifteen privilege constants, most of which were not successful in testing when run as an unprivileged user. After this, if it still does not have the required privilege, LockBit 3.0 locates the operating system process explorer.exe and calls ZwOpenProcessToken directly to read the access token for explorer.exe. Then it calls NtDuplicateToken passing in the newly acquired token handle to request read and write access to the extended attributes of the copy.
Figure 8: Duplicate the explorer.exe Process Token
In this case the Explorer process was targeted directly. However, as the program runs, each time certain processes are encountered the token privileges are checked and, if additional privileges are found, the token is duplicated. There is a noted emphasis on gaining a token with privileged domain access.
One of the first things that the malware in the main function does is check for, and create, a synchronization mutex. If the mutex is present the process will exit, ensuring that only one instance of the ransomware runs at a time. The mutex is made by first taking the MD5 hash of the supplied public key found in the pub.key file. The resulting MD5 hash is string formatted with “{%08X-%04X-%04X-%02X%02X-%02X%02X %02X %02X %02X %02X}”. Next, the MD4 hash of this formatted string is calculated, and the result is passed to the format string “Global\%.8x%.8x%.8x%.8x”. For example, a finished mutex value would be similar to Global\ea4ee28880136cbc44dff4ad5a53561f.
Next LockBit 3.0 checks that the operating system started normally. If Windows started in safe mode the ransomware does not run most of its functionality, but instead sets a registry key to run on the next normal boot.
With the mutex in place and the boot type satisfied, the main purpose of the executable is started in a multi-threaded manner. Each thread takes on the characteristic of its tasking. Some run continuously for the life of the process, and others run once only temporarily to perform a specific task.
Stop Services: Windows Defender
The first thread removes Windows Security Services. This is achieved by taking advantage of the Trusted Installer service. The Trusted Installer, usually known by its display name “Windows Modules Installer”, is normally used for downloading and installing Windows updates and optional components. If the Trusted Installer is not already running it is started, and then its access token handle is duplicated to allow the current thread to have access to most other running services. With this token LockBit 3.0 enumerates the running services and any service matching one of those predefined in config.json is stopped and deleted. Once complete, the thread exits and does not start again.
Figure 9: Notification Windows Security Center stopped
Figure 10: Error attempting to restart Windows Security Center
During testing a small taskbar notification briefly appeared to inform the user that the Windows Security Center service stopped. However, because the service was not only stopped but also deleted, the Windows notification could not be used to restart the service.
Service | Description |
SecurityHealthService | Provides current information about the protection status of the endpoint, includes monitoring of Windows and other vendor’s tools |
wscsvc | Windows Security Center Service |
Sense | Windows Defender Advanced Threat Protection Service |
sppsvc | Microsoft’s Software Protection Service – Licensing |
WdBoot | Windows Defender ELAM (Early Launch Antimalware) Driver |
WdFilter | Windows Defender Mini-Filter Driver |
WdNisDrv | Windows Defender Antivirus Network Inspection System Driver |
WdNisSvc | Windows Defender Network Inspection Service |
WinDefend | Windows Defender Service |
Table 1: Services Stopped and Deleted
It is important to consider that the Windows Security Service was targeted here because these services were listed in the default config.json file. It is highly likely that other services would be stopped if listed by threat actors using this builder.
Figure 11: Services stopped and deleted
Once the services are removed the malware will launch several additional threads. The screenshot in Figure 12 shows the threads with the longest runtime. The first priority is to launch the thread that handles files in the Windows Recycle Bin, followed by threads to monitor for and terminate the SQL process. Then there is a thread dedicated to writing ransom notes to directories. The last threads initiated are those to encrypt files. There are three threads devoted to this in the screenshot below, but the number of threads is dynamic and will increase or decrease depending on the available system resources, and the number and type of items queued for encryption. For example, network resources identified for encryption are handled separately from those on the local system.
Figure 12: Some of the LockBit 3.0 Threads
Recycle Bin Thread
As shown above, there is a special thread dedicated to handling files found in the recycle bin. The files in the recycle bin are not encrypted; instead, the content of each file is replaced with randomly generated bytes in 0x10000 byte blocks, and then they are deleted. For this reason, all files in the recycle bin are not recoverable, even with the decryptor.
Monitor and Terminate SQL Process
A separate thread runs continuously, watching for and stopping any SQL process. It does this by getting a list of services every two seconds. Each service name is passed to the function isSQL(), which looks for any occurrence of the case insensitive string SQL. If the name contains this sequence, it is terminated. Unlike many of the other threads, this thread runs for the life of the process ensuring that SQL will not run for more than two seconds while LockBit 3.0 performs ransom activity.
Figure 13: Terminate SQL Service
Delete Shadow Copies
There is a thread dedicated to the removal of Volume Shadow Copies. A shadow copy is a snapshot of a volume that duplicates all the data that is held on the volume at one well-defined instant in time. This is completed by making a call to the IWbemProvider COM object and starting an in-process server to allow queries to the Windows Management Interface. Using this it executes the WMI query “SELECT * FROM Win32_ShadowCopy”, and then deletes each of the returned Shadow Copies.
Write Ransom Notes
The ransom note thread retrieves and decrypts the embedded ransom note that was defined in config.json. The note is written to every directory not marked for exclusion. Its file name is made up of nine alphanumeric characters followed by “.README.txt” (ie xEC9do6g6.README.txt). The unique value prefixing the “.README.txt” is the base64 encoding of the first 6 bytes of the MD5 hash of the previously generated mutex GUID. Due to this method, all ransom notes left on the system are all given the same name but are unique to that system.
Encryption
Files are encrypted using the Salsa-20 algorithm. During the encryption threads, memory containing the private key is protected with heavy use of RtlEncryptMemory and RtlDecyptMemory, which makes the private key available unencrypted in memory only for the time it is necessary.
Domain Controller Discovery
Another thread attempts to logon to the infected system with the usernames and passwords found in the configuration. The usernames and passwords found in the config.json file by default are those associated with administration accounts. If any login is successful, the token membership is evaluated for membership in a domain admin group and if so, copied. Then another thread looks for and enumerates available domain controllers, getting each of their names, and attempting a remote login with the successful username and password.
Connected Drives and Shared Network Resources
Other threads check for connected drives and network resources while giving special attention to those where operating systems are installed. In all cases these newly discovered paths are passed to a function that spawns additional encryption threads.
Network Traffic
Command and control traffic occurs over TLS 1.2 to the addresses listed in the config.json file. Unfortunately, the variables and their values are AES encrypted under this TLS layer, and the order is shuffled for each request. However, the overall format of the POST request is consistent as shown in Figure 14. Consistently observed was a POST request followed by “/?” and a long string of URL style variable=value pairs separated with an ampersand, followed by the HTTP/1.1 fields. The User-Agent string is randomized, so should not be included in signatures, but the Connection, Accept-Encoding, Content-Type and Cache-Control, fields are constant. The basic format of the data section was also consistent, but the length varied slightly.
Figure 14: Initial POST Request
Although decrypting the intercepted network traffic would be close to impossible without the encryption key, the below example provides a general understanding of the information transmitted.
Figure 15: JSON Formatted Exfil Data
Post Encryption
Post encryption, the desktop background is changed to black with white text similar to the example in Figure 14. Additionally, the icons of encrypted files are changed to the LockBit “B” icon shown in the upper left corner of Figure 16.
Figure 16: Ransom Desktop and LockBit Icon
Decryptor
As the decryptor was generated with the builder, we tested its operation and use. When run, a window displays as shown below, and the user must click the large button on the right that is labeled, “Decrypt All Encrypted Files”. Once clicked the counter for All Decrypted Files ticks up as files are decrypted. As shown here, the application never closed, but by CPU usage had ceased processing files, signaling that it had completed.
There was a difference of 64 files at the end of processing. To account for these 64 files, the file system was scanned for any LockBit named files, but no matching files were found. The Recycle Bin files could account for some of the 64, but the 10 files removed from the recycle bin still left us many short of 64. These missing files aside, the Recycle Bin was not restored, and all the volume shadow copies were still erased. For all general files the decryptor did work, files were appropriately restored, and the Lockbit desktop background was removed. No conclusive tests were run to verify the number of encrypted or decrypted files with the number reported by this tool.
Figure 17: LockBit 3.0 Decryptor
MITRE ATT&CK TIDs
Tactic | ID | Name | Description |
Execution TA0002 |
T1559.001 | Component Object Model | Used for deleting volume shadow copies |
T1106 | Native API | Copious use of Windows Native API calls | |
T1047 | WMI | Used for deleting volume shadow copies | |
Persistence TA0003 |
T1547.001 | Registry Run Keys | If started in safe mode, sets registry to start on next normal boot. |
Privilege Escalation
TA0004 |
T1134.001 | Token Impersonation | Starts processes with known token with the purpose of duplicating tokens. |
Defense Evasion TA0005 |
T1562.001 | Disable or Modify Tool | Stops and deletes Windows Security Services |
T1562.002 | Disable Windows Event Logging | Stops and deletes service responsible for event logging | |
T1562.004 | Disable system firewall | Stops and deletes service for Windows Firewall. | |
T1562.009 | Safe Mode Boot | Changes behavior if booted in safe mode. | |
T1078.001 | Default Accounts | Attempts to login with default admin credentials | |
Discovery TA0007 |
T1083 | File and Directory Discovery | Traverses mounted disks and file system |
T1135 | Network Share Discovery | Traverses all shared network resources | |
T1120 | Peripheral Device Discovery | Locates removable storage devices | |
T1057 | Process Discovery | Looks for specific processes to stop | |
T1018 | Remote System Discovery | Locates domain controller and DNS server | |
T1082 | System Information Discovery | Gets specific information about the operating system | |
Lateral Movement
TA0008 |
T1021.002 | Windows Admin Shares | User of valid accounts to interact with remote network shares |
Command and Control
TA0011 |
T1071.001 | Web Protocols | Uses HTTP to communicate with C2 |
T1573 | Encrypted channel | TLS 1.2 | |
Exfiltration
TA0010 |
T1041 | Exfiltration Over C2 Channel | Sends basic system information in POST request |
Impact TA0040 |
T1485 | Data Destruction | Recycle bin and shadow copies are deleted |
T1486 | Data Encrypted for Impact | Ransomware | |
T1491.001 | Internal Defacement | Desktop changed |
Indicators of Compromise (IOCs)
IOC | Description |
c2bc344f6dde0573ea9acdfb6698bf4c | MD5 Builder File |
d6ae7dc2462c8c35c4a074b0a62f07cfef873c77 | SHA1 Builder File |
a736269f5f3a9f2e11dd776e352e1801bc28bb699e47876784b8ef761e0062db | SHA256 Builder File |
71c3b2f765b04d0b7ea0328f6ce0c4e2 | MD5 keygen File |
bf8ecb6519f16a4838ceb0a49097bcc3ef30f3c4 | SHA1 keygen file |
ea6d4dedd8c85e4a6bb60408a0dc1d56def1f4ad4f069c730dc5431b1c23da37 | SHA256 keygen file |
4d388f95a81f810195f6a8dfe86be755 | MD5 Resource 100 |
cb6fdb25a15b7797890fadc2b823984f93da5368 | SHA1 Resource 100 |
cc3d006c2b963b6b34a90886f758b7b1c3575f263977a72f7c0d1922b7feab92 | SHA256 Resource 100 |
87308ec0a44e79100db9dbec588260ec | MD5 Resource 101 |
939ff7e5eeaccb0c2f4ee080a8e403e532b6317a | SHA1 Resource 101 |
03b8472df4beb797f7674c5bc30c5ab74e8e889729d644eb3e6841b0f488ea95 | SHA256 Resource 101 |
4655a7ac60ed48df9b57648db2f567ef | MD5 Resource 103 |
02ea524429ba2aefac63fed27e924ab3659f8c00 | SHA1 Resource 103 |
a0db5cff42d0ee0de4d31cff5656ed1acaa6b0afab07d19f9f296d2f72595a56 | SHA256 Resource 103 |
23a30838502f5fadc97e81f5000c4190 | MD5 Resource 106 |
9c1142122370c9b28b13aa147c6e126b3be50845 | SHA1 Resource 106 |
ae993930cb5d97caa5a95b714bb04ac817bcacbbf8f7655ec43e8d54074e0bd7 | SHA256 Resource 106 |
Yara Rules
import "pe" rule LockBit_3_dll { meta: author = "VMware TAU" //bdana date = "2022-Oct-12" description = "Identifies LockBit 3.0 DLL encryptor by exported function names." rule_version = “1” yara_version = "4.2.3" exemplar_hash = “c2529655c36f1274b6aaa72911c0f4db7f46ef3a71f4b676c4500e180595cac6” condition: pe.exports("del") and pe.exports("gdel") and pe.exports("gdll") and pe.exports("gmod") and pe.exports("pmod") and pe.exports("sdll") and pe.exports("wdll") } rule LockBit_3_exe { meta: author = "VMware TAU" //bdana date = "2022-Oct-12" description = "Identifies LockBit 3.0 exe encryptor section names, and artifact section names." rule_version = “1” yara_version = "4.2.3" exemplar_hash = “5202e3fb98daa835cb807cc8ed44c356f5212649e6e1019c5481358f32b9a8a7” strings: $text = ".text" ascii wide $itext = ".itext" ascii wide $data = ".data" ascii wide $rdata = ".rdata" ascii wide $idata = ".idata" ascii wide $xyz = ".xyz" ascii wide $reloc = ".reloc" ascii wide $bss = ".bss" ascii wide condition: #text > 2 and #itext > 1 and #data > 1 and #rdata > 2 and #idata > 3 and $reloc and $bss and $xyz and not for any i in (0..pe.number_of_sections-1) : ( pe.sections[i].name == ".xyz" or pe.sections[i].name == ".bss" ) }