In November 2025, we analyzed a small backdoor loose on Open VSX. SleepyDuck was unremarkable in every way but one: its header was an ASCII-art duck, and its C2 was a Solana smart contract the loader polled for tasking. It was a JavaScript file, a few kilobytes, executing fetched code in memory — a toy with a mascot.

The duck came back on September 24, 2026. Two extensions appeared on Open VSX under a brand-new alejandroaranda namespace, impersonating the canonical Solidity tooling — alejandroaranda.solidity-langsupport and alejandroaranda.solidity-languini, both displaying as “Solidity,” both copying the real extension’s README word for word. Both also ship a 205 MB file named The Duck Song.mp4. A language extension has no reason to bundle a video. This one bundles it because the video is the payload: stitched into its metadata boxes is a custom-format archive holding compiled Go implants for four platforms, installed as a system service on every startup.

And packed alongside the binaries, one more file — an ASCII-art duck, over the words “your prize is nothing.”

On Windows, the campaign installs a genuine ConnectWise ScreenConnect MSI, a commercial remote-access tool that half the antivirus engines classify as “potentially unwanted application” and the other half deliberately tolerate, because the same installer sits on thousands of managed corporate desktops.

TL;DR

  • SleepyDuck is back. The ASCII-art duck that signed the 2025 Open VSX loader family reappears inside a September 24, 2026 campaign of two fake Solidity extensions (solidity-langsupport 0.0.6, solidity-languini 0.9.2), published under the new, unverified alejandroaranda namespace by a GitHub account (janeykomit) created in 2017 and inactive until the day of publishing.
  • The loader became a binary. The 2025 SleepyDuck variants were kilobyte JavaScript files executing fetched code in memory. This campaign ships evjawbreaker, a stripped, statically linked Go implant compiled for four platforms, with a TLS C2 “hub” client, an Ethereum JSON-RPC dead-drop channel (ten public RPC endpoints compiled in), an interactive PTY shell, and anti-VM/anti-debug checks — hidden inside a 205 MB MP4 through a custom NYANSTEG/NYANARCH/NYANB64X steganographic container.
  • The payload hashes predate the campaign by six months — and close a cold case. Four binaries were first submitted to VirusTotal on March 30, 2026. In April, we caught two Solidity typosquats (juannegro.solidity, juunfranbIanco.solidity) shipping a byte-identical linux_amd64 — recorded then under the family label juannegro-solidity, with no SleepyDuck connection. The duck in the September archive retroactively merges the two: same implant, same operation, rotating front ends.
  • The easter egg came back with it: an ASCII-art duck over “your prize is nothing,” packed, hashed, and shipped with the implant as a taunt for whoever extracts it.
  • On Windows, the actor stopped writing malware. The campaign silently installs app.msi — a genuine ConnectWise ScreenConnect installer (novel to this campaign), deployed through a calc.exe UAC bypass with a Defender exclusion. Commercial enterprise tooling as the backdoor: 11 of 62 engines flag it, mostly as “PUA.”
  • solidity-langsupport had accumulated over 247,000 downloads at the time of analysis — one day after first publication. The extensions are still live on Open VSX at the time of writing.

Why Solidity impersonation works

Solidity impersonation is now a recurring pattern on Open VSX. In May 2026, a threat actor uploaded the same JuanBlanco-impersonating VSIX eight times in an afternoon, iterating the execution primitive with each republish. In August, the helper-beeps/web3devtoolsx family shipped a Solidity-themed dropper that pivoted from a Cloudflare-Worker C2 to a full credential stealer over five major versions. The canonical tool is JuanBlanco.solidity — a ten-year-old Marketplace extension with millions of installs, whose Open VSX counterpart lives under a verified namespace. The display name, the README, the icon, and the marketplace badges all say “Solidity” and nothing else.

The langsupport copy had already passed 247,000 downloads a day after publication — ranking ahead of, or close to, extensions that took years to get there with an inflated download count.

The two extensions

Extension Version First published Downloads (Sep 25) Display name
alejandroaranda.solidity-langsupport 0.0.6 2026-09-24 23:42 UTC 247,380 solidity
alejandroaranda.solidity-languini 0.9.2 2026-09-24 23:46 UTC 97 Solidity

Both were published by the Open VSX account janeykomit, authenticated through a GitHub account created in April 2017. The account has 14 public repositories, zero followers, and no activity until September 24, 2026 — the profile was updated 25 minutes before the first extension went up. A nine-year-old account with no history is a classic aged-handle purchase: bought or compromised.

What activates

The package.json of both extensions is nearly empty and deliberately ordinary: Programming Languages, Snippets, keywords solidity, ethereum, blockchain, smart contracts, MIT license, and a single activation event:

{
  "main": "./out/extension.js",
  "activationEvents": ["onStartupFinished"]
}

onStartupFinished means the payload fires every time the editor starts, after the window is up — the moment when the developer has stopped paying attention.

The entry point, out/extension.js, is 48 lines of compiled TypeScript boilerplate. It imports two components and calls one function. The actual work lives in out/components/autoUpdate.js, which reads:

exports.BUNDLED_RUNNER = 'lang-resource-sync.js';
exports.BUNDLED_VIDEO = 'The Duck Song.mp4';

On activation, attemptUpdate() checks whether the deployment is already complete — on Linux and macOS by looking for specific files under ~/.solidity, on Windows by scanning for a directory whose name contains a marker string. If the deployment is not found, the extension spawns a detached Node process:

// analyst interpretation of the activation flow
const child = spawn(process.execPath, [runnerPath, videoPath], {
  detached: true,
  stdio: 'ignore'
});
child.unref();

The extension does not wait for the child, does not surface an error, and does not log anything. The editor opens normally. The syntax highlighting works. Somewhere under the hood, a 205 MB video file is being read as a container.

A final detail: on Windows, both the extension and the runner write debug logs to %TEMP%\solidity-langsupport-debug.log. A threat actor debugging their own installer through the victim’s temp directory is a rare artifact — it survived into the published build.

The steganographic container

The runner script, lang-resource-sync.js, is 21 KB of plain Node.js. It reads The Duck Song.mp4 and walks the MP4 box structure looking for one specific custom box — a box type no legitimate MP4 contains. The format is homemade, and its three magic headers spell out the campaign’s internal name:

const BOX_MAGIC = Buffer.from('NYANSTEG');      // the box glued into the MP4
const ARCHIVE_MAGIC = Buffer.from('NYANARCH');  // the archive inside the box
const OBFUSCATE_MAGIC = Buffer.from('NYANB64X'); // optional obfuscation layer

The container layers three stages:

  1. Locate. Scan the MP4 bytes for the NYANSTEG magic and take everything after it as embedded data.
  2. Deobfuscate. If the payload starts with NYANB64X, decode a substitution table: each of the 65 base64 characters is mapped to a variable-length token, and the payload body is written in those tokens.
  3. Unpack. The result is a NYANARCH archive: a file table with names, sizes, and SHA-256 digests, followed by the file bodies, each verified against its digest before extraction.

The layering has a clear purpose. The payload never exists as a file on disk, never travels over the network, and never appears as an executable inside the VSIX. It is bytes inside a box inside a video that plays correctly in any media player. File-type detection sees an MP4. Signature scanning sees a song about a duck asking for grapes.

Cross-platform persistence

The archive contains binaries named for each target: linux_amd64, linux_arm64, darwin_amd64, darwin_arm64. On macOS and Linux, the runner writes the binary to a hidden directory under the user’s home and registers it as a persistent service.

On Linux, the service definition is written as a systemd user unit named solidity-langsupport-runner.service. On macOS, it takes the form of a LaunchAgent — com.solidity.langsupport.runner.plist, installed where launchd loads it at login. The binary is marked executable, the service is enabled, and the extension’s job is done. From the next boot onward, the service starts with the user session, independent of VS Code.

The Windows path is longer and more aggressive. The runner writes a PowerShell script, then writes a Visual Basic Script launcher, then executes it:

// analyst interpretation of the launcher chain
const psCmd = `powershell.exe -WindowStyle Hidden -NoProfile ` +
  `-ExecutionPolicy Bypass -File "${postUacPath}"`;
const vbs = `CreateObject("Wscript.Shell").Run "${psCmd}", 0, False`;
const elevated = `wscript.exe //B //Nologo "${vbsPath}"`;

The VBS wrapper exists to bypass User Account Control: wscript.exe running a hidden PowerShell window does not prompt the user the way a direct PowerShell elevation would. Inside the elevated script, the installer:

  • marks the staging directory’s contents Hidden + System,
  • adds itself to the Microsoft Defender exclusion paths with Add-MpPreference -ExclusionPath,
  • copies the payload to app.msi and installs it with msiexec.exe /q /i ALLUSERS=1 — silent, all users, no visible window,
  • writes an ok flag to signal completion,
  • and in a finally block, removes the Defender exclusion, deletes the staging directory, the script, the VBS launcher, and the copied MSI.

The runner waits for the install in a loop, up to twenty seconds, watching both the ok flag and the tasklist output for msiexec.exe. When it sees the installer appear and disappear without the flag, it assumes failure and tries again. The result on every platform is the same: a native binary, installed as a service, running outside the editor, surviving uninstall of the extension that dropped it.

The payload

The archive holds seven entries, each SHA-256 verified against the manifest before extraction. Both extensions ship byte-identical copies.

File Size What it is
linux_amd64 6,291,618 ELF 64-bit, Go 1.26.0, stripped, statically linked
linux_arm64 5,832,866 ELF 64-bit ARM aarch64, Go 1.26.0, stripped
darwin_amd64 6,392,832 Mach-O x86_64, PIE
darwin_arm64 5,918,146 Mach-O arm64, PIE
app.msi 13,189,120 ScreenConnect (ConnectWise) v25.4.3.9287 installer
invoke.ps1 13,258 PowerShell UAC-bypass launcher
note.txt 866 An easter egg for whoever extracts the archive

The four native binaries are one implant compiled for four platforms. The Windows path is not the same implant: it installs a commercial remote-access support tool released by ConnectWise instead.

The hashes predate the campaign by six months

VirusTotal submission dates for the payload hashes split the archive into two groups, and the split tells the campaign’s story.

The four evjawbreaker binaries were first submitted to VirusTotal on March 30, 2026 — nearly six months before the extensions appeared on Open VSX. These exact hashes, byte for byte, were circulating in the wild half a year before this campaign packaged them. The binaries are not a fresh build for the Solidity lure; they are existing ammunition, loaded into a new delivery vehicle.

The app.msi is the opposite. The ScreenConnect installer’s hash was first submitted on September 25, 2026 by Yeeth Security. The Windows payload is novel. Nobody had uploaded this exact MSI to VirusTotal before this campaign shipped it.

Read together, the two dates sketch an evolution. The Linux and macOS stage is mature, reused, and already battle-tested. The Windows stage is the experiment — and the experiment is the interesting part. Installing a commercial RMM tool instead of a custom backdoor is a newer strategy observed as an alternative to writing your own Windows implant: the MSI is vendor-produced, signed, documented, and half the antivirus engines that flag it at all label it PUA.ConnectWise or RemoteAdmin.Win32.ConnectWise — “potentially unwanted application,” not “trojan.” The threat actor traded a detectable custom binary for a legitimate installer that most endpoint products deliberately tolerate, because the same tool sits on thousands of managed corporate desktops.

The April campaign that already had these binaries

The six-month gap has a closing entry. Yeeth Security’s records of the April 2026 Open VSX wave show two Solidity typosquats — juannegro.solidity and juunfranbIanco.solidity (the capital “I” is deliberate), both at version 0.0.189, first seen April 29–30 — that shipped a bundled bin/linux_amd64 byte-identical to the binary in the Duck Song archive: SHA-256 9b73e7cd4e1425e770392549d8df46c706139ef476f4f7b9ac405165dc8d9696. The same GitHub account published both namespaces. At the time, we recorded the finding under the family label juannegro-solidity. The SleepyDuck signature was not yet part of the picture, because the April packages carried no duck — only the implant.

Re-examined in that light, the family history reads as one threat actor with a stable implant and a rotating front end. The March 30 VirusTotal submissions now line up as the build date for the evjawbreaker binaries; April 29–30 is their first recorded deployment, through juanblanco typosquat extensions; May 29 brings the alejandro.munoz probe — eight rapid re-uploads of another Solidity impersonator, this time testing prompt-injection payloads against scanners; September 24 is the mature redeployment: the same binaries, hidden better, behind a Solidity lure, with the duck back on top and a commercial RMM closing the Windows gap. The evidence available does not establish that a single threat actor controls every one of these extensions. But the shared byte-identical implant across the April and September campaigns is a stronger link than most cluster attributions in this space get to claim, and it retroactively gives the April campaign the label it was missing: the juannegro-solidity family and SleepyDuck are the same operation.

evjawbreaker: the Go implant

The module path recovered from the binaries is evjawbreaker/cmd/evjawbreaker, with three internal packages doing distinct jobs:

  • evjawbreaker/internal/hubclient — a TLS command-and-control client. The log strings read like a session manager: hub: connected to %s as %s (%s), hub: session active, hub: tls dial %s: %v, hub: server error: %s/%v, hub: connection closed: %v. Registration fields (register, hostname, platform, exitCode) suggest the implant checks in with host identity before waiting for tasking. No hub address is present as a static string — the server is likely supplied at runtime or through the Ethereum channel below, which means killing one infrastructure host does not disable the implant.
  • evjawbreaker/internal/eth — an Ethereum JSON-RPC client implementing eth_call and eth_sendRawTransaction, with more than ten public RPC endpoints compiled in: cloudflare-eth.com, rpc.ankr.com/eth, eth.llamarpc.com, eth.meowrpc.com, eth.drpc.org, ethereum.blockpi.network/public, ethereum.publicnode.com, rpc.mevblocker.io, 1rpc.io/eth, and bloXroute endpoints under blxrbdn.com. Public Ethereum nodes are legitimate infrastructure; embedding ten of them in a binary that otherwise has no reason to touch a blockchain indicates a dead-drop channel — on-chain contract storage as a C2 mechanism that no domain blocklist touches.
  • evjawbreaker/internal/antivm — anti-analysis checks for QEMU, VirtualBox, VMware, x64dbg, WinDbg, Cuckoo, ANY.RUN, OllyDbg, VirusTotal, sandbox markers, and isDebuggerPresent.

The implant depends on github.com/creack/pty for interactive terminal sessions, and contains a command output exceeds 32MiB guard — remote command execution with output capture. On a Solidity developer’s machine, an interactive PTY plus an Ethereum transaction client is a combination aimed directly at wallets and contract keys, not at generic data theft.

The Windows payload: ScreenConnect

The app.msi in the archive is not custom malware. Its author string is “ScreenConnect Software” and its product version is 25.4.3.9287: a genuine ConnectWise ScreenConnect installer, built with WiX 3.11. ScreenConnect is a legitimate remote monitoring and management tool used by real IT departments every day. That is the point. A remote-access tool with a vendor-signed installer blends into enterprise software inventories in a way a custom implant never could, and the threat actor gets a full-featured remote desktop, file transfer, and command shell without writing one.

The invoke.ps1 launcher handles the elevation and the antivirus problem in one pass. Its default command is calc.exe — the classic auto-elevate binary used as a UAC bypass vehicle — and it decodes its second stage from a compressed base64 blob written to a temp file at run time. It checks the child’s output and exit code against a list of blocked markers (“Operation did not complete successfully because the file contains a virus”, “blocked by your antivirus”, “malicious content”), with the marker strings stored reversed so a scanner reading the script source does not see them. If the inner run is blocked, the launcher spawns a fallback through cmd.exe. The script’s own status messages announce each decision: “blocked by script scanning (AMSI/Defender)”, “Inner runner completed successfully.”

The easter egg

The seventh archive entry is note.txt. It contains no code. It is an ASCII-art duck, followed by three lines:

⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⡶⠿⠿⠷⣶⣄⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⡿⠁⠀⠀⢀⣀⡀⠙⣷⡀⠀⠀⠀
⠀⠀⠀⡀⠀⠀⠀⠀⠀⢠⣿⠁⠀⠀⠀⠘⠿⠃⠀⢸⣿⣿⣿⣿
⠀⣠⡿⠛⢷⣦⡀⠀⠀⠈⣿⡄⠀⠀⠀⠀⠀⠀⠀⣸⣿⣿⣿⠟
⢰⡿⠁⠀⠀⠙⢿⣦⣤⣤⣼⣿⣄⠀⠀⠀⠀⠀⢴⡟⠛⠋⠁⠀
⣿⠇⠀⠀⠀⠀⠀⠉⠉⠉⠉⠉⠁⠀⠀⠀⠀⠀⠈⣿⡀⠀⠀⠀
⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢹⡇⠀⠀⠀
⣿⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⡇⠀⠀⠀
⠸⣷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⡿⠀⠀⠀⠀
⠀⠹⣷⣤⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣰⡿⠁⠀⠀⠀⠀
⠀⠀⠀⠉⠙⠛⠿⠶⣶⣶⣶⣶⣶⠶⠿⠟⠛⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀

you found an easter egg
congratulations

your prize is nothing

This is the duck from the intro — and its presence did more than identify a resurgence. The April campaign that shipped these same binaries carried no duck at all, which is why we recorded it under a separate family label and never connected it to SleepyDuck. The mascot in the September archive is the tiebreaker: it links the 2025 script family to the 2026 compiled implant, and both to the same operation. In the 2025 SleepyDuck variants, the ASCII art was a header inside the malware’s own source, a signature shipped by habit. Here it is a deliberate artifact: a separate file, packed into the payload archive, hashed alongside the binaries it travels with. The threat actor moved their mascot from the code to the package, which suggests the signature was never an accident at all.

The easter egg is aimed at whoever digs the payload out of the video — a malware analyst, a takedown engineer, or a curious victim. It is the same instinct that put meme comments in the PowerShell launcher, which is decorated with three one-liners between the code blocks:

# ~ ここにいるから、歌えるんだ ~        ("because you're here, I can sing")
# ~ Leek power~! ~
# ~ Tell me your favorite song! ~

The Japanese line translates to “because you’re here, I can sing” — a line about singing, packed into a campaign whose carrier is a song. “Leek power” references the Vocaloid leek meme. Somewhere in this pipeline is a threat actor who expects their code to be read, and left jokes for the occasion.

The easter egg also carries one practical signal: the threat actor treats the MP4 container as a private channel to the analyst, not just the victim. A campaign that leaves taunts in its payload archive has a staging workflow where note.txt is a file like any other — packed, hashed, and shipped with the implant. That workflow is reusable, and the next campaign may ship it with a different duck.

Why it evades detection

Attacker choice Defender assumption it defeats
Payload embedded in an MP4 box, not a bundled binary “Malicious extensions ship executable files we can scan”
Custom NYANB64X substitution alphabet Base64-decoding the payload yields garbage without the token table
evjawbreaker implant stripped and statically linked Symbol-based detection of known malware families
C2 over public Ethereum RPC endpoints Domain/IP blocklists; “no C2 domain means no C2”
Genuine ScreenConnect MSI as the Windows payload “Detect the malware binary” — there is no malware binary
Reversed AV-block strings in invoke.ps1 String-based scanning of the launcher source
Service install via systemd/LaunchAgent/MSI, not VS Code tasks “Extension malware runs inside the editor sandbox”
wscript → hidden PowerShell chain Direct elevation detection; UAC prompts
Defender exclusion added and removed during install Real-time scanning of the staging directory
Debug log written only on Windows Analysis on Linux/macOS reveals no logging behavior
Aged GitHub account (2017) as publish identity “New accounts are the suspicious ones”

Linkage evidence

The two extensions are the same campaign, not a coincidence. The evidence:

  • Byte-identical core files. Both VSIX packages contain byte-identical copies of readme.md (26,796 bytes), lang-resource-sync.js (21,919 bytes), out/extension.js, out/components/autoUpdate.js, out/components/winDebug.js, snippets/solidity.json, syntaxes/solidity.json, and solidity.configuration.json. Only package.json, the manifest, and the icon differ.
  • Shared runner and video. Both reference lang-resource-sync.js and The Duck Song.mp4 by the same constant names, and the MP4 in both is the same 205 MB payload container.
  • Same publisher, same session. Both were published by janeykomit within four minutes of each other (23:42 and 23:46 UTC), through the same fresh alejandroaranda namespace.
  • Same impersonation target. Both ship JuanBlanco’s README verbatim, including his marketplace badges and his own warning about impersonation campaigns.

Outlook

The techniques here are a template, and templates get reused. Three things in this campaign predict what comes next:

  • The steganographic container will reappear in other file types. The NYANSTEG box format does not care whether the carrier is an MP4, a PNG, a font, or a WASM module. Any large binary that plausibly ships inside a package is a viable carrier, and any registry that inspects file types rather than file contents will pass it through.
  • Aged accounts are now the preferred publish identity. A nine-year-old GitHub profile with no followers defeats every “new account” heuristic a marketplace might run. Expect more purchased or dormant handles, woken up minutes before publishing. Publisher age is not a trust signal without activity history.
  • The service-install layer will be adapted to other lures. The runner that came with this pair is lure-agnostic: it reads a video path, extracts a binary, installs a service. Nothing in it is Solidity-specific. The same chassis can ship inside a Kanban board, a theme pack, or an AI-assistant extension with a republished MP4 and a new display name.
  • Legitimate RMM installers will replace custom Windows implants. The ScreenConnect MSI did more for the Windows stage than purpose-built malware could: a vendor binary, a signed installer, a service that IT staff recognize and hesitate to remove. The next campaign to copy this one will reach for a different commercial RMM, and host-level detection will have to distinguish “installed” from “user-requested.”
  • The Ethereum dead-drop pattern will spread. Ten public RPC endpoints compiled into the implant means the C2 channel has no domain to sinkhole and no server to seize — the contract storage is the infrastructure. Expect this pattern to migrate from crypto-targeted campaigns into general-purpose ones.

Defenders should watch for the box magic itself. NYANSTEG, NYANARCH, and NYANB64X are fixed strings in the runner; a package containing any of them is either this campaign or a direct descendant of it.

What to do

If you installed either extension:

  1. Uninstall it from VS Code or Cursor, and remove the alejandroaranda namespace entry if it remains in your extensions directory.
  2. Check for the deployment artifacts: a hidden ~/.solidity directory containing an unfamiliar binary, a systemd user service or LaunchAgent you did not install (solidity-langsupport-runner.service, com.solidity.langsupport.runner), or — on Windows — a recently installed MSI-sourced service.
  3. On Windows, check for a ScreenConnect installation you did not set up, and review %TEMP%\solidity-langsupport-debug.log. If the log exists, the installer ran on that machine.
  4. Run a full antivirus scan. On Windows, check the Defender exclusion list for entries you did not add.
  5. Treat the machine as compromised, not merely infected. The evjawbreaker implant carries an Ethereum transaction client and an interactive shell. If you work with Solidity, move wallet keys, seed phrases, and contract deployer accounts off that machine and rotate every credential that touched it.

The general principle this campaign teaches: a package’s file types are not its behavior. A 205 MB MP4 inside a 45 MB extension is not media — it is capacity. Registry-level scanning that treats media files as inert will keep passing this class of dropper, because the malice lives in the bytes the format does not require.

Indicators of Compromise

Malicious extension identifiers

  • alejandroaranda.solidity-langsupport 0.0.6 — SHA-256 e9ccb04446d570d784d05c675898164a48eb15c4b7a9ae3266a3f43ee809c788
  • alejandroaranda.solidity-languini 0.9.2 — SHA-256 66c1f6eb386ecb9bddf54a05aa48d11b3b1424e8a0bc109300e5b30f3d41d395

Publisher infrastructure

  • Open VSX publisher: alejandroaranda (unverified namespace)
  • Publishing identity: GitHub user janeykomit (account created April 2017, 0 followers, inactive until 2026-09-24)

Steganographic format markers

  • Box magic: NYANSTEG
  • Archive magic: NYANARCH
  • Obfuscation header: NYANB64X (version 1, 65-entry substitution table)

Payload identifiers (SHA-256)

File SHA-256
linux_amd64 9b73e7cd4e1425e770392549d8df46c706139ef476f4f7b9ac405165dc8d9696
linux_arm64 b601776817363b96295119f7221338a122d5247a35a77a64b04f286e1bbcc565
darwin_amd64 80d2672e2599732d3c0ae2a4cd0d1e3fe4d555a60273ce33feb99db3f34d250f
darwin_arm64 fae61f31f00988fdc5cc9e7272b51e08af2e245d81003237875415930fd27358
app.msi 7527e86d70e7c9493db4356f1c3775380431b310000f2602c1e993cf435d01da
invoke.ps1 37d14bff30762ca701e9c1f8bc6c57c065bb20ae3a2208cb7411a6530610f08e
note.txt 683ad81cdc028c538ee66da8e6b60f2a5ab070bfd900da80175df317a73886d8

Implant markers

  • Family lineage: SleepyDuck (ASCII-art duck signature; prior analysis) — retroactively merged with the April 2026 juannegro-solidity family on the strength of the shared byte-identical implant
  • Related campaigns, same binaries: juannegro.solidity 0.0.189 (first seen 2026-04-30, bundled bin/linux_amd64 SHA-256 9b73e7cd...9696 byte-identical to this campaign’s), juunfranbIanco.solidity 0.0.189 (first seen 2026-04-29, homoglyph typosquat, same publisher GitHub account juannegro id 280480368)
  • Related probe, same lure: alejandro.munoz-0.0.188 (2026-05-29, eight rapid re-uploads of a Solidity impersonator testing prompt-injection payloads)
  • Go module path: evjawbreaker/cmd/evjawbreaker with internal packages evjawbreaker/internal/hubclient, evjawbreaker/internal/eth, evjawbreaker/internal/antivm
  • Hub log strings: hub: connected to %s as %s (%s), hub: session active, hub: tls dial %s: %v, hub: server error: %s/%v, hub: connection closed: %v
  • Embedded Ethereum RPC endpoints: cloudflare-eth.com, rpc.ankr.com/eth, eth.llamarpc.com, eth.meowrpc.com, eth.drpc.org, ethereum.blockpi.network/public, ethereum.publicnode.com, rpc.mevblocker.io, 1rpc.io/eth, blxrbdn.com
  • Dependency: github.com/creack/pty v1.1.24 (interactive PTY)
  • Output guard string: command output exceeds 32MiB
  • app.msi author “ScreenConnect Software”, product version 25.4.3.9287 (legitimate ConnectWise ScreenConnect installer)
  • invoke.ps1 default command calc.exe (auto-elevate UAC bypass vehicle), reversed AV-block strings, temp-file staging under %TEMP%\uac39-inner-<guid>.ps1

Behavioral indicators

  • package.json activation event onStartupFinished with a bundled runner (lang-resource-sync.js) and a 205 MB The Duck Song.mp4 in the extension root
  • A detached child_process.spawn of Node with the runner and video as arguments, with unref() so the editor never waits on it
  • Hidden binary deployment under the user’s home directory; deployment-completeness checks before re-running
  • Linux: systemd user service registration
  • macOS: LaunchAgent registration (com.solidity.langsupport.runner.plist)
  • Windows: wscript.exe //B //Nologo → hidden PowerShell (-WindowStyle Hidden -ExecutionPolicy Bypass) → Add-MpPreference -ExclusionPath → msiexec.exe /q /i ... ALLUSERS=1, with all staging artifacts deleted in a finally block
  • Windows debug log: %TEMP%\solidity-langsupport-debug.log
  • An unexplained ScreenConnect installation on a developer workstation — check installed programs and running services for ScreenConnect entries the user did not install

Impersonation artifacts

  • JuanBlanco README copied verbatim into both extensions, including juanblanco.solidity marketplace badges
  • solidity-languini description: “Solidity and Hardhat support by the Hardhat team”
  • Display names Solidity / solidity on an unverified namespace created the same day