
CVE-2025-31200 - @Noahhw46 が解明しました
CoreAudio パッチ(CVE-2025-31200)の概念実証コードです。iOS 18.4.1 向け。解説はこちら https://blog.noahhw.dev/posts/cve-2025-31200/。
任意書き込みとまではいかなくても、制御された書き込みにまで押し込めました。解説記事は近日公開予定です。ただし、自分で確認するには、パッチ適用前(< 15.4.1)の macos バージョンでビルドする必要があります。単にオーディオを再生するだけのシンプルなハーネスを使って、check-mismatch lldb フックでオーディオを再生すれば、その書き込みを確認できます。前述のとおり、いくつかの理由から、まだ十分な任意書き込みにはなっていません。主な理由は、フレームバッファからのこれらの値がリマップされるときに、デコードパイプラインのどの段階にあるのかをまだ 100% 確信できていないからです。ただ、誰かが引き継ぎたいなら、ここで一旦止めて解説記事の執筆に取り掛かります。
私 @noahhw46 が解明しました(このセットアップ @zhouwei なしではできませんでした)。解説記事は近日公開予定です。ただし、まだ解明すべきことはたくさんあります。バグが正確に何をするのかを示すため、調査の次のステップの最初の部分をここに追加しました。check-mismatch は、動作する PoC と組み合わせて使えるもう 1 つの lldb スクリプトで、APACChannelRemapper::Process(正確には APACHOADecoder::DecodeAPACFrame)内で生じた mRemappingArray と置換マップの不一致を正確に示します。
The mRemappingArray is sized based on the lower two bytes of mChannelLayoutTag.
By creating a mismatch between them, a later stage of processing in APACHOADecoder::DecodeAPACFrame is corrupted.
When the APACHOADecoder goes to process the APAC frame (permute it according to the channel remapping array), it uses the mRemappingArray as the permutation map to do the well, channel remapping. It seems like the frame data that is being remapped is sized based on mTotalComponenets.
output.mp4 オーディオファイル(例: AVAudioPlayer)を再生すると、APACChannelRemapper::Process は範囲外の読み出しと書き込みを行います。
Xcode で Guard Malloc を有効にすると、最初の範囲外読み出しを確認できます。
Guard Malloc なしの場合、APACHOADecoder::DecodeAPACFrame はその後、無効な memmove でクラッシュします。
@zhuowei による以前の README は以下です。
iOS 18.4.1 の CoreAudio パッチ(CVE-2025-31200)を理解しようとしています。
まだ解明できていません。
現在、macOS 15.4.1 で output.mp4 をデコードすると、次のように異なるエラーメッセージが表示されます。
error 01:10:26.743480-0400 getaudiolength <private>:548 Invalid mRemappingArray bitstream in hoa::CodecConfig::Deserialize()
error 01:10:26.743499-0400 getaudiolength <private>:860 Error in deserializing ASC components
vs visionOS 2.2 の Xcode Simulator:
error 01:09:21.841805-0400 VisionOSEvaluation APACProfile.cpp:424 ERROR: Wrong profile index in GlobalConfig
error 01:09:21.841914-0400 VisionOSEvaluation APACGlobalConfig.cpp:894 Profile and level data could not be validated
つまり、新しいチェックには引っかかっているものの、実際に何かを上書きさせる方法が分かりません。
変更された関数は、/System/Library/Frameworks/AudioToolbox.framework/AudioCodecs 内の apac::hoa::CodecConfig::Deserialize であるようです。
APAC は Apple Positional Audio Codec です。
HOA は Higher-order Ambisonics です。
ffmpeg の issue トラッカーのサンプルファイル を見ると:
$ avmediainfo ~/Downloads/clap.MOV
Asset: /Users/zhuowei/Downloads/clap.MOV
<...>
Track 3: Sound 'soun'
Enabled: No
Format Description 1:
Format: APAC 'apac'
Channel Layout: High-Order Ambisonics, ACN/SN3D
Sample rate: 48000.0
Bytes per packet: 0
Frames per packet: 1024
Bytes per frame: 0
Channels per frame: 4
Bits per channel: 0
System support for decoding this track: Yes
Data size: 43577 bytes
Media time scale: 48000
Duration: 0.898 seconds
Estimated data rate: 363.142 kbit/s
Extended language tag: und
1 segment present
Index Media Start Media Duration Track Start Track Duration
1 00:00:00.000 00:00:00.898 00:00:00.000 00:00:00.898
Member of alternate group 0: (2, 3)
APAC への変換は afconvert -o sound440.m4a -d apac -f mp4f sound440hz.wav で行えます。
iOS 18.4.1 と 18.4 で bindiff を使うと、mRemappingArray の読み取り時、チャンネル数のチェックにオフセット 0x78 のリマッピング用 AudioChannelLayout* ではなく、オフセット 0x58 のグローバルな AudioChannelLayout* を使うようになったようです。
encodeme.mm は APAC をエンコードし、LLDB スクリプトが mRemappingArray とリマッピング用 AudioChannelLayout に余分な要素を強制的に追加します。
./build_encodeme.sh
./run_encodeme.sh