Windows での画像解析のファジング、パート 2: 初期化されていないメモリ

CVE-2020-0853 news

Windows の画像解析の脆弱性に関する議論を続けると、比較的人気の低い脆弱性クラスである初期化されていないメモリに注目します。この投稿では、Windows に組み込まれているイメージ パーサー、特に初期化されていないメモリの使用に関連する脆弱性について説明します。

脆弱性: 初期化されていないメモリ

C や C++ などのアンマネージ言語では、変数は既定では初期化されません。初期化されていない変数を使用すると、未定義の動作が発生し、クラッシュする可能性があります。初期化されていないメモリには、大まかに次の 2 つのバリアントがあります。

  • 初期化されていないメモリの直接使用: 初期化されていないポインタまたはインデックスが読み取りまたは書き込みで使用されています。これにより、クラッシュが発生する可能性があります。
  • 初期化されていないメモリの使用による情報漏えい (情報漏えい): 初期化されていないメモリの内容は、セキュリティ境界を越えてアクセスできます。例: 初期化されていないカーネル バッファがユーザー モードからアクセスできるため、情報漏えいにつながります。

この投稿では、攻撃者が JavaScript を使用してデコードされた画像を読み取ることができる Web ブラウザーなどの状況で、情報漏えいにつながる Windows 画像パーサーの 2 番目の亜種を詳しく見ていきます。

初期化されていないメモリの脆弱性の検出

ヒープ オーバーフローや解放後の使用などのメモリ破損の脆弱性と比較して、初期化されていないメモリの脆弱性自体は、範囲外または範囲外のメモリにアクセスしません。これにより、これらの脆弱性の検出は、メモリ破損の脆弱性よりも若干複雑になります。初期化されていないメモリを直接使用するとクラッシュが発生する可能性があり、それを検出することはできますが、通常、情報漏えいによってクラッシュが発生することはありません。それを検出するには、MemorySanitizer などのコンパイラ インストルメンテーションまたは Valgrind などのバイナリ インストルメンテーション/再コンパイル ツールが必要です。

回り道: Linux で初期化されていないメモリを検出する

少し寄り道して、Linux での初期化されていないメモリの検出を見て、Windows の組み込み機能と比較してみましょう。コンパイラは一部の初期化されていない変数について警告しますが、初期化されていないメモリ使用量の複雑なケースのほとんどは、コンパイル時に検出されません。このために、ランタイム検出メカニズムを使用できます。 MemorySanitizer は、初期化されていないメモリ読み取りを検出する、GCC と Clang の両方のコンパイラ インストルメンテーションです。それがどのように機能するかのサンプルを図 1 に示します。

$猫サンプル.cc
#include <stdio.h>

int main()
{
int *arr = 新しい int[10];
場合 (arr[3] == 0)
{
printf(“やった!n”);
}
printf(“%08xn”, arr[3]);
0 を返します。
}

$ clang++ -fsanitize=memory -fno-omit-frame-pointer -g sample.cc

$ ./a.out
==29745==警告: MemorySanitizer: 初期化されていない値の使用
#0 0x496db8 (/home/dan/uni/a.out+0x496db8)
#1 0x7f463c5f1bf6 (/lib/x86_64-linux-gnu/libc.so.6+0x21bf6)
#2 0x41ad69 (/home/dan/uni/a.out+0x41ad69)

概要: MemorySanitizer: 初期化されていない値の使用 (/home/dan/uni/a.out+0x496db8)
終了

図 1: 初期化されていないメモリの MemorySanitizer 検出

同様に、Valgrind を使用して、実行時に初期化されていないメモリを検出することもできます。

Windows で初期化されていないメモリを検出する

Linux と比較して、Windows には初期化されていないメモリ使用量を検出する組み込みメカニズムがありません。 Visual Studio と Clang-cl は最近AddressSanitizer サポートを導入しましたが、MemorySanitizer とその他のサニタイザーは、この記事の執筆時点では実装されていません。

PageHeapなど、メモリ破損の脆弱性を検出するための Windows の便利なツールの一部は、初期化されていないメモリの検出には役立ちません。反対に、PageHeap はメモリ割り当てをパターンで満たすため、基本的に初期化されます。

Dr.Memory など、バイナリ インストルメンテーションを使用してヒープ オーバーフロー、初期化されていないメモリ使用量、解放後の使用などのメモリの安全性の問題を検出するサードパーティ ツールはほとんどありません。

画像デコードにおける初期化されていないメモリの検出

Windows で初期化されていないメモリを検出するには、通常、特にソース コードにアクセスできない場合、バイナリ インストルメンテーションが必要です。初期化されていないメモリ使用量を検出するために使用できる指標の 1 つは、特に画像のデコードの場合、画像がデコードされた後の結果のピクセルです。

画像がデコードされると、生のピクセルのセットが生成されます。画像のデコードで初期化されていないメモリが使用されると、一部またはすべてのピクセルがランダムになる可能性があります。簡単に言えば、初期化されていないメモリが使用されている場合、画像を複数回デコードすると、毎回異なる出力になる可能性があります。この出力の違いを使用して、初期化されていないメモリを検出し、Windows イメージ デコーダーをターゲットとするファジング ハーネスの作成を支援できます。ファジング ハーネスの例を図 2 に示します。

#ROUNDS 20 の定義

unsigned char* DecodeImage(char *imagePath)
{
unsigned char *pixels = NULL;

// GDI または WIC を使用して画像をデコードし、結果のピクセルを取得します

ピクセルを返します。
}

void Fuzz(char *imagePath)
{
unsigned char *refPixels = DecodeImage(imagePath);

if(refPixels != NULL)
{
for(int i = 0; i < ROUNDS; i++)
{
unsigned char *currPixels = DecodeImage(imagePath);
if(!ComparePixels(refPixels, currPixels))
{
// 参照ピクセルと現在のピクセルが一致しません
// 今すぐクラッシュして、ファザーにこのファイルを知らせます
クラッシュプログラム();
}
無料 (currPixels);
}
無料 (refPixels);
}
}

図 2: デフ ハーネス

このファジング ハーネスの背後にあるアイデアは、まったく新しいものではありません。以前は、 lcamtufが同様のアイデアを使用して、オープンソースの画像パーサーで初期化されていないメモリを検出し、Web ページを使用してピクセルの違いを表示していました。

ファジング

差分ハーネスの準備ができたら、サポートされている画像形式を探して、コーパスを収集することができます。コーパス用の画像ファイルを収集することは、インターネット上でほぼ無制限に利用できることを考えるとかなり簡単ですが、同時に、独自のコード カバレッジを持つ何百万ものファイルの中から適切なコーパスを見つけることは困難です。 Windows イメージ解析のコード カバレッジ情報は、WindowsCodecs.dll から追跡されます。

通常の Windows ファジングとは異なり、PageHeap はパターンを使用してヒープ割り当てを「初期化」するため、今回は PageHeap を有効にしないことに注意してください。

結果

調査中に、Windows の組み込みイメージ パーサーをファジングしているときに、メモリ使用量が初期化されていないケースが 3 つ見つかりました。そのうちの 2 つについては、次のセクションで詳しく説明します。初期化されていないメモリ使用量の根本原因の分析は簡単ではありません。バック トレースするクラッシュの場所がなく、結果のピクセル バッファーをバック トレースに使用して根本原因を見つけるか、巧妙なトリックを使用して偏差を見つける必要があります。

CVE-2020-0853

この脆弱性の根本原因に入る前に、概念実証 (PoC) ファイルのレンダリングを見てみましょう。このために、PoC 画像を複数回読み込み、ピクセルを参照ピクセルと比較する lcamtuf の HTML を使用します。

CVE-2020-0853
図 3: CVE-2020-0853

結果の画像 (図 3) からわかるように、出力はデコードごとに大幅に変化し、この PoC が初期化されていないメモリを大量にリークしていると推測できます。

これらの脆弱性の根本原因を特定するために、Time Travel Debugging (TTD) を広範囲に使用しました。実行をさかのぼってメモリ アドレスを追跡するのは面倒な作業ですが、TTD を使用すると、アドレスと値を一定に保ち、無制限に順方向および逆方向の実行を提供することで、わずかに負担が軽減されます。

トレースのデバッグにかなりの時間を費やした後、 windowscodecs!CFormatConverter::Initializeに初期化されていないメモリのソースが見つかりました。ソースが見つかったとしても、このメモリがまったく上書きされずにピクセルの計算で終了する理由は最初は明らかではありませんでした。この謎を解決するために、PoC 実行トレースを通常の TIFF ファイルのデコードと比較することで、追加のデバッグが行われました。次のセクションでは、ピクセル計算への初期化されていない値の割り当て、コピー、および脆弱性の実際の根本原因を示します。

初期化されていないメモリの割り当てと使用

windowscodecs!CFormatConverter::Initializeは、0x40 バイトのメモリを割り当てます (図 4 参照)。

0:000>r
rax=0000000000000000 rbx=0000000000000040 rcx=0000000000000040
rdx=0000000000000008 rsi=000002257a3db448 rdi=0000000000000000
rip=00007ffaf047a238 rsp=000000ad23f6f7c0 rbp=000000ad23f6f841
r8=000000ad23f6f890 r9=0000000000000010 r10=000002257a3db468
r11=000000ad23f6f940 r12=000000000000000e r13=000002257a3db040
r14=000002257a3dbf60 r15=0000000000000000
iopl=0 nv up ei pl zr na po nc
cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
windowscodecs!CFormatConverter::Initialize+0x1c8:
00007ffa`f047a238 ff15ea081200 call qword ptr [windowscodecs!_imp_malloc (00007ffa`f059ab28)] ds:00007ffa`f059ab28={msvcrt!malloc (00007ffa`f70e9d30)}
0:000>k
# Child-SP RetAddr 呼び出しサイト
00 000000ad`23f6f7c0 00007ffa`f047c5fb windowscodecs!CFormatConverter::Initialize+0x1c8
01 000000ad`23f6f890 00007ffa`f047c2f3 windowscodecs!CFormatConverter::Initialize+0x12b
02 000000ad`23f6f980 00007ff6`34ca6dff windowscodecs!CFormatConverterResolver::Initialize+0x273

//割り当て後に初期化されていないメモリ:
0:000> デシベル @rax
00000225`7a3dbf70 d0 b0 3d 7a 25 02 00 00-60 24 3d 7a 25 02 00 00 ..=z%…`$=z%…
00000225`7a3dbf80 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ……
00000225`7a3dbf90 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ……
00000225`7a3dbfa0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ……
00000225`7a3dbfb0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ……
00000225`7a3dbfc0 00 00 00 00 00 00 00 00-64 51 7c 26 c3 2c 01 03 ……..dQ|&.,..
00000225`7a3dbfd0 f0 00 2f 6b 25 02 00 00-f0 00 2f 6b 25 02 00 00 ../k%…../k%…
00000225`7a3dbfe0 60 00 3d 7a 25 02 00 00-60 00 3d 7a 25 02 00 00 `.=z%…`.=z%…

図 4: メモリの割り当て

メモリは決して書き込まれず、初期化されていない値はwindowscodecs!CLibTiffDecoderBase::HrProcessCopyで反転され、windowscodecs! GammaConvert_16bppGrayInt_128bppRGBAでさらに処理され、後でスケーリング関数と呼ばれます。

HrProcessCopy の前に初期化されていないメモリへの読み取りまたは書き込みがないため、HrProcessCopy から実行をトレースし、実行トレースを通常の tiff デコード トレースと比較しました。通常の TIFF ファイルと比較して、 windowscodecs!CLibTiffDecoderBase::UnpackLineが PoC ファイルで動作する方法に違いが見つかりました。UnpackLineの関数パラメーターの 1 つは、初期化されていないバッファーへのポインターでした。

UnpackLine関数には、TIFF イメージのサンプルあたりのビット数 (BPS) を操作する一連の switch-case ステートメントがあります。この PoC TIFF ファイルでは、BPS 値は 0x09 ( UnpackLineではサポートされていません) であり、制御フローはバッファーに書き込むコード パスに到達しません。これが初期化されていないメモリの根本的な原因であり、パイプラインのさらに下で処理され、最終的にピクセル データとして表示されます。

パッチ

私の分析を Microsoft に提示した後、Microsoft は、サポートされていない BPS 値を含むファイルを無効にすることで、脆弱性にパッチを当てることにしました。これにより、すべてのデコードが回避され、読み込みの非常に早い段階でファイルが拒否されます。

CVE-2020-1397

CVE-2020-1397 のレンダリング
図 5: CVE-2020-1397 のレンダリング

前の脆弱性とは異なり、図 5 に示すように、この脆弱性では出力の違いはかなり限定的です。特定のタイプの初期化されていないメモリ使用量を把握するために使用できる、より単純な根本原因分析手法の 1 つは、実行トレースを比較することです。 2 つの異なる出力を生成する実行。この特定の手法は、初期化されていない変数によってプログラム内の制御フローが変更され、出力に違いが生じる場合に役立ちます。このために、バイナリ インストルメンテーション スクリプトが作成されました。このスクリプトは、実行されたすべての命令をレジスタと共に記録し、メモリ値にアクセスしました。

命令ポインター (RIP) の値を比較して 2 つの異なる実行トレースを比較したところ、初期化されていない値の使用により、 windowscodecs!CCCITT::Expand2DLineで制御フローが変更されていることがわかりました。 TTD トレースを使用して初期化されていない値を逆トレースすることは、根本原因を見つけるのに非常に役立ちました。次のセクションでは、制御フローの変更とピクセル出力の逸脱につながる、初期化されていない値の割り当て、設定、および使用について説明します。

割り当て

windowscodecs!TIFFReadBufferSetupは、図 6 に示すように、0x400 バイトのメモリを割り当てます。

windowscodecs!TIFFReadBufferSetup:

allocBuff = malloc(サイズ);
*(v3 + 16) |= 0x200u;
*(v3 + 480) = allocBuff;

0:000>k
# Child-SP RetAddr 呼び出しサイト
00 000000aa`a654f128 00007ff9`4404d4f3 windowscodecs!TIFFReadBufferSetup
01 000000aa`a654f130 00007ff9`4404d3c9 windowscodecs!TIFFFillStrip+0xab
02 000000aa`a654f170 00007ff9`4404d2dc windowscodecs!TIFFReadEncodedStrip+0x91
03 000000aa`a654f1b0 00007ff9`440396dd windowscodecs!CLibTiffDecoderBase::ReadStrip+0x74
04 000000aa`a654f1e0 00007ff9`44115fca windowscodecs!CLibTiffDecoderBase::GetOneUnpackedLine+0x1ad
05 000000aa`a654f2b0 00007ff9`44077400 windowscodecs!CLibTiffDecoderBase::HrProcessCopy+0x4a
06 000000aa`a654f2f0 00007ff9`44048dbb windowscodecs!CLibTiffDecoderBase::HrReadScanline+0x20
07 000000aa`a654f320 00007ff9`44048b40 windowscodecs!CDecoderBase::CopyPixels+0x23b
08 000000aa`a654f3d0 00007ff9`44043c95 windowscodecs!CLibTiffDecoderBase::CopyPixels+0x80
09 000000aa`a654f4d0 00007ff9`4404563b windowscodecs!CDecoderFrame::CopyPixels+0xb5

 

割り当て後:
0:000> !ヒープ -p -a @rax
アドレス 0000029744382140 で見つかりました
_ヒープ @ 29735190000
HEAP_ENTRY サイズ 前のフラグ UserPtr UserSize – 状態
0000029744382130 0041 0000 [00] 0000029744382140 00400 – (ビジー)
不明!

//割り当て後に初期化されていないメモリ
0:000> デシベル @rax
00000297`44382140 40 7c 5e 97 29 5d 5f ae-73 31 98 70 b8 4f da ac @|^.)]_.s1.pO.
00000297`44382150 06 51 54 18 2e 2a 23 3a-4f ab 14 27 e9 c6 2c 83 .QT..*#:O..’..,.
00000297`44382160 3a 25 b2 f6 9d e7 3c 09-cc a5 8e 27 b0 73 41 a9 : %….<….sA.
00000297`44382170 fb 9b 02 b5 81 3e ea 45-4c 0f ab a7 72 e3 21 e7 …..>.EL…r.!.
00000297`44382180 c8 44 84 3b c3 b5 44 8a-c9 6e 4b 2e 40 31 38 e0 .D.;..D..nK.@18.
00000297`44382190 85 f0 bd 98 3b 0b ca b8-78 b1 9d d0 dd 4d 61 66 ….;…x….Maf
00000297`443821a0 16 7d 0a e2 40 fa f8 45-4f 79 ab 95 d8 54 f9 44 .}..@..EOy…TD
00000297`443821b0 66 26 28 00 b7 96 52 88-15 f0 ed 34 94 5f 6f 94 f&(…R….4._o.

図 6: メモリの割り当て

バッファの部分的な移入

TIFFReadRawStrip1 によって、入力ファイルからこの割り当てられたバッファに 0x10 バイトがコピーされます。図 7 に示すように、バッファーの残りの部分は、ランダムな値で初期化されていないままになります。

if ( !TIFFReadBufferSetup(v2, a2, stripCount) ) {
0i64 を返します。
}
if ( TIFFReadRawStrip1(v2, v3, sizeToReadFromFile, “TIFFFillStrip”) != sizeToReadFromFile )

 

0:000>r
rax=0000000000000001 rbx=000002973519a7e0 rcx=000002973519a7e0
rdx=0000000000000000 rsi=0000000000000000 rdi=0000000000000010
rip=00007ff94404d58c rsp=000000aaa654f128 rbp=0000000000000000
r8=0000000000000010 r9=00007ff94416fc38 r10=0000000000000000
r11=000000aaa654ef60 r12=0000000000000001 r13=0000000000000000
r14=0000029744377de0 r15=0000000000000001
iopl=0 nv up ei pl nz na pe nc
cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000202
windowscodecs!TIFFReadRawStrip1:
00007ff9`4404d58c 488bc4 mov rax,rsp
0:000>k
# Child-SP RetAddr 呼び出しサイト
00 000000aa`a654f128 00007ff9`4404d491 windowscodecs!TIFFReadRawStrip1
01 000000aa`a654f130 00007ff9`4404d3c9 windowscodecs!TIFFFillStrip+0x49
02 000000aa`a654f170 00007ff9`4404d2dc windowscodecs!TIFFReadEncodedStrip+0x91
03 000000aa`a654f1b0 00007ff9`440396dd windowscodecs!CLibTiffDecoderBase::ReadStrip+0x74
04 000000aa`a654f1e0 00007ff9`44115fca windowscodecs!CLibTiffDecoderBase::GetOneUnpackedLine+0x1ad
05 000000aa`a654f2b0 00007ff9`44077400 windowscodecs!CLibTiffDecoderBase::HrProcessCopy+0x4a
06 000000aa`a654f2f0 00007ff9`44048dbb windowscodecs!CLibTiffDecoderBase::HrReadScanline+0x20
07 000000aa`a654f320 00007ff9`44048b40 windowscodecs!CDecoderBase::CopyPixels+0x23b
08 000000aa`a654f3d0 00007ff9`44043c95 windowscodecs!CLibTiffDecoderBase::CopyPixels+0x80
09 000000aa`a654f4d0 00007ff9`4404563b windowscodecs!CDecoderFrame::CopyPixels+0xb5

0:000> デシベル 00000297`44382140
00000297`44382140 5b cd 82 55 2a 94 e2 6f-d7 2d a5 93 58 23 00 6c [..U*..o.-..X#.l //ファイルから 0x10 バイト
00000297`44382150 06 51 54 18 2e 2a 23 3a-4f ab 14 27 e9 c6 2c 83 .QT..*#:O..’..,. // 初期化されていないメモリ
00000297`44382160 3a 25 b2 f6 9d e7 3c 09-cc a5 8e 27 b0 73 41 a9 : %….<….sA.
00000297`44382170 fb 9b 02 b5 81 3e ea 45-4c 0f ab a7 72 e3 21 e7 …..>.EL…r.!.
00000297`44382180 c8 44 84 3b c3 b5 44 8a-c9 6e 4b 2e 40 31 38 e0 .D.;..D..nK.@18.
00000297`44382190 85 f0 bd 98 3b 0b ca b8-78 b1 9d d0 dd 4d 61 66 ….;…x….Maf
00000297`443821a0 16 7d 0a e2 40 fa f8 45-4f 79 ab 95 d8 54 f9 44 .}..@..EOy…TD
00000297`443821b0 66 26 28 00 b7 96 52 88-15 f0 ed 34 94 5f 6f 94 f&(…R….4._o.

図 7: メモリの部分的な実装

初期化されていないメモリの使用

0:000>r
rax=0000000000000006 rbx=0000000000000007 rcx=0000000000000200
rdx=0000000000011803 rsi=0000029744382150 rdi=0000000000000000
rip=00007ff94414e837 rsp=000000aaa654f050 rbp=0000000000000001
r8=0000029744382550 r9=0000000000000000 r10=0000000000000008
r11=0000000000000013 r12=00007ff94418b7b0 r13=0000000000000003
r14=0000000023006c00 r15=00007ff94418bbb0
iopl=0 nv up ei pl nz na po nc
cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000206
windowscodecs!CCCITT::Expand2DLine+0x253:
00007ff9`4414e837 0fb606 movzx eax,byte ptr [rsi] ds:00000297`44382150=06 ;アクセス中の初期化されていないメモリ

 

0:000> デシベル 00000297`44382140
00000297`44382140 5b cd 82 55 2a 94 e2 6f-d7 2d a5 93 58 23 00 6c [..U*..o.-..X#.l //ファイルから 0x10 バイト
00000297`44382150 06 51 54 18 2e 2a 23 3a-4f ab 14 27 e9 c6 2c 83 .QT..*#:O..’..,. // 初期化されていないメモリ
00000297`44382160 3a 25 b2 f6 9d e7 3c 09-cc a5 8e 27 b0 73 41 a9 : %….<….sA.
00000297`44382170 fb 9b 02 b5 81 3e ea 45-4c 0f ab a7 72 e3 21 e7 …..>.EL…r.!.
00000297`44382180 c8 44 84 3b c3 b5 44 8a-c9 6e 4b 2e 40 31 38 e0 .D.;..D..nK.@18.
00000297`44382190 85 f0 bd 98 3b 0b ca b8-78 b1 9d d0 dd 4d 61 66 ….;…x….Maf
00000297`443821a0 16 7d 0a e2 40 fa f8 45-4f 79 ab 95 d8 54 f9 44 .}..@..EOy…TD
00000297`443821b0 66 26 28 00 b7 96 52 88-15 f0 ed 34 94 5f 6f 94 f&(…R….4._o.

 

0:000>k
# Child-SP RetAddr 呼び出しサイト
00 000000aa`a654f050 00007ff9`4414df80 windowscodecs!CCCITT::Expand2DLine+0x253
01 000000aa`a654f0d0 00007ff9`4412afcc windowscodecs!CCCITT::CCITT_Expand+0xac
02 000000aa`a654f120 00007ff9`4404d3f0 windowscodecs!CCITTDecode+0x7c
03 000000aa`a654f170 00007ff9`4404d2dc windowscodecs!TIFFReadEncodedStrip+0xb8
04 000000aa`a654f1b0 00007ff9`440396dd windowscodecs!CLibTiffDecoderBase::ReadStrip+0x74
05 000000aa`a654f1e0 00007ff9`44115fca windowscodecs!CLibTiffDecoderBase::GetOneUnpackedLine+0x1ad
06 000000aa`a654f2b0 00007ff9`44077400 windowscodecs!CLibTiffDecoderBase::HrProcessCopy+0x4a
07 000000aa`a654f2f0 00007ff9`44048dbb windowscodecs!CLibTiffDecoderBase::HrReadScanline+0x20
08 000000aa`a654f320 00007ff9`44048b40 windowscodecs!CDecoderBase::CopyPixels+0x23b
09 000000aa`a654f3d0 00007ff9`44043c95 windowscodecs!CLibTiffDecoderBase::CopyPixels+0x80
0a 000000aa`a654f4d0 00007ff9`4404563b windowscodecs!CDecoderFrame::CopyPixels+0xb5

図 8: 初期化されていない値の読み取り

初期化されていない値 (図 8) に応じて、Expand2DLine で異なるコード パスが使用され、図 9 に示すように、出力ピクセルが変更されます。

{
{
もし ( v11 != 1 || a2 )
{
unintValue = *++allocBuffer | (unintValue << 8); // uninit mem read
}
そうしないと
{
unintValue <<= 8;
++allocBuffer;
}
–v11;
v16 += 8;
}
v29 = unintValue >> (v16 – 8);
dependentUninitValue = *(l + 2i64 * v29);
v16 -= *(l + 2i64 * v29 + 1);
if (dependentUninitValue >= 0 ) // パス 1
壊す;
if (dependentUninitValue < ‘xC0’ )
0xFFFFFFFi64 を返します。 // パス 2
}
if (dependentUninitValue <= 0x3F ) // パス xx
壊す;

図 9: if条件での初期化されていないメモリの使用

パッチ

Microsoft は、割り当てられたメモリをゼロで初期化するmallocの代わりにcallocを使用して、この脆弱性にパッチを適用することを決定しました。

結論

このブログ シリーズのパート 2 では、Windows の組み込みイメージ パーサーに複数の脆弱性が存在します。次の投稿では、RAW、HEIF など、Windows でサポートされている新しい画像形式について説明します。

参照: https://www.mandiant.com/resources/blog/fuzzing-image-parsing-in-windows-uninitialized-memory

Comments

Copied title and URL