Введение
Современные стандарты кодирования видео, такие как H.264, представляют собой чудо скрытой сложности. Но со скрытой сложностью приходит скрытый риск для безопасности. Декодирование видео на практике означает взаимодействие с выделенными аппаратными ускорителями и проприетарными привилегированными программными компонентами, используемыми для их управления. Экосистема видеодекодера неясна, непрозрачна, разнообразна, высоко привилегирована, в значительной степени не протестирована и широко открыта — все это опасное сочетание.
Мы представляем и оцениваем H26FORGE, доменную инфраструктуру для анализа, создания и обработки синтаксически правильных, но семантически несовместимых видеофайлов. Используя H26FORGE, мы подробно выявляем проблемы с безопасностью в экосистеме видеодекодера, включая ошибки повреждения памяти ядра в iOS, ошибки повреждения памяти в Firefox и VLC для Windows, а также ошибки памяти ядра видеоускорителя и процессора приложений на нескольких устройствах Android.
1. Введение
Современные стандарты кодирования видео — это чудо скрытой сложности. Как отмечает SwiftOnSecurity, приложения, управляемые видео, которые мы считаем само собой разумеющимися, были бы невозможны без достижений в технологии сжатия видео, несмотря на увеличение вычислительной мощности, емкости хранения и пропускной способности сети. Но со скрытой сложностью приходит скрытый риск для безопасности.
Спецификация H.264 состоит из 800 страниц, несмотря на то, что указано только, как декодировать видео, а не как его кодировать. Поскольку декодирование является сложным и дорогостоящим, его обычно делегируют аппаратным видеоускорителям либо на графическом процессоре, либо в выделенном блоке системы на кристалле (SoC). Декодирование видео на практике означает взаимодействие с этими привилегированными аппаратными компонентами и привилегированными программными компонентами, используемыми для их управления, обычно с системным медиа-сервером и драйвером ядра. По сравнению с другими типами носителей, которые могут обрабатываться автономными изолированными программными библиотеками, поверхность атаки для обработки видео больше, более привилегирована и, как мы объясним ниже, более разнородна.
На основе руководства, которое они называют «правилом 2», разработчики Chrome стараются избегать написания кода, который выполняет не более двух из следующих действий: анализирует ненадежный ввод, написан на небезопасном для памяти языке и работает на высоких привилегиях. Стек обработки видео в Chrome нарушает Правило 2, как и соответствующие стеки в других основных браузерах и приложениях для обмена сообщениями, потому что код платформы для управления оборудованием для декодирования видео, от которого все они зависят, сам по себе нарушает Правило 2.
Поскольку для разных аппаратных видеоускорителей требуются разные драйверы, экосистема привилегированного программного обеспечения для обработки видео сильно фрагментирована; наш анализ деревьев устройств Linux выявил два десятка поставщиков ускорителей. Не существует одной доминирующей библиотеки программного обеспечения с открытым исходным кодом, которую исследователи безопасности могли бы проверить.
И функции, которые делают современные форматы видео такими эффективными, также затрудняют тестирование с высоким покрытием кода стеков декодирования видео с помощью универсальных инструментов. Возьмем H.264, самый популярный формат видео на сегодняшний день. H.264 сжимает видео, находя сходство внутри и между кадрами; сходства и различия отправляются как синтаксические элементы с энтропийным кодированием. Эти синтаксические элементы кодируются контекстно-зависимым образом: изменение значения одного синтаксического элемента полностью меняет интерпретацию декодером остального битового потока.
Наглядный пример: CVE-2022-22675.
31 марта 2022 года Apple выпустила iOS 15.4.1, в которой исправлена ошибка в драйвере ядра для семейства видеоускорителей AppleAVD, включенных в SoC, начиная с A12 2018 года. В примечаниях к выпуску говорится, что «Apple известно об отчете о том, что эта проблема могла активно использоваться».
Натали Сильванович из Google Project Zero провела анализ основной причины ошибки [43]. Сравнив драйверы до и после исправления, она обнаружила отсутствующую проверку границ синтаксического элемента cpb_cnt_minus1; она смогла создать видео, которое вызвало добавленную проверку, но не вызвало панику ядра. Проблема заключалась в отказе инструментов. Как объяснила Сильванович в Твиттере, она «подделала файл по крупицам, и это было просто ужасно. Один трюк, который я использую, состоит в том, чтобы создать ffmpeg с символами и разбить его там, где функция, которую вы пытаетесь вызвать, находится в (например, чтение HRD) [. . . ] Затем вы можете сбросить битовый поток с помощью gdb, найти соответствующее место в файле и отредактировать его».
Наши исследования.
Мы представляем и оцениваем H26FORGE, доменную инфраструктуру для анализа, создания и обработки синтаксически правильных, но семантически несовместимых видеофайлов.
H26FORGE поддерживает восстановленные синтаксические элементы H.264 в памяти и позволяет программно корректировать синтаксические элементы, при этом правильно энтропийно кодируя скорректированные значения. Никакой предыдущий инструмент не подходит для этой задачи. Большинство программ, которые считывают видео H.264 (например, OpenH264 и FFm-peg), фокусируются на максимально быстром создании изображения, поэтому оно отбрасывает восстановленные элементы синтаксиса после создания изображения. Инструменты, используемые для отладки видеофайлов (например, StreamEye от Elecard), не позволяют программно редактировать элементы синтаксиса; они сосредоточены на обеспечении обратной связи для настройки видеокодера.
H26FORGE можно использовать как автономный инструмент, который генерирует случайные видео для ввода в видеодекодер; его можно запрограммировать на создание видеороликов, подтверждающих концепцию, которые вызывают конкретную ошибку декодера, обнаруженную исследователем безопасности; и исследователь может интерактивно управлять им при изучении вопроса «что, если?» сценарии для частично изученной уязвимости.
Мы оцениваем эффективность H26FORGE с помощью двух тематических исследований.
В первом тематическом исследовании мы изучаем безопасность драйвера ядра Ap-pleAVD и драйвера ядра AppleD5500, используемого для SoC до A12.5
1. Проиграв несколько сотен случайных видеороликов, сгенерированных H26FORGE, на iPhone с A9 SoC, мы выявили две ошибки. Один из них можно использовать для контролируемого повреждения кучи ядра; другой запускает бесконечный цикл в потоке ядра, вызывая перезагрузку сторожевого таймера.
2. Мы реконструировали двоичный файл драйвера AppleD5500 и обнаружили очевидную отсутствующую проверку границ при анализе параметров H.265. Хотя H26FORGE не поддерживает генерацию H.265, энтропийное кодирование на уровне параметров аналогично, и мы смогли создать демонстрационное видео, в котором используется проверка отсутствующих границ для повреждения кучи ядра и предоставления злоумышленнику контроля счетчика программ.
3. Начиная с бинарного отличия от патча CVE-2022-22675, мы смогли расширить анализ первопричин Сильвановича, сгенерировать демонстрационное видео, которое повреждает кучу ядра и вызывает панику, и объяснить, почему POC Сильвановича, несмотря на запуск патча, не вызвало паники.
Во втором тематическом исследовании мы воспроизвели большой набор случайных видеороликов, сгенерированных H26FORGE, на различном программном обеспечении Windows и системах Android от многих устаревших, но все еще актуальных поставщиков. В целом, мы выявили уязвимость повреждения памяти при воспроизведении видео в Firefox; use-after-free при воспроизведении видео VLC с аппаратным ускорением; и глубокая ненадежность всей экосистемы аппаратного декодера, включая раскрытие неинициализированной памяти и предыдущего состояния декодера; повреждение памяти ускорителя; и повреждение памяти драйвера ядра и сбои.
Раскрытие информации и этика.
Мы связались (или пытались связаться; см. ниже) со всеми поставщиками, затронутыми нашими выводами о повреждении памяти.
Apple и Mozilla признали, исправили и присвоили CVE сообщения об ошибках. Разработчики VLC исправили обнаруженную ошибку. Мы сообщили о раскрытии неинициализированной памяти в Google и MediaTek.
Некоторые поставщики, особенно те, которые продают медиа-интеллектуальную собственность («медиа-ИС») поставщикам SoC и не имеют регулярных контактов с конечными пользователями, не ответили на наше обращение.
2 Подробности
Мы описываем особенности сжатия видео H.264 и выделяем развернутые реализации, имеющие отношение к выводам, о которых мы сообщаем в этой статье. Читатели, заинтересованные в более подробном, но все же доступном введении в H.264, должны обратиться к монографии Ричардсона [41].
2.1 Кодек H.264
Видеокодек H.264 [23] был стандартизирован в 2003 году Международным союзом электросвязи (ITU) и Группой экспертов по кино (MPEG). Благодаря этим совместным усилиям этот кодек имеет два названия: H.264, предоставленный ITU, и AVC, предоставленный MPEG. Мы по умолчанию используем H.264, когда это возможно.
Спецификация описывает, как декодировать видео, оставляя стратегии кодирования на усмотрение разработчиков программного и аппаратного обеспечения. Кодирование видео - это проблема поиска сходства внутри изображений и между ними и превращения этих сходств в энтропийно-кодированные инструкции. Спецификация H.264 описывает, как восстановить инструкции и воспроизвести изображение.
YUV, макроблоки и слайсы.
Видео представляет собой набор изображений или кадров, состоящих из пикселей. Каждый пиксель разбивается на две составляющие: яркость (яркость) и цветность (цвет). В H.264 яркость обозначается как Y, а цветность — как U и V, где последние обозначают синий и красный компоненты соответственно и используются для восстановления зеленого компонента с помощью набора линейных уравнений. Вместе они называются значениями YUV.
В H.264 кадры разбиваются на группы размером 16 × 16 пикселей, называемые макроблоками. Макроблоки — это основная единица, используемая при работе с кадрами. Макроблоки группируются в слайсы, которые используются для создания кадров.
Предсказание и деблокировка.
H.264 сжимает видео, полагаясь на методы прогнозирования для воссоздания видео в конечной точке. Отправляются инструкции прогнозирования и остаток: разница между прогнозируемым кадром и фактическим кадром. В H.264 существует два типа механизмов предсказания: внутреннее предсказание и межкадровое предсказание.
Внутреннее предсказание ищет сходства в пределах одного и того же кадра с точностью до макроблока. Для макроблока декодер берет краевые пиксели соседних макроблоков и предсказывает изображение, используя линейную комбинацию этих значений. Затем он добавляет остаток к предсказанному изображению, чтобы получить результирующее выходное изображение.
Поскольку изображения иногда просто переводятся на экран, Inter-прогнозирование ищет сходство между кадрами. Кадры с межкадровым предсказанием копируют макроблоки из опорных кадров и применяют остатки для построения окончательного макроблока. Декодер поддерживает буфер декодированных изображений (DPB) и использует его для создания списка эталонных изображений. Различные макроблоки в одном и том же изображении могут ссылаться на разные кадры в буфере. Если макроблоки в кадре используют только один опорный кадр, то этот кадр называется P-кадром. Если используются два опорных кадра, то они называются B-кадрами (для двойного предсказания).
Поскольку кадры восстанавливаются на уровне макроблока, декодер применяет удаление блочности на краях макроблока, чтобы получить более гладкое изображение.
Профили и уровни.
Профиль в H.264 указывает, какие функции используются для декодирования видео. Особенности включают тип энтропийного кодирования и наличие B-кадров. Наиболее распространенными профилями являются базовый, основной и высокий.
Уровень видео сигнализирует о возможном размере кадра видео, о том, сколько кадров хранить в DPB и какой должна быть максимально возможная скорость передачи данных.
Синтаксические элементы.
Инструкции по реконструкции видео называются элементами синтаксиса. Возможные значения, которые могут быть присвоены каждому элементу синтаксиса, определяются семантикой элементов синтаксиса H.264. Значения направляют декодер при выборе переменных предсказания и восстановлении остаточной информации.
Элементы синтаксиса сгруппированы вместе в единицы сетевого уровня абстракции (NALU). NALU имеют заголовок, сигнализирующий о типе содержимого, которое они содержат. Хотя спецификация допускает до 32 различных типов NALU, наиболее распространенными являются:
- Наборы параметров последовательности (SPS): они содержат высокоуровневые свойства видео, такие как: профиль, уровень, размер кадра, обрезка и т. д. Спецификация допускает до 32 SPS в видео, но только один активен в каждый момент времени. время.
- Наборы параметров изображения (PPS): PPS содержат параметры сжатия и инструкции по реконструкции изображения. Спецификация допускает до 256 PPS. PPS должен ссылаться на действительный SPS в видео.
- Мгновенное обновление декодера (IDR) NALU: IDR NALU содержат слайсы и вынуждают декодер очищать свой DPB, поэтому они должны содержать только слайсы, предсказанные с помощью Intra (I слайсы), которые не ссылаются на какие-либо другие кадры. Также ожидается, что первый кадр в видео будет IDR NALU. IDR NALU должен указывать на действительный PPS. Слайсы разбиваются на заголовки слайсов с информацией об изображении и данные слайсов с макроблоками, которые содержат инструкции предсказания и остаток.
- NALU без IDR: NALU без IDR содержат слайсы, которые могут быть предсказаны внутри или внутри, но сохраняют состояние декодера. Одинарные межкадровые слайсы (P слайсы) содержат макроблоки, которые ссылаются на один кадр. Бипрогнозированные слайсы (B слайсы) могут ссылаться на два кадра. NALU без IDR также указывает на действительный PPS.
Элементы синтаксиса могут иметь зависимости, влияющие на то, как будут декодироваться последующие элементы. Изменение одного элемента синтаксиса изменяет не только способ создания изображения, но и способ чтения потока.
Энтропийное кодирование.
Чтобы сжать элементы синтаксиса, энтропия H.264 кодирует их с помощью процедур кодирования без сохранения или с отслеживанием состояния.
Кодирование энтропии без сохранения состояния не зависит от соседних значений и включает двоичное, унарное и экспоненциальное-Голомба (exp-Golomb). Все SPS, PPS и заголовки слайсов кодируются таким образом без сохранения состояния и часто обрабатываются программным обеспечением.
Энтропийное кодирование с отслеживанием состояния опирается на ранее декодированные значения и используется в данных среза для кодирования режимов прогнозирования и остаточных значений. Двумя вариантами кодирования являются контекстно-адаптивное кодирование переменной длины (CAVLC) и контекстно-адаптивное двоичное арифметическое кодирование (CABAC). CAVLC — это кодирование длин серий, означающее, что значение отправляется вместе с тем, сколько раз значение появляется последовательно. CABAC — это арифметическое кодирование, при котором двоичные значения восстанавливаются из вероятностной модели, которая адаптируется к текущим и предыдущим элементам синтаксиса. И CAVLC, и CABAC более ресурсоемки, чем варианты без сохранения состояния, и поэтому часто обрабатываются аппаратно.
Организация закодированных значений.
Закодированные NALU могут быть организованы одним из двух способов: в формате «Приложение B» или в формате AVCC. Формат «Приложение B» [23] обозначает начало NALU с начальными кодами значения 0x00000001 или 0x000001. Формат AVCC включает в себя длину каждого NALU вместо начального кода и используется в файлах MP4 с четырехсимвольным атомом кода avcC, содержащим параметры SPS и PPS для видео, и атомом mdat, содержащим фрагменты.
Оба формата проходят процесс, называемый предотвращением эмуляции, в котором последовательные значения 0x00 в закодированном потоке «экранируются» путем вставки байта предотвращения эмуляции 0x03 после каждых двух 0x00. Это делается для того, чтобы декодер не принял последовательность за стартовый код.
Функции и расширения H.264.
Спецификация H.264 содержит набор функций, доступных для разных профилей. Произвольное упорядочение фрагментов (ASO) — это функция защиты от ошибок, позволяющая составлять кадры из множества фрагментов, которые могут поступать в любое время. Гибкое упорядочение макроблоков (FMO) похоже на ASO, но также позволяет размещать макроблоки в различных формах. Оба являются частью базового профиля.
С момента своего появления в спецификацию были добавлены расширения для новых приложений и сценариев. Двумя примечательными из них являются Scalable Video Coding (SVC) и Multiview Video Coding (MVC), которые позволяют использовать несколько размеров в одном закодированном видео или несколько углов в одном видео соответственно.
Конвейер декодирования.
Теперь мы опишем, как компоненты объединяются для декодирования типичного видео H.264.
Во-первых, декодер настраивается путем передачи SPS и PPS со свойствами, связанными с кадром и сжатием. Затем декодер принимает первый слайс и анализирует элементы синтаксиса заголовка слайса. Затем декодер начинает реконструкцию изображения на уровне макроблока. Затем он энтропийно декодирует элементы синтаксиса и передает их либо на путь восстановления остатка, либо на путь предсказания кадров с ранее декодированными кадрами. Затем предсказанные кадры объединяются с остатком, пропускаются через механизм деблокировки и, наконец, сохраняются в DPB, где можно получить доступ к кадрам и представить их.
2.2 Программные системы, управляющие видео
Широкий спектр программных систем обрабатывает ненадежные видеофайлы, обеспечивая широкую поверхность атаки для ошибок кодека.
Важным наблюдением является то, что аппаратное декодирование видео обходит тщательную песочницу, которая в противном случае используется для ограничения последствий ошибок декодирования мультимедиа.
Мессенджеры.
Популярные мессенджеры будут принимать видео вложения в сообщениях и предоставлять уведомление о предварительном просмотре миниатюр. В стандартной конфигурации многих мессенджеров видео обрабатывается для создания эскиза без взаимодействия с пользователем, создавая поверхность атаки без щелчка.
Есть много примеров проблем с видео на мобильных устройствах. У Android были исторические проблемы в библиотеке Stagefright для обработки файлов MP4 [10, 11]. Как мы обсуждаем в разделе 5, эскизы и декодирование видео представляют собой уязвимую поверхность для атаки в приложении Apple iMessage, несмотря на песочницу BlastDoor [18]. Также могут быть затронуты сторонние мессенджеры. В сентябре в WhatsApp обнаружил критическую ошибку при анализе видео на Android и iOS.
Веб.
Веб-браузеры уже давно позволяют страницам включать видео для воспроизведения через HTML-тег видео, что приводит к многочисленным уязвимостям в декодировании видео. Например, и Chrome, и Firefox пострадали от ошибки 2015 года при разборе VP97. В разделе 6.1 мы описываем новую уязвимость, обнаруженную нами в Firefox при обработке файлов H.264.
Несмотря на этот послужной список, веб-платформа подвергается все большему числу атак, связанных с обработкой видео. Расширения источника мультимедиа (MSE) и расширения зашифрованного мультимедиа (EME) были развернуты в основных браузерах; расширение WebCodecs [1], в настоящее время развернутое только в Chrome, позволит веб-сайтам напрямую обращаться к аппаратным декодерам, полностью пропуская проверки формата контейнера.
Современные браузеры тщательно изолируют большинство библиотек обработки мультимедиа, но они обращаются к системным средствам для декодирования видео. Аппаратное ускорение более энергоэффективно; он позволяет воспроизводить контент, для которого требуется аппаратный корень доверия [38]; и это позволяет браузерам получать выгоду от платы за лицензирование патентов, уплачиваемой поставщиками оборудования.
Онлайн платформы.
Конвейеры транскодирования видео, такие как YouTube [40] и Facebook [26], обрабатывают пользовательский контент, который может содержать видео, не соответствующие спецификациям. Это может привести к отказу в обслуживании, утечке информации из среды выполнения или других обработанных видео или даже к выполнению кода.
2.3 Аппаратное декодирование видео
Декодирование видео в современных системах ускоряется с помощью специального оборудования. IP-адрес мультимедиа, включенный в SoC или GPU, обычно лицензируется третьей стороной. В одном примечательном примере SoC от iPhone до A11 включают мультимедийный IP-адрес Imagination Technologies D5500 (см. Раздел 5), как и SoC в нескольких изученных нами телефонах Android, с очень разными драйверами ядра, наложенными сверху.
Интеграция с ОС.
Поставщики IP создают драйверы для своих аппаратных видеодекодеров, которые затем вызываются ОС через собственный уровень абстракции. Драйверы часто подготавливают оборудование к приему закодированных буферов через разделяемую память. В этом разделе мы обсудим различные уровни ОС, предоставляемые для взаимодействия с драйверами.
Хотя Stagefright — это мультимедийный движок Android9, Android использует OpenMAX (OMX) для связи с драйверами оборудования. OMX абстрагирует аппаратный уровень от Stagefright, что упрощает интеграцию пользовательских аппаратных видеодекодеров.
Другие операционные системы также имеют свой собственный уровень абстракций. Сообщество Linux поддерживает видеодекодеры через Video for Linux API версии 2.10. Подобно OMX, он абстрагирует драйвер, поэтому программа пользовательского пространства не нужна для обсуждения базового оборудования. Windows использует DirectX Video Acceleration 2.011, а Apple использует VideoToolbox.12 У Intel также есть собственный уровень абстракции Linux, называемый Video Acceleration API 13, и, аналогично, у Nvidia есть Video Decode and Presentation API для UNIX.
Компании по аппаратному декодированию видео.
В таблице 1 перечислены 25 обнаруженных нами компаний, которые имеют уникальные IP-адреса для декодирования видео. Некоторые из них могут лицензировать другие компании или могут производить свои собственные IP видеокодеки. В состав компаний входят поставщики одноплатных компьютеров (SBC), телевизионных приставок, планшетов, телефонов и систем видеоконференцсвязи. Некоторые IP-компании, занимающиеся декодированием видео, описывают предоставление драйверов, RTL и моделей для включения IP в SoC.
Мы выделяем все эти компании, чтобы продемонстрировать неоднородность доступных аппаратных видеодекодеров и, следовательно, возможность существования уязвимостей внутри или между продуктами.
3 Модель угроз
В этой статье мы предполагаем, что злоумышленник (1) создает один или несколько вредоносных видеофайлов; и (2) заставляет одну или несколько целей декодировать видео. Как мы обсуждали в Разделе 2.2, доставку видео пользователю и его декодирование — с участием пользователя или без него — во многих случаях легко осуществить. Это минимальный набор возможностей, необходимых злоумышленнику для использования уязвимости в программном или аппаратном обеспечении декодирования.
Для атак с раскрытием информации (см., например, разделы 6.1 и 6.3.2) противник (3) должен иметь возможность считывать кадры декодированного видео. Например, для вредоносных видео, доставляемых через Интернет, это можно сделать с помощью JavaScript.
H26FORGE
В этом разделе описывается H26FORGE, доменная инфраструктура для анализа, создания и управления синтаксически правильными, но семантически несовместимыми видеофайлами. Цель H26FORGE — облегчить работу с видео, закодированными в H.264, при оценке декодеров H.264. H26FORGE доступен по адресу https://github.com/h26forge/h26forge.
H26FORGE имеет два основных режима работы: редактирование и генерация. Мы предоставляем обзор H26FORGE, а затем подробно опишем каждый режим.
4.1 Обзор
Реализация.
H26FORGE написан примерно в 30 тысячах строк кода на Rust и имеет бэкэнд для написания сценариев на Python для написания сценариев модификации видео. На рис. 1 показаны различные компоненты H26FORGE. Он состоит из трех основных частей: обработка ввода, обработка синтаксиса и обработка вывода. Входная обработка содержит энтропийное декодирование H.264. Обработка синтаксиса имеет функции для изменения восстановленных элементов синтаксиса или создания случайных видео. Обработка вывода имеет энтропийное кодирование H.264, которое выводит видео в формате «Annex B», но также может выводить файл AVCC, совместимый с WebCodecs, мультиплексированный файл MP4 или дамп декодированных элементов синтаксиса JSON. Для мультиплексирования MP4 мы полагаемся на модифицированную версию крейта minimp4 Rust, который избегает модификации сгенерированного потока битов H.264 и вставляет только первый наблюдаемый SPS и PPS в атом avcC.
H26FORGE работает путем энтропийного декодирования и кодирования битовых потоков H.264 и сохранения восстановленных значений синтаксиса в памяти для изменения. Первоначально мы рассматривали возможность изменения существующего инструмента, который выполняет кодирование и декодирование H.264, но обнаружили, что все они плохо подходят для этой задачи. В частности, существующие инструменты ориентированы на максимально быстрое создание видеокадров, а не на манипулирование элементами синтаксиса, составляющими видео. В результате сами элементы синтаксиса отбрасываются, как только видеокадр декодируется. Поскольку общая архитектура и основные структуры данных существующих инструментов должны быть существенно изменены в соответствии с нашими целями, мы выбрали реализацию с нуля.
Оценка правильности.
Сосредоточив внимание только на элементах синтаксиса энтропийного декодирования и кодирования, H26FORGE поддерживает многие функции H.264. Важно отметить, что H26FORGE поддерживает зависимости между элементами синтаксиса, обеспечивая правильное энтропийное кодирование данных среза. H26FORGE поддерживает большинство профилей Baseline, Main, Extended и High, а также некоторые функции расширений SVC и MVC. В настоящее время H26FORGE не поддерживает субдискретизацию цветности CAVLC 422/444, декодирование FMO и срезы SVC/MVC.
Поскольку энтропийное кодирование и декодирование — сложный процесс, мы проверили корректность H26FORGE, запустив его на официальных тестовых видеороликах, предоставленных ITU [24]. Согласно МСЭ, декодер может заявить о соответствии профилю и уровню, если он может декодировать соответствующие тестовые видео.
Мы протестировали H26FORGE на профилях Constrained Baseline, Base-line, Extended и Main, поскольку именно эти профили поддерживаются большинством изучаемых нами декодеров. Мы достигаем 98% соответствия на тестовых видео. Из 135 тестовых видео 80 побитно идентичны после повторного кодирования с помощью H26FORGE, 52 имеют одинаковые элементы синтаксиса, а 3 базовых видео не могут быть декодированы с помощью H26FORGE, поскольку они используют FMO.
4.2 Режим редактирования
Пользователи могут программно редактировать видео с помощью скриптов Python, называемых видеопреобразованиями. Мы используем эту функцию для создания несоответствующих видео, а также видео, содержащих определенные элементы синтаксиса. Чтобы помочь преобразовать людям, мы написали «вспомогательную» библиотеку с часто встречающимися действиями, такими как обновление зависимых переменных или создание NALU со значениями по умолчанию.
В качестве примера того, как работает режим редактирования, мы представляем видео, в котором все самые верхние макроблоки настроены на вертикальное внутреннее предсказание под названием Luma Chroma Thief. Нестандартное поведение, подобное тому, что демонстрирует Luma Chroma Thief, не может естественным образом возникать в закодированном видео, и создание такого видео вручную будет затруднено из-за того, что значения кодируются CABAC. В листинге 1 мы показываем, как создать Luma Chroma Thief с преобразованием видео, которое устанавливает для всех макроблоков первого среза вертикальное внутреннее предсказание, используя всего 17 строк кода. Этот пример демонстрирует, как преобразования могут накладываться друг на друга, здесь используется преобразование, которое удаляет остаток первого кадра. Этот пример также показывает, как некоторые из зависимых элементов синтаксиса изменяются путем установки отдельных компонентов яркости и цветности шаблона кодированного блока.
В разделе 5.3 мы далее покажем, как мы используем преобразования видео для создания итеративных видео, чтобы понять и использовать ошибку в видеодекодере Apple.
4.3 Режим генерации
Генерация видео — это процесс создания видео с элементами синтаксиса в желаемом значении или диапазоне. Учитывая зависимости между элементами синтаксиса, H26FORGE обеспечит сохранение зависимостей при рандомизации значений. H26FORGE поставляется с диапазонами элементов синтаксиса, установленными на их минимальное и максимальное возможные значения, но их можно настроить, передав параметры генерации. H26FORGE намеренно игнорирует не связанные с синтаксисом ограничения, указанные в спецификации H.264, такие как тот факт, что определенные функции разрешены только в определенных профилях.
На рис. 2 показан пример сгенерированного I-кадра с режимами рандомизированного предсказания и остаточными значениями.
Варианты генерации.
При создании видео H26FORGE может игнорировать определенные синтаксические элементы или комбинации, чтобы сосредоточить усилия на различных областях, представляющих интерес. Например, макроблоки без потерь не нагружают видеодекодер, поскольку значения YUV передаются напрямую, поэтому H26FORGE включает возможность их игнорировать. Если мы хотим сосредоточиться на поиске уязвимостей на уровне набора параметров, в H26FORGE есть опция «пустые данные среза», которая не создает остатка и инструкций по прогнозированию. Поскольку некоторые декодеры могут проверять границы параметров SPS и PPS только во время инициализации, H26FORGE предоставляет опцию «безопасного добавления», которая добавляет заведомо хорошее видео к закодированному выходу, чтобы последующие SPS и PPS выполняли проверку во время стресс-тестирования.
Чтобы облегчить изучение возможностей декодера, H26FORGE имеет опцию генерации «малого» видео, которая ограничивает размер кадра до 128 × 128 пикселей. Это значительно сокращает время генерации видео, хотя и снижает возможность изучения проблем, которые могут возникнуть из-за больших буферов кадров.
Глобальные параметры видео.
Режим генерации начинается с выборки глобальных параметров видео. Во-первых, это количество NALU, которые нужно сгенерировать для видео: более длинные видео требуют больше времени для создания, но могут подвергать уязвимостям с отслеживанием состояния. Далее нужно включить определенные расширения H.264, такие как SVC или MVC. Поскольку расширения часто не поддерживаются видеодекодерами, H26FORGE склоняется к отсутствию расширений, но это можно исправить. С этими двумя глобальными параметрами видео H26FORGE продолжает генерировать содержимое каждого NALU.
Набор параметров и генерация среза.
Все интерфейсы декодирования требуют передачи SPS и PPS для подготовки декодера, поэтому H26FORGE генерирует их в первую очередь. После этого H26FORGE склоняется к созданию фрагментов NALU. Первый слайс смещен в сторону среза IDR I, чтобы уменьшить вероятность того, что декодер завершит работу на первом слайсе. Несмотря на то, что ожидается, что декодеры будут устойчивыми к ошибкам, обычно отсутствие опорного кадра препятствует правильному декодированию сегментов B или P. При создании срезов учитываются параметры свойств среза, такие как отсутствие макроблоков без потерь или пустые значения остатка.
5 Использование H26FORGE: пример Apple
Способность H26FORGE создавать синтаксически правильные файлы H.264 с определенными семантическими ошибками позволяет использовать несколько режимов анализа безопасности. В следующих разделах мы опишем три различных способа использования H26FORGE. Во-первых, H26FORGE можно использовать для поиска новых уязвимостей в коде обработки видео. Во-вторых, H26FORGE позволяет аналитику создавать видеоролики, подтверждающие правильность понимания ошибки. В-третьих, H26FORGE позволяет проводить быстрое интерактивное тестирование для понимания существующих эксплойтов.
Мы исследуем каждый из этих трех аналитических режимов в контексте драйверов Apple для обработки видео в iOS. В первых двух частях мы рассмотрим проблемы в расширении ядра AppleD5500 (kext), обнаруженном в SoC A11 и старше. D5500 — это мультимедийный IP-адрес Imagination Technologies, который декодирует MPEG4, H.264 и H.265, а AppleD5500.kext — это драйвер для облегчения аппаратной связи. Для нашего третьего аналитического режима мы рассмотрим AppleAVD.kext, собственный IP-адрес Apple для декодирования видео, доступный в SoC A12 и новее, который обрабатывает декодирование видео H.264, H.265 и VP9. Хотя оба драйвера декодируют H.264, уязвимости применимы только к указанному драйверу.
5.1 Поиск новых уязвимостей
Мы использовали генератор видео H.264 с поддержкой грамматики H26FORGE (см. Раздел 4.3) для создания синтаксически правильных видеопотоков H.264 со структурированными случайными данными. Мы воспроизвели эти видеоролики на физическом iPhone SE (первого поколения) с SoC A9 под управлением iOS 13.3 и на виртуальном iPhone SE (первого поколения) под управлением iOS 15.5 (самой последней на момент обнаружения) в Corellium.15 Corellium дает нам возможности отладки ядра, а также возможность тестирования на разных версиях iOS.
Наша настройка фаззинга состояла из (1) создания пакета из 100 видео на хост-компьютере, (2) передачи их на тестируемое устройство iOS (через iTunes на физическом телефоне и через scp на виртуальном телефоне), (3) прокрутки через папку, в которой находились видео, чтобы активировать эскизы, (4) затем открывать каждое видео в средстве просмотра QuickLook для полного декодирования. Всего было протестировано 67 партий.
С этой настройкой мы обнаружили две ошибки в AppleD5500.kext. Первая ошибка включает частично контролируемую перезапись кучи. Вторая ошибка вызывает бесконечный цикл и приводит к панике ядра. Эти ошибки были подтверждены, исправлены и присвоены CVE компанией Apple. Мы убедились, что они могут быть вызваны веб-страницей, посещенной в Safari.
Ошибка 1: частично контролируемая перезапись динамической памяти.
Первая проблема, которую мы обнаружили, — это запись за пределы ядра, вызванная переполнением буфера в считывателе битового потока AppleD5500.kext. Переполнение может быть вызвано воспроизведением или созданием эскиза предварительного просмотра искаженного видео. Видео, случайно сгенерированное H26FORGE, вызвало эту ошибку и вызвало панику ядра из-за записи на несопоставленный адрес; Затем мы реконструировали затронутый код, чтобы выполнить анализ первопричины, и использовали H26FORGE в интерактивном режиме, чтобы показать, что ошибка может быть использована для контролируемого повреждения кучи. Ей был присвоен CVE-2022-32939, и она была исправлена в iOS 15.7.1 и 16.1, а также в iPadOS 15.7.1 и 16 [2, 3].
Напомним из раздела 2.1, что байты предотвращения эмуляции (EPB) используются для исключения шаблонов, которые можно принять за стартовые коды NALU в закодированном потоке. Объект чтения битового потока Apple-D5500.kext отслеживает, сколько EPB он видел, а также битовое смещение в битовом потоке, где был найден каждый EPB (предположительно, для упрощения последующей обработки потока).
Массив, в котором отслеживаются смещения EPB, содержит 256 элементов, но отсутствует проверка на то, что встречается не более 256 EPB. 257-й EPB переполняет массив и перезаписывает переменную-член объекта считывателя сразу после него, что соответствует количеству обнаруженных до сих пор EPB. Как следствие, местоположение 258-го EPB будет записано в индексе массива, который теперь контролируется злоумышленником. Последующие EPB будут запускать непрерывные записи за пределами границ по мере увеличения этого счетчика.
Таким образом, ошибка дает злоумышленнику примитив кучи с пропуском и записью, где расположение 257-го EPB управляет объемом пропуска, а расположение 258-го и последующих EPB управляет значениями, записываемыми после пропуска.
Ограничения формата файла означают, что количество пропусков и записываемые значения лишь частично контролируются злоумышленником. EPB должны находиться в одном NALU, так как контекст считывателя битового потока сбрасывается с каждым NALU. Подробная информация о том, как вычисляется и сохраняется смещение EPB, означает, что значения, записанные после пропуска, представляют собой небольшие отрицательные 32-битные значения.
С помощью H26FORGE мы смогли подтвердить, что вредоносное видео может перезаписывать память кучи после объекта чтения битового потока с (небольшими отрицательными) значениями по выбору злоумышленника, подтверждая наш анализ основной причины. Использование ошибки для выполнения кода ядра потребует тщательной очистки кучи ядра для выбора перезаписываемого объекта и, вероятно, ошибки раскрытия памяти ядра для обхода ASLR ядра. Мы не пытались разработать сквозную цепочку эксплойтов; однако, по оценке Apple, ошибка может позволить приложению «выполнять произвольный код с привилегиями ядра».
Ошибка 2: бесконечный цикл.
Второй проблемой, которую мы обнаружили, была ошибка отказа в обслуживании в AppleD5500.kext, вызванная бесконечным циклом в потоке ядра. Бесконечный цикл заставляет устройство нагреваться, а затем перезагружаться из-за паники, вызванной тайм-аутом сторожевого таймера. Как и ошибка 1, эта ошибка может быть вызвана воспроизведением или созданием эскиза предварительного просмотра искаженного видео. Видео, случайно сгенерированное H26FORGE, вызвало эту ошибку и вызвало панику ядра; Затем мы реконструировали затронутый код, чтобы выполнить анализ первопричин. Apple присвоила этой ошибке CVE-2022-42846 и исправила ее в iOS и iPadOS версий 15.7.2 и 16.2 [4, 5].
Мы обнаружили эту проблему при создании видео с IDR NALU с типами срезов, предсказанными Inter. IDR NALU предназначены для срезов с внутренним предсказанием, которые заставляют декодер очищать свой буфер декодированных изображений (DPB); Таким образом, межкадровое предсказание имеет список из 0 DPB для работы, условие, которое код синтаксического анализа не предвидел. Отсутствие проверки на арифметическое переполнение при вычислении границ цикла и некоторые неудачные выборы типов переменных приводят к циклу вида for (uint8 i = 0; i < 256; i++). Тело цикла повреждает объект кучи, используемый декодером, но не переполняется соседними объектами кучи. Через 180 секунд сторожевой таймер вызывает панику и перезапуск устройства.
По оценке Apple, «анализ вредоносного видеофайла может привести к неожиданному завершению работы системы».
5.2 Быстрый POC
В некоторых случаях у аналитика безопасности, проверяющего код обработки видео, могут быть основания полагать, что существует ошибка — например, он может обнаружить в коде отсутствующую проверку границ. Из-за сложности современных кодировок видео, таких как H.264, сложно создать тестовое видео, демонстрирующее наличие ошибки. Это связано с отсутствием соответствующих инструментов. Например, существующие видеокодеры не будут создавать видео, не соответствующие спецификации, а из-за характера энтропийного кодирования внесение локализованных изменений в существующие видео с помощью шестнадцатеричного редактора затруднено.
С H26FORGE процесс создания ПОКа. Аналитик начинает с существующего видео и использует H26FORGE для преобразования его в видео с нужным свойством. Поскольку H26FORGE понимает формат видео, результирующее видео будет синтаксически правильным.
Ошибка в декодировании H.265.
Путем обратного проектирования декодера H.265 в AppleD5500.kext для iOS 15.5 мы обнаружили то, что, по-видимому, было отсутствин проверкт границ, потенциально приводящей к переполнению кучи в объекте декодирования H.265. Чтобы убедиться в этом, мы модифицировали H26FORGE с помощью достаточного количества инструментов H.265, чтобы создать демонстрационное видео, вызывающее управляемое переполнение кучи ядра. В отличие от ранее описанных ошибок, мы смогли вызвать эту ошибку только при воспроизведении видео, а не при создании эскизов предварительного просмотра. Apple присвоила этой ошибке CVE-2022-42850 и исправила ее в iOS и iPadOS версии 16.2.
H26FORGE не был создан для поддержки H.265, но поскольку ошибка заключалась в синтаксическом анализе SPS, для которого H.265 и H.264 используют аналогичные кодировки, мы смогли создать наше демонстрационное видео без полной переделки H26FORGE. Это потребуется для реализации энтропийных кодировок H.265 с отслеживанием состояния.
Уязвимость представляет собой отсутствующую проверку границ для num_short_term_ref_pic_sets. Это значение определяет, сколько объектов краткосрочного эталонного изображения (RPS) должно быть в SPS, которое по спецификация, но не реализации Apple, ограничивается 64. Кратковременные объекты RPS, каждый длиной 172 байта, копируются из битового потока видео переменная-член массива объекта контекста декодера; после заполнения массива последующие объекты RPS перезаписывают оставшуюся часть объекта контекста, а затем и смежные выделения кучи.
С помощью H26FORGE мы подтвердили, что вредоносное видео может перезаписывать динамическую память. Путем обратной разработки декодера мы определили стратегию эксплуатации, которая позволяет злоумышленнику получить контроль над регистром компьютера ядра, и использовали H26FORGE для разработки экспериментального эксплойта, следующего за этой стратегией. Наша стратегия перезаписывает другую переменную-член в объекте контекста, поэтому она не требует очистки кучи. Однако для этого требуется знание структуры кучи ядра, поэтому в сквозном эксплойте необходимо использовать ошибку раскрытия памяти ядра.
Переменная-член, которую мы перезаписываем, является указателем на объект с виртуальным деструктором, который вызывается, когда декодирование завершается и объект контекста освобождается. Переписывая этот указатель адресом фальшивого объекта, который сам указывает на фальшивую виртуальную таблицу, мы можем организовать вызов любого адреса по нашему выбору вместо законного деструктора.
Мы не пытались разработать сквозную цепочку эксплойтов; однако, по оценке Apple, эта ошибка, как и ошибка 1, может позволить приложению «выполнять произвольный код с привилегиями ядра».
H26FORGE сыграл решающую роль в разработке этого видео, поскольку, учитывая отсутствие выравнивания байтов в значениях, закодированных exp-Golomb, ручная настройка этого файла была бы затруднена. Обновление видео для таргетинга на новые адреса или перезапись другого объекта осуществляется с помощью нашего преобразования видео.
5.3 Интерактивное тестирование
Третий способ, которым аналитик может использовать H26FORGE, — это интерактивное тестирование декодирования видео в рамках полного изучения или даже анализа первопричин эксплойта в дикой природе. Например, CVE-2022-22675 — это запись за пределами границ из-за отсутствия проверки границ в AppleAVD.kext, затрагивающей версии iOS до 15.4. Отчет Google Project Zero об ошибке [43] включает частичное видео с доказательством концепции, которое не приводит к сбою.
Мы реконструировали AppleAVD.kext и использовали отладчик ядра, чтобы проверить наши гипотезы об ошибке и ее последствиях. H26FORGE сыграл решающую роль в создании видеовходов для этих сеансов отладки.
Обозначение.
При описании SPS и PPS мы включаем идентификатор в нижний индекс (например, SPSID, PPSID). Для слайсов мы включаем идентификатор PPS, на который он указывает, в нижнем индексе, а тип — в верхнем индексе (например, SlicePPS ID).
Ошибка CVE-2022-22675.
Эта ошибка заключалась в отсутствующей проверке границ для синтаксического элемента cpb_count_minus1, расположенного в функции с именем parseHRD, которая восстанавливает параметры гипотетического эталонного декодера (HRD), вложенные в синтаксический анализ SPS. SPS могут иметь два разных параметра HRD, а их использование и элементы синтаксиса описаны в Приложениях C и E спецификации H.264 [23]. Согласно спецификации, cpb_count_ minus1 должно иметь максимально возможное значение 31, но поскольку проверка границ отсутствует, а значение закодировано exp-Golomb, мы можем установить максимальное значение, которое AppleAVD.kext может хранить: 255. Этот параметр используется как цикл, связанный для синтаксического анализа двух значений uint32, закодированных с помощью exp-Golomb, для которых не проверяются границы, и дополнительного одиночного бита. Поскольку они хранятся в массивах длиной 32, когда счетчик превысит ожидаемую длину, AppleAVD.kext начнет запись в остальную часть объекта SPS, а затем за пределы выделенной памяти SPS. Из-за того, где находятся вторые параметры HRD в объекте SPS, это переполнение может перезаписать не более 832 байтов после объекта SPS.
Объект SPS содержится в массиве длиной 32 в пользовательском контексте AppleAVD.kext H.264. SPS индексируется по его seq_parameter_set_id, при этом последующие SPS с тем же идентификатором перезаписывают ранее декодированные. Сразу после массива SPS идет массив PPS длиной 256, аналогично проиндексированный pic_parameter_set_id. Это означает, что переполнение параметра HRD повлияет либо на соседний SPS, либо на PPS, в зависимости от seq_parameter_set_id. Объект SPS имеет длину 2224 байта, а объект PPS — 604 байта, поэтому мы можем либо перезаписать первую часть соседнего SPS, либо полностью перезаписать PPS с индексом 0 вместе с началом PPS с индексом 1.
Однако для того, чтобы перезапись имела эффект, переполненный параметр HRD должен быть декодирован после того, как доброкачественный SPS или PPS уже был декодирован, чтобы изменить то, какими должны быть параметры, в противном случае все, что записано в переполненном пространстве, будет очищено при декодировании СПС или ППС.
Доказательство концепции Project Zero.
Используя H26FORGE, мы можем объяснить, почему демонстрационное видео в статье Project Zero не вызывает сбоев. Во-первых, видео NALU неправильно упорядочены. Он начинается с SPS с идентификатором 31, содержащего значение cpb_count_minus1, выходящее за границы, PPS с идентификатором 0 и срез, указывающий на PPS 0. В нынешнем виде искаженный SPS будет декодирован до доброкачественного PPS, поэтому любые перезаписанные значения будут игнорироваться при последующем анализе PPS. Во-вторых, PPS указывает на SPS с ID 0, но, поскольку во время декодирования он не существует, декодер останавливается. Это демонстрационное видео довольно большое, 20 МБ, но мы проверили, пройдя через отладчик ядра Corellium, что декодирование останавливается, когда первый фрагмент не может найти действительный SPS.
Доказательство концепции, произведенное H26FORGE.
Мы описываем шаги, необходимые для создания видео, вызывающего контролируемое переполнение кучи ядра путем перезаписи параметра PPS. На рис. 3 показана наша общая стратегия. Более подробная информация о нашем последнем шаге находится в Приложении A.
Шаг 1: правильный порядок.
Мы используем H26FORGE для создания видео со следующими NALU: SPS0, PPS0, SPS0, SliceI0 и SliceP0. Во втором NALU SPS будет существовать переполнение parseHRD, которое приведет к повреждению PPS0.
Шаг 2: исправьте идентификаторы.
Мы создаем преобразование видео для настройки идентификаторов параметров. Мы устанавливаем идентификатор второго SPS равным 31, поэтому он будет храниться в конце массива SPS. С H26FORGE мы создаем как необработанный файл H.264, так и видео MP4 19 в следующем порядке: SPS0, PPS0, SPS31, SliceI0, SliceP0.
В левой части показан правильно упорядоченный битовый поток H.264, прочитанный сверху вниз, а в правой части показано декодированное содержимое в памяти по мере его заполнения. (1) Исходные параметры SPS и PPS: чтения, каждый с идентификатором 0 (SPS0, PPS0). (2) Анализируется SPS с идентификатором 31, где мы используем выход за границы cpb_count_minus1 в parseHRD для перезаписи PPS0. (3) PPS0 перезаписывается выходным значением num_ref_idx_l0_active_minus1, используемым при декодировании фрагмента. (4) Перезаписанный num_ref_idx_l0_active_minus1 вызывает второе переполнение в parsePredWeightTable, записывая 16-битное значение Bn больше 255 с контролируемым смещением, при этом для промежуточной памяти установлено значение по умолчанию. (5) Значения произвольной длины можно записать, регулируя смещение в каждом последующем слайсе, записывая значения в обратном порядке.
Шаг 3: добавьте перезапись.
С нашим видео, которое содержит идентификаторы в правильном порядке, теперь мы можем изменить элементы синтаксиса SPS31, чтобы активировать CVE-2022-22675. Части (1) и
(2) на рисунке 3 иллюстрирует порядок и это переполнение.
Параметры HRD являются частью необязательного элемента синтаксиса, вложенного в SPS. Сначала мы используем преобразование видео, чтобы гарантировать, что параметры будут проанализированы, затем мы устанавливаем cpb_count_ minus1 на 255. Чтобы понять, как элементы синтаксиса в цикле используются во время перезаписи, мы устанавливаем оба значения, закодированные exp-Golomb, в шаблон, и все значения флагов размером в байт равны true.
Теперь у нас есть видео со следующим порядком: SPS0, PPS0, SPS∗31, SliceI0, SliceP0, где SPS∗31 содержит перезапись.
Шаг 4: управляйте местом перезаписи и производите второе переполнение.
Установка точки останова при декодировании заголовка слайса в отладчике ядра iOS при воспроизведении видео с предыдущего шага позволяет нам проверять память и определять цели записи в PPS. Мы описываем стратегию эксплойта, которая использует описанную выше возможность для перезаписи параметра num_ref_idx_l0_active_minus1 PPS.
Этот параметр используется в качестве связанного цикла при анализе синтаксиса таблицы весов прогнозирования, parsePredWeightTable, в котором определенные 16-битовые значения копируются из потока битов в переменную-член массива в объекте пользовательского контекста H.264. Согласно спецификации, num_ref_idx_l0_active_minus1 должно быть не более 31 — ограничение, которое AppleAVD.kext корректно проверяет при анализе параметров PPS. Перезаписывая этот параметр большими значениями с помощью переполнения первого этапа, мы можем превысить его предел и заставить цикл parsePredWeightTable записывать за конец массива, выделенного для него в объекте пользовательского контекста H.264, вызывая второе переполнение. Это показано в части (3) рисунка 3.
В преобразовании видео мы устанавливаем cpb_count_minus1, чтобы остановить зацикливание в позиции, которую он может записать num_ref_idx_l0_active_minus1, и используем один из параметров HRD, закодированных exp-Golomb, чтобы установить его максимальное значение 255.
Шаг 5: удовлетворить ограничения и разрешить второе переполнение.
Недостаточно организовать для первого переполнения перезапись num_ref_idx_l0_active_minus1 большим значением. Мы должны убедиться, что другие параметры PPS, которые мы переполняем, принимают разумные значения, чтобы избежать преждевременного выхода из декодирования видео из-за неудачной проверки AppleAVD.kext. Мы также должны убедиться, что заголовки слайсов, которые ссылаются на параметры PPS, которые мы перезаписываем, являются предсказанными Inter и не имеют установленного флага num_ref_idx_active_override_flag; в противном случае анализ синтаксиса таблицы весов предсказания пропускается. Мы также должны заполнить заголовки срезов достаточным количеством параметров таблицы прогнозируемых весов, чтобы учесть перезаписанную границу цикла, а не исходный максимум 31.
При выполнении этих дополнительных ограничений мы можем вызвать панику ядра из-за записи за пределами выделенной памяти пользовательского контекста H.264.
Шаг 6: управление вторым переполнением.
К сожалению, видео сбоя не сразу полезно для повреждения кучи по двум причинам. Во-первых, перезапись, которую мы запускаем, настолько велика, что переполняет не только пользовательский контекст, но и кучу ядра в целом, потому что граница цикла определяется знаком, расширяющим параметр num_ref_idx_l0_active_minus1 с 8 бит до 32. Во-вторых, 16-битный значения, которые цикл записывает в кучу, плохо ограничены: каждое должно быть между 0 и 255, иначе цикл остановится после его записи.
Эти две проблемы аккуратно решают друг друга.
Устроив так, чтобы битовый поток включал значение больше 255, когда мы написали достаточно, мы можем заставить цикл выйти раньше, несмотря на огромную границу цикла. 16-битные значения перед последним должны по-прежнему находиться в диапазоне от 0 до 255. Часть (4) на рис. 3 показывает такое расположение, при этом последнее записанное значение обозначается как Bn.
Если мы включим дополнительные слайсы, которые ссылаются на параметры PPS, которые мы переполнили, мы можем вызвать повторное выполнение цикла переполнения, скопировав другую часть битового потока в тот же объект пользовательского контекста. Работая в этом направлении, когда каждый фрагмент записывает меньше байтов, чем предыдущий, мы избегаем отмены работы, выполненной ранее в эксплойте. Этот метод проиллюстрирован в части (5) рисунка 3. Первый срез записывает значение Bn за пределы допустимого диапазона и останавливается; второй пишет Bn−1 и останавливается; и так далее, пока после k срезов мы не запишем 2k произвольных байтов с произвольным смещением от объекта User Context. Мы предоставляем более подробную информацию о том, как мы организуем поток битов, в Приложении A.
Эксплуатация.
Мы использовали H26FORGE для автоматизации создания видео, в котором используется описанная стратегия эксплойта для записи выбранной злоумышленником полезной нагрузки по выбранному злоумышленником смещению от объекта пользовательского контекста H.264 в куче ядра iOS.
Как и в случае с нашей ошибкой 3 из раздела 5.2, использование этого примитива переполнения кучи в произвольном выполнении ядра, вероятно, потребует очистки кучи и ошибки раскрытия адреса ядра, а наличие аутентификации указателя в SoC, использующих AppleAVD, усугубляет проблему. В недавней презентации Тараканова и Лабунеца обсуждаются эти проблемы и предлагаются некоторые стратегии эксплуатации AppleAVD [45].
Современные стандарты кодирования видео, такие как H.264, представляют собой чудо скрытой сложности. Но со скрытой сложностью приходит скрытый риск для безопасности. Декодирование видео на практике означает взаимодействие с выделенными аппаратными ускорителями и проприетарными привилегированными программными компонентами, используемыми для их управления. Экосистема видеодекодера неясна, непрозрачна, разнообразна, высоко привилегирована, в значительной степени не протестирована и широко открыта — все это опасное сочетание.
Мы представляем и оцениваем H26FORGE, доменную инфраструктуру для анализа, создания и обработки синтаксически правильных, но семантически несовместимых видеофайлов. Используя H26FORGE, мы подробно выявляем проблемы с безопасностью в экосистеме видеодекодера, включая ошибки повреждения памяти ядра в iOS, ошибки повреждения памяти в Firefox и VLC для Windows, а также ошибки памяти ядра видеоускорителя и процессора приложений на нескольких устройствах Android.
1. Введение
Современные стандарты кодирования видео — это чудо скрытой сложности. Как отмечает SwiftOnSecurity, приложения, управляемые видео, которые мы считаем само собой разумеющимися, были бы невозможны без достижений в технологии сжатия видео, несмотря на увеличение вычислительной мощности, емкости хранения и пропускной способности сети. Но со скрытой сложностью приходит скрытый риск для безопасности.
Спецификация H.264 состоит из 800 страниц, несмотря на то, что указано только, как декодировать видео, а не как его кодировать. Поскольку декодирование является сложным и дорогостоящим, его обычно делегируют аппаратным видеоускорителям либо на графическом процессоре, либо в выделенном блоке системы на кристалле (SoC). Декодирование видео на практике означает взаимодействие с этими привилегированными аппаратными компонентами и привилегированными программными компонентами, используемыми для их управления, обычно с системным медиа-сервером и драйвером ядра. По сравнению с другими типами носителей, которые могут обрабатываться автономными изолированными программными библиотеками, поверхность атаки для обработки видео больше, более привилегирована и, как мы объясним ниже, более разнородна.
На основе руководства, которое они называют «правилом 2», разработчики Chrome стараются избегать написания кода, который выполняет не более двух из следующих действий: анализирует ненадежный ввод, написан на небезопасном для памяти языке и работает на высоких привилегиях. Стек обработки видео в Chrome нарушает Правило 2, как и соответствующие стеки в других основных браузерах и приложениях для обмена сообщениями, потому что код платформы для управления оборудованием для декодирования видео, от которого все они зависят, сам по себе нарушает Правило 2.
Поскольку для разных аппаратных видеоускорителей требуются разные драйверы, экосистема привилегированного программного обеспечения для обработки видео сильно фрагментирована; наш анализ деревьев устройств Linux выявил два десятка поставщиков ускорителей. Не существует одной доминирующей библиотеки программного обеспечения с открытым исходным кодом, которую исследователи безопасности могли бы проверить.
И функции, которые делают современные форматы видео такими эффективными, также затрудняют тестирование с высоким покрытием кода стеков декодирования видео с помощью универсальных инструментов. Возьмем H.264, самый популярный формат видео на сегодняшний день. H.264 сжимает видео, находя сходство внутри и между кадрами; сходства и различия отправляются как синтаксические элементы с энтропийным кодированием. Эти синтаксические элементы кодируются контекстно-зависимым образом: изменение значения одного синтаксического элемента полностью меняет интерпретацию декодером остального битового потока.
Наглядный пример: CVE-2022-22675.
31 марта 2022 года Apple выпустила iOS 15.4.1, в которой исправлена ошибка в драйвере ядра для семейства видеоускорителей AppleAVD, включенных в SoC, начиная с A12 2018 года. В примечаниях к выпуску говорится, что «Apple известно об отчете о том, что эта проблема могла активно использоваться».
Натали Сильванович из Google Project Zero провела анализ основной причины ошибки [43]. Сравнив драйверы до и после исправления, она обнаружила отсутствующую проверку границ синтаксического элемента cpb_cnt_minus1; она смогла создать видео, которое вызвало добавленную проверку, но не вызвало панику ядра. Проблема заключалась в отказе инструментов. Как объяснила Сильванович в Твиттере, она «подделала файл по крупицам, и это было просто ужасно. Один трюк, который я использую, состоит в том, чтобы создать ffmpeg с символами и разбить его там, где функция, которую вы пытаетесь вызвать, находится в (например, чтение HRD) [. . . ] Затем вы можете сбросить битовый поток с помощью gdb, найти соответствующее место в файле и отредактировать его».
Наши исследования.
Мы представляем и оцениваем H26FORGE, доменную инфраструктуру для анализа, создания и обработки синтаксически правильных, но семантически несовместимых видеофайлов.
H26FORGE поддерживает восстановленные синтаксические элементы H.264 в памяти и позволяет программно корректировать синтаксические элементы, при этом правильно энтропийно кодируя скорректированные значения. Никакой предыдущий инструмент не подходит для этой задачи. Большинство программ, которые считывают видео H.264 (например, OpenH264 и FFm-peg), фокусируются на максимально быстром создании изображения, поэтому оно отбрасывает восстановленные элементы синтаксиса после создания изображения. Инструменты, используемые для отладки видеофайлов (например, StreamEye от Elecard), не позволяют программно редактировать элементы синтаксиса; они сосредоточены на обеспечении обратной связи для настройки видеокодера.
H26FORGE можно использовать как автономный инструмент, который генерирует случайные видео для ввода в видеодекодер; его можно запрограммировать на создание видеороликов, подтверждающих концепцию, которые вызывают конкретную ошибку декодера, обнаруженную исследователем безопасности; и исследователь может интерактивно управлять им при изучении вопроса «что, если?» сценарии для частично изученной уязвимости.
Мы оцениваем эффективность H26FORGE с помощью двух тематических исследований.
В первом тематическом исследовании мы изучаем безопасность драйвера ядра Ap-pleAVD и драйвера ядра AppleD5500, используемого для SoC до A12.5
1. Проиграв несколько сотен случайных видеороликов, сгенерированных H26FORGE, на iPhone с A9 SoC, мы выявили две ошибки. Один из них можно использовать для контролируемого повреждения кучи ядра; другой запускает бесконечный цикл в потоке ядра, вызывая перезагрузку сторожевого таймера.
2. Мы реконструировали двоичный файл драйвера AppleD5500 и обнаружили очевидную отсутствующую проверку границ при анализе параметров H.265. Хотя H26FORGE не поддерживает генерацию H.265, энтропийное кодирование на уровне параметров аналогично, и мы смогли создать демонстрационное видео, в котором используется проверка отсутствующих границ для повреждения кучи ядра и предоставления злоумышленнику контроля счетчика программ.
3. Начиная с бинарного отличия от патча CVE-2022-22675, мы смогли расширить анализ первопричин Сильвановича, сгенерировать демонстрационное видео, которое повреждает кучу ядра и вызывает панику, и объяснить, почему POC Сильвановича, несмотря на запуск патча, не вызвало паники.
Во втором тематическом исследовании мы воспроизвели большой набор случайных видеороликов, сгенерированных H26FORGE, на различном программном обеспечении Windows и системах Android от многих устаревших, но все еще актуальных поставщиков. В целом, мы выявили уязвимость повреждения памяти при воспроизведении видео в Firefox; use-after-free при воспроизведении видео VLC с аппаратным ускорением; и глубокая ненадежность всей экосистемы аппаратного декодера, включая раскрытие неинициализированной памяти и предыдущего состояния декодера; повреждение памяти ускорителя; и повреждение памяти драйвера ядра и сбои.
Раскрытие информации и этика.
Мы связались (или пытались связаться; см. ниже) со всеми поставщиками, затронутыми нашими выводами о повреждении памяти.
Apple и Mozilla признали, исправили и присвоили CVE сообщения об ошибках. Разработчики VLC исправили обнаруженную ошибку. Мы сообщили о раскрытии неинициализированной памяти в Google и MediaTek.
Некоторые поставщики, особенно те, которые продают медиа-интеллектуальную собственность («медиа-ИС») поставщикам SoC и не имеют регулярных контактов с конечными пользователями, не ответили на наше обращение.
2 Подробности
Мы описываем особенности сжатия видео H.264 и выделяем развернутые реализации, имеющие отношение к выводам, о которых мы сообщаем в этой статье. Читатели, заинтересованные в более подробном, но все же доступном введении в H.264, должны обратиться к монографии Ричардсона [41].
2.1 Кодек H.264
Видеокодек H.264 [23] был стандартизирован в 2003 году Международным союзом электросвязи (ITU) и Группой экспертов по кино (MPEG). Благодаря этим совместным усилиям этот кодек имеет два названия: H.264, предоставленный ITU, и AVC, предоставленный MPEG. Мы по умолчанию используем H.264, когда это возможно.
Спецификация описывает, как декодировать видео, оставляя стратегии кодирования на усмотрение разработчиков программного и аппаратного обеспечения. Кодирование видео - это проблема поиска сходства внутри изображений и между ними и превращения этих сходств в энтропийно-кодированные инструкции. Спецификация H.264 описывает, как восстановить инструкции и воспроизвести изображение.
YUV, макроблоки и слайсы.
Видео представляет собой набор изображений или кадров, состоящих из пикселей. Каждый пиксель разбивается на две составляющие: яркость (яркость) и цветность (цвет). В H.264 яркость обозначается как Y, а цветность — как U и V, где последние обозначают синий и красный компоненты соответственно и используются для восстановления зеленого компонента с помощью набора линейных уравнений. Вместе они называются значениями YUV.
В H.264 кадры разбиваются на группы размером 16 × 16 пикселей, называемые макроблоками. Макроблоки — это основная единица, используемая при работе с кадрами. Макроблоки группируются в слайсы, которые используются для создания кадров.
Предсказание и деблокировка.
H.264 сжимает видео, полагаясь на методы прогнозирования для воссоздания видео в конечной точке. Отправляются инструкции прогнозирования и остаток: разница между прогнозируемым кадром и фактическим кадром. В H.264 существует два типа механизмов предсказания: внутреннее предсказание и межкадровое предсказание.
Внутреннее предсказание ищет сходства в пределах одного и того же кадра с точностью до макроблока. Для макроблока декодер берет краевые пиксели соседних макроблоков и предсказывает изображение, используя линейную комбинацию этих значений. Затем он добавляет остаток к предсказанному изображению, чтобы получить результирующее выходное изображение.
Поскольку изображения иногда просто переводятся на экран, Inter-прогнозирование ищет сходство между кадрами. Кадры с межкадровым предсказанием копируют макроблоки из опорных кадров и применяют остатки для построения окончательного макроблока. Декодер поддерживает буфер декодированных изображений (DPB) и использует его для создания списка эталонных изображений. Различные макроблоки в одном и том же изображении могут ссылаться на разные кадры в буфере. Если макроблоки в кадре используют только один опорный кадр, то этот кадр называется P-кадром. Если используются два опорных кадра, то они называются B-кадрами (для двойного предсказания).
Поскольку кадры восстанавливаются на уровне макроблока, декодер применяет удаление блочности на краях макроблока, чтобы получить более гладкое изображение.
Профили и уровни.
Профиль в H.264 указывает, какие функции используются для декодирования видео. Особенности включают тип энтропийного кодирования и наличие B-кадров. Наиболее распространенными профилями являются базовый, основной и высокий.
Уровень видео сигнализирует о возможном размере кадра видео, о том, сколько кадров хранить в DPB и какой должна быть максимально возможная скорость передачи данных.
Синтаксические элементы.
Инструкции по реконструкции видео называются элементами синтаксиса. Возможные значения, которые могут быть присвоены каждому элементу синтаксиса, определяются семантикой элементов синтаксиса H.264. Значения направляют декодер при выборе переменных предсказания и восстановлении остаточной информации.
Элементы синтаксиса сгруппированы вместе в единицы сетевого уровня абстракции (NALU). NALU имеют заголовок, сигнализирующий о типе содержимого, которое они содержат. Хотя спецификация допускает до 32 различных типов NALU, наиболее распространенными являются:
- Наборы параметров последовательности (SPS): они содержат высокоуровневые свойства видео, такие как: профиль, уровень, размер кадра, обрезка и т. д. Спецификация допускает до 32 SPS в видео, но только один активен в каждый момент времени. время.
- Наборы параметров изображения (PPS): PPS содержат параметры сжатия и инструкции по реконструкции изображения. Спецификация допускает до 256 PPS. PPS должен ссылаться на действительный SPS в видео.
- Мгновенное обновление декодера (IDR) NALU: IDR NALU содержат слайсы и вынуждают декодер очищать свой DPB, поэтому они должны содержать только слайсы, предсказанные с помощью Intra (I слайсы), которые не ссылаются на какие-либо другие кадры. Также ожидается, что первый кадр в видео будет IDR NALU. IDR NALU должен указывать на действительный PPS. Слайсы разбиваются на заголовки слайсов с информацией об изображении и данные слайсов с макроблоками, которые содержат инструкции предсказания и остаток.
- NALU без IDR: NALU без IDR содержат слайсы, которые могут быть предсказаны внутри или внутри, но сохраняют состояние декодера. Одинарные межкадровые слайсы (P слайсы) содержат макроблоки, которые ссылаются на один кадр. Бипрогнозированные слайсы (B слайсы) могут ссылаться на два кадра. NALU без IDR также указывает на действительный PPS.
Элементы синтаксиса могут иметь зависимости, влияющие на то, как будут декодироваться последующие элементы. Изменение одного элемента синтаксиса изменяет не только способ создания изображения, но и способ чтения потока.
Энтропийное кодирование.
Чтобы сжать элементы синтаксиса, энтропия H.264 кодирует их с помощью процедур кодирования без сохранения или с отслеживанием состояния.
Кодирование энтропии без сохранения состояния не зависит от соседних значений и включает двоичное, унарное и экспоненциальное-Голомба (exp-Golomb). Все SPS, PPS и заголовки слайсов кодируются таким образом без сохранения состояния и часто обрабатываются программным обеспечением.
Энтропийное кодирование с отслеживанием состояния опирается на ранее декодированные значения и используется в данных среза для кодирования режимов прогнозирования и остаточных значений. Двумя вариантами кодирования являются контекстно-адаптивное кодирование переменной длины (CAVLC) и контекстно-адаптивное двоичное арифметическое кодирование (CABAC). CAVLC — это кодирование длин серий, означающее, что значение отправляется вместе с тем, сколько раз значение появляется последовательно. CABAC — это арифметическое кодирование, при котором двоичные значения восстанавливаются из вероятностной модели, которая адаптируется к текущим и предыдущим элементам синтаксиса. И CAVLC, и CABAC более ресурсоемки, чем варианты без сохранения состояния, и поэтому часто обрабатываются аппаратно.
Организация закодированных значений.
Закодированные NALU могут быть организованы одним из двух способов: в формате «Приложение B» или в формате AVCC. Формат «Приложение B» [23] обозначает начало NALU с начальными кодами значения 0x00000001 или 0x000001. Формат AVCC включает в себя длину каждого NALU вместо начального кода и используется в файлах MP4 с четырехсимвольным атомом кода avcC, содержащим параметры SPS и PPS для видео, и атомом mdat, содержащим фрагменты.
Оба формата проходят процесс, называемый предотвращением эмуляции, в котором последовательные значения 0x00 в закодированном потоке «экранируются» путем вставки байта предотвращения эмуляции 0x03 после каждых двух 0x00. Это делается для того, чтобы декодер не принял последовательность за стартовый код.
Функции и расширения H.264.
Спецификация H.264 содержит набор функций, доступных для разных профилей. Произвольное упорядочение фрагментов (ASO) — это функция защиты от ошибок, позволяющая составлять кадры из множества фрагментов, которые могут поступать в любое время. Гибкое упорядочение макроблоков (FMO) похоже на ASO, но также позволяет размещать макроблоки в различных формах. Оба являются частью базового профиля.
С момента своего появления в спецификацию были добавлены расширения для новых приложений и сценариев. Двумя примечательными из них являются Scalable Video Coding (SVC) и Multiview Video Coding (MVC), которые позволяют использовать несколько размеров в одном закодированном видео или несколько углов в одном видео соответственно.
Конвейер декодирования.
Теперь мы опишем, как компоненты объединяются для декодирования типичного видео H.264.
Во-первых, декодер настраивается путем передачи SPS и PPS со свойствами, связанными с кадром и сжатием. Затем декодер принимает первый слайс и анализирует элементы синтаксиса заголовка слайса. Затем декодер начинает реконструкцию изображения на уровне макроблока. Затем он энтропийно декодирует элементы синтаксиса и передает их либо на путь восстановления остатка, либо на путь предсказания кадров с ранее декодированными кадрами. Затем предсказанные кадры объединяются с остатком, пропускаются через механизм деблокировки и, наконец, сохраняются в DPB, где можно получить доступ к кадрам и представить их.
2.2 Программные системы, управляющие видео
Широкий спектр программных систем обрабатывает ненадежные видеофайлы, обеспечивая широкую поверхность атаки для ошибок кодека.
Важным наблюдением является то, что аппаратное декодирование видео обходит тщательную песочницу, которая в противном случае используется для ограничения последствий ошибок декодирования мультимедиа.
Мессенджеры.
Популярные мессенджеры будут принимать видео вложения в сообщениях и предоставлять уведомление о предварительном просмотре миниатюр. В стандартной конфигурации многих мессенджеров видео обрабатывается для создания эскиза без взаимодействия с пользователем, создавая поверхность атаки без щелчка.
Есть много примеров проблем с видео на мобильных устройствах. У Android были исторические проблемы в библиотеке Stagefright для обработки файлов MP4 [10, 11]. Как мы обсуждаем в разделе 5, эскизы и декодирование видео представляют собой уязвимую поверхность для атаки в приложении Apple iMessage, несмотря на песочницу BlastDoor [18]. Также могут быть затронуты сторонние мессенджеры. В сентябре в WhatsApp обнаружил критическую ошибку при анализе видео на Android и iOS.
Веб.
Веб-браузеры уже давно позволяют страницам включать видео для воспроизведения через HTML-тег видео, что приводит к многочисленным уязвимостям в декодировании видео. Например, и Chrome, и Firefox пострадали от ошибки 2015 года при разборе VP97. В разделе 6.1 мы описываем новую уязвимость, обнаруженную нами в Firefox при обработке файлов H.264.
Несмотря на этот послужной список, веб-платформа подвергается все большему числу атак, связанных с обработкой видео. Расширения источника мультимедиа (MSE) и расширения зашифрованного мультимедиа (EME) были развернуты в основных браузерах; расширение WebCodecs [1], в настоящее время развернутое только в Chrome, позволит веб-сайтам напрямую обращаться к аппаратным декодерам, полностью пропуская проверки формата контейнера.
Современные браузеры тщательно изолируют большинство библиотек обработки мультимедиа, но они обращаются к системным средствам для декодирования видео. Аппаратное ускорение более энергоэффективно; он позволяет воспроизводить контент, для которого требуется аппаратный корень доверия [38]; и это позволяет браузерам получать выгоду от платы за лицензирование патентов, уплачиваемой поставщиками оборудования.
Онлайн платформы.
Конвейеры транскодирования видео, такие как YouTube [40] и Facebook [26], обрабатывают пользовательский контент, который может содержать видео, не соответствующие спецификациям. Это может привести к отказу в обслуживании, утечке информации из среды выполнения или других обработанных видео или даже к выполнению кода.
2.3 Аппаратное декодирование видео
Декодирование видео в современных системах ускоряется с помощью специального оборудования. IP-адрес мультимедиа, включенный в SoC или GPU, обычно лицензируется третьей стороной. В одном примечательном примере SoC от iPhone до A11 включают мультимедийный IP-адрес Imagination Technologies D5500 (см. Раздел 5), как и SoC в нескольких изученных нами телефонах Android, с очень разными драйверами ядра, наложенными сверху.
Интеграция с ОС.
Поставщики IP создают драйверы для своих аппаратных видеодекодеров, которые затем вызываются ОС через собственный уровень абстракции. Драйверы часто подготавливают оборудование к приему закодированных буферов через разделяемую память. В этом разделе мы обсудим различные уровни ОС, предоставляемые для взаимодействия с драйверами.
Хотя Stagefright — это мультимедийный движок Android9, Android использует OpenMAX (OMX) для связи с драйверами оборудования. OMX абстрагирует аппаратный уровень от Stagefright, что упрощает интеграцию пользовательских аппаратных видеодекодеров.
Другие операционные системы также имеют свой собственный уровень абстракций. Сообщество Linux поддерживает видеодекодеры через Video for Linux API версии 2.10. Подобно OMX, он абстрагирует драйвер, поэтому программа пользовательского пространства не нужна для обсуждения базового оборудования. Windows использует DirectX Video Acceleration 2.011, а Apple использует VideoToolbox.12 У Intel также есть собственный уровень абстракции Linux, называемый Video Acceleration API 13, и, аналогично, у Nvidia есть Video Decode and Presentation API для UNIX.
Компании по аппаратному декодированию видео.
В таблице 1 перечислены 25 обнаруженных нами компаний, которые имеют уникальные IP-адреса для декодирования видео. Некоторые из них могут лицензировать другие компании или могут производить свои собственные IP видеокодеки. В состав компаний входят поставщики одноплатных компьютеров (SBC), телевизионных приставок, планшетов, телефонов и систем видеоконференцсвязи. Некоторые IP-компании, занимающиеся декодированием видео, описывают предоставление драйверов, RTL и моделей для включения IP в SoC.
Мы выделяем все эти компании, чтобы продемонстрировать неоднородность доступных аппаратных видеодекодеров и, следовательно, возможность существования уязвимостей внутри или между продуктами.
3 Модель угроз
В этой статье мы предполагаем, что злоумышленник (1) создает один или несколько вредоносных видеофайлов; и (2) заставляет одну или несколько целей декодировать видео. Как мы обсуждали в Разделе 2.2, доставку видео пользователю и его декодирование — с участием пользователя или без него — во многих случаях легко осуществить. Это минимальный набор возможностей, необходимых злоумышленнику для использования уязвимости в программном или аппаратном обеспечении декодирования.
Для атак с раскрытием информации (см., например, разделы 6.1 и 6.3.2) противник (3) должен иметь возможность считывать кадры декодированного видео. Например, для вредоносных видео, доставляемых через Интернет, это можно сделать с помощью JavaScript.
H26FORGE
В этом разделе описывается H26FORGE, доменная инфраструктура для анализа, создания и управления синтаксически правильными, но семантически несовместимыми видеофайлами. Цель H26FORGE — облегчить работу с видео, закодированными в H.264, при оценке декодеров H.264. H26FORGE доступен по адресу https://github.com/h26forge/h26forge.
H26FORGE имеет два основных режима работы: редактирование и генерация. Мы предоставляем обзор H26FORGE, а затем подробно опишем каждый режим.
4.1 Обзор
Реализация.
H26FORGE написан примерно в 30 тысячах строк кода на Rust и имеет бэкэнд для написания сценариев на Python для написания сценариев модификации видео. На рис. 1 показаны различные компоненты H26FORGE. Он состоит из трех основных частей: обработка ввода, обработка синтаксиса и обработка вывода. Входная обработка содержит энтропийное декодирование H.264. Обработка синтаксиса имеет функции для изменения восстановленных элементов синтаксиса или создания случайных видео. Обработка вывода имеет энтропийное кодирование H.264, которое выводит видео в формате «Annex B», но также может выводить файл AVCC, совместимый с WebCodecs, мультиплексированный файл MP4 или дамп декодированных элементов синтаксиса JSON. Для мультиплексирования MP4 мы полагаемся на модифицированную версию крейта minimp4 Rust, который избегает модификации сгенерированного потока битов H.264 и вставляет только первый наблюдаемый SPS и PPS в атом avcC.
H26FORGE работает путем энтропийного декодирования и кодирования битовых потоков H.264 и сохранения восстановленных значений синтаксиса в памяти для изменения. Первоначально мы рассматривали возможность изменения существующего инструмента, который выполняет кодирование и декодирование H.264, но обнаружили, что все они плохо подходят для этой задачи. В частности, существующие инструменты ориентированы на максимально быстрое создание видеокадров, а не на манипулирование элементами синтаксиса, составляющими видео. В результате сами элементы синтаксиса отбрасываются, как только видеокадр декодируется. Поскольку общая архитектура и основные структуры данных существующих инструментов должны быть существенно изменены в соответствии с нашими целями, мы выбрали реализацию с нуля.
Оценка правильности.
Сосредоточив внимание только на элементах синтаксиса энтропийного декодирования и кодирования, H26FORGE поддерживает многие функции H.264. Важно отметить, что H26FORGE поддерживает зависимости между элементами синтаксиса, обеспечивая правильное энтропийное кодирование данных среза. H26FORGE поддерживает большинство профилей Baseline, Main, Extended и High, а также некоторые функции расширений SVC и MVC. В настоящее время H26FORGE не поддерживает субдискретизацию цветности CAVLC 422/444, декодирование FMO и срезы SVC/MVC.
Поскольку энтропийное кодирование и декодирование — сложный процесс, мы проверили корректность H26FORGE, запустив его на официальных тестовых видеороликах, предоставленных ITU [24]. Согласно МСЭ, декодер может заявить о соответствии профилю и уровню, если он может декодировать соответствующие тестовые видео.
Мы протестировали H26FORGE на профилях Constrained Baseline, Base-line, Extended и Main, поскольку именно эти профили поддерживаются большинством изучаемых нами декодеров. Мы достигаем 98% соответствия на тестовых видео. Из 135 тестовых видео 80 побитно идентичны после повторного кодирования с помощью H26FORGE, 52 имеют одинаковые элементы синтаксиса, а 3 базовых видео не могут быть декодированы с помощью H26FORGE, поскольку они используют FMO.
4.2 Режим редактирования
Пользователи могут программно редактировать видео с помощью скриптов Python, называемых видеопреобразованиями. Мы используем эту функцию для создания несоответствующих видео, а также видео, содержащих определенные элементы синтаксиса. Чтобы помочь преобразовать людям, мы написали «вспомогательную» библиотеку с часто встречающимися действиями, такими как обновление зависимых переменных или создание NALU со значениями по умолчанию.
В качестве примера того, как работает режим редактирования, мы представляем видео, в котором все самые верхние макроблоки настроены на вертикальное внутреннее предсказание под названием Luma Chroma Thief. Нестандартное поведение, подобное тому, что демонстрирует Luma Chroma Thief, не может естественным образом возникать в закодированном видео, и создание такого видео вручную будет затруднено из-за того, что значения кодируются CABAC. В листинге 1 мы показываем, как создать Luma Chroma Thief с преобразованием видео, которое устанавливает для всех макроблоков первого среза вертикальное внутреннее предсказание, используя всего 17 строк кода. Этот пример демонстрирует, как преобразования могут накладываться друг на друга, здесь используется преобразование, которое удаляет остаток первого кадра. Этот пример также показывает, как некоторые из зависимых элементов синтаксиса изменяются путем установки отдельных компонентов яркости и цветности шаблона кодированного блока.
В разделе 5.3 мы далее покажем, как мы используем преобразования видео для создания итеративных видео, чтобы понять и использовать ошибку в видеодекодере Apple.
4.3 Режим генерации
Генерация видео — это процесс создания видео с элементами синтаксиса в желаемом значении или диапазоне. Учитывая зависимости между элементами синтаксиса, H26FORGE обеспечит сохранение зависимостей при рандомизации значений. H26FORGE поставляется с диапазонами элементов синтаксиса, установленными на их минимальное и максимальное возможные значения, но их можно настроить, передав параметры генерации. H26FORGE намеренно игнорирует не связанные с синтаксисом ограничения, указанные в спецификации H.264, такие как тот факт, что определенные функции разрешены только в определенных профилях.
На рис. 2 показан пример сгенерированного I-кадра с режимами рандомизированного предсказания и остаточными значениями.
Варианты генерации.
При создании видео H26FORGE может игнорировать определенные синтаксические элементы или комбинации, чтобы сосредоточить усилия на различных областях, представляющих интерес. Например, макроблоки без потерь не нагружают видеодекодер, поскольку значения YUV передаются напрямую, поэтому H26FORGE включает возможность их игнорировать. Если мы хотим сосредоточиться на поиске уязвимостей на уровне набора параметров, в H26FORGE есть опция «пустые данные среза», которая не создает остатка и инструкций по прогнозированию. Поскольку некоторые декодеры могут проверять границы параметров SPS и PPS только во время инициализации, H26FORGE предоставляет опцию «безопасного добавления», которая добавляет заведомо хорошее видео к закодированному выходу, чтобы последующие SPS и PPS выполняли проверку во время стресс-тестирования.
Чтобы облегчить изучение возможностей декодера, H26FORGE имеет опцию генерации «малого» видео, которая ограничивает размер кадра до 128 × 128 пикселей. Это значительно сокращает время генерации видео, хотя и снижает возможность изучения проблем, которые могут возникнуть из-за больших буферов кадров.
Глобальные параметры видео.
Режим генерации начинается с выборки глобальных параметров видео. Во-первых, это количество NALU, которые нужно сгенерировать для видео: более длинные видео требуют больше времени для создания, но могут подвергать уязвимостям с отслеживанием состояния. Далее нужно включить определенные расширения H.264, такие как SVC или MVC. Поскольку расширения часто не поддерживаются видеодекодерами, H26FORGE склоняется к отсутствию расширений, но это можно исправить. С этими двумя глобальными параметрами видео H26FORGE продолжает генерировать содержимое каждого NALU.
Набор параметров и генерация среза.
Все интерфейсы декодирования требуют передачи SPS и PPS для подготовки декодера, поэтому H26FORGE генерирует их в первую очередь. После этого H26FORGE склоняется к созданию фрагментов NALU. Первый слайс смещен в сторону среза IDR I, чтобы уменьшить вероятность того, что декодер завершит работу на первом слайсе. Несмотря на то, что ожидается, что декодеры будут устойчивыми к ошибкам, обычно отсутствие опорного кадра препятствует правильному декодированию сегментов B или P. При создании срезов учитываются параметры свойств среза, такие как отсутствие макроблоков без потерь или пустые значения остатка.
5 Использование H26FORGE: пример Apple
Способность H26FORGE создавать синтаксически правильные файлы H.264 с определенными семантическими ошибками позволяет использовать несколько режимов анализа безопасности. В следующих разделах мы опишем три различных способа использования H26FORGE. Во-первых, H26FORGE можно использовать для поиска новых уязвимостей в коде обработки видео. Во-вторых, H26FORGE позволяет аналитику создавать видеоролики, подтверждающие правильность понимания ошибки. В-третьих, H26FORGE позволяет проводить быстрое интерактивное тестирование для понимания существующих эксплойтов.
Мы исследуем каждый из этих трех аналитических режимов в контексте драйверов Apple для обработки видео в iOS. В первых двух частях мы рассмотрим проблемы в расширении ядра AppleD5500 (kext), обнаруженном в SoC A11 и старше. D5500 — это мультимедийный IP-адрес Imagination Technologies, который декодирует MPEG4, H.264 и H.265, а AppleD5500.kext — это драйвер для облегчения аппаратной связи. Для нашего третьего аналитического режима мы рассмотрим AppleAVD.kext, собственный IP-адрес Apple для декодирования видео, доступный в SoC A12 и новее, который обрабатывает декодирование видео H.264, H.265 и VP9. Хотя оба драйвера декодируют H.264, уязвимости применимы только к указанному драйверу.
5.1 Поиск новых уязвимостей
Мы использовали генератор видео H.264 с поддержкой грамматики H26FORGE (см. Раздел 4.3) для создания синтаксически правильных видеопотоков H.264 со структурированными случайными данными. Мы воспроизвели эти видеоролики на физическом iPhone SE (первого поколения) с SoC A9 под управлением iOS 13.3 и на виртуальном iPhone SE (первого поколения) под управлением iOS 15.5 (самой последней на момент обнаружения) в Corellium.15 Corellium дает нам возможности отладки ядра, а также возможность тестирования на разных версиях iOS.
Наша настройка фаззинга состояла из (1) создания пакета из 100 видео на хост-компьютере, (2) передачи их на тестируемое устройство iOS (через iTunes на физическом телефоне и через scp на виртуальном телефоне), (3) прокрутки через папку, в которой находились видео, чтобы активировать эскизы, (4) затем открывать каждое видео в средстве просмотра QuickLook для полного декодирования. Всего было протестировано 67 партий.
С этой настройкой мы обнаружили две ошибки в AppleD5500.kext. Первая ошибка включает частично контролируемую перезапись кучи. Вторая ошибка вызывает бесконечный цикл и приводит к панике ядра. Эти ошибки были подтверждены, исправлены и присвоены CVE компанией Apple. Мы убедились, что они могут быть вызваны веб-страницей, посещенной в Safari.
Ошибка 1: частично контролируемая перезапись динамической памяти.
Первая проблема, которую мы обнаружили, — это запись за пределы ядра, вызванная переполнением буфера в считывателе битового потока AppleD5500.kext. Переполнение может быть вызвано воспроизведением или созданием эскиза предварительного просмотра искаженного видео. Видео, случайно сгенерированное H26FORGE, вызвало эту ошибку и вызвало панику ядра из-за записи на несопоставленный адрес; Затем мы реконструировали затронутый код, чтобы выполнить анализ первопричины, и использовали H26FORGE в интерактивном режиме, чтобы показать, что ошибка может быть использована для контролируемого повреждения кучи. Ей был присвоен CVE-2022-32939, и она была исправлена в iOS 15.7.1 и 16.1, а также в iPadOS 15.7.1 и 16 [2, 3].
Напомним из раздела 2.1, что байты предотвращения эмуляции (EPB) используются для исключения шаблонов, которые можно принять за стартовые коды NALU в закодированном потоке. Объект чтения битового потока Apple-D5500.kext отслеживает, сколько EPB он видел, а также битовое смещение в битовом потоке, где был найден каждый EPB (предположительно, для упрощения последующей обработки потока).
Массив, в котором отслеживаются смещения EPB, содержит 256 элементов, но отсутствует проверка на то, что встречается не более 256 EPB. 257-й EPB переполняет массив и перезаписывает переменную-член объекта считывателя сразу после него, что соответствует количеству обнаруженных до сих пор EPB. Как следствие, местоположение 258-го EPB будет записано в индексе массива, который теперь контролируется злоумышленником. Последующие EPB будут запускать непрерывные записи за пределами границ по мере увеличения этого счетчика.
Таким образом, ошибка дает злоумышленнику примитив кучи с пропуском и записью, где расположение 257-го EPB управляет объемом пропуска, а расположение 258-го и последующих EPB управляет значениями, записываемыми после пропуска.
Ограничения формата файла означают, что количество пропусков и записываемые значения лишь частично контролируются злоумышленником. EPB должны находиться в одном NALU, так как контекст считывателя битового потока сбрасывается с каждым NALU. Подробная информация о том, как вычисляется и сохраняется смещение EPB, означает, что значения, записанные после пропуска, представляют собой небольшие отрицательные 32-битные значения.
С помощью H26FORGE мы смогли подтвердить, что вредоносное видео может перезаписывать память кучи после объекта чтения битового потока с (небольшими отрицательными) значениями по выбору злоумышленника, подтверждая наш анализ основной причины. Использование ошибки для выполнения кода ядра потребует тщательной очистки кучи ядра для выбора перезаписываемого объекта и, вероятно, ошибки раскрытия памяти ядра для обхода ASLR ядра. Мы не пытались разработать сквозную цепочку эксплойтов; однако, по оценке Apple, ошибка может позволить приложению «выполнять произвольный код с привилегиями ядра».
Ошибка 2: бесконечный цикл.
Второй проблемой, которую мы обнаружили, была ошибка отказа в обслуживании в AppleD5500.kext, вызванная бесконечным циклом в потоке ядра. Бесконечный цикл заставляет устройство нагреваться, а затем перезагружаться из-за паники, вызванной тайм-аутом сторожевого таймера. Как и ошибка 1, эта ошибка может быть вызвана воспроизведением или созданием эскиза предварительного просмотра искаженного видео. Видео, случайно сгенерированное H26FORGE, вызвало эту ошибку и вызвало панику ядра; Затем мы реконструировали затронутый код, чтобы выполнить анализ первопричин. Apple присвоила этой ошибке CVE-2022-42846 и исправила ее в iOS и iPadOS версий 15.7.2 и 16.2 [4, 5].
Мы обнаружили эту проблему при создании видео с IDR NALU с типами срезов, предсказанными Inter. IDR NALU предназначены для срезов с внутренним предсказанием, которые заставляют декодер очищать свой буфер декодированных изображений (DPB); Таким образом, межкадровое предсказание имеет список из 0 DPB для работы, условие, которое код синтаксического анализа не предвидел. Отсутствие проверки на арифметическое переполнение при вычислении границ цикла и некоторые неудачные выборы типов переменных приводят к циклу вида for (uint8 i = 0; i < 256; i++). Тело цикла повреждает объект кучи, используемый декодером, но не переполняется соседними объектами кучи. Через 180 секунд сторожевой таймер вызывает панику и перезапуск устройства.
По оценке Apple, «анализ вредоносного видеофайла может привести к неожиданному завершению работы системы».
5.2 Быстрый POC
В некоторых случаях у аналитика безопасности, проверяющего код обработки видео, могут быть основания полагать, что существует ошибка — например, он может обнаружить в коде отсутствующую проверку границ. Из-за сложности современных кодировок видео, таких как H.264, сложно создать тестовое видео, демонстрирующее наличие ошибки. Это связано с отсутствием соответствующих инструментов. Например, существующие видеокодеры не будут создавать видео, не соответствующие спецификации, а из-за характера энтропийного кодирования внесение локализованных изменений в существующие видео с помощью шестнадцатеричного редактора затруднено.
С H26FORGE процесс создания ПОКа. Аналитик начинает с существующего видео и использует H26FORGE для преобразования его в видео с нужным свойством. Поскольку H26FORGE понимает формат видео, результирующее видео будет синтаксически правильным.
Ошибка в декодировании H.265.
Путем обратного проектирования декодера H.265 в AppleD5500.kext для iOS 15.5 мы обнаружили то, что, по-видимому, было отсутствин проверкт границ, потенциально приводящей к переполнению кучи в объекте декодирования H.265. Чтобы убедиться в этом, мы модифицировали H26FORGE с помощью достаточного количества инструментов H.265, чтобы создать демонстрационное видео, вызывающее управляемое переполнение кучи ядра. В отличие от ранее описанных ошибок, мы смогли вызвать эту ошибку только при воспроизведении видео, а не при создании эскизов предварительного просмотра. Apple присвоила этой ошибке CVE-2022-42850 и исправила ее в iOS и iPadOS версии 16.2.
H26FORGE не был создан для поддержки H.265, но поскольку ошибка заключалась в синтаксическом анализе SPS, для которого H.265 и H.264 используют аналогичные кодировки, мы смогли создать наше демонстрационное видео без полной переделки H26FORGE. Это потребуется для реализации энтропийных кодировок H.265 с отслеживанием состояния.
Уязвимость представляет собой отсутствующую проверку границ для num_short_term_ref_pic_sets. Это значение определяет, сколько объектов краткосрочного эталонного изображения (RPS) должно быть в SPS, которое по спецификация, но не реализации Apple, ограничивается 64. Кратковременные объекты RPS, каждый длиной 172 байта, копируются из битового потока видео переменная-член массива объекта контекста декодера; после заполнения массива последующие объекты RPS перезаписывают оставшуюся часть объекта контекста, а затем и смежные выделения кучи.
С помощью H26FORGE мы подтвердили, что вредоносное видео может перезаписывать динамическую память. Путем обратной разработки декодера мы определили стратегию эксплуатации, которая позволяет злоумышленнику получить контроль над регистром компьютера ядра, и использовали H26FORGE для разработки экспериментального эксплойта, следующего за этой стратегией. Наша стратегия перезаписывает другую переменную-член в объекте контекста, поэтому она не требует очистки кучи. Однако для этого требуется знание структуры кучи ядра, поэтому в сквозном эксплойте необходимо использовать ошибку раскрытия памяти ядра.
Переменная-член, которую мы перезаписываем, является указателем на объект с виртуальным деструктором, который вызывается, когда декодирование завершается и объект контекста освобождается. Переписывая этот указатель адресом фальшивого объекта, который сам указывает на фальшивую виртуальную таблицу, мы можем организовать вызов любого адреса по нашему выбору вместо законного деструктора.
Мы не пытались разработать сквозную цепочку эксплойтов; однако, по оценке Apple, эта ошибка, как и ошибка 1, может позволить приложению «выполнять произвольный код с привилегиями ядра».
H26FORGE сыграл решающую роль в разработке этого видео, поскольку, учитывая отсутствие выравнивания байтов в значениях, закодированных exp-Golomb, ручная настройка этого файла была бы затруднена. Обновление видео для таргетинга на новые адреса или перезапись другого объекта осуществляется с помощью нашего преобразования видео.
5.3 Интерактивное тестирование
Третий способ, которым аналитик может использовать H26FORGE, — это интерактивное тестирование декодирования видео в рамках полного изучения или даже анализа первопричин эксплойта в дикой природе. Например, CVE-2022-22675 — это запись за пределами границ из-за отсутствия проверки границ в AppleAVD.kext, затрагивающей версии iOS до 15.4. Отчет Google Project Zero об ошибке [43] включает частичное видео с доказательством концепции, которое не приводит к сбою.
Мы реконструировали AppleAVD.kext и использовали отладчик ядра, чтобы проверить наши гипотезы об ошибке и ее последствиях. H26FORGE сыграл решающую роль в создании видеовходов для этих сеансов отладки.
Обозначение.
При описании SPS и PPS мы включаем идентификатор в нижний индекс (например, SPSID, PPSID). Для слайсов мы включаем идентификатор PPS, на который он указывает, в нижнем индексе, а тип — в верхнем индексе (например, SlicePPS ID).
Ошибка CVE-2022-22675.
Эта ошибка заключалась в отсутствующей проверке границ для синтаксического элемента cpb_count_minus1, расположенного в функции с именем parseHRD, которая восстанавливает параметры гипотетического эталонного декодера (HRD), вложенные в синтаксический анализ SPS. SPS могут иметь два разных параметра HRD, а их использование и элементы синтаксиса описаны в Приложениях C и E спецификации H.264 [23]. Согласно спецификации, cpb_count_ minus1 должно иметь максимально возможное значение 31, но поскольку проверка границ отсутствует, а значение закодировано exp-Golomb, мы можем установить максимальное значение, которое AppleAVD.kext может хранить: 255. Этот параметр используется как цикл, связанный для синтаксического анализа двух значений uint32, закодированных с помощью exp-Golomb, для которых не проверяются границы, и дополнительного одиночного бита. Поскольку они хранятся в массивах длиной 32, когда счетчик превысит ожидаемую длину, AppleAVD.kext начнет запись в остальную часть объекта SPS, а затем за пределы выделенной памяти SPS. Из-за того, где находятся вторые параметры HRD в объекте SPS, это переполнение может перезаписать не более 832 байтов после объекта SPS.
Объект SPS содержится в массиве длиной 32 в пользовательском контексте AppleAVD.kext H.264. SPS индексируется по его seq_parameter_set_id, при этом последующие SPS с тем же идентификатором перезаписывают ранее декодированные. Сразу после массива SPS идет массив PPS длиной 256, аналогично проиндексированный pic_parameter_set_id. Это означает, что переполнение параметра HRD повлияет либо на соседний SPS, либо на PPS, в зависимости от seq_parameter_set_id. Объект SPS имеет длину 2224 байта, а объект PPS — 604 байта, поэтому мы можем либо перезаписать первую часть соседнего SPS, либо полностью перезаписать PPS с индексом 0 вместе с началом PPS с индексом 1.
Однако для того, чтобы перезапись имела эффект, переполненный параметр HRD должен быть декодирован после того, как доброкачественный SPS или PPS уже был декодирован, чтобы изменить то, какими должны быть параметры, в противном случае все, что записано в переполненном пространстве, будет очищено при декодировании СПС или ППС.
Доказательство концепции Project Zero.
Используя H26FORGE, мы можем объяснить, почему демонстрационное видео в статье Project Zero не вызывает сбоев. Во-первых, видео NALU неправильно упорядочены. Он начинается с SPS с идентификатором 31, содержащего значение cpb_count_minus1, выходящее за границы, PPS с идентификатором 0 и срез, указывающий на PPS 0. В нынешнем виде искаженный SPS будет декодирован до доброкачественного PPS, поэтому любые перезаписанные значения будут игнорироваться при последующем анализе PPS. Во-вторых, PPS указывает на SPS с ID 0, но, поскольку во время декодирования он не существует, декодер останавливается. Это демонстрационное видео довольно большое, 20 МБ, но мы проверили, пройдя через отладчик ядра Corellium, что декодирование останавливается, когда первый фрагмент не может найти действительный SPS.
Доказательство концепции, произведенное H26FORGE.
Мы описываем шаги, необходимые для создания видео, вызывающего контролируемое переполнение кучи ядра путем перезаписи параметра PPS. На рис. 3 показана наша общая стратегия. Более подробная информация о нашем последнем шаге находится в Приложении A.
Шаг 1: правильный порядок.
Мы используем H26FORGE для создания видео со следующими NALU: SPS0, PPS0, SPS0, SliceI0 и SliceP0. Во втором NALU SPS будет существовать переполнение parseHRD, которое приведет к повреждению PPS0.
Шаг 2: исправьте идентификаторы.
Мы создаем преобразование видео для настройки идентификаторов параметров. Мы устанавливаем идентификатор второго SPS равным 31, поэтому он будет храниться в конце массива SPS. С H26FORGE мы создаем как необработанный файл H.264, так и видео MP4 19 в следующем порядке: SPS0, PPS0, SPS31, SliceI0, SliceP0.
В левой части показан правильно упорядоченный битовый поток H.264, прочитанный сверху вниз, а в правой части показано декодированное содержимое в памяти по мере его заполнения. (1) Исходные параметры SPS и PPS: чтения, каждый с идентификатором 0 (SPS0, PPS0). (2) Анализируется SPS с идентификатором 31, где мы используем выход за границы cpb_count_minus1 в parseHRD для перезаписи PPS0. (3) PPS0 перезаписывается выходным значением num_ref_idx_l0_active_minus1, используемым при декодировании фрагмента. (4) Перезаписанный num_ref_idx_l0_active_minus1 вызывает второе переполнение в parsePredWeightTable, записывая 16-битное значение Bn больше 255 с контролируемым смещением, при этом для промежуточной памяти установлено значение по умолчанию. (5) Значения произвольной длины можно записать, регулируя смещение в каждом последующем слайсе, записывая значения в обратном порядке.
Шаг 3: добавьте перезапись.
С нашим видео, которое содержит идентификаторы в правильном порядке, теперь мы можем изменить элементы синтаксиса SPS31, чтобы активировать CVE-2022-22675. Части (1) и
(2) на рисунке 3 иллюстрирует порядок и это переполнение.
Параметры HRD являются частью необязательного элемента синтаксиса, вложенного в SPS. Сначала мы используем преобразование видео, чтобы гарантировать, что параметры будут проанализированы, затем мы устанавливаем cpb_count_ minus1 на 255. Чтобы понять, как элементы синтаксиса в цикле используются во время перезаписи, мы устанавливаем оба значения, закодированные exp-Golomb, в шаблон, и все значения флагов размером в байт равны true.
Теперь у нас есть видео со следующим порядком: SPS0, PPS0, SPS∗31, SliceI0, SliceP0, где SPS∗31 содержит перезапись.
Шаг 4: управляйте местом перезаписи и производите второе переполнение.
Установка точки останова при декодировании заголовка слайса в отладчике ядра iOS при воспроизведении видео с предыдущего шага позволяет нам проверять память и определять цели записи в PPS. Мы описываем стратегию эксплойта, которая использует описанную выше возможность для перезаписи параметра num_ref_idx_l0_active_minus1 PPS.
Этот параметр используется в качестве связанного цикла при анализе синтаксиса таблицы весов прогнозирования, parsePredWeightTable, в котором определенные 16-битовые значения копируются из потока битов в переменную-член массива в объекте пользовательского контекста H.264. Согласно спецификации, num_ref_idx_l0_active_minus1 должно быть не более 31 — ограничение, которое AppleAVD.kext корректно проверяет при анализе параметров PPS. Перезаписывая этот параметр большими значениями с помощью переполнения первого этапа, мы можем превысить его предел и заставить цикл parsePredWeightTable записывать за конец массива, выделенного для него в объекте пользовательского контекста H.264, вызывая второе переполнение. Это показано в части (3) рисунка 3.
В преобразовании видео мы устанавливаем cpb_count_minus1, чтобы остановить зацикливание в позиции, которую он может записать num_ref_idx_l0_active_minus1, и используем один из параметров HRD, закодированных exp-Golomb, чтобы установить его максимальное значение 255.
Шаг 5: удовлетворить ограничения и разрешить второе переполнение.
Недостаточно организовать для первого переполнения перезапись num_ref_idx_l0_active_minus1 большим значением. Мы должны убедиться, что другие параметры PPS, которые мы переполняем, принимают разумные значения, чтобы избежать преждевременного выхода из декодирования видео из-за неудачной проверки AppleAVD.kext. Мы также должны убедиться, что заголовки слайсов, которые ссылаются на параметры PPS, которые мы перезаписываем, являются предсказанными Inter и не имеют установленного флага num_ref_idx_active_override_flag; в противном случае анализ синтаксиса таблицы весов предсказания пропускается. Мы также должны заполнить заголовки срезов достаточным количеством параметров таблицы прогнозируемых весов, чтобы учесть перезаписанную границу цикла, а не исходный максимум 31.
При выполнении этих дополнительных ограничений мы можем вызвать панику ядра из-за записи за пределами выделенной памяти пользовательского контекста H.264.
Шаг 6: управление вторым переполнением.
К сожалению, видео сбоя не сразу полезно для повреждения кучи по двум причинам. Во-первых, перезапись, которую мы запускаем, настолько велика, что переполняет не только пользовательский контекст, но и кучу ядра в целом, потому что граница цикла определяется знаком, расширяющим параметр num_ref_idx_l0_active_minus1 с 8 бит до 32. Во-вторых, 16-битный значения, которые цикл записывает в кучу, плохо ограничены: каждое должно быть между 0 и 255, иначе цикл остановится после его записи.
Эти две проблемы аккуратно решают друг друга.
Устроив так, чтобы битовый поток включал значение больше 255, когда мы написали достаточно, мы можем заставить цикл выйти раньше, несмотря на огромную границу цикла. 16-битные значения перед последним должны по-прежнему находиться в диапазоне от 0 до 255. Часть (4) на рис. 3 показывает такое расположение, при этом последнее записанное значение обозначается как Bn.
Если мы включим дополнительные слайсы, которые ссылаются на параметры PPS, которые мы переполнили, мы можем вызвать повторное выполнение цикла переполнения, скопировав другую часть битового потока в тот же объект пользовательского контекста. Работая в этом направлении, когда каждый фрагмент записывает меньше байтов, чем предыдущий, мы избегаем отмены работы, выполненной ранее в эксплойте. Этот метод проиллюстрирован в части (5) рисунка 3. Первый срез записывает значение Bn за пределы допустимого диапазона и останавливается; второй пишет Bn−1 и останавливается; и так далее, пока после k срезов мы не запишем 2k произвольных байтов с произвольным смещением от объекта User Context. Мы предоставляем более подробную информацию о том, как мы организуем поток битов, в Приложении A.
Эксплуатация.
Мы использовали H26FORGE для автоматизации создания видео, в котором используется описанная стратегия эксплойта для записи выбранной злоумышленником полезной нагрузки по выбранному злоумышленником смещению от объекта пользовательского контекста H.264 в куче ядра iOS.
Как и в случае с нашей ошибкой 3 из раздела 5.2, использование этого примитива переполнения кучи в произвольном выполнении ядра, вероятно, потребует очистки кучи и ошибки раскрытия адреса ядра, а наличие аутентификации указателя в SoC, использующих AppleAVD, усугубляет проблему. В недавней презентации Тараканова и Лабунеца обсуждаются эти проблемы и предлагаются некоторые стратегии эксплуатации AppleAVD [45].