
CVE-2025-31200 - @Noahhw46 descobriu
Prova de conceito para o patch do CoreAudio (CVE-2025-31200) no iOS 18.4.1. Análise completa aqui https://blog.noahhw.dev/posts/cve-2025-31200/.
Consegui evoluir isso para uma escrita controlada, se não arbitrária. O write-up está chegando em breve. No entanto, para ver por conta própria, você precisará compilar em uma versão do macOS anterior ao patch: < 15.4.1. Você pode reproduzir o áudio com o hook check-mismatch do lldb (usando um harness simples que apenas reproduz o áudio) para visualizar a escrita. Ainda não é uma grande escrita arbitrária, como mencionei acima, por alguns motivos — mas principalmente porque ainda não tenho 100% de certeza em que estágio do pipeline de decodificação esses valores do frame buffer estão quando são remapeados. Vou parar por aqui para trabalhar no write-up, caso alguém queira dar continuidade.
Eu, @noahhw46 (não teria conseguido sem essa configuração do @zhouwei), descobri (o write-up virá em breve). No entanto, ainda há muito mais para entender. Adicionei aqui o primeiro trecho dos próximos passos da minha investigação para mostrar exatamente o que o bug faz. check-mismatch é outro script lldb que pode ser usado com um PoC funcional para mostrar exatamente a incompatibilidade criada entre o mRemappingArray e o mapa de permutação em APACChannelRemapper::Process (na verdade, em APACHOADecoder::DecodeAPACFrame).
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.
Quando você reproduz o arquivo de áudio output.mp4 (por exemplo, com AVAudioPlayer), APACChannelRemapper::Process fará uma leitura e depois uma escrita fora dos limites.
Você pode ver a primeira leitura fora dos limites se ativar o Guard Malloc no Xcode:
Sem o Guard Malloc, APACHOADecoder::DecodeAPACFrame acabará falhando com um memmove inválido:
O README anterior do @zhuowei está abaixo:
Tentando entender o patch do CoreAudio (CVE-2025-31200) no iOS 18.4.1.
Ainda não descobri.
Atualmente, recebo mensagens de erro diferentes ao decodificar output.mp4 no macOS 15.4.1:
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 Xcode Simulator para visionOS 2.2:
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
então estou atingindo a nova verificação, mas não sei como fazer com que ela realmente sobrescreva algo.
A função alterada parece ser apac::hoa::CodecConfig::Deserialize em /System/Library/Frameworks/AudioToolbox.framework/AudioCodecs.
APAC é o Apple Positional Audio Codec.
HOA é Ambisonics de ordem superior.
Se você observar um arquivo de exemplo do rastreador de issues do ffmpeg:
$ 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)
Você pode converter para APAC com afconvert -o sound440.m4a -d apac -f mp4f sound440hz.wav.
Usando bindiff no iOS 18.4.1 vs 18.4, parece que a leitura do mRemappingArray agora verifica o AudioChannelLayout* global no offset 0x58 para o número de canais, em vez do AudioChannelLayout* de remapeamento no offset 0x78.
O arquivo encodeme.mm codifica APAC, e um script LLDB força elementos extras em mRemappingArray e no AudioChannelLayout de remapeamento:
./build_encodeme.sh
./run_encodeme.sh