Skip to content
KitploitKITPLOIT
ツールブログ
提出
ツールブログ
提出

ハッキング、侵入テスト、サイバーセキュリティツールをあなたのセキュリティアーセナルに!

Kitploitはハッキング、サイバーセキュリティ、ペネトレーションテストのツールディレクトリです。最新のプロジェクトアップデートを見つけて、脆弱性の発見、システム分析、テストの自動化、セキュリティの強化を行いましょう。

··フィード·お問い合わせ·プライバシー·© 2026 Kitploit

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
CVE-2025-62821 — Microsoft HEIF 拡張機能 (msheif_store.dll) OOB-read | Kitploit
ツール/GitHubGitHub/hyunjungg/cve-2025-62821
メモリフォレンジック脆弱性分析エクスプロイトリバースエンジニアリングファジングバイナリ解析
GitHubhyunjungg/cve-2025-62821

CVE-2025-62821

Microsoft HEIF 拡張機能 (msheif_store.dll) OOB-read

リポジトリを見る
10ヶ月前未レビュー

人気

すべて見る →

コミュニティで最も使われているツールを見つけましょう。

すべてのツールを探索

ツールコレクションを閲覧

すべてのツールを見る →
共有

Microsoft HEIF Image Extensions (msheif_store.dll): CopyPixels パスにおけるソースバッファの過小割り当てにより、領域外読み取りとアクセス違反 (DoS) が発生する

WIC を介して細工された HEIF 画像をデコードするとき、msheif コーデックは 1 バイトのソースバッファを割り当てますが、その後 CopyPixels 中にそのバッファから非常に大量のピクセルデータをコピーしようとします。このコピーは stride × ROI の高さから導出されたサイズで memmove を使用しますが、ソースバッファの実際の長さを検証しません。これにより、領域外読み取りと即時のアクセス違反(クラッシュ)が発生します。実際には、悪意のある HEIF を開いたりプレビューしたりすると、HEIF Image Extensions を経由するすべての WIC コンシューマーでサービス拒否が発生します。

命名上の注記: roi_height などの変数名は、可読性のために逆アセンブリから推定したものであり、ベンダーのシンボル名を反映したものではありません。

製品Microsoft HEIF Image Extensions
モジュールmsheif_store.dll
OSWindows 11
拡張機能のバージョン1.2.22.0 (Microsoft.HEIFImageExtension_1.2.22.0_x64__8wekyb3d8bbwe\x64\msheif_store.dll)
  1. 根本原因解析

    a. 脆弱性の詳細な説明

    • デコードパイプラインは、画像ジオメトリに基づいて memmove の大きなコピー長を計算します(例: copy_size = stride * abs(roi_height))。
    • デコードされたフレーム/アイテムデータを保持するはずのソースバッファが 1 バイトに過小割り当てされます。理由は以下のとおりです:
      • CHEIFStreamReader_ReadItemData は CHEIFItemInfoEntry_GetDataSize を呼び出してアイテムのデータ長を計算します。
      • 特定の失敗分岐では、CHEIFItemInfoEntry_GetDataSize は成功を返すものの、計算されたサイズを 0 のままにします。
      • その後 CHEIFStreamReader_ReadItemData は MFCreateMemoryBuffer(0, &ppBuffer) を呼び出します。MF の動作により、これで最小割り当て 1 バイトのバッファが生成されます。
    • 下流では、CopyPixels は宛先バッファサイズを検証しますが、memmove を呼び出す前にソースバッファの長さと要求されたコピーサイズを検証しません。
    • 結果: memmove(dst, src, large_size) が 1 バイトの src をはるかに超えて読み取り、ベクトル化されたロードでフォールトします。

    このバグは、画像/ROI の幅が誤って解析された場合(例: 0x01000100 = 16,777,472)、stride と最終的なコピーサイズが膨らむことでさらに悪化します。ただし、中心となる脆弱性は、ソースの長さが計算されたコピー長に対してチェックされていないことです。

root@kitploit:~
(7de0.78e4): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
msheif_store!DllCanUnloadNow+0x228b1d:
00007ffd`841bc45d c5fe6f02        vmovdqu ymm0,ymmword ptr [rdx] ds:000002b0`65be6ff0=c0

0:000> !heap -p -a rdx
    address 000002b065be6ff0 found in
    _DPH_HEAP_ROOT @ 2b05bed1000
    in busy allocation (  DPH_HEAP_BLOCK:         UserAddr         UserSize -         VirtAddr         VirtSize)
                             2b062c2f2d8:      2b065be6ff0                1 -      2b065be6000             2000
    ...
    00007ffe75b90563 MFPlat!operator new+0x0000000000000023
    00007ffe75b83d36 MFPlat!MFCreateMemoryBuffer+0x0000000000000056
    00007ffd840157b1 msheif_store!DllCanUnloadNow+0x0000000000081e71
		...

0:000> r r8
r8=0000000001000100

b. 入力からのコードフロー

root@kitploit:~
0:000> k
 # Child-SP          RetAddr               Call Site
00 0000005d`6a9aed98 00007ffe`6fdefcc2     msheif_store!DllCanUnloadNow+0x228b21
01 0000005d`6a9aeda0 00007ffe`6fcb3adc     msheif_store!DllCanUnloadNow+0x18c382
02 0000005d`6a9aee00 00007ffe`6fcb4513     msheif_store!DllCanUnloadNow+0x5019c
03 0000005d`6a9aeef0 00007ffe`6fcb96da     msheif_store!DllCanUnloadNow+0x50bd3
04 0000005d`6a9af0a0 00007fff`318551d5     msheif_store!DllCanUnloadNow+0x55d9a
05 0000005d`6a9af1a0 00007fff`318082eb     windowscodecs!CPyramidBase::CopyPixels+0xf5
06 0000005d`6a9af260 00007fff`31857e52     windowscodecs!CFormatConverter::CopyPixels+0x22b
07 0000005d`6a9af3e0 00007ff6`15fb0f5d     windowscodecs!CFormatConverterResolver::CopyPixels+0xc2
08 0000005d`6a9af480 00007ff6`15fb04ab     heif_decoder!HEIF_LoadBitmapFromMemory+0x34d [C:\\\\Users\\\\test\\\\source\\\\repos\\\\heif_decoder\\\\heif_decoder\\\\heif_decoder.cpp @ 256]
09 0000005d`6a9af670 00007ff6`15fb1754     heif_decoder!HEIF_FuzzMemory+0x9b [C:\\\\Users\\\\test\\\\source\\\\repos\\\\heif_decoder\\\\heif_decoder\\\\heif_decoder.cpp @ 357]
0a 0000005d`6a9af830 00007ff6`15fb3039     heif_decoder!wmain+0x394 [C:\\\\Users\\\\test\\\\source\\\\repos\\\\heif_decoder\\\\heif_decoder\\\\heif_decoder.cpp @ 524]
0b 0000005d`6a9afaa0 00007ff6`15fb2ee2     heif_decoder!invoke_main+0x39 [D:\\\\a\\\\_work\\\\1\\\\s\\\\src\\\\vctools\\\\crt\\\\vcstartup\\\\src\\\\startup\\\\exe_common.inl @ 91]
0c 0000005d`6a9afaf0 00007ff6`15fb2d9e     heif_decoder!__scrt_common_main_seh+0x132 [D:\\\\a\\\\_work\\\\1\\\\s\\\\src\\\\vctools\\\\crt\\\\vcstartup\\\\src\\\\startup\\\\exe_common.inl @ 288]
0d 0000005d`6a9afb60 00007ff6`15fb30ce     heif_decoder!__scrt_common_main+0xe [D:\\\\a\\\\_work\\\\1\\\\s\\\\src\\\\vctools\\\\crt\\\\vcstartup\\\\src\\\\startup\\\\exe_common.inl @ 331]
0e 0000005d`6a9afb90 00007fff`3847e8d7     heif_decoder!wmainCRTStartup+0xe [D:\\\\a\\\\_work\\\\1\\\\s\\\\src\\\\vctools\\\\crt\\\\vcstartup\\\\src\\\\startup\\\\exe_wmain.cpp @ 17]
0f 0000005d`6a9afbc0 00007fff`3939c34c     KERNEL32!BaseThreadInitThunk+0x17
10 0000005d`6a9afbf0 00000000`00000000     ntdll!RtlUserThreadStart+0x2c

解決済みの内部呼び出し(わかりやすくするためにリネーム済み):

root@kitploit:~
CWICHeifDecoderFrame::CopyPixels
 → CWICHeifBitmapSourceBase::CopyPixels_Transform
   → CWICHeifBitmapSourceBase::CopyPixels_Base
     → sub_7FFD8411FC40  // issues memmove
       → memmove         // AV (vmovdqu load from src)

c. バッファサイズ

  • 細工された HEIF により、CHEIFItemInfoEntry_GetDataSize が早期の「サイズ 0 で成功」パスを取ります(例: sub_7FFD8408B898 が失敗し、関数が sizeBuffer = 0 で成功を返す場合)。

  • ソースバッファ: MFCreateMemoryBuffer(0) 経由で割り当てられる ⇒ 1 バイト。

  • コピーサイズ: copy_size = stride * abs(roi_height) として導出されます。誤って解析された幅(例: 0x01000100)と一般的な BPP では、stride が非常に大きくなり、非常に大きな copy_size になります。

  • 脆弱な呼び出し:

root@kitploit:~
  __int64 sub_7FFD8411FC40(__m128i* dst, __int64 a2, __m128i* src, int a4,
                           unsigned int stride, unsigned int abs_roi_height)
  {
    if (src && dst) {
      if (stride == a2 && stride == a4) {
        // No validation that 'src' contains at least (stride * abs_roi_height) bytes
        memmove(dst, src, (size_t)abs_roi_height * stride); // AV here
      }
    }
  }
  • ソースが 1 バイトである理由(割り当てパス):
root@kitploit:~
  __int64 __fastcall CHEIFStreamReader_ReadItemData(__int64 *a1, __int64 *a2, IMFMediaBuffer **a3)
  {
    ppBuffer = 0i64;
    if ( v7(a2) )
    {
      *cbMaxLength = 0i64;
      result = (*(*a2 + 0xA0))(a2, cbMaxLength); // CHEIFItemInfoEntry_GetDataSize
      if ( result < 0 )
      {
        goto LABEL_10;
      }
      if ( *cbMaxLength > 0xC800000ui64 )
      {
        result = 0xC00D36BE;
        goto LABEL_23;
      }
      // cbMaxLength may still be 0 if GetDataSize returned success early
      result = MFCreateMemoryBuffer(cbMaxLength[0], &ppBuffer);
      if ( result < 0 )
      {
        goto LABEL_34;
      }
      ...
  }
root@kitploit:~
  __int64 __fastcall CHEIFItemInfoEntry_GetDataSize(__int64 a1, unsigned __int64 *sizeBuffer)
  {
  
    if ( sizeBuffer )
    {
      *sizeBuffer = 0i64;
      DataLocationInfo = (*(*v5 + 0x78i64))(v5, 0x6D657461i64, &v32);
      if ( DataLocationInfo >= 0 )
      {
        v13 = v32;
        v14 = *(v32 + 0xF0);
        if ( v14 )
        {
          if ( !sub_7FFD8408B898((v14 + 0xC8), (a1 - 0x78), &v33, v31) )
          {
          // returns success (0/S_OK) without updating sizeBuffer
  	      // caller treats this as length=0 → MFCreateMemoryBuffer(0)
  	          DataLocationInfo = 0;
  	          goto LABEL_62;
  	        }
          v17 = v33;
          DataLocationInfo = CHEIFItemInfoEntry_GetDataLocationInfo(v5, v13, *(v33 + 16), &v29, &v30);
          if ( DataLocationInfo >= 0 )
          {
            for ( i = 0; ; ++i )
            {
              if ( i >= *v17 )
              {
                *sizeBuffer = v6;
                goto LABEL_62;
              }
              v21 = *(*(v17 + 8) + 24i64 * i + 16);
              }
              if ( v21 + v6 < v6 )
                break;
              v6 += v21;
              DataLocationInfo = 0;
            }
  
           ...
           ...
  LABEL_62:
    sub_7FFD83F91AEC();
    return DataLocationInfo;
  }

d. 推奨される修正

CopyPixels パスで、ソースバッファに少なくとも stride * abs(roi_height) バイトがあること(および src_stride/src_height が要求された領域以上であること)を検証してください。満たさない場合は、WINCODEC_ERR_INSUFFICIENTBUFFER(または同等のエラー)で失敗させてください。

e. 解析方法(シンボル再構築)

呼び出しフローを確認可能にするため、コーデック自身のログ文字列から IDA 内の内部関数名を再構築しました。

  • 目標: 主要なルーチン(…CopyPixels_Base、…CopyPixels_Transform、CHEIFStreamReader::ReadItemData など)の人間が読める関数名を特定し、クラッシュスタックと逆コンパイルされたコードを対応付けます。

  • 手順:

    1. ロギングヘルパーを見つける: クラッシュ周辺の呼び出し元の逆コンパイラビューで、呼び出し時に

      定数文字列

      の引数(関数名に似たもの。例: "CWICHeifBitmapSourceBase::CopyPixels_Base")を受け取る小さなヘルパーを特定します。

      • IDA の場合: クラッシュが発生した関数を開き、1 フレーム上に移動して、関数エントリで文字列リテラルを受け取るヘルパーの呼び出しを確認します。
    2. 呼び出し元を収集する: そのヘルパーへの xrefs を使用して、すべての呼び出し元関数を一覧表示します。

    3. 名前を抽出する: 各呼び出し元について、逆コンパイルされたビューを開き、ヘルパーの第 2 引数(文字列リテラル)を読み取ります。この文字列には常に意図された関数名が含まれています。

    4. 呼び出し元をリネームする: 各呼び出し元で N キーを押し(Edit → Rename)、関数名を復元された文字列(例: CWICHeifBitmapSourceBase::CopyPixels_Base)に設定します。

    5. クラッシュチェーン全体に意味のある名前が付くまで、近くのフレームに対して繰り返します。

検証. リネーム後、呼び出しサイトを再確認し、引数の型/動作がラベルと一致することを確認します(例: …CopyPixels_Base は stride/ROI の計算と最終的な memmove 呼び出しが行われる場所です)。

  1. 概念実証

  • 前提条件: Microsoft Store の HEIF Image Extensions がインストール/有効化されていること(HEIC/HEIF デコードに必要)。

  • 再現手順

    1. 添付の PoC ファイル(../access_violation_0000xxxxxxxxx461_00000xxxxxxxx6B0_1.heif)をダウンロードしてローカルフォルダに保存します。

    2. HEIF Image Extensions がインストールされていることを確認します(Microsoft Store を開き、「HEIF Image Extensions」を検索 → インストール)。

    3. Microsoft Photos で PoC ファイルを開きます(Photos が既定のアプリの場合はファイルをダブルクリックするか、右クリック → プログラムから開く → Photos)。

  • ソフトウェアダウンロードリンク

    HEIF Image Extensions (Microsoft Store) https://apps.microsoft.com/detail/9pmmsr1cgpwg?hl=en-US&gl=US

ツールをダウンロード