
CVE-2024-30051の詳細な技術分析と概念実証エクスプロイト。Windows DWM Core Libraryにおけるヒープベースのバッファオーバーフローにより、整合性システムレベルへのローカル権限昇格が可能になります。
このブログ記事では、Core Impact のエクスプロイトが開発された際に私が分析した、Microsoft Windows DWM Core ライブラリの脆弱性について説明します。権限のない攻撃者が、Integrity System 特権を持つ DWM ユーザーとしてコードを実行できるようにするものです (CVE-2024-30051)。
エクスプロイトを開発する当時は十分な公開情報がなかったため、多くのリバースエンジニアリングを行う必要がありました。ここでは、IDA PRO を使用して Windows 23H2 向け KB5037771 パッチをリバースエンジニアリングする方法を示し、BINDIFF を使用して dwmcore.dll バージョン 10.0.22621.3447 とバージョン 10.0.22621.3593 の間のバイナリ差分を実行し、ヒープオーバーフローがどのように発生するかを示し、その後、特権を昇格させてエクスプロイトし、最終的に機能する PoC を作成します。
インデックス:
[Windows DWM Core Library 特権昇格の脆弱性 (CVE-2024-30051) 1](#windows-dwm-core-library-elevation-of-privilege-vulnerability-cve-2024-30051)
[脆弱性の詳細: 2](#vulnerability-details)
[差分解析によるバグの発見: 3](#diffing-to-find-the-bug)
[CVE-2024-30051 をエクスプロイトする PoC の分析: 8](#analysis-of-the-poc-exploiting-cve-2024-30051)
[1) 初期化 8](#initialization)
[2) フッキング 8](#hooking)
[3) ウィンドウの作成 16](#creating-the-window)
[4) デバイスの作成 16](#create-device)
[5) ファクトリの作成 22](#create-factory)
[6) デバイスコンテキストの作成 28](#create-a-device-context)
[7) コンポジションデバイスの作成 29](#create-a-composition-device)
[8) hook3 関数の呼び出し 31](#calling-dcompositioncreatedevice-function)
[9) HWND のターゲット作成 32](#creating-a-target-for-handle-hwnd)
[10) サーフェスの作成 33](#creating-surface)
[11) BeginDraw、EndDraw、CreateVisual の呼び出し。 34](#calling-begindraw-enddraw-and-createvisual)
[11) Visual SetContent の呼び出し 36](#calling-visual-setcontent)
[12) オブジェクトの解放 38](#release-objects)
[13) コンポジションデバイスのコミット 38](#commit-composition-device)
[14) hook2 の呼び出し 39](#calling-hook2)
[15) hook の呼び出し 39](#remember-that-the-vulnerable-function-can-be-reached-using-some-methods-of-the-cprimitivegroup-class.-at-this-point-it-creates-a-heap-then-hook2-captures-and-saves-the-corresponding-heaphandle.)
[16) hook4 の呼び出し 41](#calling-the-function-hook4)
[17) ヒープスプレーの実行 49](#performing-heap-spray)
[18) 送信前のベースチャンクの変更 51](#modifying-the-base-chunk-before-send)
[19) DWM プロセスのデバッグ 52](#debugging-the-dwm-process)
[20) Integrity System レベルへの特権昇格 62](#elevating-privileges-to-integrity-system-level)
Windows DWM Core Library 特権昇格の脆弱性 CVE-2024-30051
公開日: 2024年5月14日
CNA 割り当て: Microsoft CVE-2024-30051
影響: 特権昇格
最大重要度: 重要
弱点:
CWE-122: ヒープベース のバッファオーバーフロー
CVSS: 3.1 7.8 / 7.2
この脆弱性は、Windows のメイン DWM ライブラリ dwmcore.dll 内の整数除算におけるサイズ計算エラーが原因で存在します。ローカルユーザーが dwmcore.dll の CCommandBuffer::Initialize メソッドでヒープ上にバッファオーバーフローを引き起こし、Integrity System 特権を持つ DWM ユーザーとして任意のコードを実行できる可能性があります。エクスプロイトは、DWM プロセス内でヒープスプレーを実行してメモリを準備し、最終的に dwmcore.dll でヒープオーバーフローを発生させます。これは、ヒープスプレーの特定の部分を解放することによってトリガーされます。
エクスプロイトが成功すると、DWM プロセスは、Integrity System 特権を持つ DWM ユーザーとして、私たちのコードまたは実行可能ファイル (この場合は CMD) を実行するように作成された DLL をロードします。

この脆弱性を詳しく見て、Integrity Level SYSTEM の DWM ユーザーとして実行できるようにする方法を確認しましょう。これは管理者グループに属するユーザーではないため、いくつかの特権制限があることに注意してください。
Windows 11 23H2 のパッチは以下からダウンロードできます:
https://www.catalog.update.microsoft.com/Search.aspx?q=KB5037771
windows11.0-kb5037771-x64_19a3f100fb8437d059d7ee2b879fe8e48a1bae42.msu
脆弱なバージョンの dwmcore.dll: 10.0.22621.3447
パッチ適用後のバージョンの dwmcore.dll: 10.0.22621.3593
変更された関数を分析すると、パッチ適用後のバージョンの CCommandBuffer::Initialize には多くのブロックが追加されており、パッチ未適用のバージョンとはまったく異なって見えることが明らかです。

その関数を静的にリバースした後、CD2DSharedBuffer::GetBufferSize への2つの呼び出しがあります。
最初の呼び出しは new で割り当てる サイズ を取得し、2番目の呼び出しは memcpy 用に同じサイズを取得します。

一見するとすべて正しいように見えます。しかし、割り当ての前に、サイズに対していくつかの操作を行います。

同じ CD2DSharedBuffer::GetBufferSize 関数を呼び出して buffer_size と buffer_size2 を取得し、両方とも同じ値を返します。しかし、new では、buffer_size を 0x90 で整数除算し、その後 0x90 を乗算する事前操作を実行しますが、memcpy では返された buffer_size2 をそのまま使用し、操作は行いません。
これらの操作により、最終的に new で使用されるサイズと memcpy で使用されるサイズが異なる可能性があることがわかりました。
buffer_size = buffer_size2 (返されるサイズ)
size_new = buffer_size / 0x90 * 0x90
size_memcpy = buffer_size2
たとえば、buffer_size が 0x91 の場合:
buffer_size = buffer_size2 = 0x91
size_new = buffer_size / 0x90 * 0x90 = 0x90
size_memcpy = buffer_size2 = 0x91
この例は、ヒープオーバーフロー があることを証明しています。割り当てられたよりも多くのバイトがコピーされており、サイズは制御可能です。
たとえば、POC で使用されているように buffer_size が 0x23f の場合:
buffer_size = buffer_size2 = 0x23F
size_new = buffer_size / 0x90 * 0x90 = 0x1b0
size_memcpy = buffer_size2 = 0x23f
脆弱な関数を分析した後、脆弱な関数 CCommandBuffer::Initialize に到達する方法を確認したいと思いました。ここからが複雑になり始めます。
この関数への参照を振り返ると、CPrimitiveGroup クラスのメソッドから到達しているようです:

そのようなメソッドは、CPrimitiveGroup オブジェクトの vftable からアクセスできます:

コンストラクタがあります:

そして、次のように到達します:

最初にこのプロセスを進めるにあたり、 PDF 「The Lost World of DirectComposition: Hunting Windows Desktop Window Manager Bugs」を読み、Direct Composition の世界に飛び込みました。これにより、最初の PoC を作成することができました。
また、win32ksys をリバースし、以下の関数を介してパッケージを送信しようとしました:
NtDCompositionCreateChannel
NtDCompositionProcessChannelBatchBuffer
NtDCompositionCommitChannel

最初の PoC は CPrimitiveGroup コンストラクタに到達しました。しかし、多くのリバースエンジニアリングを行った結果、これらの関数を使用して ALPC 呼び出しを介して脆弱な関数に直接到達するために、vftable メソッドへの呼び出しを処理する方法を見つけることができませんでした。
複雑なリバースエンジニアリングに多くの時間を費やしました。その過程で、この脆弱性をエクスプロイトしたマルウェアのサンプルを発見しました。これは、エクスプロイト方法が当初考えていたよりもはるかに複雑であるため、非常に役立ちました。また、システム API へのいくつかのフッキングを含み、おそらく少し疑わしいメソッドを使用しています。しかし、戦争とエクスプロイトでは何でもありなので、マルウェアを分析し始め、その分析から最終的に脆弱性をエクスプロイトする最終的な PoC を作成しました。これについては以下で説明します。