12/08/2025

Lumma Stealer: Danger lurking in fake game updates from itch.io and Patreon

Danger lurking in fake game updates from itch.io and Patreon Techblog

An analysis by Josemaria Grana

We’ve written several articles about video games as targets for cyberattacks, from Steam profile images hiding malware to a malicious patch of the game BlockBlasters gaining notoriety for affecting an innocent gamer’s life. Alongside Steam, indie game platforms such as Itch.io have also been recent targets, notably Malwarebytes’ analysis of fake Itch.io download pages containing malware that spread via compromised Discord accounts

Another malicious campaign has again been found on Itch.io, which is an online platform for distributing independently developed video games with a pay-what-you-can model for revenue. Multiple spam comments in legitimate games are claiming to be “game updates” and offering download links for the updates, but a close look into these download links instead show malware hiding their tracks. 

Scratching the surface with multiple Itch.io spam comments

Newly created Itch.io accounts spam comments in different legitimate games, with templated text messages that show Patreon links to supposed game updates. These URLs directly download an archive named “Updated Version.zip”[1]. The way these comments are written and spammed across multiple games suggests a shotgun approach, where any unsuspecting user unfamiliar with the Itch.io website might confuse the comments as real updates from the game developers. 
Most of the extracted files from “Updated Version.zip” are benign, with the notable exception of the main executable “game.exe”[2]

Leveraging nexe in JavaScript malware obfuscation

Upon execution in a virtual environment, game.exe does not proceed with any updates. Static analysis of the file reveals it is compiled with nexe, indicating that it is a Node.js application converted into a PE executable. To our knowledge no articles mentioning the use of this compiler for malware encountered “in the wild” have been published before, with recent attacks that use Node.js still requiring the node.exe runtime. 

Decompilation with nexeDecompiler reveals a JavaScript file named mains.js[3], which is obfuscated to impede analysis of the malware. 

Deobfuscation of the script shows multiple asynchronous functions which include several anti-analysis subroutines and two dropped payloads. 

Six levels of anti-analysis

The first subroutine is an anti-VM check that uses the methods os.totalmem() and os.cpus().length to return the memory size and number of CPU cores of the system, respectively. If the memory is less than 4 GB or the CPU cores are less than or equal to two, the malware determines that it is running in a virtual system and stops execution. 

The second subroutine contains a list of strings: 

  • 'george' 
  • 'shayne' 
  • 'john doe' 
  • 'mashinesssss' 
  • 'sandbox' 
  • 'honey' 
  • 'vmware' 
  • 'currentuser' 
  • 'AKo' 
  • 'MbHy' 
  • 'nepenthes' 
  • 'andy' 
  • 'hal9th' 
  • 'johndoe' 
  • 'wdagutilityaccount' 
  • 'abby' 
  • 'peter wilson' 
  • 'hmarc' 
  • 'patex' 
  • 'john-pc' 
  • 'rdhj0cnfevzx' 
  • 'keecfmwgqj' 
  • 'frank' 
  • '8nl0colnq5bq' 
  • 'lisa' 
  • 'john' 
  • 'pxmduopvyx' 
  • '8vizsm' 
  • 'w0fjuovmcpa' 
  • 'lmvwjj9b' 
  • 'pqonjhvwxss' 
  • '3u2v9m8' 
  • 'julia' 
  • 'heuerzl' 
  • 'harry johnson' 
  • 'j.seance' 
  • 'a.monaldo' 
  • 'tvmt' 
  • 'frank' 
  • 'johanna' 
  • 'johnson' 
  • 'miller' 
  • 'malware' 
  • 'maltest' 
  • 'virus' 
  • 'test user' 
  • 'sand bog' 
  • 'bruno' 
  • 'anand' 
  • 'it-admin' 
  • 'walker' 
  • 'kEecfMwgj' 
  • 'gabriella.rhodes' 

Many of the listed strings are usernames for sandboxes and malware analysis systems such as “sandbox”, “vmware”, or “malware”. It then searches for usernames from the predefined list using the method os.userInfo() which is converted to lower case and normalized using the NFC form. If it finds any of the usernames used for sandbox or malware analysis, the malware stops execution. 

The third subroutine also contains a list of strings, this time of processes used for malware analysis: 

  • 'apdagent.exe' 
  • 'apimonitor.exe' 
  • 'azurearcsystray.exe' 
  • 'binaryninja.exe' 
  • 'burpsuite.exe' 
  • 'charles.exe' 
  • 'cred-store.exe' 
  • 'cutter.exe' 
  • 'dbgx.shell.exe' 
  • 'decoder.exe' 
  • 'device-sense.exe' 
  • 'df5serv.exe' 
  • 'dnspy.exe' 
  • 'drrun.exe' 
  • 'dumpcap.exe' 
  • 'dumpit.exe' 
  • 'fakenet.exe' 
  • 'fiddler.exe' 
  • 'frida-inject.exe' 
  • 'frida-server.exe' 
  • 'frida.exe' 
  • 'gdb.exe' 
  • 'httpanalyzerv7.exe' 
  • 'httpdebugger.exe' 
  • 'httpdebuggersvc.exe' 
  • 'httpdebuggerui.exe' 
  • 'hvix64.exe' 
  • 'ida64.exe' 
  • 'idag.exe' 
  • 'idag64.exe' 
  • 'idaq.exe' 
  • 'idaq64.exe' 
  • 'idaw.exe' 
  • 'idaw64.exe' 
  • 'ilspy.exe' 
  • 'immunitydebugger.exe' 
  • 'inetsim.exe' 
  • 'joeboxcontrol.exe' 
  • 'joeboxserver.exe' 
  • 'ksdumper.exe' 
  • 'ksdumperclient.exe' 
  • 'mitmdump.exe' 
  • 'netcat.exe' 
  • 'ollydbg.exe' 
  • 'pestudio.exe' 
  • 'pin.exe' 
  • 'prl_cc.exe' 
  • 'prl_tools.exe' 
  • 'private-cloud-proxy.exe' 
  • 'procmon.exe' 
  • 'process.exe' 
  • 'processhacker.exe' 
  • 'procexp.exe' 
  • 'qemu-ga.exe' 
  • 'rammap.exe' 
  • 'rammap64.exe' 
  • 'rdpclip.exe' 
  • 'rekall.exe' 
  • 'x64dbg.exe' 
  • 'tcpdump.exe' 
  • 'tib_monitor_monitor.exe' 
  • 'tmsmonitor.exe' 
  • 'todaydeathdo.exe' 
  • 'vboxservice.exe' 
  • 'vboxtray.exe' 
  • 'vgautservice.exe' 
  • 'vmacthlp.exe' 
  • 'vmtoolsd.exe' 
  • 'vmusrvc.exe' 
  • 'vmwaretray.exe' 
  • 'vmwareservice.exe' 
  • 'vmwareuser.exe' 
  • 'vmsrvc.exe' 
  • 'vxtkernelsvcntmgr.exe' 
  • 'windasm.exe' 
  • 'windbg.exe' 
  • 'wireshark.exe' 
  • 'x32dbgn.exe' 

It then executes the command line ‘tasklist /fo csv’ which outputs the currently running processes in CSV format. The command line execution for this and the next subroutines is hidden from the user using the setting ‘windowsHide: true’. The output is compared with the predefined list of processes, with the malware stopping execution when a match is found. 

The fourth subroutine executes the command line ‘wmic path win32_VideoController get name /value’ which returns the value names from the win32_VideoController WMI class, and compares the result with the following drivers which are indicators of a virtualized system: 
 

  • microsoft basic display adapter 
  • microsoft remote display adapter 
  • standard vga graphics adapter 
  • vmware svga 3d 
  • virtualbox graphics adapter 
  • citrix display adapter 
  • microsoft hyper-v video 

Again, the malware stops execution it finds any matches from the list. 

The fifth subroutine checks the refresh rate of the system using the command line ‘wmic path Win32_VideoController get CurrentRefreshRate /value’ and exits execution if there are no valid refresh rates or the maximum refresh rate is less than 29 Hz. 

The final subroutine checks for the disk drive model values using the command line ‘wmic diskdrive get model /value’, and if the model matches any of the listed disk names the malware stops execution: 

  • dady hardiskk 
  • qemu hardiskk 
  • vbox 
  • vmware 
  • virtuozzo 
  • virtio 

Now loading: LummaStealer…

The last two asynchronous functions contain the final payload. The first function decodes its Base64-encoded string and writes the contents to the system’s %temp% directory with the filename “modules.node”[4], which is a DLL with two export functions: napi_register_module_v1 and node_api_module_get_api_version_v1. 

The second function calls the first function to write the modules.node DLL to disk and load it as a Node.js module. It then decoded the second Base64-encoded payload, which is a variant of LummaStealer and is dynamically loaded to modules.node. 

modules.node receives the function containing the LummaStealer payload in the node_api_module_get_api_version_v1 export function which contains the Node.js APIs napi_create_function and napi_set_named_property. These APIs are used to add C/C++ modules to JavaScript, and serves as a reflective loading technique to execute the LummaStealer payload in the system. 

A single threat actor who keeps covering their tracks

We mentioned multiple accounts commenting with different Patreon URL download links. Downloading from different URLs yields different nexe-compiled JavaScript files with varying encoding methods. Even after beautifying and decoding these files, there are differences between variable and function names and some methods of anti-analysis. 

For example, ‘wmic path win32_VideoController get name /value’  was used to obtain the system’s video display adapter in one of the samples, while another sample also obtained the same result via the command line ‘powershell -Command “Get-CimInstance Win32_VideoController | Select-Object -ExpandProperty Name”’. This is a technique to delay detection of newer versions of the files. 

Despite these differences, it is apparent that it is an ongoing malware campaign, due to most recent samples having the same number of anti-analysis routines used, the unique string identifiers in the decoded JavaScript, and the fact that the Itch.io comments are worded in the same templated way. While Itch.io has banned and removed some of the malicious accounts, new ones are still being created and spamming Itch.io games with their Patreon malware download links. 

Indicators of Compromise

Updated Version.zip (SHA256: 79250523a057a7dd9a6080099c8c2f83eb683ab9b37ecab149fc73524f7c4bd1) 

Game.exe (SHA256: 102b99b00a60f33246bd89bd2b3cb9cfae2844d453484e932b3a5ca634fb308c) 

mains.js (SHA256: 80e538cabade94e1883f9e72bb608dc02f79808aec48136b5bbb00c2a1717f64) 

Decoded and beautified mains.js 

modules.node (SHA256: 1d405b03bc5913b6b43c06550ef0b9b02196b270625e4dc5fa0c37e8a424be25, Detection: Win64.Trojan.Agent.Y6OBDP) 

LummaStealer payload (SHA256: a2bacb00dfdb338b496d3128705f76c8cc935e6bd33e06271fb3e34d769d0a2b, Detection: Win64.Trojan-Stealer.LummaStealer.V34XV4)