Detecting ClickFix infrastructure before it goes live
In this article we point out weaknesses in a live ClickFix operator's infrastructure. We showcase a method to preemptively detect threats by monitoring certain points of it.
In a recent campaign, we observed threat actors using ClickFix to deliver malware to visitors of compromised WordPress sites. This article presents a method for detecting the malicious landing pages proactively, by monitoring the attackers’ infrastructure in the middle of the delivery chain.
About ClickFix
ClickFix is a lure. The visitor sees a page that looks like a Cloudflare or reCAPTCHA check and is told to paste a command into the Windows Run dialog to prove they are human. The command is already in the clipboard, and running it fetches the malware.


Someone visiting a compromised website reaches the lure page through the chain in Figure 2.
A script injected into the
compromised site, the loader, opens a page from a domain the threat actor controls, the landing page. The landing page displays the lure and fills the clipboard with a malicious command.
The loader does not contain the landing page’s address. When it runs, it asks a third party for the address of the landing page currently in use, which lets the operator move to a new domain without editing the compromised sites again. We call that third party the resolver. In the campaign examined below, the loader reaches it in two steps: the only address it stores is that of a config server, and the config server answers with the location of the resolver, a file on GitHub.
The resolver is the part of the chain we will monitor, for two reasons:
- A new landing page has to be written to the resolver before any visitor can reach it.
- The loader reads the resolver from a browser without any credentials, so a defender can read it the same way.
Case study
A good example is martyhigh[.]com, a compromised WordPress site that was
detected on 25 July 2026. The website has been compromised multiple times and carries 12 injected ClickFix loaders:
- 8 copies of a loader with the landing page’s address hardcoded
- 3 copies of a loader leveraging a GitHub-based resolver
- 1 EtherHiding loader leveraging a Polygon blockchain resolver
Code and infrastructure similarity suggests that the hardcoded and GitHub-based loaders belong to the same threat actor, as different builds of the same tool.
The EtherHiding loader was seen alongside this GitHub-based loader in 55 prior occurrences, so it likely belongs to the same group.
The GitHub-based resolver is the one that delivered the lure in the 25 July capture.
The EtherHiding resolver is examined later in the article, along with what monitoring each one yields.
The lure script then draws the fake verification page in Figure 1 and replaces the clipboard with a
hidden-window PowerShell command, which downloads the final payload from nationwidely[.]net, hosted on the same IP address as the gate.
The GitHub resolver
The public repository at hxxps://github[.]com/om5678774/kt4567, created on 15 February 2026, serves as the resolver for this attack chain. It contains a goldmine of information that defenders can use to detect threats proactively.
The repository holds the lure widgets of Figure 1, in one directory per landing page, and has a fork, created in late July by a second account, probably kept as a backup.
As shown in Figure 5, the .txt pointer files are updated regularly to move traffic between landing pages.
The investigation uncovered several other active GitHub resolvers operating the same way. They are listed in the Indicators section.
The EtherHiding resolver
EtherHiding stores the next address in a smart contract on a public blockchain. The loader reads it
with an eth_call through a public RPC endpoint, and the operator changes it with a transaction.
The loader on martyhigh[.]com reads a contract at 0xf5966808a9ECbdb8794F568922809C52b0Fd2446 on Polygon.
In this case the rest of the chain differs slightly: the contract does not name a landing page directly. It names further config servers, from which the scripts for the next steps are fetched.
From June onward, every list written to the contract was scanned publicly within 3 hours of the write, and most within the hour. The technique is relatively new and has received wide attention, so the contract is already watched and reading it yields a shorter lead.
| GitHub | EtherHiding | |
|---|---|---|
| Changing a pointer file | A commit. Free. | A transaction. Costs gas. |
| Writes observed | 22 to landing.txt, February to September, still changing | 23, 21 May to 1 July, none since |
| Lead before first public sighting | 3 to 83 h | < 3 h from June on |
| What the record carries | Every version, author, timestamp, pushing tool | Sender address, timestamp, value |
| State in the 25 July capture | Delivered the lure | Branch failing; the last 3 servers resolve to one address that does not answer |
Advantages of monitoring resolvers
Monitoring the pointer files lets a defender see each new landing page as soon as it is published.
For both the GitHub repository and the Polygon contract, Figure 6 shows the lead between each write and the first public scan of the landing page it names.
GitHub-based resolvers also demand more care from the operator, for OpSec reasons that are not detailed here.
Pivoting on resolver files
The method above finds landing pages in advance. It does not yet find the compromised WordPress sites that send visitors to them.
Searching public scan data for the websites that load each landing page finds more infrastructure.
Each compromised website can reveal new loader versions, new config servers, and new resolvers.
Repeating the pivot on every new discovery maps a large part of the infrastructure. Figure 7 shows the loop.
Detection and hunting
In this case study, the GitHub loader is easy to detect on compromised websites.
It carries several unique strings that survive minification and host rotation:
the symbol registry key __inline_id_offer__, used for deduplication, and the ktl-show-original and ktl-frame-ready messages each landing page posts back to the loader.
// Excerpt of the loader on martyhigh[.]com, 25 July capture.
var TRUSTED_CONFIGS = [
{ template: "hxxps://raw.githubusercontent[.]com/{id}", useFetch: true } // {id} = path from the config server
];
var GLOBAL_KEY = (typeof Symbol === "function" && Symbol.for)
? Symbol.for("__inline_id_offer__") // one registry per page, a second copy of the loader exits here
: "__inline_id_offer__";
window.addEventListener("message", function (event) {
var data = event && event.data;
if (data.type === "ktl-show-original") { registry.destroy(); return; } // landing page asks to drop the iframe
if (data.type === "ktl-frame-ready") { registry.reveal(); return; } // landing page is drawn, show it
if (data.type === "copy") tryCopy(data.text); // clipboard relay
}); On the chain side, a page issuing an eth_call against 0xf5966808a9ECbdb8794F568922809C52b0Fd2446 is reading this operator’s contract, whatever the
page looks like.
On an endpoint, the pasted command imports Microsoft.PowerShell.Utility through the wildcard M*.P*.U* and picks its cmdlets by index in the module’s export list. Both are specific to this threat actor.
On GitHub, the tool that stages the lure files commits with the message prefix land CDN:, six
commits per batch, one to two seconds apart. A commit search on that prefix allowed us to find more resolvers. Every lure directory ships the same widget scripts, cf-main.js and re-main.js, which call back into __landShotActivate, and the hardcoded loader registers under
the symbol __03984783989377444__.
The GitHub loader in a page clickfix_github_dead_drop_loader
rule clickfix_github_dead_drop_loader
{
meta:
description = "Injected loader resolving a ClickFix landing page through a config server and a raw GitHub pointer file"
reference = "houdin.io/blog/detecting-clickfix-infrastructure-before-it-goes-live"
date = "2026-09-03"
strings:
// Symbol registry key the loader dedups against
$key = "__inline_id_offer__"
// postMessage protocol between the landing page and the loader
$msg_show = "ktl-show-original"
$msg_ready = "ktl-frame-ready"
condition:
any of them
}The lure widgets, on GitHub or in a landing page clickfix_dead_drop_lure_widget
rule clickfix_dead_drop_lure_widget
{
meta:
description = "Fake Cloudflare and reCAPTCHA checkbox widgets (cf-main.js, re-main.js) staged on GitHub for ClickFix landing pages"
reference = "houdin.io/blog/detecting-clickfix-infrastructure-before-it-goes-live"
date = "2026-09-03"
strings:
// Callback into the landing page when the checkbox is clicked
$callback = "__landShotActivate"
// Mount attribute and globals of the two widgets
$mount = "data-land-mount"
$cf = "LandCfMain"
$re = "LandReMain"
condition:
$callback or ($mount and ($cf or $re))
}Pasted command on an endpoint clickfix_dead_drop_pasted_command
rule clickfix_dead_drop_pasted_command
{
meta:
description = "Clipboard command served by the sailboaterists gate: cmdlets resolved by index into Microsoft.PowerShell.Utility"
date = "2026-09-03"
strings:
// Wildcard import of the Utility module
$ipmo = "IPMO 'M*.P*.U*'" ascii nocase
// Cmdlets picked by position in the module's export list
$idx = ".ExportedCommands.Values" ascii nocase
$pick = /\$[A-Za-z]+\[5[12]\]/ ascii
condition:
$ipmo or ($idx and $pick)
}Indicators
| Config servers 5 | |
|---|---|
klonfcrtyseaflow[.]com | |
dakiloifhsnuukka[.]com | |
remiumholdings[.]com | |
feiyuwei[.]com | |
rosrefurboss[.]com | |
| GitHub resolver 5 | |
hxxps://github[.]com/om5678774/kt4567 | |
hxxps://github[.]com/rincom316-316/kt4567 | |
hxxps://github[.]com/habitredso98/main | |
hxxps://raw.githubusercontent[.]com/om5678774/kt4567/main/land2.txt | |
hxxps://raw.githubusercontent[.]com/om5678774/kt4567/main/landing.txt | |
| Landing pages 19 | |
registeredagentsingeorgia[.]com | |
registeredagentsinkansas[.]com | |
registeredagentsindelaware[.]com | |
catholicsma[.]com | |
ipoweres[.]com | |
dasifoda[.]digital | |
asdoci[.]digital | |
onl-novo-co[.]digital | |
chrisparrycollection[.]com | |
asionamedrafter[.]com | |
wolfenbard[.]com | |
ardotcharleybuking[.]com | |
asioklaydpory[.]com | |
chickpeachix[.]com | |
clientpilotclosers[.]com | |
foliclesalonandspa[.]com | |
burutrading[.]com | |
loc-calixablanlk[.]digital | |
so-unltd-ulcbi[.]digital | |
| Gate, payload and C2 4 | |
sailboaterists[.]net | |
nationwidely[.]net | |
framework-css-styles-js[.]beer | |
thewrayforward[.]com | |
| Polygon resolver 5 | |
0xf5966808a9ECbdb8794F568922809C52b0Fd2446 | |
0xa70B18ebb5C1cF9Ee533A019975F09Aed4d276b5 | |
waysmakeyourlifebetter[.]com | |
goodpersonofourcentury[.]com | |
besthappyfamily[.]com | |
| IP addresses 5 | |
34.196.13[.]28 | |
91.92.241[.]13 | |
158.94.208[.]213 | |
88.80.150[.]25 | |
54.38.220[.]85 | |
| Operator identities 3 | |
asionamedraft[@]proton.me | |
habitredso98[@]atomicmail.io | |
faridovich2008[@]yandex.ru | |