Skip to content
KitploitKITPLOIT
ツールエクスプロイトブログ
Log in
提出
ツールエクスプロイトブログ
提出

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

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

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

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
EDRSandblast — 脆弱性のある署名済みドライバを悪用して、EDRカーネルコールバック、オブジェクトコールバック、ETW TIプロバイダ、ユーザーランドフックをバイパスし、LSASSメモリダンプと資格情報抽出を行います。 | Kitploit
ツール/GitHubGitHub/wavestone-cdt/edrsandblast
防御ツール特権昇格エクスプロイトペネトレーションテストレッドチーミング
GitHubwavestone-cdt/edrsandblast

EDRSandblast

脆弱性のある署名済みドライバを悪用して、EDRカーネルコールバック、オブジェクトコールバック、ETW TIプロバイダ、ユーザーランドフックをバイパスし、LSASSメモリダンプと資格情報抽出を行います。

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

人気

すべて見る →

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

すべてのツールを探索

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

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

EDRSandBlast

EDRSandBlast は、C で書かれたツールであり、脆弱性のある署名済みドライバを悪用して、EDR の検出(Notify Routine コールバック、Object Callbacks、ETW TI プロバイダー)や LSASS の保護をバイパスします。また、ユーザーランド監視を回避するための複数のユーザーランドアンフック技術も実装されています。

リリース時点では、ユーザーランド(--usermode)とカーネルランド(--kernelmode)の技術を組み合わせて、EDR の監視下で LSASS メモリをダンプし、ブロックされることなく、また製品(クラウド)コンソールに「OS Credential Dumping」関連のイベントを生成することもありませんでした。テストは 3 種類の異なる EDR 製品に対して実施され、それぞれ成功しました。

説明

カーネル Notify Routines の削除による EDR バイパス

EDR 製品は、Windows のカーネル「Notify Routines」コールバックを使用して、プロセスやスレッドの作成、イメージ(exe / DLL)のロードなど、システムアクティビティの通知をカーネルから受け取ります。

これらのカーネルコールバックは、カーネルランドから定義され、通常はコールバックを実装するドライバが、文書化されたいくつかの API(nt!PsSetCreateProcessNotifyRoutine、nt!PsSetCreateThreadNotifyRoutine など)を使用して定義します。これらの API は、ドライバが提供するコールバックルーチンを、カーネル空間内の文書化されていないルーチンの配列に追加します:

  • PspCreateProcessNotifyRoutine(プロセス作成用)
  • PspCreateThreadNotifyRoutine(スレッド作成用)
  • PspLoadImageNotifyRoutine(イメージロード用)

EDRSandBlast は、これらの配列で定義されたルーチンを列挙し、事前定義された EDR ドライバのリスト(1000 以上のセキュリティ製品のドライバに対応、EDR ドライバ検出セクション を参照)に関連するコールバックルーチンをすべて削除します。この列挙と削除は、脆弱性のあるドライバの悪用によって提供される任意のカーネルメモリ読み取り/書き込みプリミティブの悪用を通じて可能になります(脆弱性のあるドライバセクション を参照)。

前述の配列のオフセットは、複数の技術を使用して復元されます。詳細は オフセットセクション を参照してください。

オブジェクトコールバックの削除による EDR バイパス

EDR(および EPP)製品は、多くの場合、nt!ObRegisterCallbacks カーネル API を使用して「オブジェクトコールバック」を登録します。これらのコールバックにより、セキュリティ製品は、特定のオブジェクトタイプ(Windows ではプロセス、スレッド、デスクトップに関連するオブジェクトコールバックがサポートされています)に対するハンドル生成のたびに通知を受け取ることができます。ハンドル生成は、オブジェクトのオープン(OpenProcess、OpenThread などの呼び出し)だけでなく、ハンドルの複製(DuplicateHandle などの呼び出し)でも発生する可能性があります。

これらの各操作についてカーネルから通知を受けることで、セキュリティ製品はハンドル作成の正当性を分析し((例:未知のプロセスが LSASS を開こうとしている))、脅威が検出された場合はブロックすることもできます。

ObRegisterCallbacks を使用したコールバック登録のたびに、コールバックの影響を受けるオブジェクトのタイプ(プロセス、スレッド、デスクトップのいずれか)を記述する _OBJECT_TYPE オブジェクト内に存在する二重リンクリスト CallbackList に新しい項目が追加されます。残念ながら、これらの項目は Microsoft によって文書化されておらず、シンボルファイルにも公開されていない構造体で記述されています。しかし、さまざまな ntoskrnl.exe バージョンから調査したところ、この構造体は(少なくとも)Windows 10 ビルド 10240 から 22000(2015 年から 2022 年)の間で変更されていないようです。

言及された、オブジェクトコールバック登録を表す構造体は次のとおりです:```C typedef struct OB_CALLBACK_ENTRY_t { LIST_ENTRY CallbackList; // linked element tied to _OBJECT_TYPE.CallbackList OB_OPERATION Operations; // bitfield : 1 for Creations, 2 for Duplications BOOL Enabled; // self-explanatory OB_CALLBACK* Entry; // points to the structure in which it is included POBJECT_TYPE ObjectType; // points to the object type affected by the callback POB_PRE_OPERATION_CALLBACK PreOperation; // callback function called before each handle operation POB_POST_OPERATION_CALLBACK PostOperation; // callback function called after each handle operation KSPIN_LOCK Lock; // lock object used for synchronization } OB_CALLBACK_ENTRY;

上記の`OB_CALLBACK`構造体も未文書化であり、以下のように定義されています:```C
typedef struct OB_CALLBACK_t {
    USHORT Version;                           // usually 0x100
    USHORT OperationRegistrationCount;        // number of registered callbacks
    PVOID RegistrationContext;                // arbitrary data passed at registration time
    UNICODE_STRING AltitudeString;            // used to determine callbacks order
    struct OB_CALLBACK_ENTRY_t EntryItems[1]; // array of OperationRegistrationCount items
    WCHAR AltitudeBuffer[1];                  // is AltitudeString.MaximumLength bytes long, and pointed by AltitudeString.Buffer
} OB_CALLBACK;

EDRに登録されたオブジェクトコールバックを無効にするために、EDRSandblastには3つの手法が実装されていますが、現時点では1つだけが有効になっています。

OB_CALLBACK_ENTRY の Enabled フィールドを使用する

これはEDRSandblastでデフォルトで有効になっている手法です。EDR関連のオブジェクトコールバックを検出して無効にするために、ProcessおよびThreadタイプに関連付けられた_OBJECT_TYPEオブジェクト内にあるCallbackListリストを参照します。両方の_OBJECT_TYPEは、カーネル内の公開グローバルシンボルPsProcessTypeとPsThreadTypeによって指されています。

リストの各項目は、上記で説明したOB_CALLBACK_ENTRY構造体に適合すると想定されています(少なくとも執筆時点のすべてのWindows 10ビルドで成立すると思われる仮定)。PreOperationフィールドとPostOperationフィールドで定義された関数が、EDRドライバに属するかどうかをチェックするために特定され、該当する場合は、Enabledフラグを切り替えるだけでコールバックが無効になります。

かなり安全な手法ですが、文書化されていない構造に依存するという不便さがあります。この構造の安全でない操作のリスクを軽減するために、いくつかのフィールドが期待される値を持っていることを検証する基本的なチェックが実行されます:

  • Enabled は TRUE または FALSE のいずれかである(笑わないでください。BOOL は int なので、1 や 0 以外の値になる可能性があります)。
  • Operations は OB_OPERATION_HANDLE_CREATE、OB_OPERATION_HANDLE_DUPLICATE、またはその両方である。
  • ObjectType は PsProcessType または PsThreadType を指す。

スレッドとプロセスのCallbackListをアンリンクする

文書化されていない構造に依存しない別の戦略(したがって理論的にはNTカーネルの変更に対してより堅牢)は、プロセスとスレッドの両方に対するCallbackList全体をアンリンクすることです。_OBJECT_TYPEオブジェクトは以下の通りです:```C struct _OBJECT_TYPE { LIST_ENTRY TypeList; UNICODE_STRING Name; [...] _OBJECT_TYPE_INITIALIZER TypeInfo; [...] LIST_ENTRY CallbackList; }

Making the `Flink` and `Blink` pointers of the `CallbackList` `LIST_ENTRY` point to
the `LIST_ENTRY` itself effectively make the list empty. Since the `_OBJECT_TYPE` structure
is published in the kernel' symbols, the technique does not rely on hardcoded offsets/structures.
However, it has some drawbacks.

The first being not able to only disable callbacks from EDR; indeed, the technique affects
all object callbacks that could have been registered by "legitimate" software. It should
nevertheless be noted that object callbacks are not used by any pre-installed component
on Windows 10 (at the time of writing) so disabling them should not affect the machine
stability (even more so if the disabling is only temporary).

The second drawback is that process or thread handle operation are really frequent (nearly
continuous) in the normal functioning of the OS. As such, if the kernel write primitive used
cannot perform a `QWORD` write "atomically", there is a good chance that the
`_OBJECT_TYPE.CallbackList.Flink` pointer will be accessed by the kernel in the middle
of its overwriting. For instance, the MSI vulnerable driver `RTCore64.sys` can only perform
a `DWORD` write at a time, so 2 distinct IOCTLs will be needed to overwrite the pointer, between
which the kernel has a high probability of using it (resulting in a crash). On the other hand,
the vulnerable DELL driver `DBUtil_2_3.sys` can perform writes of arbitrary sizes in one
IOCTL, so using this method with it does not risk causing a crash.

#### Disabling object callbacks altogether
One last technique we found was to disable entirely the object callbacks support for thread
and processes. Inside the `_OBJECT_TYPE` structure corresponding to the process and
thread types resides a `TypeInfo` field, following the documented `_OBJECT_TYPE_INITIALIZER`
structure. The latter contains a `ObjectTypeFlags` bit field, whose `SupportsObjectCallbacks`
flag determines if the described object type (Process, Thread, Desktop, Token, File, etc.)
supports object callback registering or not. As previously stated, only Process, Thread and
Desktop object types supports these callbacks on a Windows installation at the time of writing.

Since the `SupportsObjectCallbacks` bit is checked by `ObpCreateHandle` or
`ObDuplicateObject` before even reading the `CallbackList` (and before executing
callbacks, of course), flipping the bit at kernel runtime effectively disable all object callbacks
execution.

The main drawback of the method is simply that *KPP* ("*PatchGuard*") monitors the integrity
of some (all ?) `_OBJECT_TYPE` structures, and triggers a [`0x109 Bug Check`](https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/bug-check-0x109---critical-structure-corruption)
with parameter 4 being equal to `0x8`, meaning an object type structure has been altered.

However, performing the disabling / re-enabling (and "malicious" action in-between) quickly
enough should be enough to "race" *PatchGuard* (unless you are unlucky and a periodic
check is performed just at the wrong moment).
ツールをダウンロード