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

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

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

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

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
CVE-2022-37969 — CVE-2022-37969 の概念実証エクスプロイト。Windows Common Log File System ドライバーのローカル権限昇格の脆弱性です。ヒープスプレー、トークンスティーリング、任意カーネル書き込みを実証し、SYSTEM 権限を獲得します。 | Kitploit
ツール/GitHubGitHub/fortra/cve-2022-37969
特権昇格メモリフォレンジック脆弱性分析エクスプロイトバイナリエクスプロイト
GitHubfortra/cve-2022-37969

CVE-2022-37969

CVE-2022-37969 の概念実証エクスプロイト。Windows Common Log File System ドライバーのローカル権限昇格の脆弱性です。ヒープスプレー、トークンスティーリング、任意カーネル書き込みを実証し、SYSTEM 権限を獲得します。

リポジトリを見る
1353813年前Kitploit レビュー済み

人気

すべて見る →

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

すべてのツールを探索

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

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

CVE-2022-37969 Windows ローカル特権昇格 PoC

著者: Ricardo Narvaja & Daniel Kazimirow (Solid)

デモンストレーション目的のみ。完全なエクスプロイトは脆弱な Windows 11 21H2 システムで動作します。

以前にZscaler が公開した情報に基づく機能的な PoC

解説記事はこちら: CVE-2022-37969 Windows Common Log File System ドライバのローカル特権昇格を理解する

使用方法

CVE-2022-37969 Windows Common Log File System ドライバのローカル特権昇格を理解する

エクスプロイトのウォークスルー:

  • 初期 BLF ログファイルの作成
    • 複数のランダムな BLF ログファイルの作成
    • 初期ログファイルの細工
    • 制御されたヒープスプレーの実行
    • CreatePipe() / NtFsControlFile() の準備
    • メモリを準備したら脆弱性をトリガー
    • システムトークンの読み取り
    • トークンの検証
    • 自プロセスのトークンをシステムトークンで上書き
    • システムとしてプロセスを実行
    • パッチのリバース: 構造体の解析
    • "pContainer" ポインタの破壊
    • パッチの再検討
    • SignatureOffset の破壊
    • さらなる値の破壊
    • SYSTEM トークンを読み取る関数の制御
    • 自プロセスに書き込んでローカル特権昇格を達成
    • PoC ソースコード

使用したシナリオは Windows 11 21H2 (OS ビルド 22000.918) clfs.sys v10.0.22000.918

初期 BLF ログファイルの作成

最初のステップは、CreateLogFile() 関数を使用して、パブリックフォルダ (%public%) に MyLog.blf というファイルを作成することです:

複数のランダムな BLF ログファイルの作成

次に、ループを使用してランダムな名前のログファイルを複数作成します。

そしてループ内で、getBigPoolInfo() 関数を呼び出します:

NtQuerySystemInformation() を、最初の引数 0x42 (10 進数 66) で呼び出すと、v5 に bigpool で行われたレイドに関する情報が返ります。その構造体は SYSTEM_BIGPOOL_INFORMATION 型です。

この関数は 2 回呼び出す必要があります。1 回目はエラーが返りますが、正しいバッファサイズが得られるため、2 回目で目的の情報を取得できます。

Interfaz de usuario gráfica, Aplicación Descripción generada automáticamente

v5 は SYSTEM_BIG_POOL_INFORMATION 構造体の情報を受け取ります。

bigpool の割り当て数は、最初のフィールド Count に格納され、2 番目のフィールドには SYSTEM_BIGPOOL_ENTRY 構造体の配列があります。

次に、すべての構造体を検索して "Clfs" タグとサイズ 0x7a00 のものを探します。

CLFS タグかつサイズ 0x7a00 の各構造体の最初のフィールドである VirtualAddress を、kernelAddrArray という配列に格納します。以降、両方の条件を満たすプールを「適切なプール」と呼びます。

各適切なプールを配列に格納するだけでなく、最後に見つかった適切なプールを、関数の引数として使用される a2 変数の内容に格納します。

Interfaz de usuario gráfica, Texto, Aplicación Descripción generada automáticamente

このようにして、a2 は常に最後に作成された CLFS タグかつサイズ 0x7a00 の適切なプールを指します。

変数 v26 は、常に前に見つかった適切なプールを格納します。getBigPoolinfo() を呼び出す前に v26=v24 と等しく設定されますが、この呼び出しを抜けるときに v24 が最後に見つかった適切なプールで更新され、v26 は前に見つかった適切なプールのままになります。

Interfaz de usuario gráfica, Texto, Aplicación Descripción generada automáticamente

次に、両方のアドレスを減算し、結果が負の場合はオペランドを反転して常に正になるようにします。

Interfaz de usuario gráfica, Texto, Aplicación Descripción generada automáticamente

このようにして、v32 には最後の 2 つの適切なプールの VirtualAddress の差が格納されます。

次に同様の処理を行います。この場合、v23 は最初は 0 なので、最初のループで v23 = v32 となります。

次のループでは v23 は同じ値のまま 0 ではないため、ループを抜けてここに来ます。

v32 は最新の差、v23 は前回の差を持っています。それらが等しい場合はループを抜けてカウンタを 1 増やしますが、等しくない場合はカウンタを 0 にリセットします。

目的は、CLFS タグかつサイズ 0x7a00 の 6 つの連続した比較を行い、それらの差が等しいこと、そしてその差が 0x11000 であることを確認することです。実行時に、6 つの連続した等間隔の適切なプールが見つかると、その間隔の値が得られることがわかります。

Texto Descripción generada automáticamente

ここで、6 つの連続した適切なプールが見つかり、ログファイルを作成するループを抜けています。

"public" フォルダに作成されたファイルが確認できます。

初期ログファイルの細工:

craftFile() 関数は、元のファイル (MyLog.blf) を開いて変更し、バグをトリガーします。

ファイルを変更した後、CRC32 を変更する必要があります。そうしないとファイル破損エラーが発生します。

この値はファイルのオフセット 0x80C にあります。

制御されたヒープスプレーの実行

次に、VirtualAlloc() 関数を使用してヒープスプレーを実行し、任意のアドレス 0x10000 と 0x5000000 にそれぞれメモリを割り当て、2 番目の割り当て (0x10000) に 0x10 バイトごとに値 0x5000000 を保存します。

CreatePipe() / NtFsControlFile() の準備

CreatePipe() を使用して匿名パイプを作成し、NtFsControlFile() を引数 0x11003c で呼び出して属性を追加します。後で同じ関数を引数 0x110038 で呼び出して読み取ることができます。

この方法の詳細は こちら にあります。

そこには、追加している属性である入力バッファがあります。NtFsControlFile() を引数 0x11038 で再度呼び出すと、出力に同じ属性が返されるはずです。

作成された属性のタグ (NpAt) についてプールを検索します。

見つかったら、そのプールの VirtualAddress を v30.Pointer に保存します。

V30.pointer+24 はカーネルプール内の AttributeValueSize を指しており、それを以前に行ったヒープスプレーの 1 つに保存します。

目的は、そのカーネルアドレス+8 に書き込み、AttributeValue を上書きすることです。

Texto Descripción generada automáticamente

PipeAttribute 構造体は、最初のフィールドとして 16 バイトのサイズの LIST_ENTRY を持ち、次に属性の名前へのポインタ(8 バイト)、そしてオフセット 0x18 (24 進数) に AttributeValueSize フィールドがあります。これがヒープスプレーに保存しているものです。

その後、CLFS.sys と ntoskrnl をユーザーモードでロードし、GetProcAddress() を使用して ClfsEarlierLsn() と SeSetAccessStateGenericMapping() 関数のアドレスを見つけます。

次に、FindKernelModulesBase() 関数を呼び出して、NtquerySystemInformation() を使用し、今回は SystemModuleInformation 引数ですべてのモジュールに関する情報を返すことで、両方の同じモジュールのカーネルベースを見つけます。

このようにして、各関数のオフセットを計算し、それらをカーネルで取得できます。

メモリを準備したら脆弱性をトリガー:

pipeArbitraryWrite() 関数が 2 回呼び出されます。最初の呼び出しではフラグが 0、2 回目の呼び出しでは値が 1 になり、ヒープスプレーの値が変更されます。

Texto Descripción generada automáticamente

最初の呼び出しでは、0x5000000 のメモリアドレスに次の値が配置されます。

この値は、そのアドレスへの割り当てに加えて、ヒープスプレーにも保存されることに注意してください。

最初の呼び出し後のメモリは次のようになります。前述の通り、0x5000000 付近のアドレスです。

そして、0x10000 からのメモリのヒープスプレーには、0x10 バイトごとに AttributeValueSize へのポインタと、0x5000000 へのポインタが格納されます。

システムトークンの読み取り:

このシーケンスがバグをトリガーします:

細工したファイルと、ランダムな名前の別のファイルに対して、再度 CreateLogFile() が呼び出されます。

次に、それらのファイルのハンドルを使用して AddLogContainer() が呼び出されます。

NtSetinformationFile() が呼び出され、ポインタが破壊されるハンドルが閉じられます(後で説明)。

Interfaz de usuario gráfica, Aplicación Descripción generada automáticamente con confianza media

ヒープスプレーは、この時点で BSOD が発生するのを防ぎます:

そこにブレークポイントを設定すると、ポインタが破壊されてヒープスプレーを指しており、vtable の次の 2 つの関数呼び出しを処理できることがわかります。

Interfaz de usuario gráfica, Texto, Aplicación Descripción generada automáticamente

Texto Descripción generada automáticamente

RAX は値 0x5000000 を取り、最初に 0x5000000+18 にある関数にジャンプし、次に 0x5000000+8 にジャンプします。

Texto Descripción generada automáticamente con confianza media

Imagen que contiene Interfaz de usuario gráfica Descripción generada automáticamente

したがって、最初に fnClfsEarlierLsn() にジャンプし、次に fnSeSetAccessStateGenericMapping() にジャンプします。

ブレークポイントからトレースすると、CLFS!ClfsEarlierLsn() に到達することがわかります。

Texto Descripción generada automáticamente

この関数は特に、戻るときに EDX を 0xFFFFFFFF に設定するために呼び出されています。

Interfaz de usuario gráfica Descripción generada automáticamente con confianza media

アドレス 0xFFFFFFFF には、SYSTEM _EPROCESS & 0xFFFFFFFFFFFFFFF000 の結果を保存していました。

Interfaz de usuario gráfica, Texto, Aplicación Descripción generada automáticamente

前述の通り、CLFS!ClfsEarlierLsn() から戻ると、RDX の値は 0x00000000FFFFFFFF です。

Texto Descripción generada automáticamente

次に、2 番目の関数 nt!SeSetAccessStateGenericMapping() に来ます。

Interfaz de usuario gráfica, Aplicación Descripción generada automáticamente

この関数は有用です。なぜなら RCX はヒープスプレーを指し、RDX の値は 0xFFFFFFFF であり、その内容は制御可能だからです。

Interfaz de usuario gráfica, Aplicación, Teams Descripción generada automáticamente

Texto Descripción generada automáticamente

RCX+0x48 の内容は、v30.Pointer+24 に保存されていた AttributeValueSize へのポインタです。

Interfaz de usuario gráfica, Texto Descripción generada automáticamente

Interfaz de usuario gráfica, Texto Descripción generada automáticamente con confianza media

Interfaz de usuario gráfica, Texto Descripción generada automáticamente

その AttributeValueSize のポインタ値が RAX に移動され、次にアドレス 0xFFFFFFFF の内容(SYSTEM _EPROCESS & 0xFFFFFFFFFFFFFFF000 のアドレスを保存していた)を読み取ります。

Interfaz de usuario gráfica, Texto, Aplicación Descripción generada automáticamente

次に、RAX+8 の次のフィールドである AttributeValue() を上書きします。

Texto Descripción generada automáticamente

Texto Descripción generada automáticamente

当然ながら、通常は AttributeValue はカーネル内で追加した属性を指しています。

Calendario Descripción generada automáticamente

そして今度は、SYSTEM _EPROCESS & 0xFFFFFFFFFFFFFFF00 の結果へのポインタで上書きされます。

これは、NtFsControlFile() 関数を再度、今度は引数 0x110038 で呼び出して属性を読み取ると、AttributeValue ポインタが指していた "A" の代わりに、_EPRROCESS & 0xFFFFFFFFFFFFFFFFF000 から要求されたバイト数を読み取り、出力バッファに返すことを意味します。これにより、最初の呼び出しで SYSTEM TOKEN の値を取得できます。

Texto Descripción generada automáticamente

v9b は、System EPROCESS & 0xFFFFFFFFFFFFFFF000 の結果の内容がコピーされた Output Buffer の開始アドレスです。

それに、System EPROCESS の最後の 3 バイトである v14 を加え、さらにこのバージョンの Windows 11 の Token のオフセットである 0x4b8 を加えると、そのアドレスに System Token の値が保存されているのを見つけます。

Interfaz de usuario gráfica, Texto, Aplicación Descripción generada automáticamente

Texto Descripción generada automáticamente

トークンの検証

Texto Descripción generada automáticamente con confianza baja

最後の 4 ビットは変更されていますが、重要ではないため、値は依然として一致します。

自プロセスのトークンをシステムトークンで上書き

2 回目の呼び出しでは、最初の呼び出しの最後にフラグが 1 に増加されているため、フラグの値は 1 です。

Interfaz de usuario gráfica, Texto, Aplicación, Correo electrónico Descripción generada automáticamente

ここで値が格納される順序がわかります。

Interfaz de usuario gráfica, Texto Descripción generada automáticamente

アドレス 0xFFFFFFFF には、見つけたばかりの System Process Token の値があります。

Interfaz de usuario gráfica, Texto Descripción generada automáticamente

Texto Descripción generada automáticamente

そしてヒープスプレーには、自プロセスの Token アドレスから 8 を引いた値があります。この値に 8 を加えたものがターゲットとして使用されます。書き込みは RAX+8 が指すアドレスに行われることに注意してください。

Graphical user interface, text Description automatically generated

Texto Descripción generada automáticamente

0x5000000 から始まるメモリアドレスでは:

Interfaz de usuario gráfica Descripción generada automáticamente

また、別のコンテナ名を使用していることもわかります。前のコンテナはシステムプロセスによって使用されているため、再度開いたり削除したりできません。

次に、最初と同じ方法でバグが 2 回目にトリガーされます。

再び CLFS!ClfsEarlierLsn() に来ます。

Interfaz de usuario gráfica, Texto, Aplicación Descripción generada automáticamente

RDX を 0xFFFFFFFF に設定:

Una captura de pantalla de un celular Descripción generada automáticamente

次に nt!SeSetAccessStateGenericMapping() に来ます。

Texto Descripción generada automáticamente

書き込む先の自プロセスの Token アドレスから 8 を引いたアドレスを読み取ります。

Texto Descripción generada automáticamente

次に SYSTEM TOKEN を読み取ります。

Texto Descripción generada automáticamente

そして、自プロセスの Token アドレス(8 を加える)に System Token を書き込みます。

これにより、自プロセスは System Token を持つことになります。

Texto Descripción generada automáticamente

トークンが書き込まれたら、権限を確認するためのプロセスを開始します。この場合は Notepad.exe を起動します。

システムとしてプロセスを実行:

Texto Descripción generada automáticamente

Interfaz de usuario gráfica, Aplicación, Word Descripción generada automáticamente

Texto Descripción generada automáticamente con confianza baja

この PoC は Windows 11 でのみ動作することに注意してください。Windows 10 では BSOD が発生するため、正しく動作させるにはいくつかの修正が必要です。このブログ記事では説明しません。

パッチのリバース:

構造体の解析

CLFS ファイル形式に関する構造体とほとんどのドキュメントは、IONESCU 氏の優れた CLFS Internals から引用しています。

ClfsBaseFilePersisted::LoadContainerQ 関数にチェックが追加されていることがわかります。

Texto Descripción generada automáticamente con confianza media

加算を行う値は、__CLFS_BASE_RECORD_HEADER 構造体に属します。

Escala de tiempo Descripción generada automáticamente con confianza media

Base Block はファイルのオフセット 0x800 から始まり、オフセット 0x71FF で終了します。最初の 0x70 バイトは Log Block Header に対応します。

良い習慣として、IDA に _CLFS_LOG_BLOCK_HEADER 構造体を追加できます。

struct _CLFS_LOG_BLOCK_HEADER

{

UCHAR MajorVersion;

UCHAR MinorVersion;

UCHAR Usn;

char ClientId;

USHORT TotalSectorCount;

USHORT ValidSectorCount;

ULONG Padding;

ULONG Checksum;

ULONG Flags;

CLFS_LSN CurrentLsn;

CLFS_LSN NextLsn;

ULONG RecordOffsets[16];

ULONG SignaturesOffset;

};

次に、ファイルの先頭からオフセット 0x870 から始まり、長さ 0x1338 バイトの ベースレコードヘッダー (_CLFS_BASE_RECORD_HEADER) があります。

Interfaz de usuario gráfica, Texto, Aplicación, Correo electrónico Descripción generada automáticamente

IDA にインポートする場合は、事前に次の型と不足している構造体を追加する必要があります。

typedef GUID CLFS_LOG_ID;
typedef UCHAR CLFS_LOG_STATE;

struct _CLFS_METADATA_RECORD_HEADER

{

ULONGLONG ullDumpCount;

};

これで追加する準備が整いました:

typedef struct _CLFS_BASE_RECORD_HEADER

{

CLFS_METADATA_RECORD_HEADER hdrBaseRecord;

CLFS_LOG_ID cidLog;

ULONGLONG rgClientSymTbl[0x0b];

ULONGLONG rgContainerSymTbl[0x0b];

ULONGLONG rgSecuritySymTbl[0x0b];

ULONG cNextContainer;

CLFS_CLIENT_ID cNextClient;

ULONG cFreeContainers;

ULONG cActiveContainers;

ULONG cbFreeContainers;

ULONG cbBusyContainers;

ULONG rgClients[0x7c];

ULONG rgContainers[0x400];

ULONG cbSymbolZone;

ULONG cbSector;

USHORT bUnused;

CLFS_LOG_STATE eLogState;

UCHAR cUsn;

UCHAR cClients;

} CLFS_BASE_RECORD_HEADER, *PCLFS_BASE_RECORD_HEADER;

Interfaz de usuario gráfica, Texto Descripción generada automáticamente

構造体を含めた後、cbSymbolZone と _CLFS_BASE_RECORD_HEADER の終了アドレスとの間で加算が行われることに気付きます。 (start + 1338h)Texto, Aplicación Descripción generada automáticamente

cbSymbolZone は細工されたログファイルで 0x000000F8 から 0x0001114B に変更されたことを思い出してください。

(ファイルのオフセット 0x1b98)

0x800(ベースブロック開始オフセット) + 0x70 (logBlockHeader) + 0x1328 (cbsymbolZone)

0x800+0x70+0x1328 = 0x1b98

MyLog.blf ファイル上の細工された cbsymbolZone:

Tabla Descripción generada automáticamente

Imagen que contiene Texto Descripción generada automáticamente

パッチが CClfsBaseFilePersisted::LoadContainerQ 関数にあるため、CClfsBaseFilePersisted オブジェクトを確認する必要があります。

CLFS!CClfsBaseFilePersisted::LoadContainerQ にブレークポイントを設定し、CreateLogFile が細工されたファイルのハンドルで呼び出されるとそこで停止します。

Interfaz de usuario gráfica, Texto, Aplicación Descripción generada automáticamente

CClfsBaseFile::GetBaseLogRecord 関数を呼び出して、ベースログレコード (_CLFS_BASE_RECORD_HEADER) のアドレスを取得します。

Graphical user interface, application, timeline Description automatically generated

RAX は _CLFS_BASE_RECORD_HEADER のアドレスを指します。

Interfaz de usuario gráfica, Texto, Aplicación, Correo electrónico Descripción generada automáticamente

メモリ内の _CLFS_BASE_RECORD_HEADER 構造体と cbsymbolZone フィールド 0x1328 に注意してください。

バイト前方

Imagen que contiene Texto Descripción generada automáticamente

Texto Descripción generada automáticamente

r14 は "this" に対応する構造体を格納します。これは CClfsBaseFilePersisted であり、関数 CClfsBaseFilePersisted: :LoadContainerQ の this だからです。

Interfaz de usuario gráfica, Aplicación Descripción generada automáticamente

メモリ内の CClfsBaseFilePersisted 構造体:

Texto Descripción generada automáticamente

それでは、リバースしながらフィールドを完成させるために、長さ 0x21c0 の構造体を作成しましょう (これは未文書化構造体です)。これを struct_CClfsBaseFilePersisted と呼びます。

Tabla Descripción generada automáticamente con confianza media

関数 CClfsBaseFile::GetBaseLogRecord() 内で _CLFS_BASE_RECORD_HEADER へのポインタを取得します。そして、その関数の "this" が構造体 struct_CClfsBaseFilePersisted であることがわかっています。

Escala de tiempo Descripción generada automáticamente con confianza media

2 つのフィールドを読み取ります (オフセット 0x28 と 0x30)。

Interfaz de usuario gráfica, Aplicación, Tabla Descripción generada automáticamente

フィールド 0x28 はワードで値 6 を持っているため、構造体の型を word に変更します。

Texto Descripción generada automáticamente

Texto Descripción generada automáticamente con confianza media

Interfaz de usuario gráfica, Texto, Aplicación Descripción generada automáticamente

今のところ、定数 6 (const_6) に名前を変更します。

Texto Descripción generada automáticamente

Interfaz de usuario gráfica, Texto, Aplicación Descripción generada automáticamente

ドキュメントによると、6 はブロック数 CLFS_METADATA_BLOCK_COUNT です。このフィールドはこの値を指している可能性があります。

そして、そのポインタはオフセット 0x30 にあります。

Tabla Descripción generada automáticamente

そこに示されているサイズには、長さ 0x10 のヘッダーが含まれていることに注意してください。

Texto Descripción generada automáticamente

Forma Descripción generada automáticamente con confianza media

ExAllocatePoolWithTag 関数が呼び出されるときに数バイトが要求されますが、ヘッダーは含まれないため、呼び出しでは 0x90 バイト (0xa0 – 0x10) が要求されます。

テキスト +30h] で検索すると、オフセット 0x30 に書き込む命令が多数見つかりますが、オブジェクトの型 CClfsBaseFilePersisted でリストをフィルタリングすると、結果は少なくなり、そのサイズが割り当てられている場所と、同じタグがすぐに見つかります。 (ヒント: Create や Initialize 関数名は、常に最初に確認する場所です。)

Texto Descripción generada automáticamente con confianza baja

Interfaz de usuario gráfica, Texto, Aplicación Descripción generada automáticamente

まだ名前がわからないので、pool_0x90 とします。これは別の未文書化構造体であり、そのサイズの構造体を作成します。

Texto Descripción generada automáticamente

Interfaz de usuario gráfica, Tabla Descripción generada automáticamente

メモリ内の pool_0x90 は、自身のオフセット 0x30 に別のポインタを持っています。

Aplicación, Tabla Descripción generada automáticamente con confianza media

この別のポインタは、ファイル内のベースブロックを指します (ベースブロックはオフセット 0x800 から始まります)。

Forma Descripción generada automáticamente

A picture containing calendar Description automatically generated

Zscaler のブログ記事 から引用した画像:

Graphical user interface, application, email Description automatically generated

割り当ては巨大です。これにはベースブロック全体が含まれているからです。

Text Description automatically generated

Graphical user interface, text, application Description automatically generated

それでは、サイズ 0x7a00 の新しい構造体を作成し、BASE_BLOCK と呼びます。

Graphical user interface, text, application Description automatically generated

最初の 70 バイトは _CLFS_LOG_BLOCK_HEADER に対応し、次の 0x1338 バイトは _CLFS_BASE_RECORD_HEADER に対応することが既にわかっています。

Text Description automatically generated

したがって、ベースブロックの先頭に次のレコードへのオフセット (0x70) を加算すると、_CLFS_BASE_RECORD_HEADER が得られます。

Application Description automatically generated with low confidence

メモリ上の _CLFS_BASE_RECORD_HEADER。

Calendar Description automatically generated

同じ CClfsBaseFilePersisted オブジェクトの他のメソッドを見ると、CClfsBaseFilePersisted::AddContainer では CClfsBaseFile::GetBaseLogRecord を使用して _CLFS_BASE_RECORD_HEADER のアドレスも取得しています。

Text Description automatically generated

次に、cbOffset を使用して CClfsBaseFile::OffsetToAddr を呼び出し、_CLFS_CONTAINER_CONTEXT のアドレスを取得し、cboffset を _CLFS_BASE_RECORD_HEADER のオフセット 0x328 にある rgbcontainers 配列に格納します。

Graphical user interface, application Description automatically generated

CClfsBaseFile::OffsetToAddr 関数は、オフセットから構造体のアドレスを見つけるために使用されます。

Graphical user interface, text, application Description automatically generated

この時点で、0x328 に格納されるコンテナオフセットはまだ 0 です。まだコンテナを追加していないからです。

Background pattern Description automatically generated with low confidence

PoC は CreateLogFile を 2 回呼び出します。1 回目は不正なファイル MyLog.blf を使用し、2 回目は通常の MyLogxxx.blf ファイルを使用します。そのため、上記のすべての場所でデバッグを 2 回停止し、両方のファイルの上記構造体のアドレスをメモ帳にメモする必要があります。

Text Description automatically generated

少し先に進み、CLFS!CClfsLogFcbPhysical::AllocContainer にブレークポイントを設定し、そこまで実行しましょう。

POC で AddLogContainer() に到達すると、ブレークポイントで停止します。

A picture containing application Description automatically generated

また、既に確認した CClfsBaseFilePersisted::AddContainer+176 にブレークポイントを設定しましょう。ここでは、_CLFS_CONTAINER_CONTEXT 構造体へのオフセットとポインタが見つかります。

A screenshot of a computer Description automatically generated with medium confidence

Graphical user interface, text, application Description automatically generated

デバッガが停止すると、オフセットが 0x1468 であることがわかります。

Text Description automatically generated

RAX は _CLFS_CONTAINER_CONTEXT 構造体のアドレスを返します。

Graphical user interface, text, application, table Description automatically generated

この構造体はまだ空です。コンテナがまだ追加されていないからです。

Text Description automatically generated

不正なファイルのオフセット 0x868 に書き込んだ SignatureOffset=0x50 の値が、ベースブロックの先頭 0x800 を差し引くと、_CLFS_LOG_BLOCK_HEADER 構造体のオフセット 0x68 にあることに注意してください。

Graphical user interface, text, application Description automatically generated

Text, letter Description automatically generated

PoC が不正なファイルを使用して AddLogContainer() 関数を呼び出すと、_CLFS_LOG_BLOCK_HEADER のオフセット 0x68 には、そこに書き込んだ 0x50 の値ではなく、メモリ上では現在 0xFFFF0050 が格納されています。

A picture containing text Description automatically generated

ある時点で、その値がプログラムによって変更されました。それがいつ発生したかを確認するために、次の実行で書き込みメモリブレークポイントを設定します。

オフセットは r15 + 0x328 に格納されています (r15 は _CLFS_BASE_RECORD_HEADER 構造体を指します)。

Text Description automatically generated with medium confidence

Graphical user interface Description automatically generated with low confidence

RBX はオフセット 0x1468 を格納します。

A picture containing calendar Description automatically generated

したがって、Base Block アドレス + 0x70 + 見つけたオフセット 0x1468 に、CLFS_CONTAINER_CONTEXT コンテナのアドレスが存在します。

Text Description automatically generated

CLFS_CONTAINER_CONTEXT 構造体のオフセット 0x18 には、そこに格納される pContainer ポインタがあります。書き込みブレークポイントを設定して、いつ書き込まれるかを確認できます。

Text Description automatically generated

A picture containing text Description automatically generated

これが、我々が破損させなければならないポインタです。脆弱性が存在する関数では、最初に CLFS_CONTAINER_CONTEXT を読み取り、次にそれを r15 に移動し、次に r15+18 の値を読み取ります。これが、ちょうど書き込みブレークポイントを設定したこのポインタです。

Graphical user interface, application, table Description automatically generated

Graphical user interface, application, Word Description automatically generated

pContainer を struct_CClfsBaseFilePersisted 構造体のオフセット 0x1c0 に格納します。

Text, application, whiteboard Description automatically generated

何度か停止した後、破損が発生する瞬間に到達します。ポインタアドレスの上位が FF からゼロに変更されています。

Calendar Description automatically generated

これは、不正なファイルの 2 回目の AddLogContainer() が呼び出されたときに発生し、前の MyLogxxx のポインタが破損します。

問題は、SignaturesOffset が 0x50 であるべきところが、現在 0xFFFF0050 になっているために発生し、後続の memset で範囲外への書き込みが可能になります。

Graphical user interface, text, application Description automatically generated

Graphical user interface, text Description automatically generated

"pContainer" ポインタの破損:

memset() 関数は、その下にある _CLFS_CONTAINER_CONTEXT 構造体を破損します。この構造体は MyLogxxx ファイルに対応します。作成時に互いに 0x11000 バイト離れて配置されたからです。

この方法で、次の構造体に書き込む正確な位置を計算し、ポインタの上位をゼロにして、HeapSpray が作成されたユーザーヒープを指すようにします。

不正なファイルのベースブロック構造体は、MyLogxxx ファイルのもののちょうど 0x11000 前にあります。

不正:

Shape Description automatically generated

MyLogxxx

A picture containing text Description automatically generated

RCX は RDX より小さいです。0x50 (本来の値) ではなく、0xFFFF0050 が加算されたからです。

Graphical user interface, text, application Description automatically generated

そして、memset() 関数に到達し、0xb0 バイトをゼロで設定します。RCX は MyLogxxx ファイルの CLFS_CONTAINER_CONTEXT 構造体、具体的には pContainer の上位 5 バイトを指しています。

Text Description automatically generated

このポインタは、最初のバイトを上書きすることで破損します:

Text Description automatically generated

残りは、以前 HeapSpray によって制御されたメモリアドレスを指すようになります。

Text Description automatically generated

A picture containing text Description automatically generated

次に、MyLogxxx ファイルのハンドルが閉じられ、CClfsBaseFilePersisted::RemoveContainer に到達し、脆弱性が最終的にトリガーされます。

Text, application Description automatically generated with medium confidence

パッチの再検討

より多くの情報が得られたので、ここで Base_Block.LOG_BLOCK_HEADER.SignaturesOffset と Base_Block. .LOG_BLOCK_HEADER.TotalSectorCount を読み取っていることに気付きます。

パッチの最初の部分では、SignaturesOffset が 0x7a00 より大きくてはなりません。私たちのものでは元々 0x50 でしたが、もし 0x7a00 より大きい値で到着すると、アウトになります。

A picture containing diagram Description automatically generated

パッチ適用済みのマシンで PoC を実行すると、0x50 と 0x7a00 を比較し、小さいので続行されます。

Text Description automatically generated

次のブロックでは、不正な cbSymbolZone が _CLFS_BASE_RECORD_HEADER の終了アドレスの値に加算され、この合計が result_1 に格納されます。

Text Description automatically generated

次に、Base_Block のアドレスに SignatureOffset の値が加算されます。通常のファイルではこれは 0x7980 です。

Text Description automatically generated

base_block の最大アドレスは 0x7a00 です。これで、SymbolZone は制限の 0x80 前まで許可されます。

これは result_2 に格納されます。つまり、base block 内の SymbolZone の最大制限になります。次に、両方の結果を比較し、最初の結果が 2 番目より大きい場合、範囲外になったことを意味します。

Text Description automatically generated

Text Description automatically generated

明らかに、最初のメンバーは 2 番目より大きくなり、続行されません。なぜなら、cbSymbolZone + _CLFS_BASE_RECORD_HEADER の終了アドレスの最初の合計が制限 (つまり result_2) を超え、「範囲外」になるからです。

Graphical user interface, text, application Description automatically generated

SignatureOffset の破損

最後に解明すべきことは、SignatureOffset の値 0x50 がどのようにして 0xFFFF0050 になるかということです。では、やり直して、再起動し、値がまだメモリ内で変更されておらず、依然として 0x50 である CLFS!CClfsBaseFilePersisted::LoadContainerQ で停止しましょう。

SignatureOffset のオフセット 0x68 にアクセスブレークポイントを設定します。

Calendar Description automatically generated

そして、数回の停止の後、ClfsEncodeBlockPrivate で値が変更される正しい瞬間を検出します。

Graphical user interface, text Description automatically generated

この関数はパッチされていないため、0x50 の低い値と操作されている他の値によって引き起こされる動作である可能性があります。

細工された値の中に、_CLFS_BASE_RECORD_HEADER 構造体で rgClients という名前を持ち、Client Context オブジェクトを指すオフセットの配列を表す ccoffsetArray 値があります。

rgClients フィールドは、_CLFS_BASE_RECORD_HEADER 構造体のオフセット 0x138 (0x9a8-0x800-0x70) にあります。

Graphical user interface, table Description automatically generated

Text Description automatically generated with medium confidence

PoC では、この値は FakeClientContext と呼ばれる偽のクライアントコンテキストオブジェクトを指すように破損されています。

Text, whiteboard Description automatically generated

A screenshot of a computer Description automatically generated with medium confidence

これは Client Context 構造体 _CLFS_CLIENT_CONTEXT です。

struct _CLFS_CLIENT_CONTEXT

{

CLFS_NODE_ID cidNode;

CLFS_CLIENT_ID cidClient;

USHORT fAttributes;

ULONG cbFlushThreshold;

ULONG cShadowSectors;

ULONGLONG cbUndoCommitment;

LARGE_INTEGER llCreateTime;

LARGE_INTEGER llAccessTime;

LARGE_INTEGER llWriteTime;

CLFS_LSN lsnOwnerPage;

CLFS_LSN lsnArchiveTail;

CLFS_LSN lsnBase;

CLFS_LSN lsnLast;

CLFS_LSN lsnRestart;

CLFS_LSN lsnPhysicalBase;

CLFS_LSN lsnUnused1;

CLFS_LSN lsnUnused2;

CLFS_LOG_STATE eState;

union

{

HANDLE hSecurityContext;

ULONGLONG ullAlignment;

};

};

eState 値は構造体の先頭からオフセット 0x78 にあり、細工されたファイルでは 0x23a0+0x78 です。

Text Description automatically generated with medium confidence

Chart, scatter chart Description automatically generated

この値はログの状態を示します。

typedef UCHAR CLFS_LOG_STATE, *PCLFS_LOG_STATE;
const CLFS_LOG_STATE CLFS_LOG_UNINITIALIZED = 0x01;
const CLFS_LOG_STATE CLFS_LOG_INITIALIZED = 0x02;
const CLFS_LOG_STATE CLFS_LOG_ACTIVE = 0x04;
const CLFS_LOG_STATE CLFS_LOG_PENDING_DELETE = 0x08;
const CLFS_LOG_STATE CLFS_LOG_PENDING_ARCHIVE = 0x10;
const CLFS_LOG_STATE CLFS_LOG_SHUTDOWN = 0x20;
const CLFS_LOG_STATE CLFS_LOG_MULTIPLEXED = 0x40;
const CLFS_LOG_STATE CLFS_LOG_SECURE = 0x80;

この値は CLFS_LOG_STATE CLFS_LOG_SHUTDOWN =0x20 に設定されています。

もう一つの破損した値は fAttributes で、これはベースログファイルに関連付けられた FILE_ATTRIBUTE フラグのセット(System や Hidden など)に対応します。

Graphical user interface Description automatically generated with low confidence

Text, letter Description automatically generated

フィールドは 0xa で1バイト早く始まり、2バイトにまたがるため、fAttributes の値は 0x100 です。

A picture containing table Description automatically generated

Graphical user interface, text, application Description automatically generated

最後に、オフセット 0x1bb8 を指す blocknameoffset 値があります。つまり、0x78 と 0x800 を加算するとファイルのオフセット 0x2428 を指します。

Text Description automatically generated

Text, letter Description automatically generated

Client Context へのオフセットは 0x1b30 であることに注意してください。

Table Description automatically generated

したがって、Client Context はオフセット 0x23a0 にあります。

Text Description automatically generated with medium confidence

Table Description automatically generated

そして、そのちょうど 0x10 前に blocknameoffset に対応する値があります。

Text, letter Description automatically generated

Table Description automatically generated with low confidence

これは名前を持つ文字列を指すことになります。

最後のものは blockattributeoffset で、Client Context の 0xC 前の 0x2394 にあります。

Table Description automatically generated

これらの最後の2つの値は、Client Context の前にあり、長さが0x30バイトの構造体 _CLFSHASHSYM に属しています。

typedef struct _CLFSHASHSYM
{
CLFS_NODE_ID cidNode;
ULONG ulHash;
ULONG cbHash;
ULONGLONG ulBelow;
ULONGLONG ulAbove;
LONG cbSymName;
LONG cbOffset;
BOOLEAN fDeleted;
} CLFSHASHSYM, *PCLFSHASHSYM;

A picture containing diagram Description automatically generated

Text Description automatically generated

これらは _CLFSHASHSYM 構造体の先頭から0x20および0x24バイトの位置にあります。したがって、_CLFSHASHSYM 構造体において、POC で blockNameOffset と呼ばれる値は cbSymName フィールドであり、blockAttributteoffset は cbOffset フィールドです。

A picture containing text Description automatically generated

Text Description automatically generated with medium confidence

これらが破損した値です。次に、これらがどのように影響して SignaturesOffset を 0x50 の値から 0xFFFF0050 に変更するかを見る必要があります。

クライアントコンテキストを返すはずの CClfsBaseFile::AcquireClientContext() 関数を見てみましょう。

Graphical user interface, text, application, email Description automatically generated

この関数は、Client Context へのポインタを格納する第4引数 _CLFS_CLIENT_CONTEXT ** を指定して CClfsBaseFile::GetSymbol を呼び出します。

Graphical user interface, text, application Description automatically generated

CClfsBaseFile::GetSymbol 関数内で、破損した ccoffsetArray オフセットを CClfsBaseFile::OffsetToAddr に渡してクライアントコンテキストのアドレスを取得します。CreatelogFile で作成されたファイルを呼び出すときに停止するように、そこにブレークポイントを設定しましょう。

Graphical user interface, application Description automatically generated with medium confidence

そこでは、細工された ccoffsetArray 引数で停止しています。

Graphical user interface, application Description automatically generated

Table Description automatically generated

CClfsBaseFile::OffsetToAddr 関数は偽の Client Context を返します。

A picture containing graphical user interface Description automatically generated

そして、RAX にある _CLFS_CLIENT_CONTEXT 構造体の前に 0xC が見つかるため、cbOffset の値がゼロでないことを確認します。

A screenshot of a computer Description automatically generated

A picture containing text Description automatically generated

次に、cbOffset と ccoffsetArray(RSI にある)を比較し、等しくなければエラーになります。

A screenshot of a computer Description automatically generated

また、cbSymName が cbOffset+0x88 に等しいことを確認し、そうでなければ同様にエラーになります。

Graphical user interface, text, application Description automatically generated with medium confidence

最後に、cidClient バイトをゼロと比較します。

A picture containing diagram Description automatically generated

これらすべてのチェックが成功すると、client context が保存されます。

A screenshot of a computer Description automatically generated

関数 r14 の出力は Client Context を指します。

Graphical user interface, text, application Description automatically generated

CClfsLogFcbPhysical::Initialize から終了するとき、CLFS_CLIENT_CONTEXT のアドレスを取得します。

Text Description automatically generated

次に、fAttributes (0x100) の値を読み取ります。

Graphical user interface, text, application Description automatically generated

この関数はクラス CClfsLogFcbPhysical に属しています。

Text Description automatically generated

Graphical user interface, text, application Description automatically generated

これはここで割り当てられ、そのサイズは 0x15d0、タグは "ClfC" です。

Text Description automatically generated with medium confidence

リバースエンジニアリングしている内容を保存するための構造体を作成しましょう。名前は struct_CClfsLogFcbPhysical とします。

A picture containing table Description automatically generated

0x2b0 で CClfsBaseFilePersisted 構造体のアドレスを保存することに注意してください。

A picture containing application Description automatically generated

構造体に多くの値を保存した後、重要な部分に進みます。eState を 0x20 でテストします。

Graphical user interface, text, application Description automatically generated

Graphical user interface, text, application, table Description automatically generated

細工された値は 0x20 だったため、テストは1を返します。

Table Description automatically generated

Graphical user interface, text, application Description automatically generated

コンストラクタの vtable に次のものがあることがわかります。

Text Description automatically generated

ファイルが multiplexed であるかどうかをチェックします。

Graphical user interface, application Description automatically generated

したがって、目的のパスを通り、CClfsLogFcbPhysical::ResetLog に到達します。

Graphical user interface, application Description automatically generated

Text, application, table Description automatically generated with medium confidence

いくつかのフィールドはゼロに初期化されますが、1つだけ 0xFFFFFFFF00000000 に初期化されます。

Graphical user interface Description automatically generated with low confidence

ここで Client Context を取得します。

Graphical user interface, application Description automatically generated with medium confidence

値 0xFFFFFFFF00000000 を格納します。

Graphical user interface, application Description automatically generated

Graphical user interface, application Description automatically generated

A picture containing calendar Description automatically generated

0xFFFFFFFF をオフセット 0x5c に書き込みます。これは CLFS_LSN lsnRestart.ullOffset の上位部分です。

Text Description automatically generated with medium confidence

Graphical user interface, text, letter Description automatically generated

次に、ClfsEncodeBlockPrivate() 関数を実行します。この関数は、以前見たように 0x50 を 0xFFFF0050 で上書きする役割を担います。

そこで、SignatureOffset = 0x50 の値を読み取ります。これは破損ファイルに設定したままの値で、それを CLFS_LOG_BLOCK_HEADER の先頭に加算します。

Text Description automatically generated

これは2バイトを書き込むループです。SignatureOffset が正しい値(通常のファイルでは高い値、例えば 0x3f8 で先の方に書き込む)を指す代わりに、ここでは同じ CLFS_LOG_BLOCK_HEADER 内に書き込むことになります。

アイデアは、書き込み先を変更して SignatureOffset の値を破損しようとするものです。

通常のファイル

Table Description automatically generated

この時点で、ループが開始され、2バイトを書き込みます。

Graphical user interface, application Description automatically generated

カウンタが値 0x3d に達するとループを終了します。

Graphical user interface, application Description automatically generated

RCX は 0x200 から増加しており、すでに3サイクル目で、その値は 0x600 です。

Graphical user interface, text, application Description automatically generated

イテレーション 0xe では、RCX は 0x1a00 です。

Graphical user interface, text Description automatically generated

A picture containing calendar Description automatically generated

それが 0xFFFFFFFF000000 を書き込んだ場所でした。

Graphical user interface, text, application Description automatically generated

Table Description automatically generated with medium confidence

最後の2バイト FFFF を読み取っています。

Text Description automatically generated

そしてそれを R8 にコピーします。

A picture containing calendar Description automatically generated

A picture containing calendar Description automatically generated

これまで見てきたように、この値は重要であり、チェックをバイパスして範囲外に書き込み、memset() の後に続くファイルの pContainer ポインタを破損し、先頭にゼロを書き込んで、制御下にあるメモリ(HeapSpray)を指すようにすることができます。

CClfsBaseFilePersisted::AllocSymbol では、memset の出力先を取得する同じ加算(cbSymbolZone + CLFS_BASE_RECORD_HEADER の最終アドレス)を、前に Base_block + 0xFFFF0050 と比較するため、方程式の両側で値が破損しています。

CbSymbolZone= 0x1114B

これは破損した値であり、CLFS_BASE_RECORD_HEADER の最終アドレスに加算されると範囲外への書き込みを引き起こします。比較のもう一方のメンバーは Base Block + SignatureOffset のアドレスであるべきですが、SignatureOffset =0xFFFF0050 のままであるため、このチェックを通過し、memset() で範囲外に書き込み、ポインタの先頭をゼロにして、HeapSpray を指したままにすることができます。

Graphical user interface, application, table Description automatically generated

RCX が RDX よりも小さいため。

Graphical user interface, application Description automatically generated

以前見たように(値は前の実行に属するため異なる場合があります)。

ポインタを破損し、最上位バイトを0に設定します。

Table Description automatically generated

HeapSpray を通じて制御するメモリ領域を指したままにします。

A screenshot of a computer Description automatically generated with low confidence

Table Description automatically generated

したがって、脆弱性がトリガーされると、CClfsBaseFilePersisted::RemoveContainer に到達します。

A picture containing graphical user interface Description automatically generated

そこにはすでに破損したポインタがあり、以前見たように悪用可能です。

Graphical user interface, application Description automatically generated

この時点でバグが悪用され、SYSTEM トークンを読み取り、自プロセスに書き込んでローカル権限昇格を達成する関数を制御できるようになります。

お役に立てれば幸いです。ご質問があれば、[email protected] または [email protected] までご連絡ください。

お楽しみください!

ツールをダウンロード