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

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

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

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

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
EDRSandblast-GodFault — EDRSandblast-GodFault | Kitploit
ツール/GitHubGitHub/gabriellandau/edrsandblast-godfault
防御ツール特権昇格メモリフォレンジックエクスプロイトポストエクスプロイトレッドチーミングペイロード開発Archived
GitHubgabriellandau/edrsandblast-godfault

EDRSandblast-GodFault

EDRSandblast-GodFault

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

人気

すべて見る →

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

すべてのツールを探索

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

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

EDRSandblast-GodFault

Gabriel Landau(Elastic Security)による。EDRSandblast の改変版 - 詳細は以下にある元のREADMEを参照。

GodFault を EDR Sandblast に統合し、脆弱なドライバーを使用せずに同じ結果を実現します。

出力例```

C:\Users\user\Desktop\Offsets>EDRSandblast.exe --kernelmode cmd


| | __ | __ \ / | | | | | | | | | | | | | | |) | ( __ _ _ __ | | | | | __ _ | | | | | | | | _ / _ \ / | '_ \ / _ | ' | |/ ` / __| __| | || || | | \ \ ) | (| | | | | (| | |) | | (| _ | | ||_____/|| _|/ _,|| ||_,|_./||_,|__/__|

D3FC0N 30 Edition | Thomas DIOT (@_Qazeer) & Maxime MEIGNAN (@th3m4ks)

[!] If kernel mode bypass is enabled, it is recommended to enable usermode bypass as well (e.g. to unhook the NtLoadDriver API call)

[===== KERNEL MODE =====]

[+] Setting up prerequisites for the kernel read/write primitives... [+] Loading kernel related offsets from the CSV file [*] System's ntoskrnl.exe file version is: ntoskrnl_22621-1702.exe [+] Offsets are available for this version of ntoskrnl.exe (ntoskrnl_22621-1702.exe)! [+] Checking if any EDR kernel notify rountines are set for image loading, process and thread creations... [+] [NotifyRountines] Enumerating process creation callbacks [+] Running command: GodFault.exe -t 2684 [?] Server does not appear to be running. Attempting to install it... [+] CSRSS PID is 748 [+] Testing initial ability to acquire PROCESS_ALL_ACCESS to System: Failure [+] Ready. Spawning WinTcb. [+] SpawnPPL: Waiting for child process to finish. [+] Thread 2684 (KTHREAD FFFF910961E4C080) has been blessed by GodFault [+] [NotifyRountines] fffff8034df25500 [cng.sys + 0x5500] [+] [NotifyRountines] fffff8034e9efdc0 [WdFilter.sys + 0x4fdc0] [+] [NotifyRountines] Found callback belonging to EDR driver WdFilter.sys [+] [NotifyRountines] fffff803487bc460 [ksecdd.sys + 0x1c460] [+] [NotifyRountines] fffff8034eff3fd0 [tcpip.sys + 0x13fd0] [+] [NotifyRountines] fffff8034f5ed980 [iorate.sys + 0xd980] [+] [NotifyRountines] fffff8034dea8890 [CI.dll + 0x88890] [+] [NotifyRountines] fffff803525079f0 [dxgkrnl.sys + 0x179f0] [+] [NotifyRountines] fffff80352be0a70 [vm3dmp.sys + 0x10a70] [+] [NotifyRountines] fffff8036ebccd00 [peauth.sys + 0x3cd00] [+] [NotifyRountines] fffff8036eda1550 [wtd.sys + 0x1550] [+] [NotifyRountines] Found a total of 1 EDR / security products driver(s) [+] [NotifyRountines] Enumerating thread creation callbacks [+] [NotifyRountines] fffff8034e9f15c0 [WdFilter.sys + 0x515c0] [+] [NotifyRountines] Found callback belonging to EDR driver WdFilter.sys [+] [NotifyRountines] fffff8034e9f1350 [WdFilter.sys + 0x51350] [+] [NotifyRountines] Found callback belonging to EDR driver WdFilter.sys [+] [NotifyRountines] fffff8036eb71010 [mmcss.sys + 0x1010] [+] [NotifyRountines] Found a total of 2 EDR / security products driver(s) [+] [NotifyRountines] Enumerating image loading callbacks [+] [NotifyRountines] fffff8034e9f0820 [WdFilter.sys + 0x50820] [+] [NotifyRountines] Found callback belonging to EDR driver WdFilter.sys [+] [NotifyRountines] fffff80352ab5710 [ahcache.sys + 0x25710] [+] [NotifyRountines] Found a total of 1 EDR / security products driver(s)

[+] Checking if EDR callbacks are registered on processes and threads handle creation/duplication... [+] [ObjectCallblacks] Enumerating Process object callbacks : [+] [ObjectCallblacks] Callback at FFFF800C5E2F2940 for handle creations & duplications: [+] [ObjectCallblacks] Status: Enabled [+] [ObjectCallblacks] Preoperation at 0xfffff8034e9eda30 [WdFilter.sys + 0x4da30] [+] [ObjectCallblacks] Callback belongs to an EDR and is enabled! [+] [ObjectCallblacks] Enumerating Thread object callbacks : [+] [ObjectCallblacks] Object callbacks are present !

[+] [ETWTI] Checking the ETW Threat Intelligence Provider state... [+] [ETWTI] ETW Threat Intelligence Provider is ENABLED!

[+] Process is NOT "safe" to launch our payload, removing monitoring and starting another process...

[+] [ETWTI] Disabling the ETW Threat Intel provider by patching ProviderEnableInfo at 0xffff91095ce8c430 with 0x00. [+] [ETWTI] The ETW Threat Intel provider was successfully disabled!

[+] Removing kernel callbacks registered by EDR for process creation, thread creation and image loading... [+] [NotifyRountines] Removing process creation callbacks [+] [NotifyRountines] Removing callback of EDR driver "WdFilter.sys" [callback addr: 0xfffff8034970c2a8 | callback struct: 0xffff91095dbf3a5f | callback function: 0xfffff8034e9efdc0] [+] [NotifyRountines] Removing thread creation callbacks [+] [NotifyRountines] Removing callback of EDR driver "WdFilter.sys" [callback addr: 0xfffff8034970c4a0 | callback struct: 0xffff91095dbf3b1f | callback function: 0xfffff8034e9f15c0] [+] [NotifyRountines] Removing callback of EDR driver "WdFilter.sys" [callback addr: 0xfffff8034970c4a8 | callback struct: 0xffff91095dbf3b4f | callback function: 0xfffff8034e9f1350] [+] [NotifyRountines] Removing image loading callbacks [+] [NotifyRountines] Removing callback of EDR driver "WdFilter.sys" [callback addr: 0xfffff8034970c6a0 | callback struct: 0xffff91095dbf3e4f | callback function: 0xfffff8034e9f0820]

[+] Disabling kernel callbacks registered by EDR for process and thread opening or handle duplication... [+] [ObjectCallblacks] Disabling WdFilter.sys callback...

[+] All EDR drivers were successfully removed from Kernel callbacks!

================================================== Starting a new unmonitored process...

[!] If kernel mode bypass is enabled, it is recommended to enable usermode bypass as well (e.g. to unhook the NtLoadDriver API call)

[===== KERNEL MODE =====]

[+] Setting up prerequisites for the kernel read/write primitives... [+] Loading kernel related offsets from the CSV file [*] System's ntoskrnl.exe file version is: ntoskrnl_22621-1702.exe [+] Offsets are available for this version of ntoskrnl.exe (ntoskrnl_22621-1702.exe)! [+] Checking if any EDR kernel notify rountines are set for image loading, process and thread creations... [+] [NotifyRountines] Enumerating process creation callbacks [+] Running command: GodFault.exe -t 8344 [+] Thread 8344 (KTHREAD FFFF91096169F080) has been blessed by GodFault [+] Initial blessing successful [+] [NotifyRountines] fffff8034df25500 [cng.sys + 0x5500] [+] [NotifyRountines] fffff803487bc460 [ksecdd.sys + 0x1c460] [+] [NotifyRountines] fffff8034eff3fd0 [tcpip.sys + 0x13fd0] [+] [NotifyRountines] fffff8034f5ed980 [iorate.sys + 0xd980] [+] [NotifyRountines] fffff8034dea8890 [CI.dll + 0x88890] [+] [NotifyRountines] fffff803525079f0 [dxgkrnl.sys + 0x179f0] [+] [NotifyRountines] fffff80352be0a70 [vm3dmp.sys + 0x10a70] [+] [NotifyRountines] fffff8036ebccd00 [peauth.sys + 0x3cd00] [+] [NotifyRountines] fffff8036eda1550 [wtd.sys + 0x1550] [+] [NotifyRountines] No EDR driver(s) found! [+] [NotifyRountines] Enumerating thread creation callbacks [+] [NotifyRountines] fffff8036eb71010 [mmcss.sys + 0x1010] [+] [NotifyRountines] No EDR driver(s) found! [+] [NotifyRountines] Enumerating image loading callbacks [+] [NotifyRountines] fffff80352ab5710 [ahcache.sys + 0x25710] [+] [NotifyRountines] No EDR driver(s) found!

[+] Checking if EDR callbacks are registered on processes and threads handle creation/duplication... [+] [ObjectCallblacks] Enumerating Process object callbacks : [+] [ObjectCallblacks] Callback at FFFF800C5E2F2940 for handle creations & duplications: [+] [ObjectCallblacks] Status: Disabled [+] [ObjectCallblacks] Preoperation at 0xfffff8034e9eda30 [WdFilter.sys + 0x4da30] [+] [ObjectCallblacks] Callback belongs to an EDR but is disabled. [+] [ObjectCallblacks] Enumerating Thread object callbacks : [+] [ObjectCallblacks] Object callbacks are not found !

[+] [ETWTI] Checking the ETW Threat Intelligence Provider state... [+] [ETWTI] ETW Threat Intelligence Provider is DISABLED!

[+] Process is "safe" to launch our payload

[+] Kernel callbacks have normally been removed, starting cmd.exe WARNING: EDR kernel callbacks will be restored after exiting the cmd prompt (by typing exit) WARNING: While unlikely, the longer the callbacks are removed, the higher the chance of being detected / causing a BSoD upon restore is!

Microsoft Windows [Version 10.0.22621.1702] (c) Microsoft Corporation. All rights reserved.

C:\Users\user\Desktop\Offsets>

root@kitploit:~
# EDRSandBlast

`EDRSandBlast` は、`C` で書かれたツールで、脆弱性のある署名済みドライバを悪用して EDR 検出(通知ルーチンコールバック、オブジェクトコールバック、`ETW TI` プロバイダ)および `LSASS` 保護をバイパスします。ユーザーランド監視を回避するために、複数のユーザーランドアンフック手法も実装されています。

リリース時点では、ユーザーランド(`--usermode`)とカーネルランド(`--kernelmode`)の手法を組み合わせて、EDR の監視下で `LSASS` メモリをダンプし、製品(クラウド)コンソールでブロックされたり「OS 資格情報のダンプ」関連イベントが生成されたりすることはありませんでした。テストは 3 つの異なる EDR 製品に対して実施され、いずれの場合も成功しました。

## 説明

### カーネル通知ルーチン削除による EDR バイパス

EDR 製品は、Windows 上のカーネル「通知ルーチン」コールバックを使用して、プロセスやスレッドの作成、イメージ(`exe` / `DLL`)の読み込みなどのシステムアクティビティをカーネルから通知されます。

これらのカーネルコールバックは、通常はコールバックを実装するドライバからカーネルランドで定義され、文書化された API(`nt!PsSetCreateProcessNotifyRoutine`、`nt!PsSetCreateThreadNotifyRoutine` など)を使用します。これらの API は、ドライバが提供するコールバックルーチンを、カーネル空間の文書化されていないルーチンの配列に追加します。
  - `PspCreateProcessNotifyRoutine`(プロセス作成用)
  - `PspCreateThreadNotifyRoutine`(スレッド作成用)
  - `PspLoadImageNotifyRoutine`(イメージ読み込み用)

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

前述の配列のオフセットは複数の手法を使用して復元されます。[オフセットセクション](#ntoskrnl-and-wdigest-offsets) を参照してください。

### オブジェクトコールバック削除による 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
struct _CALLBACK_ENTRY_ITEM
{
    _CALLBACK_ENTRY_ITEM *CallbackListItemFlink;
    _CALLBACK_ENTRY_ITEM *CallbackListItemBlink;
    // その他のフィールド...
};
``````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;

root@kitploit:~
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;
}

CallbackListのLIST_ENTRYのFlinkポインタとBlinkポインタを自分自身のLIST_ENTRYを指すようにすることで、リストを効果的に空にすることができます。_OBJECT_TYPE構造体はカーネルシンボルで公開されているため、この手法はハードコードされたオフセットや構造体に依存しません。ただし、いくつかの欠点があります。

1つ目は、EDRからのコールバックだけを無効にできないことです。実際、この手法は「正規の」ソフトウェアによって登録された可能性のあるすべてのオブジェクトコールバックに影響を与えます。ただし、現時点(執筆時点)では、Windows 10のプリインストールコンポーネントはオブジェクトコールバックを使用していないため、それらを無効にしてもマシンの安定性に影響を与えるべきではないことに注意してください(無効化が一時的なものであればなおさらです)。

2つ目の欠点は、OSの通常の動作において、プロセスやスレッドのハンドル操作が非常に頻繁(ほぼ継続的)に行われることです。そのため、使用しているカーネル書き込みプリミティブがQWORD書き込みを「アトミックに」実行できない場合、_OBJECT_TYPE.CallbackList.Flinkポインタが上書きの途中でカーネルによってアクセスされる可能性が高くなります。例えば、MSIの脆弱なドライバRTCore64.sysは一度にDWORD書き込みしか実行できないため、ポインタを上書きするには2つの異なるIOCTLが必要であり、その間にカーネルがポインタを使用する可能性が高く(クラッシュが発生します)。一方、脆弱なDELLドライバDBUtil_2_3.sysは1つのIOCTLで任意のサイズの書き込みを実行できるため、この手法を使用してもクラッシュのリスクはありません。

オブジェクトコールバックの完全無効化

私たちが発見した最後の手法は、スレッドとプロセスのオブジェクトコールバックサポートを完全に無効にすることです。プロセスとスレッドタイプに対応する_OBJECT_TYPE構造体の中には、文書化された_OBJECT_TYPE_INITIALIZER構造体に従ったTypeInfoフィールドがあります。後者にはObjectTypeFlagsビットフィールドが含まれており、そのSupportsObjectCallbacksフラグは、記述されたオブジェクトタイプ(Process、Thread、Desktop、Token、Fileなど)がオブジェクトコールバックの登録をサポートするかどうかを決定します。前述の通り、現時点ではWindowsのインストールにおいてProcess、Thread、Desktopオブジェクトタイプのみがこれらのコールバックをサポートしています。

SupportsObjectCallbacksビットは、ObpCreateHandleまたはObDuplicateObjectによってCallbackListを読み取る前(もちろんコールバックを実行する前)にチェックされるため、カーネル実行時にこのビットを反転すると、すべてのオブジェクトコールバックの実行が効果的に無効になります。

この方法の主な欠点は、KPP("PatchGuard")が一部(すべて?)の_OBJECT_TYPE構造体の整合性を監視し、パラメータ4が0x8(オブジェクトタイプ構造体が変更されたことを意味する)の0x109 Bug Checkをトリガーすることです。

ただし、無効化/再有効化(およびその間の「悪意のある」アクション)を十分に迅速に実行すれば、PatchGuardを「競争」するのに十分です(不運にも、ちょうど悪いタイミングで定期的なチェックが実行されない限り)。

ETW Microsoft-Windows-Threat-Intelligenceプロバイダーの無効化によるEDRバイパス

ETW Microsoft-Windows-Threat-Intelligenceプロバイダーは、悪意のある目的で一般的に使用される一部のWindows APIの使用状況に関するデータをログに記録します。これには、nt!MiReadWriteVirtualMemory APIが含まれます。このAPIはnt!NtReadVirtualMemory(LSASSメモリのダンプに使用される)によって呼び出され、nt!EtwTiLogReadWriteVm関数によって監視されます。

EDR製品は、それぞれSERVICE_LAUNCH_PROTECTED_ANTIMALWARE_LIGHTまたはPS_PROTECTED_ANTIMALWARE_LIGHTとして実行され、Early Launch Anti Malware (ELAM)ドライバに関連付けられたサービスまたはプロセスを通じて、ETW TIプロバイダーが生成したログを消費できます。

slaeryan氏によるCNO Development Labsのブログ記事で公開されているように、ETW TIプロバイダーは、カーネルメモリ内でそのProviderEnableInfo属性を0x0にパッチすることで完全に無効化できます。この手法の詳細については、前述の素晴らしいブログ記事を参照してください。

カーネルコールバックの削除と同様に、必要なntoskrnl.exeのオフセット(nt!EtwThreatIntProvRegHandleOffset、_ETW_REG_ENTRYのGuidEntry、_ETW_GUID_ENTRYのProviderEnableInfo)は、多くのWindowsカーネルバージョンについてNtoskrnlOffsets.csvファイルで計算されています。

ユーザーランドフッキングのバイパスによるEDRバイパス

ユーザーランドフッキングの仕組み

プロセスによって実行されるアクションを簡単に監視するために、EDR製品はしばしばユーザーランドフッキングと呼ばれるメカニズムを採用します。まず、EDR製品はカーネルコールバック(通常はイメージロードまたはプロセス作成コールバック、上記参照)を登録し、各プロセスの開始時に通知を受け取れるようにします。

Windowsによってプロセスがロードされ、実際に起動する前に、EDRはその監視ロジックを含むカスタムDLLをプロセスアドレス空間に注入できます。ロード中に、このDLLはEDRによって監視される各関数の先頭に「フック」を注入します。実行時、監視下のプロセスによって監視対象の関数が呼び出されると、これらのフックは制御フローをEDRのDLL内の監視コードにリダイレクトし、それらの呼び出しの引数と戻り値を検査できるようにします。

ほとんどの場合、監視対象の関数はシステムコール(NtReadVirtualMemory、NtOpenProcessなど)であり、その実装はntdll.dllに存在します。Nt*関数への呼び出しをインターセプトすることで、製品はユーザーランド/カーネルランド境界に可能な限り近づくことができます(ユーザーランドに留まりながら)。ただし、いくつかの高レベルDLLの関数も監視される場合があります。

以下は、同じ関数がEDR製品によってフックされる前と後の例です:```assembly NtProtectVirtualMemory proc near mov r10, rcx mov eax, 50h test byte ptr ds:7FFE0308h, 1 jnz short loc_18009D1E5 syscall retn loc_18009D1E5: int 2Eh retn NtProtectVirtualMemory endp

root@kitploit:~
未知のバイナリに対するリバースエンジニアリングやエクスプロイト開発を始める際、私はよく`strings`を使います。多くの場合、バイナリ内の文字列には有用な情報が含まれています。

### 文字列からスクリプトへ

私がよく使う一般的な`strings`の*ワンライナー*は、コマンド文字列のように見える文字列だけを抽出する方法です。通常、バイナリにはコマンド、サブコマンド、オプションなどの文字列が含まれています。これらは通常、文字で始まり、小文字とハイフンのみを含む文字列で、たとえば`add`、`delete`、`backup`、`do-thing`のようなものです。

これらの文字列を自動的に抽出するには`rawdog`を使います。```assembly
NtProtectVirtualMemory proc near
	jmp     sub_7FFC74490298     ; --> "hook", jump to EDR analysis function
	int 3                        ; overwritten instructions
	int 3                        ; overwritten instructions
	int 3                        ; overwritten instructions
	test byte_7FFE0308, 1        ; <-- execution resumes here after analysis
	jnz short loc_7FFCB44AD1E5
	syscall
	retn
loc_7FFCB44AD1E5:
	int 2Eh
	retn
NtProtectVirtualMemory   endp			

フック検出

ユーザーランドフックには、ユーザーランドメモリに配置されるという「弱点」があり、それは監視対象のプロセスから直接観測・変更可能であることを意味します。プロセスアドレス空間内のフックを自動的に検出するためには、ディスク上の元のDLLと、EDRによって変更された可能性のあるメモリ上のライブラリとの差分を比較することが主なアイデアです。この比較を行うために、EDRSandblastは以下の手順を実行します。

  • ロードされたすべてのDLLのリストは、PEB内のInLoadOrderModuleListを使用して列挙されます(監視や疑わしい可能性のあるAPIを呼び出さないため)。
  • ロードされた各DLLについて、ディスク上の内容が読み取られ、ヘッダーが解析されます。対応するメモリ上のライブラリも解析され、セクション、エクスポートなどが特定されます。
  • DLLのリロケーションが解析・適用され、対応するロード済みライブラリのベースアドレスが考慮されます。これにより、メモリ上のライブラリとディスク上のDLLの内容が(リロケーションが適用されるセクションにおいて)完全に同一となり、比較が信頼できるものになります。
  • エクスポートされた関数が列挙され、「メモリ上」と「ディスク上」のバージョンの先頭バイトが比較されます。差異がある場合は、DLLのロード後に行われた変更を示しており、したがってほぼ確実にEDRフックです。

注: このプロセスは、書き込み不可能なセクション内の任意の場所(たとえばEDR製品が関数の途中にフックを適用し始めた場合など)の差異を見つけるように一般化できます。そのため、ツールでは使用されていませんが、findDiffsInNonWritableSections に実装されています。

これらのフックによる監視を回避するためには、複数の手法が可能であり、それぞれに利点と欠点があります。

フックバイパス(... アンフックを使用)

フックベースの監視をバイパスする最も直感的な方法は、フックを削除することです。フックはプロセス自身がアクセス可能なメモリに存在するため、フックを削除するにはプロセスは単に以下の操作を行います。

  • フックが配置されているページの権限を変更する(RX → RWX または RW)
  • ディスク上のDLLの内容から既知の元のバイトを書き込む
  • 権限をRXに戻す

この方法は非常にシンプルで、検出されたすべてのフックを一度に削除するために使用できます。攻撃ツールの開始時に実行されることで、残りのコードはフック機構を完全に認識せず、監視されることなく正常に動作できるようになります。

ただし、主に2つの欠点があります。EDRはおそらくNtProtectVirtualMemoryの使用を監視しているため、これを使用してフックがインストールされたページの権限を変更することは(少なくとも概念的には)悪い考えです。また、EDRによってスレッドが実行され、定期的にフックの整合性をチェックする場合、これも検出を引き起こす可能性があります。

実装の詳細については、unhook_methodがUNHOOK_WITH_NTPROTECTVIRTUALMEMORYの場合のunhook()関数のコードパスを確認してください。

重要な注意: 簡略化のため、この手法はEDRSandblastにおいて、他のバイパス手法を紹介するための基本手法として実装されています。各手法は、監視されていないNtProtectVirtualMemoryを取得する方法を示していますが、その後は同じ操作(特定のフックのアンフック)を実行します。

カスタムトランポリンを使用したフックバイパス

特定のフックをバイパスするには、単に「ジャンプオーバー」して関数の残りの部分をそのまま実行することが可能です。まず、EDRがフックをインストールするために上書きした監視対象関数の元のバイトを、DLLファイルから復元する必要があります。前のコード例では、これは以下の命令に対応するバイトになります。```assembly mov r10, rcx mov eax, 50h

root@kitploit:~
これらのバイトを特定するのは簡単な作業です。なぜなら、前述の通り、ライブラリのメモリバージョンとディスクバージョンの両方のクリーンな*diff*を実行できるからです。次に、フックの直後に続くコードへ制御フローをリダイレクトするためのジャンプ命令を組み立てます。アドレス `NtProtectVirtualMemory + sizeof(overwritten_instructions)` において。```assembly
jmp NtProtectVirtualMemory+8

最後に、これらのオペコードを連結し、(新しく)実行可能なメモリに格納して、それらへのポインタを保持します。このオブジェクトは「トランポリン」と呼ばれ、元の NtProtectVirtualMemory 関数と厳密に同等の関数ポインタとして使用できます。

このテクニックの主な利点は、以下に示すすべてのテクニックと同様に、フックが決して消去されないため、EDRによってフックに対して実行される整合性チェックを通過できることです。ただし、書き込み可能なメモリを割り当ててから実行可能なメモリにする必要があり、これはシェルコードの割り当てに典型的であり、EDRの監視を引きつけます。

実装の詳細については、unhook_method が UNHOOK_WITH_INHOUSE_NTPROTECTVIRTUALMEMORY_TRAMPOLINE の場合の unhook() 関数のコードパスを確認してください。このテクニックは私たちの実装でのみ紹介されており、結局のところ、以下のすべてのテクニックと同様に、メモリからフックを削除するために使用されることを覚えておいてください。

EDR自身のトランポリンを使ったフックバイパス

EDR製品は、そのフックが機能するために、削除したオペコードをメモリのどこかに保存する必要があります。さらに悪いことに(あるいは攻撃者の視点から見れば「より良い」ことに)、元の命令を効果的に使用するために、EDRはおそらく自身でトランポリンをどこかに割り当て、呼び出しを傍受した後に元の関数を実行します。

このトランポリンを検索して、フックされた関数の代わりとして使用できます。その際、実行可能メモリを割り当てたり、VirtualQuery(無害な関数であるため、ほとんどの場合監視されていない)以外のAPIを呼び出す必要はありません。

メモリ内のトランポリンを見つけるために、VirtualQueryを使ってアドレス空間全体をブラウズし、コミット済みで実行可能なメモリを探します。そのようなメモリ領域ごとに、上書きされた命令の次のアドレス(前述の例では NtProtectVirtualMemory+8)をターゲットとするジャンプ命令を探すためにスキャンします。その後、そのトランポリンを使用して、フックをトリガーせずにフックされた関数を呼び出すことができます。

このテクニックは驚くほど効果的で、テストしたEDR上のほとんどすべてのトランポリンを回復します。実装の詳細については、unhook_method が UNHOOK_WITH_EDR_NTPROTECTVIRTUALMEMORY_TRAMPOLINE の場合の unhook() 関数のコードパスを確認してください。

重複DLLを使用したフックバイパス

NtProtectVirtualMemory 関数の監視されていないバージョンにアクセスする別の簡単な方法は、プロセスのアドレス空間に ntdll.dll ライブラリの重複バージョンをロードすることです。2つの同一のDLLは異なる名前であれば同じプロセスにロードできるため、正規の ntdll.dll ファイルを別の場所にコピーし、LoadLibrary を使用してロードする(またはロード処理を再実装する)だけで、例えば GetProcAddress を使用して関数にアクセスできます。

このテクニックは理解と実装が非常に簡単で、成功の可能性も十分にあります。なぜなら、ほとんどのEDR製品はプロセス実行中に新しくロードされたDLLにフックを再インストールしないからです。ただし、大きな欠点は、Microsoft署名済みのバイナリを別の名前でコピーすること自体がEDR製品によって疑わしいと見なされることが多いことです。

それでもこのテクニックは EDRSandblast に実装されています。実装の詳細については、unhook_method が UNHOOK_WITH_DUPLICATE_NTPROTECTVIRTUALMEMORY の場合の unhook() 関数のコードパスを確認してください。

ダイレクトシステムコールを使用したフックバイパス

システムコール関連の関数を使用するために、プログラムはシステムコールを(アセンブリで)再実装し、EDRによって監視される可能性のある ntdll.dll 内のコードに実際に触れることなく、対応するOS機能を呼び出すことができます。これにより、ntdll.dll 内のシステムコール関数に対して行われたユーザーランドフックを完全にバイパスします。

ただし、これにはいくつかの欠点があります。まず、プログラムが必要とする関数のシステムコール番号のリストを把握する必要があり、これはWindowsのバージョンごとに異なります。しかし、これはWindows NTの過去すべてのバージョンで動作することが知られている複数のヒューリスティック(ntdll の Zw* エクスポートのソート、関連する ntdll 関数内の mov rax, #system_call_number 命令の検索など)を実装し、それらがすべて同じ結果を返すことを確認することで緩和されています(詳細は Syscalls.c を参照)。

また、技術的にはシステムコールではない関数(例:LoadLibraryX/LdrLoadDLL)も監視される可能性があり、単純にシステムコールで再実装することはできません。

ダイレクトシステムコールのテクニックは EDRSandblast に実装されています。前述の通り、これは安全に NtProtectVirtualMemory を実行し、検出されたすべてのフックを削除するためだけに使用されます。

実装の詳細については、unhook_method が UNHOOK_WITH_DIRECT_SYSCALL の場合の unhook() 関数のコードパスを確認してください。

脆弱なドライバの悪用

前述の通り、カーネルメモリの読み取りまたは書き込みを必要とするすべてのアクションは、このプリミティブを提供する脆弱なドライバに依存しています。EDRSandblast では、読み取り/書き込みプリミティブを提供する新しいドライバのサポートを追加することは「簡単に」行えます。実装する必要がある関数は3つだけです:

  • ReadMemoryPrimitive_DRIVERNAME(SIZE_T Size, DWORD64 Address, PVOID Buffer) 関数:カーネルアドレス Address から Size バイトをユーザーランドバッファ Buffer にコピーします。
  • WriteMemoryPrimitive_DRIVERNAME(SIZE_T Size, DWORD64 Address, PVOID Buffer) 関数:ユーザーランドバッファ Buffer から Size バイトをカーネルアドレス Address にコピーします。
  • CloseDriverHandle_DRIVERNAME() 関数:ドライバへのすべてのハンドルが閉じられていることを確認します(現在、ドライバ非依存のアンインストール操作の前に必要です)。

例として、現在 EDRSandblast では2つのドライバがサポートされています:RTCore64.sys(SHA256: 01AA278B07B58DC46C84BD0B1B5C8E9EE4E62EA0BF7A695862444AF32E87F1FD)および DBUtils_2_3.sys(SHA256: 0296e2ce999e67c76352613a718e11516fe1b0efc3ffdb8918fc999dd76a73a5)。使用する脆弱なドライバを変更する場合、または新しいドライバを実装する場合には、以下の KernelMemoryPrimitives.h 内のコードを更新する必要があります。```C #define RTCore 0 #define DBUtil 1 // Select the driver to use with the following #define #define VULN_DRIVER RTCore

#if VULN_DRIVER == RTCore #define DEFAULT_DRIVER_FILE TEXT("RTCore64.sys") #define CloseDriverHandle CloseDriverHandle_RTCore #define ReadMemoryPrimitive ReadMemoryPrimitive_RTCore #define WriteMemoryPrimitive WriteMemoryPrimitive_RTCore #elif VULN_DRIVER == DBUtil #define DEFAULT_DRIVER_FILE TEXT("DBUtil_2_3.sys") #define CloseDriverHandle CloseDriverHandle_DBUtil #define ReadMemoryPrimitive ReadMemoryPrimitive_DBUtil #define WriteMemoryPrimitive WriteMemoryPrimitive_DBUtil #endif

root@kitploit:~
### EDRドライバーとプロセスの検出
特定のドライバーまたはプロセスがEDR製品に属するかどうかを判断するために、現在複数の手法が使用されています。

まず、ドライバー名をその目的のために単純に使用できます。実際、Microsoftはカーネルにコールバックを挿入する必要があるすべてのドライバーに「Altitude」と呼ばれる特定の番号を割り当てています。これにより、登録順序に関係なく、ドライバーの使用状況のみに基づいて、コールバック実行の決定論的な順序が可能になります。特定の*altitude*を予約しているドライバー(のベンダー)のリストは[MSDN](https://docs.microsoft.com/en-us/windows-hardware/drivers/ifs/allocated-altitudes)にあります。その結果、Microsoftは主に「FSFilter Anti-Virus」および「FSFilter Activity Monitor」のリストにおいて、セキュリティ製品に関連するセキュリティドライバー名のほぼ包括的なリストを提供しています。これらのドライバー名のリストはEDRSandblastに組み込まれており、さらに追加の貢献もあります。

さらに、EDRの実行可能ファイルやDLLは、多くの場合、ベンダーの署名証明書を使用してデジタル署名されています。したがって、プロセスに関連付けられた実行可能ファイルまたはDLLの署名者を確認することで、EDR製品を迅速に識別できる可能性があります。

また、ドライバーはカーネル空間にロードされるために、Microsoftによって直接署名される必要があります。ドライバーのベンダーがドライバー自体の直接の署名者ではないものの、ベンダー名が署名の属性内に含まれていると思われます。ただし、この検出手法はまだ調査および実装されていません。

最後に、EDRSandblastに未知のEDRに直面した場合、最善のアプローチはツールを「監査」モードで実行し、カーネルコールバックを登録したドライバーのリストを確認することです。その後、ドライバー名をリストに追加し、ツールを再コンパイルして再実行できます。

### RunAsPPLバイパス

「Local Security Authority (LSA) Protection」メカニズムは、Windows 8.1およびWindows Server 2012 R2で最初に導入され、「Protected Process Light (PPL)」テクノロジを活用して`LSASS`プロセスへのアクセスを制限します。`PPL`保護は、`SeDebugPrivilege`権限を持つプロセスからであっても、保護されたプロセスのメモリインジェクションやメモリダンプなどの操作を規制および制限します。プロセス保護モデルでは、より高い保護レベルで実行されているプロセスのみが、保護されたプロセスに対して操作を実行できます。

Windowsカーネルがプロセスをカーネルメモリ内で表現するために使用する`_EPROCESS`構造体には、`Type`(`_PS_PROTECTED_TYPE`)および`Signer`(`_PS_PROTECTED_SIGNER`)属性を通じてプロセスの保護レベルを定義する`_PS_PROTECTION`フィールドが含まれています。

カーネルメモリに書き込むことにより、EDRSandblastプロセスは自身の保護レベルを`PsProtectedSignerWinTcb-Light`に昇格できます。このレベルは、`RunAsPPL`メカニズムで実行されている`LSASS`プロセスの保護レベルである`PsProtectedSignerLsa-Light`を「支配」するため、`LSASS`プロセスのメモリをダンプするのに十分です。

`EDRSandBlast`は次のように自己保護を実装します:
  - 現在のプロセスへのハンドルを開く
  - `NtQuerySystemInformation`を使用してすべてのシステムハンドルをリークし、現在のプロセスで開かれているハンドルと、カーネルメモリ内の現在のプロセスの`EPROCESS`構造体のアドレスを見つける。
  - `Micro-Star MSI Afterburner`ドライバーの任意読み取り/書き込みの脆弱性を利用して、カーネルメモリ内の現在のプロセスの`_PS_PROTECTION`フィールドを上書きする。`_PS_PROTECTION`フィールドの`EPROCESS`構造体(使用中の`ntoskrnl`バージョンによって定義される)に対するオフセットは、`NtoskrnlOffsets.csv`ファイルで計算されます。

### Credential Guardバイパス

Microsoftの`Credential Guard`は、仮想化ベースの分離テクノロジであり、Microsoftの`Windows 10 (Enterprise edition)`で導入され、`LSASS`プロセスに保存されている資格情報への直接アクセスを防ぎます。

`Credentials Guard`がアクティブ化されると、`LSAIso`(*LSA Isolated*)プロセスが`Virtual Secure Mode`で作成されます。これは、CPUの仮想化拡張機能を利用してメモリ内のデータのセキュリティを強化する機能です。`LSAIso`プロセスへのアクセスは、`NT AUTHORITY\SYSTEM`セキュリティコンテキストを持つアクセスであっても制限されます。ハッシュを処理するとき、`LSA`プロセスは`LSAIso`プロセスに`RPC`呼び出しを実行し、`LSAIso`の結果を待って続行します。したがって、`LSASS`プロセスにはシークレットは含まれず、代わりに`LSA Isolated Data`が保存されます。

`N4kedTurtle`によって行われた元の研究で述べられているように:「`Wdigest`は、メモリ内の`g_fParameter_useLogonCredential`および`g_IsCredGuardEnabled`の値をパッチすることで、Credential Guardが有効なシステムで有効にできます」。`Wdigest`のアクティブ化により、新しいインタラクティブログオンに対してクリアテキスト資格情報が`LSASS`メモリに保存されるようになります(システムの再起動は不要)。この手法の詳細については、[元の研究ブログ記事](https://teamhydra.blog/2020/08/25/bypassing-credential-guard/)を参照してください。

`EDRSandBlast`は元のPoCを少しだけOpSecフレンドリーにし、いくつかの`wdigest.dll`バージョン(`g_fParameter_useLogonCredential`および`g_IsCredGuardEnabled`の計算されたオフセットを通じて)をサポートします。

### オフセットの取得

カーネル監視バイパス操作を確実に実行するために、EDRSandblastはカーネルメモリのどこを読み書きするかを正確に知る必要があります。これは、対象イメージ(ntoskrnl.exe、wdigest.dll)内のグローバル変数のオフセット、およびシンボルファイル内でMicrosoftによって定義が公開されている構造体の特定のフィールドのオフセットを使用して行われます。これらのオフセットは対象イメージの各ビルドに固有であり、特定のプラットフォームバージョンに対して少なくとも1回収集する必要があります。

EDRSandblastで使用される構造体および変数を見つけるためにパターン検索ではなく「ハードコードされた」オフセットを使用する選択は、カーネルコールバックの追加/削除を担当する文書化されていないAPIが変更される可能性があり、間違ったアドレスでカーネルメモリを読み書きしようとすると(多くの場合)`Bug Check`(`Blue Screen of Death`)が発生する可能性があるという事実によって正当化されます。マシンのクラッシュは、レッドチーミングおよび通常のペネトレーションテストの両方のシナリオで許容できません。クラッシュしたマシンは防御側から非常に目立ち、攻撃時にメモリ内に残っていた資格情報も失われるためです。

Windowsの特定のバージョンごとにオフセットを取得するために、2つのアプローチが実装されています。

#### 手動オフセット取得

必要な`ntoskrnl.exe`および`wdigest.dll`のオフセットは、提供されている`ExtractOffsets.py` Pythonスクリプトを使用して抽出できます。このスクリプトは、`radare2`および`r2pipe`に依存してPDBファイルからシンボルをダウンロードおよび解析し、そこから必要なオフセットを抽出します。オフセットは後でEDRSandblastが使用するためにCSVファイルに保存されます。

幅広いWindowsビルドをすぐにサポートするために、多くのバージョンの`ntoskrnl.exe`および`wdigest.dll`バイナリが[Winbindex](https://winbindex.m417z.com/)で参照されており、`ExtractOffsets.py`によって自動的にダウンロード(およびそのオフセットが抽出)されます。これにより、Windows Updateパッケージで公開されたほぼすべてのファイルからオフセットを抽出できます(現在までに450以上の`ntoskrnl.exe`と30以上の`wdigest.dll`バージョンが利用可能で、事前計算されています)。

#### 自動オフセット取得と更新

`EDRSandBlast`には、プログラムがMicrosoftシンボルサーバーから必要な`.pdb`ファイルを自分でダウンロードし、必要なオフセットを抽出し、対応する`.csv`ファイルが存在する場合はそれを更新できるようにする追加オプションが実装されています。

`--internet`オプションを使用すると、ツールの実行がはるかに簡単になりますが、追加のOpSecリスクが発生します。これは、プロセス中に`.pdb`ファイルがダウンロードされてディスクに保存されるためです。これはシンボルデータベースの解析に使用される`dbghelp.dll`関数で必要とされます。ただし、この要件をなくしツールのフットプリントを減らすために、将来は完全なインメモリPDB解析が実装される可能性があります。

## 使用方法

脆弱な`RTCore64.sys`ドライバーは以下から入手できます:```
http://download-eu2.guru3d.com/afterburner/%5BGuru3D.com%5D-MSIAfterburnerSetup462Beta2.zip

簡単な使い方```

Usage: EDRSandblast.exe [-h | --help] [-v | --verbose] <audit | dump | cmd | credguard> [--usermode [--unhook-method ]] [--kernelmode] [--dont-unload-driver] [--dont-restore-callbacks] [--driver <RTCore64.sys>] [--service <SERVICE_NAME>] [--nt-offsets <NtoskrnlOffsets.csv>] [--wdigest-offsets <WdigestOffsets.csv>] [--add-dll ]* [-o | --dump-output <DUMP_FILE>]

root@kitploit:~
### オプション```
-h | --help             Show this help message and exit.
-v | --verbose          Enable a more verbose output.

Actions mode:

        audit           Display the user-land hooks and / or Kernel callbacks without taking actions.
        dump            Dump the LSASS process, by default as 'lsass' in the current directory or at the
                        specified file using -o | --output <DUMP_FILE>.
        cmd             Open a cmd.exe prompt.
        credguard       Patch the LSASS process' memory to enable Wdigest cleartext passwords caching even if
                        Credential Guard is enabled on the host. No kernel-land actions required.

--usermode              Perform user-land operations (DLL unhooking).
--kernelmode            Perform kernel-land operations (Kernel callbacks removal and ETW TI disabling).

--unhook-method <N>
   Choose the userland un-hooking technique, from the following:

        1 (Default)     Uses the (probably monitored) NtProtectVirtualMemory function in ntdll to remove all
                        present userland hooks.
        2               Constructs a 'unhooked' (i.e. unmonitored) version of NtProtectVirtualMemory, by
                        allocating an executable trampoline jumping over the hook, and remove all present
                        userland hooks.
        3               Searches for an existing trampoline allocated by the EDR itself, to get an 'unhooked'
                        (i.e. unmonitored) version of NtProtectVirtualMemory, and remove all present userland
                        hooks.
        4               Loads an additional version of ntdll library into memory, and use the (hopefully
                        unmonitored) version of NtProtectVirtualMemory present in this library to remove all
                        present userland hooks.
        5               Allocates a shellcode that uses a direct syscall to call NtProtectVirtualMemory,
                        and uses it to remove all detected hooks

Other options:

--dont-unload-driver                    Keep the vulnerable driver installed on the host
                                        Default to automatically unsinstall the driver.
--dont-restore-callbacks                Do not restore the EDR drivers' Kernel Callbacks that were removed.
                                        Default to restore the callbacks.

--driver <RTCore64.sys>                 Path to the vulnerable driver file.
                                        Default to 'RTCore64.sys' in the current directory.
--service <SERVICE_NAME>                Name of the vulnerable service to intall / start.

--nt-offsets <NtoskrnlOffsets.csv>      Path to the CSV file containing the required ntoskrnl.exe's offsets.
                                        Default to 'NtoskrnlOffsets.csv' in the current directory.
--wdigest-offsets <WdigestOffsets.csv>  Path to the CSV file containing the required wdigest.dll's offsets
                                        (only for the 'credguard' mode).
                                        Default to 'WdigestOffsets.csv' in the current directory.

--add-dll <dll name or path>            Loads arbitrary libraries into the process' address space, before starting
                                        anything. This can be useful to audit userland hooking for DLL that are not
                                        loaded by default by this program. Use this option multiple times to load
                                        multiple DLLs all at once.
                                        Example of interesting DLLs to look at: user32.dll, ole32.dll, crypt32.dll,
                                        samcli.dll, winhttp.dll, urlmon.dll, secur32.dll, shell32.dll...

-o | --output <DUMP_FILE>               Output path to the dump file that will be generated by the 'dump' mode.
                                        Default to 'lsass' in the current directory.

-i | --internet                         Enables automatic symbols download from Microsoft Symbol Server
                                        If a corresponding *Offsets.csv file exists, appends the downloaded offsets to the file for later use
                                        OpSec warning: downloads and drops on disk a PDB file for ntoskrnl.exe and/or wdigest.dll

ビルド

EDRSandBlast(x64のみ)はVisual Studio 2019(Windows SDK バージョン: 10.0.19041.0、プラットフォームツールセット: Visual Studio 2019 (v142))でビルドされました。

ExtractOffsets.py の使い方

なお、ExtractOffsets.py はWindows上でのみテストされています。```

Installation of Python dependencies

pip.exe install -m .\requirements.txt

Script usage

ExtractOffsets.py [-h] -i INPUT [-o OUTPUT] [-d] mode

positional arguments: mode ntoskrnl or wdigest. Mode to download and extract offsets for either ntoskrnl or wdigest

optional arguments: -h, --help show this help message and exit -i INPUT, --input INPUT Single file or directory containing ntoskrnl.exe / wdigest.dll to extract offsets from. If in download mode, the PE downloaded from MS symbols servers will be placed in this folder. -o OUTPUT, --output OUTPUT CSV file to write offsets to. If the specified file already exists, only new ntoskrnl versions will be downloaded / analyzed. Defaults to NtoskrnlOffsets.csv / WdigestOffsets.csv in the current folder. -d, --download Flag to download the PE from Microsoft servers using list of versions from winbindex.m417z.com.

root@kitploit:~
## Detection
From the defender (EDR vendor, Microsoft, SOC analysts looking at EDR's telemetry, ...) point of view, multiple indicators can be used to detect or prevent this kind of techniques.

### Driver whitelisting
Since every action performed by the tool in kernel-mode memory relies on a vulnerable driver to read/write arbitrary content, driver loading events should be heaviliy scrutinized by EDR product (or SOC analysts), and raise an alert at any uncommon driver loading, or even block known vulnerable drivers. This latter approach is even [recommended by Microsoft themselves](https://docs.microsoft.com/en-us/windows/security/threat-protection/windows-defender-application-control/microsoft-recommended-driver-block-rules): any HVCI (*Hypervisor-protected code integrity*) enabled Windows device embeds a drivers blocklist, and this will be progressively become a default behaviour on Windows (it already is on Windows 11).

### Kernel-memory integrity checks
Since an attacker could still use an unknown vulnerable driver to perform the same actions in memory, the EDR driver could periodically check that its kernel callbacks are still registered, directly by inspecting kernel memory (like this tool does), or simply by triggering events (process creation, thread creation, image loading, etc.) and checking the callback functions are indeed called by the executive kernel.

As a side note, this type of data structure could be protected via the recent [Kernel Data Protection (KDP)](https://www.microsoft.com/security/blog/2020/07/08/introducing-kernel-data-protection-a-new-platform-security-technology-for-preventing-data-corruption/) mechanism, which relies on Virtual Based Security, in order to make the kernel callbacks array non-writable without calling the right APIs.

The same logic could apply to sensitive ETW variables such as the `ProviderEnableInfo`, abused by this tool to disable the ETW Threat Intelligence events generation.

### User-mode detection
The first indicator that a process is actively trying to evade user-land hooking is the file accesses to each DLL corresponding to loaded modules; in a normal execution, a userland process rarely needs to read DLL files outside of a `LoadLibrary` call, especially `ntdll.dll`.

In order to protect API hooking from being bypassed, EDR products could periodically check that hooks are not altered in memory, inside each monitored process.

Finally, to detect hooking bypass (abusing a trampoline, using direct syscalls, etc.) that does not imply the hooks removal, EDR products could potentially rely on kernel callbacks associated to the abused syscalls (ex. `PsCreateProcessNotifyRoutine` for `NtCreateProcess` syscall, `ObRegisterCallbacks` for `NtOpenProcess` syscall, etc.), and perform user-mode call-stack analysis in order to determine if the syscall was triggered from a normal path (`kernel32.dll` -> `ntdll.dll` -> syscall) or an abnormal one (ex. `program.exe` -> direct syscall).


## Acknowledgements

- Kernel callbacks enumeration and removal:
  https://github.com/br-sn/CheekyBlinder

- Kernel memory Read / Write primitives through the vulnerable
  `Micro-Star MSI Afterburner` driver:
  https://github.com/Barakat/CVE-2019-16098/

- Disabling of the ETW Threat Intelligence provider:
  https://public.cnotools.studio/bring-your-own-vulnerable-kernel-driver-byovkd/exploits/data-only-attack-neutralizing-etwti-provider

- Driver install / uninstall: https://github.com/gentilkiwi/mimikatz

- Initial list of EDR drivers names:
  https://github.com/SadProcessor/SomeStuff/blob/master/Invoke-EDRCheck.ps1

- Credential Guard bypass by re-enabling `Wdigest` through `LSASS` memory
  patching: https://teamhydra.blog/2020/08/25/bypassing-credential-guard/


## Authors

[Thomas DIOT (Qazeer)](https://github.com/Qazeer/)
[Maxime MEIGNAN (themaks)](https://github.com/themaks)

## Licence

CC BY 4.0 licence - https://creativecommons.org/licenses/by/4.0/
ツールをダウンロード