{
	"id": "2c436657-5de0-4aeb-9724-048d798f1fc2",
	"created_at": "2026-04-06T00:08:57.450481Z",
	"updated_at": "2026-04-10T03:31:18.996302Z",
	"deleted_at": null,
	"sha1_hash": "3f65dd00445e97926d18dc3df79e90148cbb9e02",
	"title": "LockBit Ransomware v2.0",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 6097726,
	"plain_text": "LockBit Ransomware v2.0\r\nBy Chuong Dong\r\nPublished: 2022-03-19 · Archived: 2026-04-05 19:04:37 UTC\r\nReverse Engineering  · 19 Mar 2022\r\nLockBit Ransomware v2.0\r\nLockBit CTI\r\nOverview\r\nIOCS\r\nRansom Note\r\nStatic Code Analysis\r\nAnti-Analysis: Anti-Debug Check\r\nAnti-Analysis: Stack String\r\nAnti-Analysis: Inline Dynamic API Resolving\r\nComputer Language Check\r\nDenying Access To Ransomware Process\r\nDefault Error \u0026 Privilege Setting\r\nConfiguration Decryption\r\nPrivilege Escalation \u0026 Relaunch\r\nLogging\r\nCommand-line Arguments\r\nMasquerade Explorer \u0026 UAC Bypass\r\nRun-once Mutant\r\nSetting Group Policy For Active Directory\r\nChecking If Running On Primary Domain Controller\r\nRetrieving DNS Domain Name\r\nRetrieving Domain Account Admin Name\r\nCOM Retrieve IGroupPolicyObject Interface\r\nConnect To Active Directory Domain\r\nSetting GPO’s attributes\r\nUpdating GPT.INI\r\nUpdating the GPO Folder\r\nForcing GPUpdate On All Hosts Through PowerShell\r\nForcing GPUpdate On All Hosts Manually\r\nPersistence Registry\r\nSet LockBit Default Icon\r\nPre-Encryption System Clean-Up\r\nStopping Services\r\nTerminating Processes\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 1 of 111\n\nDeleting Backups\r\nPrinting Ransom Note To Printers\r\nSetup Wallpaper\r\nDropping Ransom HTML Application File\r\nFile Encryption\r\nMounting Volumes on Drives\r\nCryptography \u0026 Multithreading Initialization\r\nTraversing Local Drive\r\nChild Thread\r\nEncryption State 1\r\nEncryption State 2\r\nEncryption State 3\r\nEncryption State 4\r\nTraversing Network Hosts\r\nScanning For Live Hosts\r\nLaunching Threads To Traverse Live Hosts’ Network Shares\r\nTraversing Network Drives\r\nImpersonation Process With The Same Authentication ID\r\nImpersonation Shell Process Window\r\nDropping Ransom Note\r\nSelf-Deletion\r\nReferences\r\nLockBit CTI\r\nOn 4 February 2022, the FBI issued FLASH security advisory on Indicators of Compromise (IOCs) associated\r\nwith LockBit 2.0 ransomware, one of the most active ransomware groups in the current cybercrime ecosystem.\r\nThe LockBit gang (aka Bitwise Spider) are the developers of the LockBit Ransomware-as-a-Service (RaaS).\r\nLockBit ransomware first appeared in September 2019 and in June 2021, the group rebranded to LockBit 2.0, like\r\nseveral other families did in 2021. LockBit 2.0 has been responsible for various high-profile attacks in 2021,\r\nincluding victims such as Accenture, following the launch of a marketing campaign to recruit new affiliates in\r\nmid-2021. The rebranded version of LockBit includes several new features, including self-propagation, removal\r\nof shadow copies, bypass User Account Control (UAC), ESXi support, and the printing of ransom notes via\r\nprinters detected on the victim’s network. The group also prides itself on having the fastest encryption on the\r\nransomware market. This is because it uses a multithreaded approach in encryption and only partially encrypts the\r\nfiles, as only 4 KB of data is encrypted per file.\r\nLockBit 2.0 is represented on the Russian-speaking cybercrime forums as “LockBitSupp” on multiple sites,\r\nincluding RAMP, Exploit[.]in, and XSS[.]is, where they recruit affiliates and advertises its RaaS. LockBit has\r\ngrown to become the leading group for the highest number of victims published to its darknet leak site after\r\novertaking Conti in early 2022. Prior to encryption, Lockbit affiliates can use the StealBit application obtained\r\ndirectly from the Lockbit panel to exfiltrate specific file types. The desired file types can be configured by the\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 2 of 111\n\naffiliate to tailor the attack to the victim. The affiliate configures the application to target a desired file path, and,\r\nupon execution, the tool copies the files to an attacker-controlled server using http. Due to the nature of the\r\naffiliate model, some attackers use other data theft available tools such as Rclone and MEGAsync to achieve the\r\nsame results. Lockbit 2.0 actors also use cloud file sharing services including, privatlab[.]net, anonfiles[.]com,\r\nsendspace[.]com, fex[.]net, transfer[.]sh, and send.exploit[.]in to send data stolen from victim networks.\r\nAll credits in this part goes to Equinix’s Will Thomas for the awesome intel on the ransomware group!\r\nOverview\r\nThis report is my brief analysis for the LockBit Ransomware v2.0.\r\nIn the analysis, I cover all of LockBit’s ransomware functionalities. However, I left out details about some\r\nfunctionalities because I was really lazy and burned out by the time I finished analyzing lol.\r\nLockBit uses a hybrid-cryptography scheme of Libsodium’s XSalsa20-Poly1305-Blake2b-Curve25519 and\r\nAES-128-CBC to encrypt files. The malware’s configuration is XOR-encrypted and stored in static memory. Like\r\nREvil and BlackMatter, LockBit’s child threads use a shared structure to divide the encryption work into\r\nmultiple states while encrypting a file.\r\nWith the elaborated multithreading architecture, LockBit’s performance is relatively fast compared to most\r\nransomware in the field.\r\nFigure 1: LockBit Leak Site.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 3 of 111\n\nLockBit is definitely the most sophisticated ransomware I have taken a look at, and it was a lot of fun analyzing\r\nand figuring it out.\r\nMy analysis is 96% based on static analysis in IDA because I am unfortunately too lazy for dynamic analysis.\r\nTherefore, this report only covers what I see in the code and how I understand them. Enjoy!\r\nIOCS\r\nThe sample I used is a 32-bit Windows executable. Huge shoutout to vx-underground for sharing it.\r\nMD5: 63dcf75ad743b292e4a6cd067ffc2c18\r\nSHA256: 9feed0c7fa8c1d32390e1c168051267df61f11b048ec62aa5b8e66f60e8083af\r\nSample:\r\nhttps://bazaar.abuse.ch/sample/9feed0c7fa8c1d32390e1c168051267df61f11b048ec62aa5b8e66f60e8083af/\r\nFigure 2: LockBit Victim Portal.\r\nRansom Note\r\nThe content of the ransom note is XOR-encrypted in LockBit’s executable, which is dynamically decrypted once\r\nand written to the ransom note file in every directory.\r\nThe ransom note filename is Restore-My-Files.txt.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 4 of 111\n\nFigure 3: LockBit Ransom Note.\r\nStatic Code Analysis\r\nAnti-Analysis: Anti-Debug Check\r\nAt the beginning of the entry point function, LOCKBIT checks the NtGlobalFlag field in the Process Control\r\nBlock (PEB) to detect if the malware process is being debugged.\r\nThis is done by comparing the field’s value to 0x70, which indicates that the flags\r\nFLG_HEAP_ENABLE_TAIL_CHECK, FLG_HEAP_ENABLE_FREE_CHECK,\r\nFLG_HEAP_VALIDATE_PARAMETERS are set.\r\nIf the process is being debugged, the malware hangs indefinitely.\r\nFigure 4: Anti-Debug Check.\r\nAnti-Analysis: Stack String\r\nMost important strings in LockBit’s executable are encoded and stored as a stack string. Before being used, they\r\nare decoded dynamically through some simple computation such as addition, subtraction, or XOR-ing.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 5 of 111\n\nFigure 5: Stack String Obfuscation.\r\nAnti-Analysis: Inline Dynamic API Resolving\r\nLike most major ransomware, LockBit resolves APIs dynamically to make static analysis harder, but unlike many,\r\nLockBit inlines the entire resolving process, making the decompiled code much larger to analyze.\r\nFirst, to resolve these APIs dynamically, their respective libraries need to be loaded in memory initially. Since\r\nKernel32 is already loaded from LockBit’s few imports, the malware locates it and resolves LoadLibraryA to\r\nload others in memory.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 6 of 111\n\nFigure 6: Stack String Obfuscation.\r\nAfter retrieving LoadLibraryA, LockBit resolves each DLL’s name is resolved as a stack string and calls\r\nLoadLibraryA to load it in memory.\r\nBelow is the list of the loaded libraries.\r\ngdiplus.dll, ws2_32.dll, shell32.dll, advapi32.dll, user32.dll, ole32.dll, netapi32.dll, gpredit.dll,\r\noleaut32.dll, shlwapi.dll, msvcrt.dll, activeds.dll, gdiplus.dll, mpr.dll, bcrypt.dll, crypt32.dll, iphlpapi.dll,\r\nwtsapi32.dll, win32u.dll, Comdlg32.dll, cryptbase.dll, combase.dll, winspool.drv\r\nWhen retrieving an API address from memory, the malware first locates its DLL’s base by iterating the PEB’s\r\nloader module linked list and checks the library name of each entry. Each name (in lowercase) is hashed using\r\nFNV1A and compared to a hard-coded hash, and the corresponding DLL base is returned.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 7 of 111\n\nFigure 7: Locating DLL Base.\r\nUsing the DLL base, LockBit accesses its export directory table and iterates through the name of each export API.\r\nFor each API’s name, the malware converts its characters to lower case and hash it with FNV1A. The final hash is\r\ncompared against a target hash, and if the hashes match, the malware retrieves the address of the API’s name\r\nordinals and uses that to index into the export table’s AddressOfFunctions array to return the target API address.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 8 of 111\n\nFigure 8: Iterating Through Export Directory Table.\r\nFigure 9: Retrieving Target API’s Address.\r\nFor most of the APIs used throughout the executable, this process is completely inline every time, which\r\nsignificantly increases the amount of compiled code we need to look at. LockBit stores the resolved DLL bases\r\nand APIs in global memory to reuse them, so despite having a larger static code, the number of dynamic\r\ninstructions is about the same compared to if this process is not inline. This makes reverse engineering the sample\r\na bit more annoying while not compromising the performance of the code itself.\r\nComputer Language Check\r\nLike a lot of ransomwares, LockBit checks the system’s languages to avoids encrypting machines in Russia and\r\nnearby countries.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 9 of 111\n\nThe malware resolves GetSystemDefaultUILanguage and GetUserDefaultUILanguage and call them to check\r\nif the system or user default UI language is in the list to avoid below.\r\nAzerbaijani (Cyrillic, Azerbaijan), Azerbaijani (Latin, Azerbaijan), Armenian (Armenia), Belarusian\r\n(Belarus), Georgian (Georgia), Kazakh (Kazakhstan), Kyrgyz (Kyrgyzstan), Russian (Moldova), Russian\r\n(Russia), Tajik (Cyrillic, Tajikistan), Turkmen (Turkmenistan), Uzbek (Cyrillic, Uzbekistan), Uzbek (Latin,\r\nUzbekistan), Ukrainian (Ukraine)\r\nFigure 10: Checking Blacklist Languages.\r\nIf the user or system UI language is blacklisted, the malware resolves ExitProcess and calls it to terminates itself\r\nimmediately.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 10 of 111\n\nFigure 11: Terminating If Language Is Blacklisted.\r\nDenying Access To Ransomware Process\r\nAfter loading all required libraries into memory, LockBit attempts to restrict access to its own process by\r\nmodifying its own access control list.\r\nFirst, it resolves and calls NtOpenProcess to get a handle to the current ransomware process. Then, the malware\r\nresolves and calls GetSecurityInfo to retrieve the process’s security descriptor ACL.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 11 of 111\n\nFigure 12: Retrieving Process’s Security Descriptor ACL.\r\nNext, LockBit resolves and calls RtlAllocateAndInitializeSid to allocate and initialize an SID with the authority\r\nof SECURITY_WORLD_SID_AUTHORITY for the EVERYONE group. It then calls\r\nRtlQueryInformationAcl and RtlLengthSid to retrieve the process’s ACL length, calculates the size of a new\r\nACL and allocate a virtual buffer for it. After creating the buffer, LockBit calls RtlCreateAcl to create that new\r\nACL and calls RtlAddAccessDeniedAce to add an ACCESS_DENIED access control entry (ACE) to this ACL\r\nfor the EVERYONE group using the newly created SID above.\r\nFigure 13: Creating A New ACL With Denied Access For EVERYONE Group.\r\nFinally, LockBit calls RtlGetAce to iterate through each ACE in the ransomware process’s ACL and RtlAddAce\r\nto add the ACEs into the new ACL. After all the ACEs have been added to the new ACL, the malware calls\r\nSetSecurityInfo to set the new ACL to its own running process, which denies access from everyone to itself.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 12 of 111\n\nFigure 14: Populating \u0026 Setting New ACL To Current Process.\r\nDefault Error \u0026 Privilege Setting\r\nLockBit calls NtSetInformationProcess to set the current process’s default hard error mode to these 3 flags.\r\nSEM_FAILCRITICALERRORS: The system does not display the critical-error-handler message box\r\nand sends the error to the calling process.\r\nSEM_NOGPFAULTERRORBOX: The system does not display the Windows Error Reporting dialog.\r\nSEM_NOALIGNMENTFAULTEXCEPT: The system automatically fixes alignment faults.\r\nIt also calls RtlAdjustPrivilege to enable the SE_TAKE_OWNERSHIP_PRIVILEGE privilege to be able to\r\nlater take ownership of files during encryption.\r\nFigure 15: Default Error \u0026 Privilege Setting.\r\nConfiguration Decryption\r\nLockBit’s configuration is divided into two different parts, which are data and flags.\r\nThe data part is encoded and stored statically in the executable, which contains the following fields.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 13 of 111\n\nEMF file 1: Contain the vector graphic for the text “ALL YOUR IMPORTANT FILES ARE STOLEN\r\nAND ENCRYPTED”\r\nEMF file 2: Contain the vector graphic for the text “LOCKBIT 2.0”\r\nBlender Pro Medium TTF file\r\nProxima Nova TTF file\r\nLockBit text PNG\r\nLockBit icon PNG\r\nLockBit icon large PNG\r\nProcess list: list of processes to terminate, each separated by a comma\r\nService list: list of services to stop, each separated by a comma\r\nFigure 16: Decoding Configuration Data.\r\nThe decoding process is quite simple since it’s just XOR-ing each encoded byte with 0x5F.\r\nFigure 17: Configuration Decoding Algorithm.\r\nYou can find the files listed above here.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 14 of 111\n\nBelow is the process and service to terminate lists.\r\nProcess list:\r\nwxServer,wxServerView,sqlmangr,RAgui,supervise,Culture,Defwatch,winword,QBW32,QBDBMgr,qbupdate,axlbridge\r\nService list:\r\nwrapper,DefWatch,ccEvtMgr,ccSetMgr,SavRoam,Sqlservr,sqlagent,sqladhlp,Culserver,RTVscan,sqlbrowser,SQLAD\r\nBecause the service/process names are separated by commas, the malware allocates a separate array in virtual\r\nmemory to contain pointers to each name by copying the name into this new array for easy access.\r\nThe process list is also parsed into two different arrays of pointers, one for storing the names as normal ASCII\r\nstrings and one for storing them as wide strings.\r\nFigure 18: Parsing Lists of Processes \u0026 Services To Terminate.\r\nThe flags part of the configuration is stored in an array of bytes. Each byte corresponds to a specific execution flag\r\nthat LockBit checks for. The flag is enabled if the corresponding byte is 0xFF, and it’s disabled if the\r\ncorresponding byte is 0xAA.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 15 of 111\n\nFigure 19: Configuration Flags.\r\nBelow are the flags and their order in the array.\r\nIndex 0: Disable UAC bypass\r\nIndex 1: Enable self deletion\r\nIndex 2: Enable logging\r\nIndex 3: Enable network traversal for file encryption\r\nIndex 4, 5, 6: If all 3 are set, set group policies for Active Directory\r\nIndex 7: Set registry for LockBit’s extension default icon\r\nIndex 8: Print ransom note to network printer\r\nPrivilege Escalation \u0026 Relaunch\r\nIn its first attempt, LockBit tries to privilege escalate if the user that runs the ransomware process is a service\r\naccount.\r\nFirst, the malware resolves NtOpenProcessToken and calls it to retrieve a handle for its own process’s token.\r\nNext, it calls GetTokenInformation using that token handle to retrieve information about the user associated with\r\nthat token.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 16 of 111\n\nFigure 20: Privilege Escalation: Retrieving Token \u0026 User Information.\r\nNext, LockBit calls AllocateAndInitializeSid to create an SID with S-1-5-18 as the SID identifier authority,\r\nwhich is an SID of a service account that is used by the operating system. It then calls EqualSid to compare the\r\ncurrent user’s SID with the service account SID to check if the current user is a service account.\r\nFigure 21: Privilege Escalation: Checking Service Account Privilege.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 17 of 111\n\nIf the current user account is a service account, LockBit begins to escalate itself.\r\nFirst, it calls LoadLibraryA to load “Wtsapi32.dll” into memory and calls GetProcAddress to retrieve the\r\naddress of WTSQueryUserToken. Then, it calls GetModuleFileNameW to retrieve a full path to its own\r\nransomware executable.\r\nFigure 22: Privilege Escalation: Retrieving Path Of Ransomware Executable.\r\nNext, the malware calls WTSQueryUserToken with the session ID of\r\nINTERNAL_TS_ACTIVE_CONSOLE_ID (0x7FFE02D8) to retrieve the primary access token for the active\r\nTerminal Services console session. If this function fails, the malware calls CreateProcessW to relaunch its own\r\nexecutable as an interactive process with “winsta0\\default” as the default interactive session.\r\nFigure 23: Privilege Escalation: Unable To Get Active Terminal Services Console Session \u0026 Relaunching.\r\nIf the WTSQueryUserToken call is executed successfully, LockBit calls DuplicateTokenEx to duplicate the\r\nTerminal Services console token and uses that duplicate token to create an elevated process to launch itself\r\nthrough CreateProcessAsUserW.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 18 of 111\n\nFigure 24: Privilege Escalation: Impersonating Active Terminal Services Console \u0026 Escalating.\r\nOnce the new process is spawned, the malware process calls ExitProcess to terminate itself.\r\nLogging\r\nIf the configuration flag at index 2 is set, LockBit logs its process in a separately running window.\r\nThe malware spawns a thread to manually set up the UI for the window through a lot of Bitmap shenanigans, but I\r\nwon’t cover how it does that because I’m too burned out as I’m writing this blog lol.\r\nThe log window setup function first calls GetModuleHandleW to retrieve the handle of the running executable.\r\nNext, the malware populates a WNDCLASSEXW structure using this handle as the instance of the logging\r\nwindow. The window procedure field of the structure is set to a function that will handle logging communication\r\nbetween the main ransomware process and the window. Again, I won’t cover this since I do indeed value my\r\nmental health!\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 19 of 111\n\nFigure 25: Logging: Setting Up Logging Window Structure.\r\nAfter finishing populating the WNDCLASSEXW structure, the malware calls RegisterClassExW to registers the\r\nwindow class and calls CreateWindowExW to create the logging window with “LockBit_2_0_Ransom” as the\r\nclass name and “LockBit 2.0 Ransom” as the window name.\r\nFigure 26: Logging: Creating Logging Window.\r\nAfter creating the window, LockBit calls ShowWindow with the SW_HIDE flag to hide it and UpdateWindow\r\nto update this change.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 20 of 111\n\nFigure 27: Logging: Auto Hiding Logging Window.\r\nTo be able to display this window manually, LockBit developers add a call to RegisterHotKey to register the\r\nShift + F1 combination with the hot key ID of 1, which will communicate with the window process to call\r\nShowWindow with the SW_SHOW flag to display itself. There is also another call to RegisterHotKey to\r\nregister the F1 key with the hot key ID of 2, which will hide the logging window if it’s displayed.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 21 of 111\n\nFigure 28: Logging: Registering Hot Keys to Hide/Unhide Logging Window.\r\nEach time the main thread wants to display a logging message, it calls a function that internally calls\r\nSendMessageA to send that message to the logging window.\r\nFigure 29: Logging: Main Thread Sending Logging Messages.\r\nBelow is the UI of the logging window.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 22 of 111\n\nFigure 30-31: Logging: General UI.\r\nCommand-line Arguments\r\nLockBit can run with or without command-line arguments.\r\nCommand-line arguments can come in the form of a path to a file or a folder to be processed. Execution is\r\nterminated once the target file/folder are encrypted.\r\nMasquerade Explorer \u0026 UAC Bypass\r\nBefore performing UAC bypass, LockBit first checks if it has admin privilege. This is done by calling\r\nNtOpenProcessToken to retrieve the handle for the ransomware process’s token and NtQueryInformationToken\r\nto retrieve the token’s elevation information and return if the token is elevated.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 23 of 111\n\nFigure 32: Checking Admin Privilege.\r\nIf the process is elevated or the configuration flag at index 0 is set, UAC bypass is skipped.\r\nTo begin UAC bypass, the malware checks if the process is in the administrator group. It calls\r\nNtOpenProcessToken to retrieve a handle to the current process and CreateWellKnownSid to create an SID\r\nwith type WinBuiltinAdministratorsSid.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 24 of 111\n\nFigure 33: Creating Admin SID.\r\nNext, LockBit calls CheckTokenMembership to check if the current process is a member of the admin SID\r\ngroup, then UAC bypass is skipped.\r\nIf the current process is not a member of the group, the malware calls NtQueryInformationToken to retrieve a\r\nhandle to a token that is linked with the current process and calls CheckTokenMembership again to check if the\r\nlinked token is a member of the admin SID group.\r\nFigure 34: Checking Token Membership For Admin Group.\r\nIf the token is in the admin group, the malware masquerades explorer.exe to bypass UAC.\r\nFirst, it calls NtAllocateVirtualMemory to allocate a virtual buffer and writes the Windows directory path\r\nappended by ”\\explorer.exe” in.\r\nFigure 35, 36: Allocating \u0026 Populating Explorer Path.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 25 of 111\n\nNext, LockBit calls RtlInitUnicodeString to convert the Explorer path to a unicode string and writes it in the\r\nprocess’s image path name. It also makes another call to RtlInitUnicodeString to convert “explorer.exe” to a\r\nunicode and writes it in the process’s command-line.\r\nFigure 37: Modifies Process’s Image Path \u0026 Command-line.\r\nThen, the malware calls RtlReleasePebLock to release the PEB lock and LdrEnumerateLoadedModules to\r\nenumerate all loaded modules in memory and calls a function to find and masquerade explorer.exe.\r\nFigure 38: Enumerates To Find \u0026 Masquerade Explorer.\r\nFor each loaded module, the callback function checks if the module’s base address is the same as LockBit base\r\naddress to find the data table entry corresponding to the malware process in memory.\r\nIf the context of the callback function is to masquerade Explorer, the function stores LockBit’s full name and base\r\nname into global variables to later restore them. Then, the full Explorer path is used as the new full executable\r\nname for LockBit’s data table entry.\r\nFigure 39: Module Enumerate Callback Function.\r\nFinally, the function calls RtlInitUnicodeString to write the full Explorer path to LockBit’s entry’s full DLL\r\nname and “explorer.exe” as the base DLL name, which now masquerades the LockBit process as an Explorer\r\nprocess.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 26 of 111\n\nFigure 40: Masquerading LockBit As Explorer.\r\nMasquerading as Explorer, LockBit starts performing UAC bypass.\r\nIt first resolves the address of CoInitializeEx and CoUninitialize by calling GetProcAddress. Then, the malware\r\ncalls CoInitializeEx to initializes the COM library for apartment-threaded object concurrency.\r\nFigure 41: Initializing COM Library.\r\nThen, LockBit basically performs UAC bypass using ColorDataProxy/CCMLuaUtil COM interfaces. The\r\nsource code of this technique can be viewed here, so I won’t dive into it.\r\nRun-once Mutant\r\nLockBit avoids having multiple ransomware instances running at once by checking for a specific mutant object.\r\nFirst, it decodes the following stack string “\\BaseNamedObjects\\{\\%02X%02X%02X%02X-%02X%02X-\r\n%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X}” and calls wsprintfW to write the\r\nformatted data into a buffer. Each formatted field corresponds to a byte at a specific index of LockBit’s hard-coded public key.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 27 of 111\n\nFigure 42: Populating Mutant Name.\r\nLockBit then calls RtlInitUnicodeString to convert the mutant name into a Unicode string and NtCreateMutant\r\nto try opening a mutant with the specified name. If the result is STATUS_OBJECT_NAME_COLLISION, the\r\nmalware terminates by calling ExitProcess to avoid having multiple running instances.\r\nFigure 43: Opening Mutant \u0026 Checking For Name Collision.\r\nSetting Group Policy For Active Directory\r\nChecking If Running On Primary Domain Controller\r\nIf the malware process has admin privilege, the OS version is Windows Vista and above, and any of the\r\nconfiguration flags at index 4, 5, 6 is set, LockBit tries to create and set new group policies for other hosts\r\nthrough Active Directory.\r\nFirst, LockBit checks if it’s currently executed on a primary domain controller. It calls GetComputerNameW to\r\nretrieve the NetBIOS name of the local computer that it’s running on.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 28 of 111\n\nFigure 44: Group Policy: Retrieving PC Name.\r\nThen, the malware calls NetGetDCName to retrieve the name of the primary domain controller and lstrcmpiW to\r\ncompare the local PC name with that DC name.\r\nFigure 45: Group Policy: Checking If PC Is The Primary Domain Controller.\r\nRetrieving DNS Domain Name\r\nIf LockBit is running on the domain controller, it tries to retrieve the DNS domain name. First, the malware calls\r\nNtOpenProcessToken to get the handle to the process’s token and NtQueryInformationToken_1 to retrieve\r\ninformation about the user corresponding to that token.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 29 of 111\n\nFigure 46: Group Policy: Retrieving User Information.\r\nNext, LockBit calls GetWindowsAccountDomainSid to retrieve the SID of the domain of the user’s SID. It then\r\ncalls CreateWellKnownSid to create an SID for the user’s domain admin group and CheckTokenMembership\r\nto check if the user has elevated privilege.\r\nFigure 47: Group Policy: Checking Admin Privilege.\r\nIf the user has admin privilege, LockBit calls GetComputerNameExW to retrieve the name of the DNS domain\r\nof the local computer.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 30 of 111\n\nFigure 48: Group Policy: Retrieving DNS Domain Name.\r\nRetrieving Domain Account Admin Name\r\nAfter doing the usual NtOpenProcessToken and NtQueryInformationToken routine to retrieve admin user\r\ntoken information, LockBit calls LookupAccountSidW to look up the admin’s account name and domain name.\r\nFigure 49: Group Policy: Retrieving Admin User Account \u0026 Domain Names.\r\nTo get the full domain admin name, LockBit resolves the stack string ”//” and builds the name with the format\r\n”\u003cdomain name\u003e//\u003caccount name\u003e”\r\nCOM Retrieve IGroupPolicyObject Interface\r\nTo retrieve the IGroupPolicyObject Interface, LockBit resolves and calls CoCreateInstance with the CLSID\r\n{EA502722-A23D-11D1-A7D3-0000F87571E3} and IID {EA502723-A23D-11d1-A7D3-0000F87571E3}.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 31 of 111\n\nFigure 50: Group Policy: Retrieve IGroupPolicyObject Interface.\r\nConnect To Active Directory Domain\r\nTo connect to the AD domain, LockBit first generates the LDAP display name for the Group Policy Object (GPO)\r\nby resolving the stack string “%02X%02X%02X%02X%02X%02X%02X” and formats it with values from its\r\npublic key.\r\nFigure 51: Group Policy: Building LDAP Display Name For GPO.\r\nNext, the malware manually extracts two domain components from the DNS domain name and formats the string\r\n“LDAP://\u003cDomain Controller name\u003e.\u003cDNS domain name\u003e/DC=\u003cDomain component 1\u003e,DC=\u003cDomain\r\nComponent 2\u003e”. This string is used as the AD domain name when LockBit calls the method\r\nIGroupPolicyObject::New to create the GPO. Then, it calls IGroupPolicyObject::GetName to get the GUID\r\ncorresponding to the created GPO.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 32 of 111\n\nFigure 52: Group Policy: Creating GPO.\r\nNext, LockBit builds the Active Directory path by formatting the string “LDAP://DC=\u003cDomain component\r\n1\u003e,DC=\u003cDomain Component 2\u003e”.\r\nFigure 53: Group Policy: Building Active Directory Path.\r\nLockBit also builds the GPO path by formatting the string “LDAP://CN=\u003cGPO\r\nGUID\u003e,CN=Policies,CN=System,DC=\u003cDomain component 1\u003e,DC=\u003cDomain Component 2\u003e”\r\nFinally, the Active Directory path and the GPO path are used to call CreateGPOLink to connect the GPO to the\r\nspecified Active Directory domain.\r\nFigure 54: Group Policy: Connecting GPO To Active Directory Domain.\r\nSetting GPO’s attributes\r\nTo modify the GPO to inject LockBit’s custom policies, it first needs to update the object’s client-side extensions\r\n(CSEs). This requires setting the GPO’s attributes gPCMachineExtensionNames and\r\ngPCUserExtensionNames.\r\nFirst, given the GPO’s path, LockBit calls ADsGetObject to retrieve an object of the IADs interface\r\ncorresponding to the GPO using the IID {FD8256D0-FD15-11CE-ABC4-02608C9E7553}.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 33 of 111\n\nFigure 55: Group Policy: Retrieving IADs Object.\r\nNext, to set the GPO’s gPCMachineExtensionNames attribute, LockBit creates a VARIANT structure\r\ncontaining the following extension pairs for the desired GPO modification.\r\n[{00000000-0000-0000-0000-000000000000}{BFCBBEB0-9DF4-4C0C-A728-434EA66A0373}{CC5746A9-9B74-4BE5-AE2E-64379C86E\r\n[{35378EAC-683F-11D2-A89A-00C04FBBCFA2}{D02B1F72-3407-48AE-BA88-E8213C6761F1}]\r\n[{6A4C88C6-C502-4F74-8F60-2CB23EDC24E2}{BFCBBEB0-9DF4-4C0C-A728-434EA66A0373}]\r\n[{91FBB303-0CD5-4055-BF42-E512A681B325}{CC5746A9-9B74-4BE5-AE2E-64379C86E0E4}]\r\nFigure 56: Group Policy: Populating gPCMachineExtensionNames Variant.\r\nNext, it resolves the stack string “gPCMachineExtensionNames” and calls IADs::Put to set the value of the\r\ngPCMachineExtensionNames for the GPO to the value in the VARIANT structure.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 34 of 111\n\nFigure 57: Group Policy: Setting GPO’s gPCMachineExtensionNames Attribute.\r\nSimilarly, LockBit sets the GPO’s gPCUserExtensionNames attribute with the following extension pairs.\r\n[{00000000-0000-0000-0000-000000000000}{3BAE7E51-E3F4-41D0-853D-9BB9FD47605F}{CAB54552-DEEA-4691-817E-ED4A4D1AF\r\n[{7150F9BF-48AD-4DA4-A49C-29EF4A8369BA}{3BAE7E51-E3F4-41D0-853D-9BB9FD47605F}]\r\n[{AADCED64-746C-4633-A97C-D61349046527}{CAB54552-DEEA-4691-817E-ED4A4D1AFC72}]\r\nFigure 58: Group Policy: Setting GPO’s gPCUserExtensionNames Attribute.\r\nThe malware also sets the GPO’s versionNumber attribute to “2621892”.\r\nFigure 59: Group Policy: Setting GPO’s versionNumber Attribute.\r\nUpdating GPT.INI\r\nNext, LockBit locates the root GPO GUID directory that contains a file called “GPT.ini. By updating the Version\r\nproperty inside this file, LockBit can signal to gpupdate that there is a new modification to apply the new\r\nsettings.\r\nFirst, using the IGroupPolicyObject object, the malware calls IGroupPolicyObject::GetFileSysPath to retrieve\r\nthe root GPO GUID directory. It also calls IGroupPolicyObject::GetDisplayName to get the GPO’s display\r\nname.\r\nFigure 60: Group Policy: Retrieving Root GPO Directory \u0026 Display Name.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 35 of 111\n\nNext, LockBit resolves the stack string “GPT.INI” and appends it to the root directory by calling\r\nPathAppendW. Using this GPT.INI path, the malware calls CreateFileW to get the handle to that file.\r\nFigure 61: Group Policy: Retrieving The Handle To GPT.INI.\r\nThen, the malware formats the following string and converts it into multibyte string by calling\r\nWideCharToMultiByte.\r\n[General]\r\nVersion=2621892\r\ndisplayName=\u003cGPO display name\u003e\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 36 of 111\n\nFigure 62, 63: Group Policy: Generating New GPT.INI Content.\r\nFinally, LockBit calls WriteFile to write the updated content into the GPO’s GPT.INI file to signal gpupdate.\r\nFigure 64: Group Policy: Writing New GPT.INI Content.\r\nUpdating the GPO Folder\r\nThe next part is for LockBit to drop group policy XML files into the GPO’s Machine Preferences folder (\u003cGPO\r\nGUID\u003e\\MACHINE\\Preferences) on the domain controller machine.\r\nThese files specify new group policies for the Domain Controller to push out to the network. Below is the list of\r\nthese files and their destinations:\r\n\u003cGPO GUID\u003e\\MACHINE\\Preferences\\NetworkShares\\NetworkShares.xml\r\n\u003cGPO GUID\u003e\\MACHINE\\Preferences\\Services\\Services.xml\r\n\u003cGPO GUID\u003e\\MACHINE\\Preferences\\Files\\Files.xml\r\n\u003cGPO GUID\u003e\\MACHINE\\Preferences\\ScheduledTasks\\ScheduledTasks.xml:\r\nC:\\Windows\\System32\\taskkill.exe\u003c/Command\u003e/IM #proc_name for each process in\r\nWIDESTR_PROCESSES_EXE_LIST # /F\r\n\u003cGPO GUID\u003e\\MACHINE\\Registry.pol\r\n\u003cGPO GUID\u003e\\MACHINE\\comment.cmtx\r\nFirst, the NetworkShares.xml below is formatted to define a network share for each drive on the network hosts\r\nonce the Domain Controller pushes it out. This will share all each host’s drives on the network for LockBit to\r\nencrypt them.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 37 of 111\n\n\u003c?xml version=\"1.0\" encoding=\"UTF-8\"?\u003e\r\n\u003cNetworkShareSettings clsid=\"{520870D8-A6E7-47e8-A8D8-E6A4E76EAEC2}\"\u003e\r\n \u003cNetShare clsid=\"{2888C5E7-94FC-4739-90AA-2C1536D68BC0}\" image=\"2\" name=\"%%ComputerName%%_D\" changed=\"%s\" uid\r\n \u003cProperties action=\"U\" name=\"%%ComputerName%%_D\" path=\"D:\" comment=\"\" allRegular=\"0\" allHidden=\"0\" allAdmi\r\n \u003c/NetShare\u003e\r\n \u003cNetShare clsid=\"{2888C5E7-94FC-4739-90AA-2C1536D68BC0}\" image=\"2\" name=\"%%ComputerName%%_E\" changed=\"%s\" uid\r\n \u003cProperties action=\"U\" name=\"%%ComputerName%%_E\" path=\"E:\" comment=\"\" allRegular=\"0\" allHidden=\"0\" allAdmi\r\n \u003c/NetShare\u003e\r\n \u003cNetShare clsid=\"{2888C5E7-94FC-4739-90AA-2C1536D68BC0}\" image=\"2\" name=\"%%ComputerName%%_F\" changed=\"%s\" uid\r\n \u003cProperties action=\"U\" name=\"%%ComputerName%%_F\" path=\"F:\" comment=\"\" allRegular=\"0\" allHidden=\"0\" allAdmi\r\n \u003c/NetShare\u003e\r\n \u003cNetShare clsid=\"{2888C5E7-94FC-4739-90AA-2C1536D68BC0}\" image=\"2\" name=\"%%ComputerName%%_G\" changed=\"%s\" uid\r\n \u003cProperties action=\"U\" name=\"%%ComputerName%%_G\" path=\"G:\" comment=\"\" allRegular=\"0\" allHidden=\"0\" allAdmi\r\n \u003c/NetShare\u003e\r\n \u003cNetShare clsid=\"{2888C5E7-94FC-4739-90AA-2C1536D68BC0}\" image=\"2\" name=\"%%ComputerName%%_H\" changed=\"%s\" uid\r\n \u003cProperties action=\"U\" name=\"%%ComputerName%%_H\" path=\"H:\" comment=\"\" allRegular=\"0\" allHidden=\"0\" allAdmi\r\n \u003c/NetShare\u003e\r\n \u003cNetShare clsid=\"{2888C5E7-94FC-4739-90AA-2C1536D68BC0}\" image=\"2\" name=\"%%ComputerName%%_I\" changed=\"%s\" uid\r\n \u003cProperties action=\"U\" name=\"%%ComputerName%%_I\" path=\"I:\" comment=\"\" allRegular=\"0\" allHidden=\"0\" allAdmi\r\n \u003c/NetShare\u003e\r\n \u003cNetShare clsid=\"{2888C5E7-94FC-4739-90AA-2C1536D68BC0}\" image=\"2\" name=\"%%ComputerName%%_J\" changed=\"%s\" uid\r\n \u003cProperties action=\"U\" name=\"%%ComputerName%%_J\" path=\"J:\" comment=\"\" allRegular=\"0\" allHidden=\"0\" allAdmi\r\n \u003c/NetShare\u003e\r\n \u003cNetShare clsid=\"{2888C5E7-94FC-4739-90AA-2C1536D68BC0}\" image=\"2\" name=\"%%ComputerName%%_K\" changed=\"%s\" uid\r\n \u003cProperties action=\"U\" name=\"%%ComputerName%%_K\" path=\"K:\" comment=\"\" allRegular=\"0\" allHidden=\"0\" allAdmi\r\n \u003c/NetShare\u003e\r\n \u003cNetShare clsid=\"{2888C5E7-94FC-4739-90AA-2C1536D68BC0}\" image=\"2\" name=\"%%ComputerName%%_L\" changed=\"%s\" uid\r\n \u003cProperties action=\"U\" name=\"%%ComputerName%%_L\" path=\"L:\" comment=\"\" allRegular=\"0\" allHidden=\"0\" allAdmi\r\n \u003c/NetShare\u003e\r\n \u003cNetShare clsid=\"{2888C5E7-94FC-4739-90AA-2C1536D68BC0}\" image=\"2\" name=\"%%ComputerName%%_M\" changed=\"%s\" uid\r\n \u003cProperties action=\"U\" name=\"%%ComputerName%%_M\" path=\"M:\" comment=\"\" allRegular=\"0\" allHidden=\"0\" allAdmi\r\n \u003c/NetShare\u003e\r\n \u003cNetShare clsid=\"{2888C5E7-94FC-4739-90AA-2C1536D68BC0}\" image=\"2\" name=\"%%ComputerName%%_N\" changed=\"%s\" uid\r\n \u003cProperties action=\"U\" name=\"%%ComputerName%%_N\" path=\"N:\" comment=\"\" allRegular=\"0\" allHidden=\"0\" allAdmi\r\n \u003c/NetShare\u003e\r\n \u003cNetShare clsid=\"{2888C5E7-94FC-4739-90AA-2C1536D68BC0}\" image=\"2\" name=\"%%ComputerName%%_O\" changed=\"%s\" uid\r\n \u003cProperties action=\"U\" name=\"%%ComputerName%%_O\" path=\"O:\" comment=\"\" allRegular=\"0\" allHidden=\"0\" allAdmi\r\n \u003c/NetShare\u003e\r\n \u003cNetShare clsid=\"{2888C5E7-94FC-4739-90AA-2C1536D68BC0}\" image=\"2\" name=\"%%ComputerName%%_P\" changed=\"%s\" uid\r\n \u003cProperties action=\"U\" name=\"%%ComputerName%%_P\" path=\"P:\" comment=\"\" allRegular=\"0\" allHidden=\"0\" allAdmi\r\n \u003c/NetShare\u003e\r\n \u003cNetShare clsid=\"{2888C5E7-94FC-4739-90AA-2C1536D68BC0}\" image=\"2\" name=\"%%ComputerName%%_Q\" changed=\"%s\" uid\r\n \u003cProperties action=\"U\" name=\"%%ComputerName%%_Q\" path=\"Q:\" comment=\"\" allRegular=\"0\" allHidden=\"0\" allAdmi\r\n \u003c/NetShare\u003e\r\n \u003cNetShare clsid=\"{2888C5E7-94FC-4739-90AA-2C1536D68BC0}\" image=\"2\" name=\"%%ComputerName%%_R\" changed=\"%s\" uid\r\n \u003cProperties action=\"U\" name=\"%%ComputerName%%_R\" path=\"R:\" comment=\"\" allRegular=\"0\" allHidden=\"0\" allAdmi\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 38 of 111\n\nNetShare\u003e NetShare\u003e NetShare\u003e NetShare\u003e NetShare\u003e NetShare\u003e NetShare\u003e NetShare\u003e\nNext, the Services.xml below is formatted to add policies to stop and disable certain services on the AD hosts.\nThe list of stopped services are:\n\"SQLPBDMS\", \"SQLPBENGINE\", \"MSSQLFDLauncher\", \"SQLSERVERAGENT\", \"MSSQLServerOLAPService\",\n\"SSASTELEMETRY\", \"SQLBrowser\", \"SQL Server Distributed Replay Client\",\n\"SQL Server Distributed Replay Controller\", \"MsDtsServer150\", \"SSISTELEMETRY150\",\n\"SSISScaleOutMaster150\", \"SSISScaleOutWorker150\", \"MSSQLLaunchpad\", \"SQLWriter\", \"SQLTELEMETRY\", \"MSSQLSERVER\"\n?xml version=\"1.0\" encoding=\"UTF-8\"?\u003e\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\nPage 39 of 111\n\nNTService\u003e NTService\u003e Before dropping the Files.xml file, LockBit self-propagates to the Domain Controller’s SYSVOL folder.\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\nPage 40 of 111\n\nFirst, the malware calls GetModuleFileNameW to get its own executable path and builds the following new path.\r\n%SystemRoot%\\SYSVOL_DFSR\\sysvol\\\u003cDomain DNS name\u003e\\siripts\r\nThen, it calls CopyFileW to copy its executable to this siripts file. Since SYSVOL is a directory for all public\r\nActive Directory files, the malicious executable is now accessible to all hosts on the network domain.\r\nFigure 65 66: Group Policy: Propagating Self To SYSVOL.\r\nFinally, LockBit formats and drops the Files.xml file below. The fromPath field’s value is formatted to the\r\nexecutable path in the SYSVOL folder, and the targetPath field’s value is set to\r\n%%DesktopDir%%\\%02X%02X%02X.exe, which is formatted using LockBit’s public key. Ultimately, this\r\nfile’s policy is dropping the malicious executable from the Domain Controller’s SYSVOL directory to every\r\nnetwork host’s Desktop directory.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 41 of 111\n\nFigure 67: Group Policy: Generating Desktop Drop Path.\n?xml version=\"1.0\" encoding=\"UTF-8\"?\u003e\nThe raw ScheduledTasks.xml content is documented below. This file contains the policy to terminate the\nspecified processes in the configuration’s process list.\n?xml version=\"1.0\" encoding=\"UTF-8\"?\u003e\n%s%sInteractiveTokenHighestAvailablePT10MPT1HfalsefalseIgnoreNewfalsefalsetruetruetruefalseP3D7 https://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\nPage 42 of 111\n\ntrue %s %s LockBit formats this to execute a taskkill.exe for each of the process in the configuration’s process list. This is\ndone through crafting these tags and include them in the main ScheduledTasks.xml file where the\n“Process_Name” field is the name of the process to be terminated.\nC:\\Windows\\System32\\taskkill.exe/IM \"Process_Name\" /F Finally, LockBit drops the Registry.pol file and the comment.cmtx file below.\n?xml version=\"1.0\" encoding=\"UTF-8\"?\u003e\nThe Registry.pol contains the following list of registry paths and the values to configure them.\nSoftware\\Policies\\Microsoft\\Windows Defender\\DisableAntiSpyware: True\nSoftware\\Policies\\Microsoft\\Windows Defender\\Real-Time Protection\\DisableRealtimeMonitoring:\nTrue\nSoftware\\Policies\\Microsoft\\Windows Defender\\Spynet\\SubmitSamplesConsent: Never send\nSoftware\\Policies\\Microsoft\\Windows Defender\\Threats\\Threats_ThreatSeverityDefaultAction:\nEnabled\nSoftware\\Policies\\Microsoft\\Windows Defender\\Threats\\ThreatSeverityDefaultAction\\Low: Ignored\nSoftware\\Policies\\Microsoft\\Windows Defender\\Threats\\ThreatSeverityDefaultAction\\Medium:\nIgnored\nSoftware\\Policies\\Microsoft\\Windows Defender\\Threats\\ThreatSeverityDefaultAction\\High: Ignored\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\nPage 43 of 111\n\nSoftware\\Policies\\Microsoft\\Windows Defender\\Threats\\ThreatSeverityDefaultAction\\Severe:\r\nIgnored\r\nSoftware\\Policies\\Microsoft\\Windows Defender\\UX Configuration\\Notification_Suppress: Enabled\r\nThese following registry configurations disable Windows Defender features such as anti-spyware, real-time\r\nprotection, submitting samples to Microsoft servers, default actions, and displaying notification on all network\r\nhosts.\r\nForcing GPUpdate On All Hosts Through PowerShell\r\nAfter adding these new policies, LockBit calls Sleep to wait for 1 minute for the changes to be applied before\r\ncreating a process to invoke gpupdate.exe to run on these network hosts.\r\nFirst, using an IADs object from the Domain Controller’s rootDSE, the malware calls IADs::Get to retrieve the\r\ndefault naming context to retrieve the name of the Active Directory domain.\r\nFigure 68: Group Policy: Retrieving AD Domain Name.\r\nNext, LockBit formats the following command where the search base is set to the Active Directory domain name.\r\nThis Powershell command search through all computers on the Active Directory domain, and for each found, it\r\nforce-invokes GPUpdate on that host to apply the new Group Policy changes. The malware launches this\r\ncommand by calling CreateProcessW.\r\npowershell.exe -Command \"Get-ADComputer -filter * -Searchbase '%s' | foreach{ Invoke-GPUpdate -computer $_.name\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 44 of 111\n\nFigure 69: Group Policy: Launching Powershell Command To Force GPUpdate.\r\nForcing GPUpdate On All Hosts Manually\r\nIf the above fails, LockBit attempts to force running GPUpdate manually.\r\nAfter retrieving the name of the Active Directory domain, the malware appends it to “LDAP://” to build the full\r\ndomain path and calls ADsOpenObject to retrieve an IDirectorySearch object to perform queries on AD hosts.\r\nFigure 70: Group Policy: Getting IDirectorySearch Object.\r\nNext, LockBit calls IDirectorySearch::SetSearchPreference to set the search preference to\r\nADS_SEARCHPREF_SEARCH_SCOPE and IDirectorySearch::ExecuteSearch to search for the name of\r\neach computer in the AD domain.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 45 of 111\n\nFigure 71, 72: Group Policy: Executing AD Search For PC Names.\r\nNext, LockBit calls GetFirstRow and GetNextRow to iterate through each row of the search result. For each\r\nrow, it calls GetNextColumnName and GetColumn to get the data from each column of that row. The malware\r\naccesses the DNString field in each named column to retrieve a Distinguished Name (DN) of a network host in\r\nthe domain. Given the host name, LockBit calls CreateThread to launch a thread to manually execute GPUpdate\r\nand force the host to restart.\r\nFigure 73, 74: Group Policy: Enumerating AD Hosts’ Distinguished Name.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 46 of 111\n\nThe thread function only executes if the malware is currently running on a Domain Controller.\r\nFirst, LockBit calls CoCreateInstance to retrieve an ITaskService object and calls ITaskService::Connect to\r\nestablish a connection to the network host using its DN.\r\nFigure 75, 76: Group Policy: Connecting To AD Hosts.\r\nNext, it calls ITaskService::GetFolder to retrieve an ITaskFolder objet corresponding to a folder of registered\r\ntasks and calls ITaskFolder::DeleteTask to delete any existing task for this specific host.\r\nLockBit then calls ITaskService::NewTask to create a new task for the network host.\r\nFigure 77: Group Policy: Creating New Task.\r\nAfter retrieving the IPrincipal object, the malware calls IPrincipal::put_LogonType to set the task to be started\r\nin the user’s interactive logon session. It also calls IPrincipal::put_RunLevel to set the task to run with the least\r\nprivileges.\r\nFigure 78: Group Policy: Setting Task Properties.\r\nAfter retrieving the ITaskDefinition object, LockBit calls ITaskDefinition::get_Triggers to retrieve an\r\nITriggerCollection object. It then calls ITriggerCollection::Create to create a new trigger for the task which is\r\ntriggered when the task is registered.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 47 of 111\n\nFigure 79: Group Policy: Creating Trigger For Task.\r\nUsing the ITaskDefinition object, the malware also calls ITaskDefinition::get_Actions to retrieve an\r\nIActionCollection object. It then calls IActionCollection::Create to create a new action for the task specifying\r\nthat it is an executable action.\r\nFigure 80: Group Policy: Creating Executable Action For Task.\r\nNext, using the action object IExecAction, LockBit calls IExecAction::put_Path to set the path of the\r\nexecutable action to “gpupdate.exe”.\r\nFigure 81: Group Policy: Setting Action Path To gpupdate.exe.\r\nNext, it calls IExecAction::put_Arguments to put “/force” the executable’s argument,\r\nITaskFolder::RegisterTaskDefinition to register the task’s definition, and IRegisteredTask::Run to run the task\r\nimmediately.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 48 of 111\n\nFigure 82: Group Policy: Registering \u0026 Force-Running GPUpdate Task.\r\nThis will run GPUpdate on the network host immediately and whenever someone is logging into the host, which\r\nwill then apply the Group Policy changes from the Domain Controller.\r\nFinally, LockBit forces the network host to restart itself.\r\nIt does this by calling CoCreateInstance to retrieve an IWbemLocator object. Using the object, it calls\r\nIWbemLocator::ConnectServer to connect to ”\\\\\u003cAD Host Name\u003e\\ROOT\\CIMV2”.\r\nFigure 83: Group Policy: Connecting To Host’s ROOT\\CIMV2 Namespace.\r\nNext, the malware calls IWbemServices::GetObjectA to retrieve an IWbemClassObject object corresponding\r\nto all Win32 processes on the network host. Using this object, it calls IWbemClassObject::GetMethod to\r\nretrieve an IWbemClassObject object corresponding to a method to create processes. Then, it calls\r\nIWbemClassObject::SpawnInstance to create a new instance of the process creation method.\r\nFigure 84: Group Policy: Process Creation Method.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 49 of 111\n\nFinally, it resolves the stack string “cmd.exe /c “shutdown.exe /r /f /t 0”“, calls IWbemClassObject::Put with\r\nthe property name “CommandLine”, and IWbemServices::ExecMethod to execute the process creation method\r\nto spawn a command-line process to execute the command above.\r\nThis command forces running applications to close without warning users and restarts the computer after shutting\r\ndown immediately.\r\nFigure 85: Group Policy: Executing Command To Restart.\r\nPersistence Registry\r\nPrior to executing encryption routines, LockBit sets up persistence through the registry in case the malware gets\r\ninterrupted by the system shutting down midway through.\r\nFirst, the malware resolves the stack string “SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run” and calls\r\nRegCreateKeyExA to get the handle to this registry key.\r\nFigure 86: Retrieving Persistence Registry Key Handle.\r\nFirst, the malware resolves the stack string ”{\\%02X%02X%02X%02X-%02X%02X-%02X%02X-\r\n%02X%02X-%02X%02X%02X%02X%02X%02X}” and formats it using its public key. This formatted string\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 50 of 111\n\nwill be used as the value name to set up the persistence registry key.\r\nFigure 87: Generating Persistence Registry Key Value Name.\r\nNext, the malware calls RegQueryValueExW to retrieve the data at the registry key above. If this is successful,\r\nLockBit tests to see if the data is correct by calling lstrcmpiW to compare it with the malware executable path. If\r\nretrieving the data fails because the registry value has not been set or the data inside is incorrect, the malware calls\r\nRegSetValueExW to set the data to its own path to establish persistence.\r\nFigure 88: Establishing Persistence Through Registry.\r\nOnce the encryption is finished, the malware removes this persistence key by calling RegDeleteValueW to\r\nprevent itself from running again if the user decides to restart their encrypted machine.\r\nFigure 89: Removing Persistence Registry Key Post-Encryption.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 51 of 111\n\nSet LockBit Default Icon\r\nBecause all files encrypted by LockBit have the extension .lockbit, the malware attempts to change the registry to\r\nset up the default icon for this extension using an embedded icon file in memory. This is only executed when the\r\nmalware has admin privilege and the configuration flag at index 7 is set.\r\nFigure 90: LockBit Default Icon For .lockbit Extension.\r\nFirst, LockBit resolves the stack string ”\\??\\C:\\windows\\system32\\%02X%02X%02X.ico” and formats it using\r\nits public key.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 52 of 111\n\nFigure 91: Generating Icon File Path.\r\nNext, using this file path, the malware calls NtCreateFile to retrieve a handle to this file in the System32 folder. It\r\nalso calls NtWriteFile to write the embedded icon file content into this file.\r\nFigure 92: Writing Icon File.\r\nLockBit then resolves the stack string “\\Registry\\Machine\\Software\\Classes\\.lockbit” and calls NtCreateKey\r\nto create this registry key corresponding to the “.lockbit” extension.\r\nFigure 93: Creating .lockbit Extension Registry Key.\r\nIf the registry key above is created sucessfully, LockBit resolves the stack string\r\n“\\Registry\\Machine\\Software\\Classes\\.lockbit\\DefaultIcon” string, calls NtCreateKey to create this registry\r\nkey, and calls NtSetValueKey to set the data of the DefaultIcon value to the icon file path in System32.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 53 of 111\n\nFigure 94: Creating \u0026 Setting .lockbit Extension DefaultIcon Registry Key.\r\nFinally, LockBit resolves and calls SHChangeNotify with the event ID SHCNE_ASSOCCHANGED to notify\r\nthe system that a file type association has changed, which updates all files with extension .lockbit to have this\r\nparticular icon.\r\nFigure 95: Notifying \u0026 Applying Icon Change.\r\nPre-Encryption System Clean-Up\r\nBefore launching a thread to perform pre-encryption system clean-up, LockBit attempts to gain\r\nSeDebugPrivilege privilege. This privilege allows the malware to debug and freely access other processes in the\r\nsystem.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 54 of 111\n\nFirst, it calls NtOpenProcessToken to retrieve its own process token, LookupPrivilegeValueA to retrieve the\r\nlocally unique identifier (LUID) of the SeDebugPrivilege privilege, and NtAdjustPrivilegesToken to give itself\r\nthat privilege.\r\nFigure 96: Setting SeDebugPrivilege Privilege.\r\nStopping Services\r\nPrior to stopping all services in the configuration’s service list, LockBit resolves and calls\r\nWow64DisableWow64FsRedirection to disables file system redirection. Then, it calls OpenSCManagerA to\r\nretrieve a service control manager handle. With the handle, LockBit iterates through the configuration’s service\r\nlist and calls OpenServiceA to retrieve a handle to each service.\r\nFigure 97: Retrieving Each Target Service Handle.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 55 of 111\n\nNext, LockBit calls QueryServiceStatusEx to query the service’s process’s status. If the state of the service is\r\nSERVICE_STOPPED, it moves on to the next service in the list.\r\nFigure 98: Checking If Service Is Already Stopped.\r\nIf the service’s status is SERVICE_STOP_PENDING, LockBit calculates the time sleep based on the wait hint\r\nand wait until the pending status is over. After the Sleep call, the malware calls QueryServiceStatus to check if\r\nthe service is stopped.\r\nFigure 99: Processing Service’s Stop Pending Status.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 56 of 111\n\nLockBit does not wait forever if the SERVICE_STOP_PENDING status persists. It calls GetTickCount at the\r\nbeginning and when every time it checks for the SERVICE_STOPPED signal onward. If the time difference\r\n(timeout) is greater than 30 seconds, the malware moves on to the next service.\r\nFigure 100: Max Timeout For Service Processing.\r\nIf the service’s status is not SERVICE_STOP_PENDING or SERVICE_STOPPED, LockBit attempts to stop\r\nit.\r\nFirst, the malware tries to stop all dependent services of the target service. It does this by calling\r\nEnumDependentServicesA on the service handle to retrieve an ENUM_SERVICE_STATUSA array for all of\r\nthe dependent services.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 57 of 111\n\nFigure 101: Begins Dependent Services Enumeration.\r\nFor each dependent service, LockBit calls OpenServiceA with its name to retrieve its handle from the service\r\ncontrol manager. Then, it calls ControlService to send a SERVICE_CONTROL_STOP signal to stop the\r\ndependent service. After sending the signal, LockBit goes through the same status checking procedure above to\r\nensure each dependent service is fully stopped before moving on.\r\nFigure 102, 103: Stopping Dependent Services.\r\nFinally, LockBit calls ControlService to send a SERVICE_CONTROL_STOP signal to stop the main service.\r\nFigure 104: Stopping Main Service.\r\nTerminating Processes\r\nTo terminate all processes in the configuration’s process list, LockBit calls CreateToolhelp32Snapshot to get a\r\nsnapshot handle to all system’s processes.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 58 of 111\n\nFigure 105: Retrieving Process Snapshot Handle.\r\nNext, the malware calls Process32First and Process32Next with the snapshot handle to enumerate through all\r\nprocesses in the system. For each process, it calls PathRemoveExtensionA to remove the process’s file extension\r\nand lstrcmpiA to compare the process’s name to each in the configuration’s process list. If the process’s name is\r\nin the list, LockBit calls a function to terminate it.\r\nFigure 106: Retrieving Process Snapshot Handle.\r\nTo terminate a process, LockBit calls CreateToolhelp32Snapshot to get a snapshot handle and\r\nProcess32First/Process32Next to enumerate all processes. For each found process, the malware compares the\r\nprocess ID with the target’s ID to find the target process. LockBit then calls OpenProcess with the target process\r\nID to retrieve a handle to the process and calls NtTerminateProcess to terminate it.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 59 of 111\n\nFigure 107, 108: Terminating Each Target Process.\r\nDeleting Backups\r\nTo delete shadow copies, LockBit first resolves the following string.\r\n/c vssadmin delete shadows /all /quiet \u0026 wmic shadowcopy delete \u0026 bcdedit /set {default} bootstatuspolicy ignor\r\nThen, it passes the appropriate fields to ShellExecuteA to launch that command with cmd.exe. This command\r\nuses vssadmin and wmic to delete all shadow copies and bcdedit to disable file recovery.\r\nFigure 109: Launching Cmd.exe Command To Delete Backups Through ShellExecuteA.\r\nNext, LockBit resolves the following stack strings in an array of strings.\r\n- /c vssadmin Delete Shadows /All /Quiet\r\n- /c bcdedit /set {default} recoveryenabled No\r\n- /c bcdedit /set {default} bootstatuspolicy ignoreallfailures\r\n- /c wmic SHADOWCOPY /nointeractive\r\n- /c wevtutil cl security\r\n- /c wevtutil cl system\r\n- /c wevtutil cl application\r\nFinally, it iterates through this array and calls CreateProcessA to launch these commands from cmd.exe. Besude\r\nthe commands already ran before, the wevtutil commands clear all events from the security, system, and\r\napplication logs.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 60 of 111\n\nFigure 110: Launching Cmd.exe Command To Delete Backups Through CreateProcessA.\r\nPrinting Ransom Note To Printers\r\nIf the configuration flag at index 8 is set, the malware attempts to print the ransom note on the printers that the\r\nmachine is connected to.\r\nTo print the ransom note to physical printers, LockBit first calls EnumPrintersW to retrieve an enumerator for\r\nprinter’s information. Using the enumerator to enumerate printer names, the malware calls a function to print the\r\nransom note to each printer.\r\nFigure 111: Enumerating \u0026 Printing Ransom Note On All Printers.\r\nThe internal function resolves the two strings “Microsoft Print to PDF” and “Microsoft XPS Document\r\nWriter”, calls lstrcmpiW to compare them with the printer’s name. If the printer’s name is one of those two, the\r\nfunction exits, and the ransom note is not printed. This is to avoid printing the ransom note to a file on the system\r\nand only print the note to physical printers that the machine is connected to.\r\nFigure 111: Avoiding Print-to-file Drivers.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 61 of 111\n\nNext, LockBit populates a DOC_INFO_1 with the printer’s name and the printing data type as “RAW”. Then, it\r\ncalls StartDocPrinter to notify the print spooler that a document is to be spooled for printing and\r\nStartPagePrinter to notify the spooler that a page is about to be printed.\r\nFigure 113, 114, 115: Notifying Print Spooler About The Print Job.\r\nFinally, LockBit calls WritePrinter to print the ransom note physically on the printer.\r\nFigure 116: Printing Ransom Note On Printer.\r\nSetup Wallpaper\r\nTo setup the wallpaper on the victim’s machine, the malware first does some bitmap shenanigan to generate the\r\nwallpaper image with texts to notify the victim that their files have been encrypted. Because the function to\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 62 of 111\n\ngenerate this bitmap manually is almost as annoying as the function to set up the logging window UI, I will simply\r\nsay that this is some voodoo witchcraft stuff and pretend like the wallpaper is magically generated in this analysis!\r\nAfter creating the wallpaper image, LockBit calls GetTempPathW and GetTempFileNameW to retrieve a path\r\nto a temporary file in the %TEMP% folder.\r\nFigure 117: Generating A Temp Path For Storing The Wallpaper.\r\nWith the wallpaper bitmap object, the malware calls GdipSaveImageToFile to save the bitmap image to the\r\ntemporary file using a Bitmap decoder.\r\nNext, LockBit resolves the string “Control Panel\\Desktop” and calls RegOpenKeyA to retrieve a registry key\r\nhandle of that name. With the registry key handle, it calls RegSetValueExA to set the wallpaper style to “2” and\r\nthe TileWallpaper property to “0”.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 63 of 111\n\nFigure 118, 119, 120: Setting Registry For Wallpaper Properties.\r\nFinally, the malware calls SystemParametersInfoW to set the desktop wallpaper to the wallpaper stored that the\r\ntemporary path appended by “.bmp”.\r\nFigure 121: Setting Desktop Wallpaper.\r\nBelow is the generated Bitmap wallpaper.\r\nFigure 122: Setting Desktop Wallpaper.\r\nDropping Ransom HTML Application File\r\nBeside dropping ransom notes and changing the desktop’s wallpaper, LockBit also drops an HTML Application\r\n(HTA) file on the system and sets up the registry keys to open the file whenever an encrypted file with the .lockbit\r\nextension is ran.\r\nFirst, the malware generate the full path to drop the file to by calling SHGetFolderPathW to retrieve the folder’s\r\ncurrent path and appends “\\LockBit_Ransomware.hta” to the end.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 64 of 111\n\nFigure 123: Retrieving Full HTA Path.\r\nThe entire content of the HTA file is resolved as a stack string, so IDA and the decompiler have trouble displaying\r\nthis function. This kinda suck because I have to patch it over in order to be able to analyze the rest of the function.\r\nFigure 124: HTA File Encoded Content Being Pushed To The Stack.\r\nAfter resolving the file’s content, LockBit calls CreateFileW to create the HTA file at the path and calls\r\nWriteFile to write to it.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 65 of 111\n\nFigure 125: Dropping HTA File.\r\nNext, the malware sets up registry keys to open the HTA file whenever an encrypted file with the .lockbit\r\nextension is ran.\r\nFirst, LockBit resolves the following strings and calls NtCreateKey to create the registry keys corresponding to\r\nthem.\r\n\\Registry\\Machine\\Software\\Classes\\Lockbit\r\n\\Registry\\Machine\\Software\\Classes\\Lockbit\\DefaultIcon\r\n\\Registry\\Machine\\Software\\Classes\\Lockbit\\shell\r\n\\Registry\\Machine\\Software\\Classes\\Lockbit\\shell\\Open\r\n\\Registry\\Machine\\Software\\Classes\\Lockbit\\shell\\Open\\Command\r\nFor the DefaultIcon registry key, the malware resolves the path to the icon file similarly to the Set LockBit\r\nDefault Icon section and sets it to the value of the registry key.\r\nNext, it resolves the string “C:\\Windows\\system32\\mshta.exe” “%s”“ which contains the command to execute\r\nmshta.exe, a Windows executable used to execute HTA files, and formats it with the dropped HTA file path. The\r\nmalware then calls NtSetValueKey to set this string to the data of the\r\n\\Registry\\Machine\\Software\\Classes\\Lockbit\\shell\\Open\\Command registry key. With this, whenever a file\r\nwith the .lockbit extension is ran, the mshta.exe will automatically open the dropped HTA file.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 66 of 111\n\nFigure 126: Setting Registry Keys To Launch HTA File.\r\nBelow is the dropped HTA file.\r\nFigure 127: HTA File Content.\r\nLockBit also sets the persistence for the file to be ran every time the system boots up. The malware does this by\r\nresolving the registry path “SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run” and sets its key\r\n“{2C5F9FCC-F266-43F6-BFD7-838DAE269E11}” to the HTA file path.\r\nFile Encryption\r\nMounting Volumes on Drives\r\nPrior to file encryption, LockBit calls FindFirstVolumeW and FindNextVolumeW to enumerate through\r\nvolumes on the victim’s machine.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 67 of 111\n\nFigure 128: Volumes Enumeration.\r\nFor each found volume name, the malware calls GetVolumePathNamesForVolumeNameW to retrieves a list of\r\ndrive letters and mounted folder paths for the specified volume. It also calls GetDriveTypeW to check the\r\nvolume’s type. LockBit avoids mounting the volume if its type is not DRIVE_REMOVABLE and\r\nDRIVE_FIXED or if it has more than 4 mounted folder paths.\r\nFigure 129, 130: Checking Volume To Mount.\r\nNext, LockBit resolves and formats the string “%s\\bootmgr” with the volume name to retrieve the bootmgr path\r\nfor the specified volume. It calls CreateFileW with the OPEN_EXISTING flag to check if the volume has a\r\nbootmgr file and skips it if it does not.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 68 of 111\n\nFigure 131: Checking Volume’s Bootmgr File.\r\nThe malware then iterates through each drive path using the format string “%C:\" and formats it with a drive letter\r\nfrom Z down to A every time. For each drive path, the malware tries calling SetVolumeMountPointW to mount\r\nthe volume to a specific drive letter and stops once it successfully mounts the volume on one.\r\nFigure 132: Mounting Volumes To A Specific Drive.\r\nCryptography \u0026 Multithreading Initialization\r\nBecause LockBit uses Libsodium for public-key cryptography, we don’t really need to analyze most of the crypto\r\ninitialization because it’s just a mess. It’s a lot quicker to just recognize specific Libsodium’s functions once we\r\nencounter them.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 69 of 111\n\nFigure 133: Libsodium Cryptography Initialization.\r\nFor the function to generate random data, LockBit tries to load bcrypt.dll in memory with LoadLibraryA, and if\r\nthat suceeds, it will use BCryptGenRandom for the RNG function. If not, the malware just uses\r\nCryptGenRandom for it.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 70 of 111\n\nFigure 134: Determining RNG Function.\r\nNext, LockBit resolves and formats the string “SOFTWARE\\%02X%02X%02X%02X%02X%02X%02X”\r\nwith its public key. This is then uses as the registry key name to later store the victim’s cryptographic keys.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 71 of 111\n\nFigure 135, 136: Resolving LockBit Cryptographic Registry Key.\r\nIf the RegCreateKeyExW fails, LockBit skips setting the crypto registry key on the victim machine.\r\nFirst, the malware calls Libsodium’s crypto_box_keypair to randomly generate a 32-byte private key and the\r\ncorresponding 32-byte public key for the victim. Next, it encrypts the 64-byte buffer containing the victim’s public\r\nand private key using Libsodium’s crypto_box_easy function and wipes the victim’s private key from memory.\r\nFigure 137: Generating \u0026 Encrypting Victim’s Public \u0026 Private Key.\r\nThe encryption routine is shown below. For each encryption, a public-private key pair is generated using the same\r\nalgorithm as above, and for the sake of simplicity, we’ll call this the encrypted box’s public-private key pair. The\r\nmalware then generates the nonce for the crypto_box_easy function by hashing the box public key appended by\r\nthe first 8 bytes of the given public key, and it calls the crypto_box_easy function to encrypt the given data using\r\nthe box private key and the given public key.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 72 of 111\n\nFigure 138: Calling Libsodium’s crypto_box_easy Authenticated Encryption Function.\r\nThe encrypted result is returned in the following format:\r\nstruct encrypted_box {\r\n byte box_public_key[0x20];\r\n byte box_encrypted_data[input_size + 0x10];\r\n}\r\nIn this case, the box’s encrypted data stores the encrypted victim’s public-private key pair, and we will call this the\r\nsession box. For this, LockBit’s decryptor can call Libsodium’s crypto_box_open_easy function using their\r\nprivate key and the box public key to decrypt its encrypted data. Of course, the nonce generation during\r\ndecryption is simple too because LockBit has access to both its own public key and the box public key.\r\nIf the registry key above is created/opened successfully, LockBit does not generate and encrypt these keys.\r\nInstead, it calls RegQueryValueExA to query them into memory. The session box is stored in the “Private” key’s\r\ndata and the victim’s public key is stored in the “Public” key’s data if they exist.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 73 of 111\n\nFigure 139: Retrieving Session Box \u0026 Victim’s Public Key From Registry.\r\nIf querying the registry fails, the malware generates the victim’s public-private key pair, encrypts them, and calls\r\nRegSetValueExA to set the appropriate registry keys.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 74 of 111\n\nFigure 140: Generating Cryptographic Keys \u0026 Setting Registry.\r\nAfter setting up the cryptographic keys, LockBit initializes its multithreading setup for encryption. It calls\r\nNtCreateIoCompletion to create an I/O completion port and CreateThread to spawn child threads for\r\nencryption. The number of child threads is equal to the number of processors on the system that it retrieves from\r\nthe PEB.\r\nFor each child thread, the malware calculates its affinity mask using its index in the thread array. With the mask,\r\nLockBit calls NtSetInformationThread to set the processor affinity mask for the specific child thread. This\r\nregisters a binding the child thread to one specific CPU, so that the thread will only execute on that designated\r\nprocessor. This provides cache affinity to the child thread to have warm cache which tremendously reduces cache\r\nmisses and increases performance when the child thread is scheduled to run.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 75 of 111\n\nFigure 141: Multithreading Setup.\r\nThe functionality of the child thread function is discussed in the later Child Thread section.\r\nTraversing Local Drive\r\nTo traverse through all local drives, LockBit calls GetLogicalDrives to retrieves a bitmask representing the\r\ncurrently available disk drives. Using the bitmask, the malware checks each bit to skip processing drives that are\r\nnot available.\r\nFigure 142: Searching For Available Disk Drives.\r\nFor each available drive, the malware calls GetDriveTypeW to check and avoid drives whose type is not\r\nDRIVE_FIXED, DRIVE_REMOVABLE, and DRIVE_RAMDISK.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 76 of 111\n\nFigure 143: Checking Drive Types.\r\nNext, after resolving each drive’s name, LockBit spawns a thread to traverse it. The thread handle is added to a\r\nglobal thread array structure for cleaning up afterward.\r\nFigure 144: Spawning Threads To Traverse Drives.\r\nTo traverse each drive, the malware first compares the drive name to “tsclient” and “Microsoft Terminal\r\nServices” to avoid processing these. Drives that have been traversed have their name added to a global array, so\r\nfor each new drive to be processed, LockBit iterates through this array and checks if the drive’s name is in there\r\nto avoid traversing any drive multiple times.\r\nFigure 145: Avoiding Traversing Drives Multiple Times.\r\nBefore traversing a drive, the malware formats the string “%s\\%02X%02X%02X%02X.lock” with its public\r\nkey to generate a file name with the .lock extension in the target drive. Because this file being in a drive used as a\r\nsign that the drive is being encrypted, LockBit calls CreateFileW to try creating this file in the target drive. If the\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 77 of 111\n\nfile already exists, the malware’s thread just exits immediately to avoid having multiple threads encrypting a file\r\nat once.\r\nFigure 146, 167: Creating .lock File To Enforce One Encryption Thread Per Drive.\r\nOnce the drive is ready to be encrypted, the malware adds it to the global drive array so other threads can later\r\nignore it.\r\nFigure 148: Adding Drive Name To Processed Drive Array.\r\nIt also calls SHEmptyRecycleBinW to remove all files in the drive’s Recycle Bin folder and\r\nGetDiskFreeSpaceW to retrieve memory information about the drive to send to the logging window. Also, the\r\nnumber of bytes per sector retrieved from the function is used as the block size for encrypting file.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 78 of 111\n\nTo traverse the drive, LockBit calls FindFirstFileExW and FindNextFileW to enumerate through all\r\nfiles/folders in the drive. It first avoids the filenames ”.” and .., which corresponds to the drive’s current and\r\nparent directory.\r\nFigure 149: Drive Enumeration.\r\nIf the malware finds a subfolder inside with the FILE_ATTRIBUTE_DIRECTORY type, it calls CharLowerW\r\nand compares the folder’s name in lower case with the following names to avoid encrypting.\r\n$Windows.~bt, intel, msocache, $recycle.bin, $windows.~ws, tor browser, boot, windows nt,\r\nmsbuild, microsoft, all users, system volume information, perflog, google, application data,\r\nwindows, windows.old, appdata, mozilla, microsoft.net, microsoft shared, internet explorer,\r\ncommon files, opera, windows journal, windows defender, windowsapp, windowspowershell, usoshared,\r\nwindows security, windows photo viewer\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 79 of 111\n\nFigure 150: Blacklisting Folder Names.\r\nIf the folder name is valid, LockBit calls the traversing function on the folder to recursively traversing it.\r\nFigure 151: Recursive Folder Traversal.\r\nIf a file whose type is not FILE_ATTRIBUTE_SYSTEM is encountered, LockBit compares its extension with\r\nthe following extensions to avoid encrypting.\r\n.386, .cmd, .ani, .adv, .msi, .msp, .com, .nls, .ocx, .mpa, .cpl, .mod, .hta,\r\n.prf, .rtp, .rpd, .bin, .hlp, .shs, .drv, .wpx, .bat, .rom, .msc, .spl, .msu,\r\n.ics, .key, .exe, .dll, .lnk, .ico, .hlp, .sys, .drv, .cur, .idx, .ini, .reg,\r\n.mp3, .mp4, .apk, .ttf, .otf, .fon, .fnt, .dmp, .tmp, .pif, .wav, .wma, .dmg,\r\n.iso, .app, .ipa, .xex, .wad, .msu, .icns, .lock, .lockbit, .theme, .diagcfg,\r\n.diagcab, .diagpkg, .msstyles, .gadget, .woff, .part, .sfcache, .winmd\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 80 of 111\n\nFigure 152: Blacklisting Extensions.\r\nLockBit also avoids encrypting the file if its name is in the following file list.\r\nntldr, ntuser.dat.log, bootsect.bak, autorun.inf, thumbs.db, iconcache.db, restore-my-files.txt\r\nIf the file’s attribute is FILE_ATTRIBUTE_READONLY, LockBit calls SetFileAttributesW to set it to\r\nFILE_ATTRIBUTE_NORMAL to be able to encrypt data and write to it. Finally, it calls a function to set up the\r\nfile structure to be sent to child threads to encrypt via I/O completion port.\r\nFigure 153: Setting File’s Attribute \u0026 Setting Up Shared File Structure.\r\nBelow is a rough recreation of the shared file structure, which is exactly 24656 bytes in size.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 81 of 111\n\nstruct __declspec(align(8)) LOCKBIT_FILE_STRUCT\r\n{\r\n byte AES_IV[16];\r\n byte AES_key[16];\r\n uint64_t file_size;\r\n uint32_t block_size;\r\n uint32_t chunk_count;\r\n HANDLE file_handle;\r\n UNICODE_STRING file_NT_path_name;\r\n DWORD chunk_size;\r\n LARGE_INTEGER last_chunk_offset;\r\n DWORD number_of_chunks_allocated;\r\n DWORD unk2;\r\n LOCKBIT_CHUNK_STRUCT chunk_structs[512];\r\n};\r\nFirst, because each file is encrypted in chunks, the malware calculates the size of the chunks based on the block\r\nsize (which is also the number of bytes per sector). If the block size is not retrieved successfully, the default block\r\nsize is set to 512 bytes.\r\nFigure 154: Calculating Chunk Size.\r\nNext, LockBit appends the encrypted extension “.lockbit” to the end of the filename and calls\r\nRtlDosPathNameToNtPathName to set the path name in the file structure’s file_NT_path_name field.\r\nIt also calls NtCreateFile to retrieve a file handle to the target file to set the structure’s file_handle field, and if\r\nthat fails, the malware attempts to terminate any processes that is using the file.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 82 of 111\n\nFigure 155: Retrieving File Handle.\r\nTo terminate file owners, LockBit calls NtOpenFile to retrieve the file handle and calls\r\nNtQueryInformationFile to query the file information class FileProcessIdsUsingFileInformation to retrieve a\r\nlist of IDs for processes that are accessing the file. LockBit calls NtQuerySystemInformation to query all\r\nrunning processes on the system and iterates through each until it finds processes that accesses the file.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 83 of 111\n\nFigure 156, 157: Enumerating To Find File Owners.\r\nFor each of those proccess, the malware retrieves its executable name, hashes it with ROR13, and compares it to a\r\nlist of process hashes to avoid.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 84 of 111\n\nFigure 158: Enumerating To Find File Owners.\r\nBelow is the list of hashes to avoid terminating.\r\n0x2C99BB9E, 0xE3040AC3, 0xDFF94C0E, 0x230D4C0F, 0xEDFFA2DF, 0x7679DAD9, 0xDFD4E1B0, 0x2C03BAC0, 0xB2E7021A, 0xA\r\nNow I can sit here and bruteforce to try and guess what process each of these hashes corresponds to, but you know\r\nwhat they say.\r\nIf the hash of the process’s name is not in the list above, LockBit retrieves its ID and calls NtTerminateProcess\r\nto terminate it.\r\nFigure 159: Terminating Each File Owner Process.\r\nNext, the malware calls NtCreateFile to try and retrieving the file handle again. After doing this successfully,\r\nLockBit calls NtSetInformationFile with the information class FileCompletionInformation to associate the\r\nfile’s shared structure with the I/O completion port to communicate with the child threads.\r\nFigure 160: Associating File Shared Structure With I/O Completion Port.\r\nIt also sets up the structure’s file_size, chunk_size, block_size fields. Because the last chunk being written will\r\ncontain the LockBit’s file footer, the malware also calculates the appropriate last_chunk_offset field and the final\r\nencrypted file size. It also calls NtSetInformationFile to set the file information class\r\nFileEndOfFileInformation to the new file size.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 85 of 111\n\nFigure 161: Calculating Chunking Information For The File Structure.\r\nIf the file size is too large (greater than 0x8000000000000000 bytes) or too small (less than the chunk size), the\r\nstructure’s chunk_size field is set to the entire file size and the chunk_count field is set to 1. This means for these\r\nfiles, LockBit reads the entire file into 1 chunk and encrypts it.\r\nFigure 162: Checking For Full File Encryption Scenarios.\r\nFor the rest of the files, the chunk_count field is also sets to 1, which means LockBit only encrypts the first\r\nchunks for other files. However, for files that are categorized by LockBit as large files, this field is modified based\r\non its extension and size.\r\nThe following extensions are categorized as large file extensions.\r\n.rar, .zip, .ckp, .db3, .dbf, .dbc, .dbs, .dbt, .dbv, .frm, .mdf, .mrg,\r\n.mwb, .myd, .ndf, .qry, .sdb, .sdf, .sql, .tmd, .wdb, .bz2, .tgz, .lzo,\r\n.db, .7z, .sqlite, .accdb, .sqlite3, .sqlitedb, .db-shm, .db-wal, .dacpac, .zipx, .lzma\r\nFor these files, if the file size is less than the chunk size, the file is ignored and only the first chunk is encrypted. If\r\nthe file size is larger than the chunk size, below is the ranges of file size and their corresponding chunk count.\r\nchunk_size -\u003e 0x100000 bytes: 2 chunks\r\n0x100000 -\u003e 0x600000 bytes: 4 chunks\r\n0x600000 -\u003e 0x3200000 bytes: 16 chunks\r\n0x3200000 -\u003e 0x6400000 bytes: 32 chunks\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 86 of 111\n\n0x6400000 -\u003e 0x1F400000 bytes: 64 chunks\r\n0x1F400000 -\u003e 0x80000000 bytes: 128 chunks\r\n0x80000000 -\u003e 0x300000000 bytes: 256 chunks\r\n0x300000000 bytes or above: 512 chunks\r\nFigure 163: Calculating The Number Of Chunks For Large Files.\r\nNext, LockBit populates the LOCKBIT_CHUNK_STRUCT structures in the file structure’s chunk_structs\r\nfield. The number of chunk structures populated is equal to the number of chunk count calculated above.\r\nstruct __declspec(align(8)) LOCKBIT_CHUNK_STRUCT\r\n{\r\n DWORD crypt_state;\r\n PIO_STATUS_BLOCK chunk_IoStatusBlock;\r\n DWORD unk;\r\n byte AES_IV[20];\r\n LARGE_INTEGER byte_offset;\r\n byte *chunk_buffer;\r\n DWORD chunk_size;\r\n};\r\nFirst, the malware calls the RNG function to randomly generate a 16-byte AES key and 16-byte AES IV and\r\nwrites them in the file structure’s AES_IV and AES_key field. For each chunk structure to be populated, LockBit\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 87 of 111\n\ncopies the file structure’s AES IV into its AES_IV field. It also calls NtAllocateVirtualMemory to allocate a\r\nvirtual memory buffer with the size of the chunk size and sets the chunk_buffer field to the buffer’s pointer. The\r\nmalware then writes the file offset to start reading data into this particular chunk at byte_offset, and this offset is\r\nincremented by 1MB for every chunk. This means that LockBit only encrypts one chunk for every 1 MB in the\r\nfile.\r\nFigure 164: Populating Chunk Structures.\r\nFor each chunk structure populated, LockBit calls NtReadFile to read the file data at the offset specified by the\r\nbyte_offset with the size specified by the chunk_size field into the virtual buffer at the chunk_buffer field. After\r\nthese calls, each chunk contains the appropriate file chunk for the child threads to encrypt and write back to the\r\nfile. Also, when LockBit fires this file I/O operation by calling NtReadFile, it takes in the chunk structure as the\r\nAPC context for the entry added to the main I/O completion object.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 88 of 111\n\nFigure 165: I/O Operation To Read File Data Into Chunks.\r\nLockBit also renames the file before encrypting it. The malware does this by populating a\r\nFILE_RENAME_INFORMATION with the encrypted filename and calls NtSetInformationFile with the\r\ninformation class FileRenameInformation.\r\nFigure 166: Renaming File To Contain .lockbit Extension.\r\nFor congestion control among the working threads, LockBit keeps track of the number of files that are actively\r\nprocessed in a global variable. If there are more than 1000 files being processed at a time, the malware calls Sleep\r\nand spins until that number goes down.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 89 of 111\n\nFigure 167: Encryption Congestion Control.\r\nFinally, the file structure is delivered to the child threads through the NtSetInformationFile call with the\r\ninformation class FileCompletionInformation.\r\nFigure 168: Sending Populated File Structure To Child Threads.\r\nOnce the drive is fully traversed, LockBit calls DeleteFileW to delete the .lock file in the drive.\r\nChild Thread\r\nUpon being created, each child thread spins on the NtRemoveIoCompletion calls until it can remove an entry\r\nfrom the I/O completion port. Once this is done successfully, LockBit’s thread receives the file shared structure as\r\nthe key context and the chunk structure as the APC context that comes with the specific I/O operation.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 90 of 111\n\nFigure 169: Child Thread: Waiting To Receive A Shared File Structure \u0026 Chunk Structure.\r\nBecause each malware thread receives and processes one chunk at a time through the I/O completion port, the\r\nwork is divided evenly among all threads. The encryption process is divided into multiple different states, and\r\nLockBit executes the encryption routine depending on the chunk structure’s crypt_state field.\r\nEncryption State 1\r\nIf the crypt_state field is 1, LockBit encrypts the data in the chunk buffer using AES-CBC. The AES key is\r\nretrieved from the file structure’s AES_key field and the AES_IV is retrieved from the chunk structure.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 91 of 111\n\nFigure 170: Child Thread State 1: Encrypting Chunk Data Using AES-CBC.\r\nNext, if the file size is greater than the chunk size, the malware sets the chunk’s next state to 4. Else, the file size is\r\nless than the chunk size, which means all data is fully encrypted. In this case, LockBit generates a file footer and\r\nappends it to the end of the chunk. Below is my recreated structure for this file footer.\r\nstruct LOCKBIT_FILE_FOOTER_STRUCT\r\n{\r\n struct file_box {\r\n byte file_public_key[0x20];\r\n struct encrypted_file_data {\r\n byte AES_IV[16];\r\n byte AES_key[16];\r\n uint64_t file_size;\r\n uint32_t block_size;\r\n uint32_t chunk_count;\r\n byte encryption_padding[0x10];\r\n } encrypted_file_box;\r\n } file_box;\r\n struct session_box {\r\n byte session_public_key[0x20];\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 92 of 111\n\nstruct encrypted_session_data {\r\n byte victim_public_key[0x20];\r\n byte victim_private_key[0x20];\r\n byte encryption_padding[0x10];\r\n } encrypted_session_data;\r\n } session_box;\r\n byte LockBit_public_key_noncegen[0x8];\r\n byte victim_public_key_noncegen[0x8];\r\n};\r\nFirst, using Libsodium’s crypto_box_easy function, LockBit encrypts the AES IV, AES key, file size, block size,\r\nand chunk count data in the file shared structure using the victim’s public key. Next, it adds the session box to the\r\nfile footer, which contains the public key to decrypt the session box data and the encrypted victim’s public-private\r\nkey pair. Finally, the malware adds the first 8 bytes of its own public key (for session box’s nonce generation) and\r\nthe first 8 bytes of the victim’s public key (for file box’s nonce generation). It then sets the chunk’s next state to 2.\r\nFigure 171: Child Thread State 1: Generating File Footer.\r\nOnce the chunk data has been fully processed and written to, the malware calls NtWriteFile to fire an I/O\r\noperation to write the chunk data to the file at the chunk’s specific offset. It also passes the chunk structure back in\r\nas the APC context so other child threads can retrieve it from the I/O completion port for the next state.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 93 of 111\n\nFigure 172: Child Thread State 1: Writing Encrypted Data To File.\r\nWith this file footer setup, LockBit can decrypt each file by first decrypting the session box using its own private\r\nkey and the session box’s public key. It then can use the victim’s private key and the file box’s public key to\r\ndecrypt the file box to get the AES key and IV to decrypt the file data.\r\nEncryption State 2\r\nBy viewing the number_of_chunks_allocated field in the file’s shared structure, LockBit can check to see if the\r\nchunk being processed is the last chunk. If they are, the malware calls NtSetInformationFile with the information\r\nclass FileRenameInformation to rename the file with the encrypted .lockbit extension.\r\nFinally, the number_of_chunks_allocated field is decremented, and LockBit iterates through all chunk structures\r\nin the file shared structure and free the virtual memory buffers inside.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 94 of 111\n\nFigure 173, 174: Child Thread State 2: Renaming File \u0026 Cleaning Up Chunks.\r\nTo wrap up the file encryption, the malware increments the COMPLETED_FILE_NUM global variable and\r\ndecrements the ACTIVE_FILE_BEING_PROCESSED global variable. It calls NtClose to close the file handle,\r\nRtlFreeUnicodeString to free the filename buffer, and NtFreeVirtualMemory to free the file’s shared structure.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 95 of 111\n\nFigure 175: Child Thread State 2: Wrapping Up Encryption.\r\nEncryption State 3\r\nThis state just cleans up the chunk structures and file structure before wrapping up the encryption similar to state\r\n2. This state is solely used for cleaning up the ransom note structure. More details is discussed in the Dropping\r\nRansom Note section.\r\nFigure 176: Child Thread State 3: Cleaning Structures For Ransom Note.\r\nEncryption State 4\r\nLockBit transitions into state 4 when the file size is greater than the chunk size, so there might be more than 1\r\nchunk being processed in the file.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 96 of 111\n\nIt performs similar tasks to state 2, where it checks if the encryption is done to rename the file. The malware\r\nthread also cleans up the structures similar to state 2 and wraps up the encryption there.\r\nFigure 177: Child Thread State 4: Renaming File \u0026 Wrapping Up Encryption.\r\nIf the current chunk is the last chunk to process, LockBit generates the file footer, writes it to the end of the chunk\r\nbuffer, and calls NtWriteFile to write the data to the file. The chunk’s next state is set to 2 to clean up the\r\nencryption.\r\nFigure 178: Child Thread State 4: Writing File Footer \u0026 Transitioning To State 2.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 97 of 111\n\nIf the encryption is not done and there are still more chunks to be encrypted, the child thread moves on to wait for\r\nfor other chunks to come by calling NtRemoveIoCompletion.\r\nTraversing Network Hosts\r\nIf the configuration flag at index 3 is set, LockBit create threads to traverse and encrypt other network hosts and\r\nnetwork drives from the victim’s machine.\r\nScanning For Live Hosts\r\nLockBit first calls socket to create an IPv4 TCP socket. Using the socket handle, it calls WSAIoctl with the\r\nGUID “{0x25a207b9,0x0ddf3,0x4660,{0x8e,0xe9,0x76,0xe5,0x8c,0x74,0x06,0x3e}}” to retrieve the\r\nLPFN_CONNECTEX function’s address.\r\nFigure 179, 180: Retrieving LPFN_CONNECTEX function.\r\nNext, it calls GetAdaptersInfo to retrieve adapter information for the local computer. Using the\r\nIP_ADAPTER_INFO structure it gets, the malware calls inet_addr to convert the computer’s IP address and the\r\nIP mask into long values in IP network order. LockBit retrieves the base address of the network by performing a\r\nbitwise AND operation on these values. Also, by flipping all the bits on the mask and OR-ing it with the\r\nmachine’s IP address, LockBit also retrieves the broadcast address of the network.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 98 of 111\n\nFigure 181, 182, 183, 184, 185: Retrieving Network Base Address \u0026 Broadcast Address.\r\nTo scan the network, LockBit iterates from the network base address up to the broadcast address by incrementing\r\nthe network address value each time. For each of these addresses, the malware tries to connect to it through port\r\n135 and 445. If the connection is successful, it tries to encrypt these network hosts.\r\nFigure 186: Iterating To Scan Network.\r\nFor each address, LockBit builds the following socket structure.\r\nstruct __declspec(align(4)) SOCKET_STRUCT\r\n{\r\n OVERLAPPED overlapped;\r\n HANDLE socket_event;\r\n HANDLE socket_wait_object_handle;\r\n int enable_traversal;\r\n SOCKET socket;\r\n sockaddr_in target_addr;\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 99 of 111\n\nint cleaned_flag; // 1 == not cleaned\r\n};\r\nIt populates this structure by calling socket to create an IPv4 TCP socket and sets that to the socket field and\r\ncalling bind to bind the socket to the local machine. It then calls CreateEventW to create an event handle for the\r\nsocket to set it to the socket_event field and calls NtSetInformationFile with the information class\r\nFileCompletionInformation to associate the socket structure with an I/O completion port. And finally, it\r\npopulates the target_addr with the appropriate port and the target’s IP address.\r\nFigure 187, 188, 189, 190: Populating Socket Shared Structure.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 100 of 111\n\nNext, the malware calls RegisterWaitForSingleObject to register an event handle for when the socket’s event is\r\nsignaled. The event handler is just a wrapper for CancelIoEx, which cancels all I/O operations for the current\r\nprocess. Finally, it calls LPFN_CONNECTEX to perform an I/O operation to create a connection to the network\r\nhost. If the network host is not alive and the function fails to execute, LockBit cleans up the structure and moves\r\non to test another host.\r\nFigure 191: Connecting To Remote Host.\r\nLaunching Threads To Traverse Live Hosts’ Network Shares\r\nPrior to scanning the network, LockBit calls NtCreateIoCompletion to create an I/O completion object for\r\ncommunication on network host encryption. It also calls CreateThread to create threads that will spin on this I/O\r\ncompletion object to receive a specific network host to traverse and encrypt.\r\nFigure 192: Creating Threads To Traverse Network Hosts.\r\nThe child thread has an infinite while loop to call NtRemoveIoCompletion and wait until it receives a socket\r\nstructure when the parent thread makes the call to LPFN_CONNECTEX for a specific network host.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 101 of 111\n\nFigure 193: Waiting To Receive Socket Structure For Network Host.\r\nFor each network host received, it calls WSAAddressToStringW to convert the host’s address to a string and\r\ntraverses through network shares on it.\r\nFigure 194: Traversing Network Host.\r\nTo traverse through network shares on a host, the malware first calls WNetAddConnection2W to establish a\r\ndirect connection to the host and NetShareEnum to retrieve information about its shared resources. For each\r\nshared resource, the malware formats the following path ”\\\u003chost address\u003e\\\u003cshared resource name\u003e” and calls\r\nthe traversal function from the Traversing Local Drive section to traverse and encrypt it.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 102 of 111\n\nFigure 195, 196: Traversing \u0026 Encrypting Network Hosts’ Shared Resources.\r\nTraversing Network Drives\r\nAfter encrypting shared resources on network hosts, LockBit also traverses and encrypts remote drives on the\r\nvictim’s machine.\r\nImpersonation Process With The Same Authentication ID\r\nLockBit spawns a thread to encrypt remote drives while impersonating a process with the same authentication ID.\r\nIt impersonates by calling NtQueryInformationToken to query the elevation type of the current process’s token\r\nto check if it is elevated. If it is, the malware calls NtQueryInformationToken to retrieve a handle to another\r\ntoken that is linked to this elevated token and the linked token’s authentication ID.\r\nFigure 197: Retrieving Linked Token.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 103 of 111\n\nFor the given authentication ID, the malware calls CreateToolhelp32Snapshot to get a snapshot handle of all\r\nprocesses on the system. It calls Process32FirstW and Process32NextW to enumerate through all processes. For\r\neach process, LockBit calls OpenProcess using the process’s ID to retrieve the process handle and\r\nNtQueryInformationToken to retrieve the process’s authentication ID. It enumerates until finding a process with\r\nthe same authentication ID as the linked token above.\r\nFigure 198: Enumerating To Find Process With The Same Authentication ID.\r\nOnce found, LockBit calls DuplicateToken to duplicate and impersonate the target process’s token and\r\nSetThreadToken to set the duplicated token to its own process.\r\nFigure 199, 200: Impersonating Process With The Same Authentication ID.\r\nAfter impersonating, LockBit begins to traverse through all network drives on the system. It enumerates through\r\ndrives by calling GetLogicalDrives and performs a bit test on each bit to only find drives that exists on the\r\nsystem. For each of these drives, the malware calls WNetGetConnectionW to retrieve the drive’s network path\r\nand creates a thread to traverse it.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 104 of 111\n\nFigure 201, 202, 203: Enumerating Network Drives.\r\nThe function for traversing this is basically just a wrapper for the traversal function from the Traversing Local\r\nDrive section.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 105 of 111\n\nFigure 204: Traversing \u0026 Encrypting Network Drives.\r\nImpersonation Shell Process Window\r\nLockBit also spawns a thread to encrypt remote drives while impersonating as the shell process window.\r\nFirst, it calls GetShellWindow to retrieves a handle to the Shell’s desktop window and\r\nGetWindowThreadProcessId to get the process’s ID. Next, it calls OpenProcess to retrieve the process’s handle\r\nusing its ID and NtOpenProcessToken to retrieve the process’s token.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 106 of 111\n\nFigure 205, 206, 207: Retrieving Shell Process’s Token.\r\nFinally, to impersonate this process, LockBit calls DuplicateToken to duplicate the process’s token and\r\nSetThreadToken to set the duplicated token to its own process.\r\nFigure 208, 209: Impersonating As Shell Process.\r\nThe rest of the network drive traversal routine is the same as documented above.\r\nDropping Ransom Note\r\nThe ransom note is dropped during the parent’s thread traversal routine in Traversing Local Drive. LockBit first\r\ngenerates the ransom note path in the folder by appending ”\\Restore-My-Files.txt” after the folder path.\r\nFigure 210: Generating Ransom Note Path.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 107 of 111\n\nIf the ransom note does not exist in the folder yet, LockBit creates a shared file structure and populates it with the\r\nransom note path. The malware also calls NtCreateFile to create the ransom note and NtSetInformationFile to\r\nassociate the file structure with the I/O completion object.\r\nFigure 211, 212: Setting Up Ransom Note Shared File Structure.\r\nAfter populating a chunk structure with the ransom note content and sets the chunk’s next state to 3, it calls\r\nNtWriteFile to write the content into the ransom note. This will add an entry to the I/O completion object, where\r\none child thread will receive and cleans up the ransom note’s chunk and file structure.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 108 of 111\n\nFigure 213: Dropping Ransom Note In Directory.\r\nIf the ransom note already exists in the directory, this step is skipped.\r\nSelf-Deletion\r\nAfter finishing file encryption, LockBit deletes itself if the configuration flag at index 1 is set.\r\nIt first resolves the stack string ” /C ping 127.0.0.7 -n 3 \u003e Nul \u0026 fsutil file setZeroData offset=0 length=524288\r\n“%s” \u0026 Del /f /q “%s”“ and formats this with its own executable path.\r\nFigure 214: Building Self-deletion Command.\r\nThis command pings localhost with 3 echo Request messages to delay and wait for the malware to finish\r\nexecuting, executes fsutil to empty the malware’s executable, and force-delete the file in quiet mode.\r\nLockBit also calls MoveFileExW to set itself to be deleted after the system reboots.\r\nFigure 215: Setting Self To Be Deleted After Reboot.\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 109 of 111\n\nFinally, the malware calls ShellExecuteExW to execute the command above to delete itself.\r\nFigure 216: Executing Command To Delete Self.\r\nReferences\r\nhttps://asec.ahnlab.com/en/17147/\r\nhttps://news.sophos.com/en-us/2020/04/24/lockbit-ransomware-borrows-tricks-to-keep-up-with-revil-and-maze/\r\nhttps://www.trustedsec.com/blog/weaponizing-group-policy-objects-access/\r\nhttps://www.bleepingcomputer.com/news/security/lockbit-ransomware-now-encrypts-windows-domains-using-group-policies/\r\nhttps://devblogs.microsoft.com/oldnewthing/20080314-00/?p=23113\r\nhttps://www.ic3.gov/Media/News/2022/220204.pdf\r\nhttps://www.crowdstrike.com/blog/how-crowdstrike-prevents-volume-shadow-tampering-by-lockbit-ransomware/\r\nhttps://talos-intelligence-site.s3.amazonaws.com/production/document_files/files/000/095/481/original/010421_LockBit_Interview.pdf\r\nhttps://www.prodaft.com/m/reports/LockBit_Case_Report___TLPWHITE.pdf\r\nhttps://www.cyber.gov.au/acsc/view-all-content/advisories/2021-006-acsc-ransomware-profile-lockbit-20\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 110 of 111\n\nhttps://symantec-enterprise-blogs.security.com/blogs/threat-intelligence/ransomware-trends-lockbit-sodinokibi\r\nhttps://libsodium.gitbook.io/doc/public-key_cryptography/authenticated_encryption\r\nSource: https://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nhttps://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/\r\nPage 111 of 111\n\nbuffer, and calls encryption. NtWriteFile to write the data to the file. The chunk’s next state is set to 2 to clean up the\nFigure 178: Child Thread State 4: Writing File Footer \u0026 Transitioning To State 2.\n   Page 97 of 111",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"references": [
		"https://chuongdong.com/reverse%20engineering/2022/03/19/LockbitRansomware/"
	],
	"report_names": [
		"LockbitRansomware"
	],
	"threat_actors": [
		{
			"id": "67bf0462-41a3-4da5-b876-187e9ef7c375",
			"created_at": "2022-10-25T16:07:23.44832Z",
			"updated_at": "2026-04-10T02:00:04.607111Z",
			"deleted_at": null,
			"main_name": "Careto",
			"aliases": [
				"Careto",
				"The Mask",
				"Ugly Face"
			],
			"source_name": "ETDA:Careto",
			"tools": [
				"Careto"
			],
			"source_id": "ETDA",
			"reports": null
		},
		{
			"id": "0fc739cf-0b82-48bf-9f7d-398a200b59b5",
			"created_at": "2022-10-25T16:07:23.797925Z",
			"updated_at": "2026-04-10T02:00:04.752608Z",
			"deleted_at": null,
			"main_name": "LockBit Gang",
			"aliases": [
				"Bitwise Spider",
				"Operation Cronos"
			],
			"source_name": "ETDA:LockBit Gang",
			"tools": [
				"3AM",
				"ABCD Ransomware",
				"CrackMapExec",
				"EmPyre",
				"EmpireProject",
				"LockBit",
				"LockBit Black",
				"Mimikatz",
				"PowerShell Empire",
				"PsExec",
				"Syrphid"
			],
			"source_id": "ETDA",
			"reports": null
		},
		{
			"id": "3940f08b-39aa-492c-8699-86bfe515fa70",
			"created_at": "2023-01-06T13:46:39.470535Z",
			"updated_at": "2026-04-10T02:00:03.339964Z",
			"deleted_at": null,
			"main_name": "BITWISE SPIDER",
			"aliases": [],
			"source_name": "MISPGALAXY:BITWISE SPIDER",
			"tools": [],
			"source_id": "MISPGALAXY",
			"reports": null
		},
		{
			"id": "f5bf6853-3f6e-452c-a7b7-8f81c9a27476",
			"created_at": "2023-01-06T13:46:38.677391Z",
			"updated_at": "2026-04-10T02:00:03.064818Z",
			"deleted_at": null,
			"main_name": "Careto",
			"aliases": [
				"The Mask",
				"Ugly Face"
			],
			"source_name": "MISPGALAXY:Careto",
			"tools": [],
			"source_id": "MISPGALAXY",
			"reports": null
		}
	],
	"ts_created_at": 1775434137,
	"ts_updated_at": 1775791878,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/3f65dd00445e97926d18dc3df79e90148cbb9e02.pdf",
		"text": "https://archive.orkl.eu/3f65dd00445e97926d18dc3df79e90148cbb9e02.txt",
		"img": "https://archive.orkl.eu/3f65dd00445e97926d18dc3df79e90148cbb9e02.jpg"
	}
}