コンテンツに移動
脅威インテリジェンス

変換で失われることがない: macOS への侵入における Rosetta 2 アーティファクト

2025年3月27日
Mandiant

 


※この投稿は米国時間 2025 年 3 月 4 日に、Google Cloud blog に投稿されたものの抄訳です。

エグゼクティブ サマリー

  • Rosetta 2 は、Apple シリコン(ARM64)搭載の macOS システムで x86-64 バイナリを実行するための、Apple の変換テクノロジーです。

  • Rosetta 2 変換では事前(AOT)ファイルのキャッシュが作成され、重要なフォレンジック アーティファクトとして機能します。

  • Mandiant は、巧妙な脅威アクターが x86-64 でコンパイルされた macOS マルウェアを利用する動きを確認しています。ARM64 バイナリに比べて互換性が広く、実行ポリシーが緩いためだと考えられます。

  • AOT ファイルの分析と FSEvents や Unified Log(カスタム プロファイル)を組み合わせると、macOS への侵入の調査に役立ちます。

はじめに

2020 年に macOS 11(Big Sur)で Rosetta 2(macOS での別名 OAH)が導入されたことにより、x86-64 アーキテクチャ用にコンパイルされたバイナリを Apple シリコン(ARM64)アーキテクチャで実行できるようになりました。Rosetta 2 は、署名付きと署名なしの x86-64 バイナリの実行時に、ジャストインタイム変換または事前変換を行います。Mandiant はこの 1 年で、高度に巧妙化した新しい macOS マルウェアのバリアント、特に x86-64 アーキテクチャ用にコンパイルされたものを複数確認しました。このアーキテクチャが選ばれたのは、被害システムと互換性があることが多く、実行ポリシーが緩いためである可能性が高いと Mandiant は評価しています。特に macOS では、Rosetta 2 で実行される ARM64 バイナリに x86-64 バイナリよりも厳格なコード署名要件が適用されるため、署名なしの ARM64 バイナリの実行は困難になります。にもかかわらず、Mandiant がこの 1 年で新たに特定した APT マルウェア ファミリーはすべて自己署名でした。これはおそらく、macOS に導入されている他の補完的なセキュリティ管理を回避するためです。

Rosetta 2 キャッシュ

Rosetta 2 がインストールされたシステムで x86-64 バイナリが実行されると、Rosetta 2 デーモン プロセス(oahd)が、データ ボリュームの Rosetta 2 キャッシュ ディレクトリ(/var/db/oah/<UUID>/)内にバイナリ用の事前(AOT)ファイルがすでに存在しているかどうかをチェックします。このファイルパスの UUID 値は、インストール時またはアップデート時、ランダムに生成されると見られます。AOT ファイルが存在しない場合は、変換コードを .in_progress ファイルに書き込んでから、そのファイル名を元のバイナリと同じ名前の .aot ファイルに変更することで AOT ファイルを作成します。その後、Rosetta 2 デーモン プロセスが変換されたバイナリを実行します。

/var/db/oah ディレクトリとその子ディレクトリは、OAH デーモン ユーザー アカウント _oahd によって保護され、所有されています。他のユーザー アカウントによるこれらのファイルの操作は、システム整合性保護(SIP)が無効になっている場合にのみ可能です。そのためには、リカバリモードで起動する必要があります。

/var/db/oah/<UUID>/ 下のディレクトリは、変換されたバイナリに対応するバイナリ UUID 値です。具体的には、これらのバイナリ UUID 値は、バイナリ ファイルパス、Mach-O ヘッダー、タイムスタンプ(作成、更新、変更)、サイズ、所有権情報の組み合わせから生成された SHA-256 ハッシュです。これらの属性のいずれかが変更された状態で同じバイナリを実行すると、新しい Rosetta AOT キャッシュ ディレクトリとファイルが作成されます。バイナリの内容はハッシュ関数の一部ではありませんが、APFS ファイル システム上のファイルの内容を変更すると、変更されたタイムスタンプが更新されます。これは、内容の変更によって新しいバイナリ UUID と AOT ファイルが作成される可能性があることを事実上意味します。つまり、このメカニズムは、AOT ポイズニングのリスクを軽減するために、x86-64 バイナリへのバイトおよびファイル システム レベルでのあらゆる変更に対して感受性がきわめて高くなるように設計されています。

https://storage.googleapis.com/gweb-cloudblog-publish/images/rosetta2-fig1.max-1100x1100.png

図 1: Rosetta 2 キャッシュ ディレクトリの構造と内容の例

Rosetta 2 キャッシュのバイナリ UUID ディレクトリと、そこに含まれる AOT ファイルは、macOS のシステム アップデートが行われるまで残ると見られます。システム アップデートによってキャッシュ ディレクトリ(ランダム UUID ディレクトリ)が削除されることが確認されています。アップグレード後、UUID 値の異なるディレクトリが作成されます。その後 x86-64 バイナリが初めて起動したとき、新しいバイナリ UUID ディレクトリと AOT ファイルが作成されます。

変換とユニバーサル バイナリ

Rosetta 2 変換を経て稼働している x86-64 プロセスがユニバーサル バイナリ(x86-64 コードと ARM64 コードの両方を含む)を実行すると、これらのバイナリの x86-64 バージョンが実行され、AOT ファイルが作成されます。

https://storage.googleapis.com/gweb-cloudblog-publish/images/rosetta2-fig2.max-1300x1300.png

図 2: Rosetta 2 で変換された X86-64 プロセスと ARM64 プロセスによるユニバーサル バイナリの実行の概要

Mandiant は朝鮮民主主義人民共和国(北朝鮮)による暗号通貨窃取事件の調査において、macOS バックドア POOLRAT の x86-64 バリアントがデプロイされていることと、攻撃者がそのバックドアを通じて pingchmodsudoidcat を含むユニバーサル システム バイナリを実行していることを確認しました。このとき作成された AOT ファイルにより、攻撃者がマルウェアを介してシステムを操作した証拠が得られました(図 5)。

macOS への侵入の初期感染ベクトルに、ユニバーサル バイナリとして配布されたマルウェアを実行する正規の x86-64 コードが関与している場合もあります。最初の x86-64 コードが Rosetta 2 で実行されるため、悪意のあるユニバーサル バイナリの x86-64 バージョンが実行され、AOT ファイルなどの Rosetta 2 アーティファクトが残ります。あるケースでは、悪意のある Python 2 スクリプトによって、悪意のあるユニバーサル バイナリがダウンロードされて実行される結果となりました。ARM64 バージョンが利用できないため、Python 2 インタープリタは Rosetta 2 で実行されます。そのため、システムは悪意のあるユニバーサル バイナリの x86-64 バージョンを実行し、AOT ファイルが作成されました。攻撃者は後で悪意のあるバイナリを削除していましたが、Mandiant は AOT ファイルの分析を通じてその機能を把握することができました。

Unified Log

Rosetta 2 デーモンは macOS Unified Log にログを出力しますが、バイナリ名の値は非公開としてマークされます。これらの値は、カスタム プロファイルをインストールすることで、ログに表示されるように構成できます。情報ログが記録されるのは、AOT ファイルのルックアップの際、キャッシュに保存された利用可能な AOT ファイルが利用されたとき、変換が行われて完了したときです。Unified Log にログを出力するように構成されておらず、インタラクティブに起動されていないバイナリの場合、これが Unified Log 内における実行の唯一の証拠となることもあります。実行は他の補助的なアーティファクトと相関している可能性がありますが、必ずしもそうとは限りません。

0x21b1afc Info 0x0 1596 0 oahd: <private>(1880): 
Aot lookup request for <private>

0x21b1afc Info 0x0 1596 0 oahd: <private>(1880): 
Translating image <private> -> <private>

0x21b1afc Info 0x0 1596 0 oahd: <private>(1880): 
Translation finished for <private>

0x21b1afc Info 0x0 1596 0 oahd: <private>(1880): 
Aot lookup request for <private>

0x21b1afc Info 0x0 1596 0 oahd: <private>(1880): 
Using cached aot <private> -> <private>

図 3: Rosetta のルックアップ、キャッシュに保存されたファイルの使用、プライベート データが無効の変換(デフォルト)を示す macOS Unified Log

0x2ec304 Info 0x0 668 0 oahd: my_binary (Re(34180): 
Aot lookup request for /Users/Mandiant/my_binary

0x2ec304 Info 0x0 668 0 oahd: my_binary (Re(34180): 
Translating image /Users/Mandiant/my_binary -> 
/var/db/oah/237823680d6bdb1e9663d60cca5851b63e79f6c
8e884ebacc5f285253c3826b8/1c65adbef01f45a7a07379621
b5800fc337fc9db90d8eb08baf84e5c533191d9/my_binary.in_progress

0x2ec304 Info 0x0 668 0 oahd: my_binary (Re(34180): 
Translation finished for /Users/Mandiant/my_binary

0x2ec304 Info 0x0 668 0 oahd: my_binary(34180): 
Aot lookup request for /Users/Mandiant/my_binary

0x2ec304 Info 0x0 668 0 oahd: my_binary(34180): 
Using cached aot /Users/Mandiant/my_binary -> 
/var/db/oah/237823680d6bdb1e9663d60cca5851b63e
79f6c8e884ebacc5f285253c3826b8/1c65adbef01f45a7
a07379621b5800fc337fc9db90d8eb08baf84e5c533191d9/my_binary.aot

図 4: Rosetta のルックアップ、キャッシュに保存されたファイルの使用、プライベート データが有効の変換(カスタム プロファイルがインストールされている)を示す macOS Unified Log

FSEvents

FSEvents を使用すると、Unified Log や Rosetta 2 キャッシュ内のファイルが利用できない場合や削除されている場合でも、x86-64 バイナリの過去の実行を特定できます。これらのレコードには、Rosetta 2 キャッシュ ディレクトリ内のディレクトリの作成や、.in_progress ファイルの作成、そしてそのファイルが元のバイナリ名にちなんだ名前の AOT ファイルに変更される様子が記録されます。

private/var/db/oah/433955637247d22a05957b32fa7f08e0b2f022
ed40311775d461444ce17beadb/5660060629e3493074db75fba3
5cff449a366ea59b26af7d54c59779cdfac161 
FolderEvent; FolderCreated; 35102230

private/var/db/oah/433955637247d22a05957b32fa7f08e0b2f022
ed40311775d461444ce17beadb/5660060629e3493074db75fba35
cff449a366ea59b26af7d54c59779cdfac161/
com.apple.systemsettings.cache.aot.in_progress 
FileEvent; Created;Renamed;Modified; 35102231

private/var/db/oah/433955637247d22a05957b32fa7f08e0b2f022
ed40311775d461444ce17beadb/5660060629e3493074db75fba35
cff449a366ea59b26af7d54c59779cdfac161/com.apple.systemsettings.cache.aot 
FileEvent; Renamed; 35102231

private/var/db/oah/433955637247d22a05957b32fa7f08e0b2f022
ed40311775d461444ce17beadb/31a32b61c112dae22363556599f
73f25fab17744eb0c51b8d0071c53bb878471 
FolderEvent; FolderCreated; 35102223

private/var/db/oah/433955637247d22a05957b32fa7f08e0b2f022
ed40311775d461444ce17beadb/31a32b61c112dae22363556599
f73f25fab17744eb0c51b8d0071c53bb878471/sudo.aot.in_progress 
FileEvent; Created;Renamed;Modified; 35102224

private/var/db/oah/433955637247d22a05957b32fa7f08e0b2f022
ed40311775d461444ce17beadb/31a32b61c112dae22363556599
f73f25fab17744eb0c51b8d0071c53bb878471/sudo.aot
FileEvent; Renamed; 35102224

private/var/db/oah/433955637247d22a05957b32fa7f08e0b2f022
ed40311775d461444ce17beadb/9d8b46ee31e24e4988f923ac2e5
23171b7868f20b671cbaeb39d8db6199f4629 
FolderEvent; FolderCreated; 35102259

private/var/db/oah/433955637247d22a05957b32fa7f08e0b2f022
ed40311775d461444ce17beadb/9d8b46ee31e24e4988f923ac2e5
23171b7868f20b671cbaeb39d8db6199f4629/id.aot.in_progress 
FileEvent; Created;Renamed;Modified; 35102260

private/var/db/oah/433955637247d22a05957b32fa7f08e0b2f022
ed40311775d461444ce17beadb/9d8b46ee31e24e4988f923ac2e5
23171b7868f20b671cbaeb39d8db6199f4629/id.aot 
FileEvent; Renamed; 35102260
private/var/db/oah/433955637247d22a05957b32fa7f08e0b2f022
ed40311775d461444ce17beadb/fc9130581b8efed813de3826cfd
4bb34586b0872a0977efaa1d51f0861f564c9 
FolderEvent; FolderCreated; 35102355

private/var/db/oah/433955637247d22a05957b32fa7f08e0b2f022
ed40311775d461444ce17beadb/fc9130581b8efed813de3826cfd
4bb34586b0872a0977efaa1d51f0861f564c9/chmod.aot.in_progress 
FileEvent; Created;Renamed;Modified; 35102356

private/var/db/oah/433955637247d22a05957b32fa7f08e0b2f022
ed40311775d461444ce17beadb/fc9130581b8efed813de3826cfd
4bb34586b0872a0977efaa1d51f0861f564c9/chmod.aot 
FileEvent; Renamed; 35102356

private/var/db/oah/433955637247d22a05957b32fa7f08e0b2f022
ed40311775d461444ce17beadb/c38ceae510d3b2a96bfa6f040fdf
7587121eb388f508c5d50f53efc40cf35dde 
FolderEvent; FolderCreated; 35102671

private/var/db/oah/433955637247d22a05957b32fa7f08e0b2f022
ed40311775d461444ce17beadb/c38ceae510d3b2a96bfa6f040fdf
7587121eb388f508c5d50f53efc40cf35dde/cat.aot.in_progress 
FileEvent; Created;Renamed;Modified; 35102672

private/var/db/oah/433955637247d22a05957b32fa7f08e0b2f022
ed40311775d461444ce17beadb/c38ceae510d3b2a96bfa6f040fdf
7587121eb388f508c5d50f53efc40cf35dde/cat.aot 
FileEvent; Renamed; 35102672

図 5: macOS における x86-64 POOLRAT バリアントの変換と、その後にマルウェアによってユニバーサル システム バイナリが x86-64 として実行された様子を示す、デコードされた FSEvents レコード

AOT ファイルの分析

Rosetta 2 キャッシュ内の AOT ファイルからは、x86-64 バイナリの実行に関する過去の証拠として貴重な分析情報が得られます。Mandiant は過去 1 年間に複数のケースで、暗号通貨組織を標的とする APT グループの初期侵入ベクトルが macOS システムであることを特定しました。これらのケースのほとんどで、暗号通貨の窃取から数分以内に攻撃者がシステム上のマルウェアを削除した証拠が見つかっています。しかし、AOT ファイルはそのまま残されていました。これは、SIP による保護と、このフォレンジック アーティファクトが比較的目立たないことによるものだと考えられます。

フォレンジックの観点からすると、これらの AOT ファイルの作成と更新のタイムスタンプは、SHA-256 ハッシュの生成に使用された属性の組み合わせが固有であるため、システム上で指定されたバイナリが最初に実行されたときの証拠となります。これらのタイムスタンプを、バイナリの実行に関連する他のアーティファクト(Unified Log、ExecPolicy、XProtect、TCC データベースなど)や、FSEvents レコードに記録されたファイル システム アクティビティと照合することで、子プロセスが実行された場合の感染や攻撃者が取り得る行動について、より明確に全体像を把握できます。

Rosetta 2 キャッシュ内の異なるバイナリ UUID ディレクトリに、同じオリジン バイナリに対する複数の AOT ファイルが存在し、それらの AOT ファイルの内容(ファイル ハッシュ)が同じ場合、これは通常、ファイルデータ セクションの変更、より一般的にはファイル システム メタデータのみの変更があったことを示しています。

Mandiant は、AOT ファイルを解析して、シンボルの相関関係からマルウェアを特定できることを以前に示しました。AOT ファイルは、元の ARM64 コードから変換された x86-64 命令を含む Mach-O バイナリです。元のバイナリへのジャンプバックが含まれており、参照する API 呼び出しは含まれていません。一部の機能は AOT ファイルのリバース エンジニアリングによって特定できますが、ネットワーク ベースの指標や構成データなどの静的データは復元できないのが一般的です。Mandiant は、北朝鮮による有名な暗号通貨窃取事件で確認されたある macOS ダウンローダから、AOT ファイルに含まれる基本的な Mach-O 情報の一部としてデベロッパーのファイルパス文字列を発見しました。元のバイナリは攻撃者が窃取後に削除したため復元できませんでしたが、脅威アクターの帰属とマルウェア ファミリーの評価を裏付ける有用なデータポイントが得られました。

/Users/crown/Library/Developer/Xcode/DerivedData/
DownAndMemload-becawjfobisdcocirecqedzcixcf/Build/Intermediates.noindex/
DownAndMemload.build/Release/DownAndMemload.build/
Objects-normal/x86_64/main.o
/Users/crown/Library/Developer/Xcode/DerivedData/
DownAndMemload-becawjfobisdcocirecqedzcixcf/Build/Intermediates.noindex/
DownAndMemload.build/Release/DownAndMemload.build/Objects-normal/
x86_64/queue.o
/Volumes/Data/Development/DownAndMemload/DownAndMemload/
_g_szServerUrl
_szgetpwuid
_szsleep

図 6: 復元できなかったが、悪意のある北朝鮮のダウンローダに関連する AOT ファイルから得られた興味深い文字列

いずれにしても、AOT ファイルには元のバイナリに存在するコンテキスト情報がほとんど含まれていないため、マルウェアの機能を判断するには、元の完全なバイナリを使用する方が効果的です。これには静的データと完全な Mach-O ヘッダーが含まれます。

AOT ファイルのポイズニング

業界内では、AOT ファイルの更新や導入によって Rosetta 2 キャッシュのポイズニングが行われる可能性があることについて、数多く論じられてきました。SIP が無効になっている場合、これは有効な攻撃ベクトルとなります。Mandiant はこの手法が実際に使用された例を確認したことはありませんが、脅威ハンティングや調査を行う際は、AOT ポイズニングの証拠を探すことをおすすめします。そのためには、ARM64 AOT ファイルの内容を、元の x86-64 実行ファイルから予想される内容と比較することが最善です。つまり、元の x86-64 実行ファイルを使用して正常な AOT ファイルを生成し、それをキャッシュ内の AOT ファイルと比較します。不一致、特にシェルコードの挿入があった場合、AOT ポイズニングを示している可能性があります。

まとめ

macOS のフォレンジック アーティファクトには、バイナリ実行の過去の証拠が記録されている可能性があります。しかし、フォレンジックに精通した攻撃者による高度な侵入で、元のバイナリが削除され、セキュリティ モニタリング ソリューションが他にないこともあります。その場合は、FSEvents、Unified Log、さらに重要なのはディスク上に残った AOT ファイルを組み合わせることで、macOS システムへの侵入の残留証拠を得ることができます。

署名付きの macOS ARM64 バイナリが将来的に主流になるかもしれませんが、現時点では、macOS への侵入が疑われるケースの分析で AOT ファイルとその周辺のアーティファクトを確認し、可能な限り脅威ハンティングの機会に活用する必要があります。

今回紹介したケースで特定された動作は、macOS 13.5 から 14.7.2 までのさまざまなバージョンで確認されています。macOS と Rosetta 2 の今後のバージョンや以前のバージョンでは、動作が異なる場合があります。

謝辞

Matt Holley、Mohamed El-Banna、Robert Wallace、Adrian Hernandez に感謝します。

-Mandiant、執筆者: Joshua Goddard

投稿先