Bitdefenderの研究者は、ゲーム「NIKKE」のランチャーを介して多機能な情報窃取型マルウェア(インフォスティーラー)を配布する認証情報窃取キャンペーンを調査しました。
「勝利の女神:NIKKE(Goddess of Victory: NIKKE)」は、Shift Upが開発し、Level InfinteがPC、iOS、Android向けに配信する基本プレイ無料のSF RPGシューティングゲームです。パブリッシャーの2026年10月の発表によると、同作はリリース以来、全世界で4,500万回以上ダウンロードされています。
攻撃者は、この人気の基本プレイ無料ゲームのランチャーに対し、プレイヤーのマシン上でペイロードをダウンロードして実行するよう遠隔から指示しました。利用したのは、サーバーからプッシュされるタスクチャネルです。クライアントが何をダウンロードして実行するかは、このチャネルを通じて伝えられます。
バイナリの改ざんも、脆弱性の悪用も、ゲーム配布物への不正ファイルの混入もありませんでした。ペイロードはLuaベースのスティーラー(本稿では「k2f-agent」と呼びます)で、難読化されたLuaJITバイトコードとして、ごく普通のログファイルの姿で届きました。
k2f-agentはランチャーに組み込まれたブラウザエンジン内で動作し、Chrome、Edge、Operaに保存されたパスワードやCookieを窃取できます。ChromeのApp-Bound Encryptionで保護されたものも対象です。
このマルウェアは、MetaMask、Phantom、Coinbase Wallet、Keplr、TronLinkという5つの暗号資産ウォレット用ブラウザ拡張機能も標的にします。
さらに、SSH鍵、GPG鍵、Git認証情報、Kubernetes設定、環境変数、シェル履歴、Windows資格情報マネージャーのエントリ、NuGet.Config、PowerShellプロファイルも収集できます。
窃取したデータは、ランチャーの通常の外部通信に乗せて送信されます。ダウンロード、収集、外部送信、痕跡の削除までは10分足らずで完了し、悪意のあるアーティファクトはほとんど残りませんでした。
ペイロードを配信していたドメインは攻撃の約5週間前に登録されたもので、アイスランドのホスティングプロバイダーが速やかにサーバーを停止しました。
重要ポイント
- 攻撃者は、NIKKEの正規ランチャーを通じてスティーラーを配布しました。バイナリには手を加えず、サーバーからプッシュされるタスクチャネルを利用しています。
- ペイロードはログファイルに偽装され、署名済みランチャーのプロセス内で実行されました。Luaベースのk2f-agentには、認証情報の窃取、ファイル収集、リモートコマンドを担う46個のモジュールが含まれます。
- 標的は、ブラウザのパスワード、暗号資産ウォレット、開発者向けシークレットです。このスティーラーはChromeのApp-Bound Encryptionに対応し、MetaMask、Phantom、Coinbase Wallet、Keplr、TronLinkを狙います。
- 窃取データは、ランチャーの既存のテレメトリ接続を通じて送られます。ダウンロード、収集、外部送信、痕跡の削除は10分未満で完了し、ディスク上に残る不審な痕跡はごくわずかです。
- Bitdefenderは、観測した保護対象システムでこの攻撃を検知してブロックしました。これらのシステムでは、Advanced Threat Defense機能が、個人情報が外部に送信される前にランチャーを終了させました。
- 悪意ある配信サーバーは停止されました。運営者の正体や、ランチャーのタスクチャネルをどのように掌握したのかは不明です。ゲームの開発元やパブリッシャーが攻撃に関与したことを示す証拠はありません。
検知データに見つかった異常
調査のきっかけは、「勝利の女神:NIKKE」のランチャー(NIKKE launcher)に関する検知件数の急増でした。このバイナリのメインプロセスは、署名済みの正規バイナリであるにもかかわらず、ブラウザの認証情報ストアを読み取っていました。
検知は10月30日に始まり、週末にかけて続きました。
同じ時期に、Bitdefenderがゲームランチャー自体を検知している状況についてRedditへの投稿がありました。投稿者は、誤検知なのか実際に感染しているのか判断できずにいました。
私たちは、このランチャーが認証情報を窃取していることを確認しました。
ランチャーを経由したペイロード配信
サーバープッシュ型のタスクチャネル
NIKKEのランチャーは、ゲームプラットフォームのフレームワーク上に構築されています。クライアント側のアーキテクチャには、クライアントとサーバー間の常時接続のタスクチャネル(内部ではCGIタスクマネージャーと呼ばれます)があります。ランチャーはログイン時に、バックエンドへタスクを問い合わせます。
組み込みのダウンローダーは、そのタスクに含まれるURLからファイルをディスクにダウンロードします。URLは実行時にバックエンドから渡されるため、同じビルドのランチャーが、チャネル経由で指定された任意のURLからダウンロードできてしまいます。
問題の攻撃当日、ランチャーはログインしてタスクを要求しました。応答を受け取った1.6秒後に、次のダウンロードがキューに登録されています。
CGIMgr::FireEvents.OnCGITaskRsp, task_id=1073741867, result=0, rsp_code=200
tiny_downloader::TinyDownloader::AddTask.add task, task_id=2147483648,
url=https://analytics.insightjs[.]com/comm/assets/insight.bundle
新規登録されたインフラ
攻撃時、analytics.insightjs[.]comはアイスランドのサーバーである89.127.233.127に名前解決されていました。ドメインの登録記録によると、insightjs[.]comは攻撃の約5週間前にあたる2026年9月27日に登録されています。
この名前は、既存のオープンソースの分析ライブラリ「insight.js」に似せて正当性を装うために選ばれたとみられます。ただし、このライブラリやそのメンテナーが関与している形跡はありません。
ログファイルに偽装されたペイロード
ダウンローダーは、205,135バイトの応答を次のパスに保存しました。
Launcher\log\tinyget\tinyget.20261103-030255-271.log
このファイルはランチャーのログディレクトリに置かれ、標準的なダウンロードログの命名規則に従っていました。一見するとごく普通のログファイルですが、中身はLuaJIT 2.1バイトコード(マジックナンバーは\x1bLJ)、つまりデバッグ情報をすべて削除したコンパイル済みLuaでした。
私たちは、出荷されているすべての実行ファイル、DLL、設定ファイル、アーカイブを、さまざまなエンコーディングで調べましたが、配信URLは見つかりませんでした。インストールファイルには含まれていないため、実行時にサーバーの応答として渡されている可能性が高いと考えられます。
JavaScript-ネイティブ間ブリッジによる実行
ランチャーのインターフェースには、Chromium 94ベースのCEFビルドが使われています。組み込みブラウザエンジン(CEF)には、十分に文書化されたJS-ネイティブ間ブリッジがあります。WebView内のJSがcall_service(<name>, <json>)を呼び出すと、ランチャーのサービスディスパッチャーがその呼び出しを、登録済みのネイティブまたはLuaのハンドラーに渡す仕組みです。
ダウンロードされたバンドルが読み込まれると、そのエントリモジュールは、このブリッジ上に新しいサービスk2f_chanを登録します。
local comm = rawget(_G, "comm_center")
if type(comm) == "table" and type(comm["reg_service"]) == "function" then
comm["reg_service"]("k2f_chan", handler)
end
この登録によって、攻撃者のコマンドチャネルが確立されます。以降の実行チェーンは、すべて正規のランチャープロセス内で完結します。このため、振る舞いテレメトリ上では、認証情報の窃取が署名済みの信頼された実行ファイルによるものとして記録されました。
C2 server ── CGI task response ──> launcher downloader ──> disguised .log (LuaJIT bytecode)
──> launcher's Lua VM loads bundle ──> k2f_chan service registered
──> remote operator issues JSON ops over the JS bridge
──> launcher process performs file/crypto/registry operations
悪意あるロジックは、出荷されたファイルには含まれていません。メモリフォレンジックの結果、k2f関連の文字列とコードのアーティファクトはすべて、ランチャープロセスのバッキングされていないヒープメモリ上で見つかり、ディスク上のモジュールには一切存在しませんでした。
ペイロード「k2f-agent」:ログファイルに潜む46モジュールのスティーラー
私たちはバンドルを回収し、LuaJITバイトコードを逆コンパイルしました。ペイロードには標準的なLuaの難読化ツールが使われており、1790エントリの暗号化文字列テーブルとテーブル置換のプレリュードを備えています。デコーダーは独自のものが2つあり、1つは独自アルファベットのbase64用、もう1つはbase85用です。
私たちは、実際のモジュール名を含む平文のソース全体を復元するため、完全なオフラインデコーダーを構築しました。ペイロードにはビルドタグK2F_LUA_BUILD = “722b99d8d0e9″も含まれています。
ソースは全部で46モジュールあり、オペレーター向けコマンド18個、Windowsバックエンド13個、専用の収集ステージ7つ、データ駆動型のディスパッチャーで構成されています。C2が公開しているコマンドは次のとおりです。
| コマンド | 機能 |
|---|---|
browserscan |
ブラウザ認証情報の全面スキャン(詳細は後述) |
wallet_files |
暗号資産ウォレット用ブラウザ拡張機能のボールト抽出 |
keyscan |
シークレットストアのスキャン:SSH、GPG、Git認証情報、Kubernetes設定、環境変数、シェル履歴、Windows資格情報マネージャー、開発者のプロジェクトファイル |
file_chunk |
汎用のチャンク分割ファイル送信(2 MiB単位で読み取り、%APPDATA%などのマクロを解決) |
payload_cleanup |
実行後に、偽装バンドルとステージングされたすべてのアーティファクトを削除 |
creds |
Windows資格情報マネージャーの収集(DPAPI) |
chrome_scan / chrome_install / chrome_cleanup / chrome_uninstall |
Chromium専用の標的化ステージ |
exec |
入出力をパイプ接続したプロセスの起動 |
download |
追加ファイルをホストに送り込む |
ls / cat / cd |
対話的なファイルシステムへのアクセス |
screens |
スクリーンショットの取得 |
sysinfo / host_facts / whoami |
偵察 |
ブラウザ認証情報の収集と復号
BrowserScan操作は、見つけられるすべてのChrome、Edge、Operaのプロファイルディレクトリを検索します(このビルドはFirefox/Geckoにも対応しています)。Login Data、Login Data for Account、Cookies、Local Stateの各ファイルは、すべて収集されます。
検索は、正規のブラウザプロセスがアクセスしないrecovery、cache、safety listの各サブディレクトリにまで及びます。収集した各データベースは、次の命名規則でtempディレクトリに配置されます。
%TEMP%\k2f-bcreds-<unix-time>-<random>.db (+ .db-wal / .db-shm / .db-journal)
スティーラーは、ステージングしたデータベースに対し、Chromeのパスワードストア用の次のSQLを実行します。
SELECT origin_url, username_value, password_value FROM logins
従来のv10 AES-256-GCM形式のデータに対しては、Local StateからDPAPIで展開したOS-Cryptキーを使って復号します。Chrome 127で導入されたApp-Bound Encryptionにも対応しており、新しいブラウザビルドに追従するには保守が必要になるとみられます。
Cookieを収集するかどうかは、被害者ごとにサーバー側が決定します。捕捉した実行例ではcollect_cookies:falseが指定されており、事実上Cookieの収集は無効でした(もちろん、運営者は遠隔でこの設定を変更できます)。
暗号資産ウォレットの窃取
wallet_files操作は、拡張機能IDによってブラウザ拡張機能のボールトを特定し、そのLevelDBストレージを直接読み取ります。
| ブラウザ拡張機能ID | ウォレット |
|---|---|
nkbihfbeogaeaoehlefnkodbefgpgknn |
MetaMask |
bfnaelmomeimhlpmgjnjophhpkkoljpa |
Phantom (Solana) |
aflkmfhebedbjioipglgcbcmnbpgliof |
Coinbase Wallet |
bhhhlbepdkbapadjdnnojkbgioiodbic |
Keplr (Cosmos) |
acmacodkjbdgmoleebolmdjonilkdbch |
TronLink |
MetaMaskの.ldbボールトとブラウザのLocal Stateのマスターキーがあれば、攻撃者はオフラインでシードフレーズを復元し、ウォレットの資産を抜き取れます。
開発者・システムのシークレット
捕捉した実行例では、パッケージフィードの認証情報を含む%APPDATA%\NuGet\NuGet.Configと、%USERPROFILE%\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1も取得されていました。これらの標的からは、ゲームのプレイヤーだけでなく、ソフトウェア開発者とそのサプライチェーンへのアクセス権にも関心があることがうかがえます。
keyscanモジュールは存在していましたが、今回の実行では運営者は呼び出していません。このモジュールは、PuTTYの.ppkファイルを含むSSH秘密鍵のほか、GPGキーリング、Git認証情報ストア、Kubernetes設定、環境変数、シェル履歴を収集できます。
ランチャーの通信を利用した外部送信
ペイロードのダウンロードと窃取データの送信は、異なるネットワーク経路を通ります。
- ペイロードは、攻撃者が最近登録したアイスランドのドメインから届きました。
- 窃取データは、ランチャーが既に使っているTLS暗号化済みのプラットフォームテレメトリチャネルで(通常のハートビートメッセージと並んで)送信されます。データはこのチャネルの不透明な拡張フィールドに格納されるため、ネットワーク監視には標準的なゲームのテレメトリとしか映らず、不審な点は見当たりません。
ランチャーのバイナリ、組み込みブラウザ、サービスブリッジ、ダウンローダー、テレメトリチャネルは改変されておらず、攻撃者はそれらを悪用しました。外部送信の通信は、ランチャーの通常のテレメトリ基盤を経由しており、この基盤を攻撃者が制御しているとは考えていません。私たちは、このキャンペーンを運営しているのは配信ドメインinsightjs[.]comの運営者だと考えています。
運営者が誰なのか、どのようにランチャーのタスクチャネルへアクセスしたのかは分かっていません。悪意あるバンドルには、特定のゲームに依存したロジックはありません。同じサーバープッシュ型のタスクチャネルとJS-ネイティブ間のサービスブリッジを備えたアプリであれば、同様に悪用される可能性があります。
この活動は、いくつかの理由から検知が困難です。
- 配信URLは、出荷されたゲームファイルのどこにも含まれていません。バンドルは実行時にログとして届きます。
- スティーラーのコードと文字列は、署名済みの信頼されたプロセスのヒープメモリ上にしか存在しません。
- 再構築したタイムラインでは、バンドルのダウンロードから収集完了までは約6〜10分です。
- 実行後はpayload_cleanupがバンドルとステージングされた認証情報データベースを削除します。すでに削除済みのSQLite WALファイルを削除しようとして失敗する試みも確認しました。
- 外部送信は既存の正規の接続を利用し、新たなソケットは開きません。
Bitdefenderによる検知の仕組み
防御側がこの攻撃を検知してブロックできる段階は2つあります。1つは配信URLをブロックし、スティーラーのダウンロード自体を防ぐ方法です。
今回、このドメインは登録されて間もなく、評判の履歴がまったくありませんでした。そのため、ブロックにつながる警告は出ていませんでした。
もう1つの段階は第2段階の検知です。Bitdefender Advanced Threat Defenseは、ブラウザ以外のプロセスがブラウザの認証情報ストアにアクセスする挙動を捉え、個人情報が外部に送信される前に、影響を受けたユーザーのマシン上でゲームランチャーを終了させました。
ユーザーは事実上ゲームを起動できなくなりましたが、この介入によってデータの窃取は防がれました。
サーバーの停止とその他の報告
アイスランドのホスティングプロバイダーは、悪意あるサーバーを停止しました。配信ドメインに到達できなくなったため、確認された攻撃チェーンではバンドルのダウンロード、k2f_chanの登録、認証情報の収集開始ができません。ランチャーの通常機能には影響ありません。
また、本分析を公開する旨を11月10日に開発元とパブリッシャーへ通知しましたが、まだ返答はありません。
Redditのユーザーも同じパターンに気づき、独自に調査していました。その貢献に謝意を表します。
https://gist.github.com/MotherSphere/d6c049a09ba8ac3085c51ee9df24a4e5
推奨される対策
攻撃が行われた期間にNIKKE(または影響を受けたランチャー)をプレイした場合は、そのマシンが侵害されたものとして扱ってください。
- Chrome、Edge、Operaに保存されているすべてのパスワードを変更してください。このスティーラーは、認証情報データベースと、オフラインで復号するために必要なマスターキーの両方をコピーするよう設計されています。
- ブラウザ拡張機能のウォレットは危険にさらされているものとして扱ってください。MetaMask、Phantom、Coinbase Wallet、Keplr、TronLinkのウォレットにある資産は、クリーンなマシンで新たに生成したシードフレーズのウォレットへ移してください。
- 開発者向けシークレットも更新してください。対象は、SSH鍵、GPG鍵、Git認証情報、Kubernetes設定、NuGetフィードの認証情報、シェル履歴や環境変数、Windows資格情報マネージャーのエントリに含まれるあらゆる情報です。
- 可能な限り、フィッシング耐性のある多要素認証(MFA)を有効にしてください。盗まれたCookieやセッションがあれば、パスワードなしでアクセスされる恐れがあります。
キャンペーンの実行後にディスク上へ残る永続的なアーティファクトは、ごくわずかです。防御側が振る舞い監視とネットワーク監視で確認できる指標は次のとおりです。
- ブラウザ以外のプロセス(特にゲームランチャー)が、… \User Data…\Login Data、Login Data For Account、Local State、または拡張機能のLocal Extension Settings*.ldbファイルを開く動作。
- %TEMP%\k2f-bcreds-.dbに一致するファイル(-wal/-shm/-journalの付随ファイルを含む)。
- 先頭の数バイトがテキストではなく\x1bLJ\x01(LuaJITバイトコード)で始まる、約50KBを超える*.logファイル。
- ランチャーやゲームのプロセスが、ベンダーの既知のインフラ以外のドメイン、特に最近登録されたドメインに接続する動作。
免責事項
本記事は、情報提供および公益的なセキュリティ研究の目的のみで公開しています。内容は、執筆時点で入手できたデータに基づくBitdefenderの技術的分析であり、不完全な部分を含む可能性があります。また、新たな情報が判明すれば変更される場合があります。重要な新事実が判明した場合は、記事を更新します。
本記事は、Shift Up、Level Infinite、Tencent、insight.jsのメンテナー、ホスティングプロバイダー、その他本文中に名前を挙げた企業や個人が、ここに記載された悪意ある活動に関与した、承認した、または知っていたと述べたり、示唆したりするものではありません。調査結果が示しているのは、身元不明の第三者が正規のソフトウェアとインフラを悪用したという事実です。
製品、サービス、商標への言及は識別のみを目的としており、それぞれの所有者に帰属します。提携や推奨を示すものではありません。
Bitdefender製品の性能に関する記述は、今回のインシデントで私たちが観測した保護対象システムに限ったものです。あらゆる環境で同じ結果が得られることを保証するものではありません。推奨事項と侵害指標(IoC)は一般的な指針であり、特定の状況に対する専門的な助言ではありません。読者はご自身のシステムを評価し、必要に応じて資格のある専門家の支援を受けてください。法令で認められる範囲で、Bitdefenderは本記事に基づいて行われた、または行われなかった行為について責任を負いません。
第三者のリンクは参考のために掲載しています。その内容を当社が管理しているわけではなく、責任も負いません。コミュニティの研究者については、本人の同意を得てクレジットを記載しています。本記事の情報に誤りがある、または自分自身に関係すると思われる場合は、[email protected]までご連絡ください。速やかに確認します。
侵害指標(IoC)
| 指標の種類 | 値 |
|---|---|
| ドメイン | analytics.insightjs[.]com, insightjs[.]com |
| IPアドレス | 89.127.233.127 |
| URLパス | /comm/assets/insight.bundle |
| ペイロードのファイルパス | Launcher\log\tinyget\tinyget.<yyyymmdd>-<hhmmss>-<pid>.log — LuaJITバイトコードを含む |
| SHA-256 | CC0AD05BFE85940A6067B3A72C182D3953339129206634141926D5D0B35973EC |
| 収集された認証情報のファイルパス | %TEMP%\k2f-bcreds-<unix>-<rand>.db — 収集されたブラウザ認証情報を含む |
| ペイロードのビルドタグ | K2F_LUA_BUILD = "722b99d8d0e9" |
翻訳元: https://www.bitdefender.com/en-us/blog/labs/nikke-game-launcher-malware