PhantomSync: npm Krypto-pakketten ferbergje Wallet Stealer

PhantomSync: acht krypto-ûntwikkelder npm-pakketten ferbergje in fertrage, sels-oanhâldende dropper

TL; DR

In inkele npm-útjouwer ferstjoerde acht lytse pakketten waans nammen lêze as deistige boublokken foar blockchain- en walletûntwikkeling, base58-utils, abi-encode, eth-dev, arb-kit, layer2-sdk, solana-key-utils, eth-wallet-helpers, en crypto-validate-libElk befettet wol in wurkjend hulpprogramma. Nei dat hulpprogramma wurdt lykwols in selsoproppend blok koade tafoege dat rint op it momint dat de module ymportearre wurdt.

Sawat 37 sekonden nei ymport, dat blok dekodearret in lading dy't yn it pakket ferstjoerd wurdt ferklaaid as in testfixture, skriuwt it nei in ferburgen bestân ûnder de thúsmap fan 'e brûker, registrearret himsels om opnij te starten op elke login oer Windows, macOS en Linux, en start it dekodearre skript as in loskeppele proses. Neat hjirfan wurdt aktivearre tidens npm-ynstallaasje; it wachtet oant de koade ymportearre en útfierd wurdt, wat in stiller momint is as ynstallaasje.

De lading is net ûntrochsichtich. It wurdt ferstjoerd as gewoane base64, dus it ûntsiferjen fan 'e "testfixture" herstelt de twadde etappe folslein: in krypto-wallet en geheimendiever dat wachtet oant de masine idle sit, priveekaaien en siedfrasen rispet, elke fynst fersiferet mei in hurdkodearre RSA-4096-kaai, en it eksfiltrearret troch it te pinnen oan iepenbiere IPFS-opslach, en elke 12 oeren werom beaconet.

Wy folgje it kluster as PhantomSyncAlle acht pakketten wiene live yn it npm-register op it momint fan analyze, publisearre ûnder ien akkount.

Ekosysteemnpm
Packagesbase58-utils, abi-encode, eth-dev, arb-kit, layer2-sdk, solana-key-utils, eth-wallet-helpers, crypto-validate-lib
Platfoarms rjochteWindows, macOS, Linux
KearngedrachFertrage, ymporttiiddropper ferburgen as in testfixture; ynstallearret cross-platform persistinsje
NuttelastKrypto-wallet en geheimendiever, RSA-4096-fersifering, eksfiltraasje fia iepenbiere IPFS-pinning

Oanfalsanatomy

Elk pakket sjocht der by it earste lêzen ûnopmerklik út. base58-utils, bygelyks, is in pear kilobytes fan nul-ôfhinklike Base58 / Bitcoin-WIF helperkoade - presys wat de namme belooft. De relevante koade sit efter de module syn module.eksports, dêr't in lêzer dy't de boppekant fan it bestân oersjocht wierskynlik net sil sykje: in selsoproppende funksje dy't himsels mei in timer pland.

De keatling fan operaasjes, rekonstruearre út 'e pakketboarne, rint sa:

1. Package is required() by the host project 2. A self-invoking function schedules a callback ~37,000 ms later (setTimeout) 3. On fire, the callback reads test/fixtures/keypairs.dat (a base64 blob) 4. It base64-decodes that blob into a Node.js script 5. It writes the script to ~/.cache-db/.node-sync/syncd.js (mode 0o700) 6. It installs login-persistence for that script (see below) 7. It spawns "node syncd.js" as a detached process

Twa ûntwerpkeuzes falle op.

De lading reizget as in testapparaat. De twadde etappe is net skreaun as dúdlike koade. It libbet yn test/fixtures/kaaipearen.dat, in base64-bestân waans namme oergiet yn in pakket dat beweart kaaipearen te behanneljen. Foar in minske dy't de tarball skimt, liket it op foarbyldgegevens; foar de taheakke koade is it in skript om te dekodearjen en út te fieren. De dropper sels befettet gjin netwurkadres - dy libje yn 'e twadde faze - mar d'r is gjin ekstra fertsjustering: de fixture is in inkele laach fan base64, dus it dekodearjen dêrfan (basis64 -d) herstelt it folsleine syncd.js en syn netwurkgedrach. De folgjende seksje giet troch wat dy herstelde faze docht.

Detonaasje is fertrage en keppele oan ymport, net oan ynstallaasje. Omdat de trigger is fereaskje() plus in timer fan ~37 sekonden ynstee fan in ynstallaasjeheak, giet it gedrach omleech nei kontrôles dy't allinich de npm ynstallearje stap, en de fertraging duorret langer as in protte koarte sandbox- en CI-runs. Tsjin 'e tiid dat der wat útfierd wurdt, is de ynstallaasje dy't it pakket deryn helle hat al lang klear.

Sadree't it dekodearre skript op skiif stiet op ~/.cache-db/.node-sync/syncd.js — in paad keazen om te lêzen as in routine cache-map — de dropper soarget derfoar dat it opnij starte op alle trije grutte platfoarms oerlibet:

  • Linux: in cron-yngong dy't it skript opnij starte. De yngong wurdt ynstalleare troch it filterjen fan de besteande crontab fia grep -v syngronisearre, wat it side-effekt hat dat de nije yngong bûten in gewoane list wurdt litten dy't greps hat foar deselde namme.
  • Windows: in plande taak mei de namme WinNodeSync, ynsteld om opnij út te fieren mei in ynterval fan 12 minuten.
  • MacOS: in launchd-taak mei it label com.apple.syncd, oanwêzich yn ferskate fan 'e pakketten - in label dat in legitime Apple-systeemtsjinst neimakket.

It skript wurdt dan fuortendaliks starte as in loskeppele proses, sadat it trochgiet mei rinnen nei't it ymportearjende programma ôfsletten is.

Wat de twadde etappe docht

Omdat de fixture in inkele base64-laach is, dekodearret de twadde etappe skjin en kin folslein lêzen wurde. Alle acht pakketten befetsje ien fan trije farianten fan itselde skript, dat himsels identifisearret yn in koptekstkommentaar as phantom syncd v3 - top durmiente (“sliepende mol”). Syn taak is om materiaal fan krypto-wallets en ûntwikkeldersgeheimen te stellen en se fan 'e masine te ferstjoeren. It rint yn dizze stappen:

  • 1. Wachtsje oant de masine stil stiet. Foardat jo wat dogge, syncd.js kontrolearret hoe lang de brûker ynaktyf west hat en giet allinich fierder as in drompelwearde (sawat 15 minuten) — xprintidle op Linux, ioreg HIDIdleTime op macOS, en in PowerShell idle-time query op Windows. Harvesting bart dêrom faak as nimmen oan it toetseboerd sit.
  • 2. Helje in op ôfstân bestjoerbere aktivearringsskeakelIt skript hellet in lytse konfiguraasje út in dead-drop foardat it hannelet. De primêre boarne is in GitHub gist raw URL (gist.githubusercontent.com/juang55/…/cfg.txt); it skript wurdt allinich aktivearre as dy konfiguraasje lêst aktyf=1As de gist net beskikber is, falt it werom op trije hurd kodearre IPFS-ynhâldsidentifikators, dy't fia de iepenbiere gateways ophelle wurde. gateway.pinata.cloud, ipfs.io, en cloudflare-ipfs.comDit jout de operator in kontrôle foar it yn-/útskeakeljen fan wapens nei it ynskeakeljen en in fallback-funksje dy't bestand is tsjin útskeakeljen. (De lytste fariant, ferstjoerd yn krypto-validearje-lib, eth-wallet-helpers, en solana-kaai-utils, hat de gist-laach fuorthelle en fertrout allinich op 'e IPFS-identifiers.)
  • 3. Sammelje materiaal en geheimen foar de wallet. It skript rint troch de thúsmap fan 'e brûker - ~/.config/solana, ~/.ethereum/kaaiwinkel, ~/.gieterije, ~/.hurde hoed, ~ / .ssh, en desktop/dokuminten/downloads (ynklusyf mapnammen yn it Spaansk), plus ~/.omjouwing en shell rc-bestannen, en it lykweardige Applikaasjegegevens lokaasjes op Windows. It rjochtet him op Ethereum priveekaaien, Bitcoin WIF-kaaien, BIP-39 siedfrasen, Solana-kaaipearen, Ethereum-kaaiwinkel JSON, SSH-kaaien en geheimdragende omjouwingsfariabelen. De gruttere fariant (yn abi-kodearje, base58-utils, eth-ûntwikkelder) befettet it folsleine BIP-39 wurdboek fan 2048 wurden en brûkt reguliere útdrukkings om extract yndividuele kaaien en validearre siedfrasen út elke tekst dy't it lêst; de twa lytsere farianten fine ynstee bestannen op basis fan kaaiwurd (sied, mnemonyk, wallet, metamask, phantom, ledger, trezor, …) en uploade hiele bestannen.
  • 4. Fersiferje en eksfiltrearje fia in iepenbiere pinningtsjinst. Elke fynst wurdt bondele mei in fingerprint fan in gasthear (brûkersnamme@hostnamme, platfoarm, tiidstempel) en fersifere mei in hurdkodearre RSA-4096 iepenbiere kaai ynbêde yn it skript. De fersifere rekord wurdt dan uploaden troch it te pinnen oan IPFS fia api.pinata.cloud/pinning/pinJSONToIPFS, autentisearre mei hurdkodearre Pinata API-gegevens. Der is gjin maatwurk C2-tsjinner om yn beslach te nimmen: de stellen gegevens wurde parkeard yn iepenbiere desintralisearre opslach, dy't troch de operator weromhelle wurde kin mei de resultearjende ynhâldshashes. Uploads wurde tusken ferskate sekonden willekeurige jitter pleatst, en in lokale log fan tiidstempel | kaaitype | weromjûne hash wurdt hâlden by ~/.cache-db/.node-sync/.sl.
  • 5. Oanhâlde en beaken op in syklus fan 12 oeren. De twadde etappe herstelt syn eigen persistinsje - in cron-yngong op Linux, in com.apple.syncd launchd-taak op macOS, en in plande taak mei de namme WindowsNodeSync op Windows - ynsteld om elke 12 oeren opnij út te fieren. Tink derom dat dit in ferskillend Windows-taaknamme fan dejinge dy't de dropper ynstallearret (WinNodeSync); beide binne it wurdich om nei te sykjen.

Timeline

De acht pakketten waarden yn in koarte útbarsting publisearre op 13-07-2026 en 14-07-2026. Ferskate hawwe mear as ien ferzje; de ​​dropper is identyk foar alle ferzjes, mei allinich line-offsets dy't ferskowe as de grutte fan 'e goedaardige nutskoade derboppe feroaret.

Datum Barren
2026-07-13 De earste pakketten yn it kluster ferskine ûnder ien útjouwer (solana-key-utils, eth-wallet-helpers, crypto-validate-lib en iere ferzjes fan 'e rest)
2026-07-13 → 07-14 Oerbleaune nammen en opfolgferzjes publisearre; deselde tafoege dropper ferstjoerd yn elk
2026-07-14 Alle acht markearre en analysearre; elk pakket noch te ynstallearjen fanút it register

Oer de hiele útbarsting feroare de registerreputaasje fan 'e útjouwer fan rûchwei neutraal oan it begjin fan it kluster nei sterk negatyf doe't deteksjes opstapelen - in waarnimbere side-effekt fan 'e pakketten dy't markearre waarden, net in ûntwurpen funksje.

Yndikatoaren fan kompromis

Alle ûndersteande yndikatoaren waarden befêstige oanwêzich op it momint fan analyse - dy yn 'e tabellen fan' e "Twadde faze" troch dekodearring test/fixtures/kaaipearen.dat en it lêzen fan it weromfûne syncd.js.

Bestannen en paden

indicator rol
~/.cache-db/.node-sync/syncd.js Dekodearre twadde etappe, skreaun mei modus 0o700
~/.cache-db/.node-sync/.sl Lokaal eksfiltraasjelogboek (tiidstempel | kaaitype | IPFS-hash)
test/fixtures/keypairs.dat Base64-kodearre lading yn 'e tarball opsteld as in "testfixture"

Netwurkynfrastruktuer fan 'e twadde faze (hersteld fan syncd.js)

indicator rol
gist.githubusercontent.com/juang55/b298754cb72942b1cdcf02ccd45cde2f/raw/cfg.txt Aktivaasje dead-drop; skript rint allinich as konfiguraasje lêst active=1
Qmcqz3w8j4qFQXDAXAxnrdc2oSX3nzBT4NqtpTqL8mr1ga IPFS-konfiguraasjefallback (CID)
QmdTXoqVmTHY1i4ZWLdLkoQ9YChp5TXPh5cWXwnAYZt5iF IPFS-konfiguraasjefallback (CID)
QmfJkLU5gdCpqbbqEjWYC2anXW9FmuEeSLLeLiHVJKYUjp IPFS-konfiguraasjefallback (CID)
gateway.pinata.cloud, ipfs.io, cloudflare-ipfs.com IPFS-gateways dy't brûkt wurde om de konfiguraasje-fallback op te heljen
api.pinata.cloud/pinning/pinJSONToIPFS Eksfiltraasje-eindpunt, stellen gegevens fêstmakke oan iepenbiere IPFS
Pinata API-kaai 13c766575b9270a9825d, hurdkodearre eksfiltraasje-referinsje

Kolleksjedoelen fan 'e twadde faze (hersteld fan syncd.js)

indicator rol
~/.config/solana, ~/.ethereum/keystore, ~/.foundry, ~/.hardhat, ~/.ssh, ~/.env, shell rc-bestannen Mappen/bestannen trochsocht nei kaaien en geheimen
AppData\Roaming\Solana, AppData\Local\ethereum\keystore Windows-ekwivalinten trochsocht
Artefakttypen rispe ETH privee kaaien, Bitcoin WIF, BIP-39 siedfrasen, Solana kaaipearen, Ethereum kaaiwinkel JSON, SSH-kaaien, geheime omjouwingsfarianten

Persistinsje-artefakten

platfoarm indicator
linux cron-yngong lansearring syncd.js; ynstalleare fia crontab filtere troch grep -v syncd
Windows plande taak WinNodeSync (dropper) en WindowsNodeSync (twadde etappe)
MacOS lansearringslabel com.apple.syncd
Alle De twadde etappe hâldt himsels wer oan yn in syklus fan 12 oeren

Behavioraal

  • Selsopropende funksje tafoege nei module.eksports, skema a setTimeout fan ~37,000 ms by ymport.
  • bern_proses spawn("knooppunt", ) mei de losse opsjeset.
  • Idle-gated aktivearring yn 'e twadde faze (xprintidle / ioreg HIDIdleTime / PowerShell idle-tiid; ~15-minuten drompel).
  • RSA-4096-fersifering per fynst, dan HTTPS PEAL nei in iepenbiere IPFS pinning API.

Pakketten en ferzjes (npm, útjouwer solbuilder_io)

Pakket versions
base58-utils 1.0.0, 1.0.1, 1.0.3
abi-encode 1.0.0, 1.0.1, 1.0.2
eth-dev 1.0.0, 1.0.1, 1.0.2
arb-kit 1.0.0, 1.0.1
layer2-sdk 1.0.0, 1.0.1
solana-key-utils 1.0.0
eth-wallet-helpers 1.0.0
crypto-validate-lib 1.0.0

Útjouwer

  • solbuilder_io - angel_lopez89[@]proton[.]my, e-post net ferifiearre, gjin ferifiearre boarne-kontrôle akkount, gjin keppele repository.

Attribúsje en waarnommen gedrach

De acht pakketten diele ien útjouwersakkount en ien lading. Elk is in triviaal pakket - in pear kilobytes echte nutskoade mei deselde dropper deroan tafoege - publisearre sûnder in keppele repository en ûnder in net-ferifiearre wegwerp-e-postadres. Dy uniformiteit, it dielde droppad, de dielde persistinsjelabels, en de dielde kaaipearen.dat staging-bestannen binne wat it kluster byinoar bine.

De pakketten binne ungewoan iepenhertich oer har eigen gedrach. solana-kaai-utils befettet inline-opmerkings dy't it tafoege blok yn ienfâldige termen beskriuwe - men labelt it FANTOOM: ûnsichtbere oanhâldendheid, in oar (yn it Spaansk) lêst Topo op 'e eftergrûn útsmite, "fier de mol op 'e eftergrûn út." Dit binne de eigen annotaasjes fan 'e koade fan wat it docht; de namme fan 'e kampanje yn dizze post is ôflaat fan dat earste label tegearre mei it falske knooppunt "sync daemon" (syngronisearre) dat de persistinsjemasjinerie imitearret.

Wy beskriuwe allinich wat de koade waarnimber docht. De nammejouwing fan 'e pakketten - allegear krypto-, wallet- en blockchain-toolingtermen - jout oan hokker ûntwikkelderspublyk se it meast wierskynlik by namme sil brûke; it stelt net op himsels fêst wa't de útjouwer is. De twadde etappe wie folslein te herstellen troch de base64-fixture te dekodearjen, en it gedrach dêrfan wurdt hjirboppe beskreaun: it sammelt wallet-kaaien, siedfrasen en geheimen en eksfiltrearret se, RSA-fersifere, nei iepenbiere IPFS-opslach fia Pinata. In opmerklike ûntwerpkeuze is de ôfwêzigens fan in privee C2-tsjinner - konfiguraasje komt fan in GitHub-gist en IPFS, en stellen gegevens wurde parkeard yn iepenbiere desintralisearre opslach mei kaaien fan ynhâldshash, dy't beide dreger te pakken binne as in inkele oanfaller-kontroleare host. Gjin eardere iepenbiere rapportaazje dy't oerienkomt mei dit kluster waard fûn op it momint fan skriuwen.

Wa is bleatsteld. Elkenien dy't ien fan dizze pakketten tafoege hat oan in Node-projekt en doe koade útfierd hat dy't it ymportearret. Omdat detonaasje ymporttiid is ynstee fan ynstallaasjetiid, is it net genôch om it pakket gewoan oanwêzich te hawwen - mar elk normaal gebrûk dat de module laadt berikt de lading. De loknammen binne rjochte op ûntwikkelders dy't bouwe op Ethereum, Solana, Arbitrum, Layer-2, en algemiene wallet/kodearringstools - de populaasje dy't it wierskynlikst presys de aktiva hat dy't de twadde faze siket. Elkenien dy't ien fan dizze modules útfierd hat op in masine mei walletkaaien, siedfrasen, kaaiwinkels, SSH-kaaien, of ... .en V geheimen moatte dy ynloggegevens as kompromittearre behannelje en se rotearje.

Twa patroanen dy't it wurdich binne om te internalisearjen. Earste, lading-as-fixture: it ferstjoeren fan 'e twadde etappe as base64 yn in gegevensbestân mei in plausibele namme (test/fixtures/kaaipearen.dat) hâldt de sichtbere boarne fan it pakket skjin en drukt de kweade ynhâld yn in bestân dat resinsje-ark en minsklike skims faak as ynerte gegevens behannelje. Twadde, ymporttiidfertrage útfiering mei cross-platform persistinsje: it ferpleatsen fan 'e trigger fan' e ynstallaasjeheak, it tafoegjen fan in timer, en dan oanhâlden oer cron, plande taken en launchd is in bewuste stap fuort fan 'e lawaaierige ynstallaasjeskripttechniken dy't automatisearre registerscannen it nauwst yn 'e gaten hâldt.

Rjochtlinen foar ferdigeners en ûnderhâlders:

  • Behannelje tafoege koade nei module.eksports as in resinsjeprioriteit - dropper-logika ferberget him faak ûnder it "echte" module-oerflak.
  • Nim net oan dat gegevensbestannen ynert binne. In base64-blob ûnder test/wedstriden/ dat lêzen wurdt by runtime en dekodearre is útfierber-oanbuorjend; markearje runtime-lêzingen fan fixture-bestannen dy't in fiede Funksje/eval/skriuw-dan-spawn ketting.
  • Sykje nei it droppaad ~/.cache-db/.node-sync/ en foar de persistinsje-ienheden WinNodeSync (plande taak) en com.apple.syncd (launchd) op ûntwikkeldersmasines dy't dizze nammen helle hawwe.
  • Warskôging foar Node-prosessen dy't cron-yngongen, plande taken of launchd-taken oanmeitsje - legitime bibleteken dogge dit selden by ymport.
  • Jou foarkar oan lockfiles en fêstmakke ferzjes, en kontrolearje it ferskil fan elke nije lytse "utility"-ôfhinklikens, foaral nul-ôfhinklikenspakketten publisearre troch net-ferifiearre akkounts sûnder keppele repository.

Foar registerferdigeners is de konklúzje dat install-hook-monitoring needsaaklik is, mar net genôch: in ymporttiid-, timer-fertrage dropper dy't yn in gegevensbestân pleatst is, sil in allinich-ynstallaasjetiid-kontrôle trochstean, en de persistinsjestap is faak it lûdste waarnimbere sinjaal dat oerbliuwt om op te fangen.

sca-tools-software-komposysje-analyse-ark
Prioritearje, ferhelpe en befeiligje jo softwarerisiko's
Krij jo fergese akkount.
Gjin kredytkaart nedich.

Befeiligje jo softwareûntwikkeling en levering

mei Xygeni Produkt Suite