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

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

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

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

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
BYOVD-DriverKiller — 驱动程序逆向与利用 | Kitploit
ツール/GitHubGitHub/alex3o/byovd-driverkiller
エクスプロイトリバースエンジニアリングポストエクスプロイトバイナリ解析学習と教育レッドチーミング
GitHubalex3o/byovd-driverkiller

BYOVD-DriverKiller

驱动程序逆向与利用

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

人気

すべて見る →

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

すべてのツールを探索

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

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

BYOVD-DriverKiller

⚠️ 警告: このプロジェクトは厳密に教育的・デモンストレーション目的です。悪意のある目的で使用することを意図していません。目的は、リバースエンジニアリングの手法とWindowsドライバーのエクスプロイト手順を学ぶことです。


ここでは、d1rk(SaadAhla) https://github.com/SaadAhla が提供する演習を解くために私が取ったアプローチを説明します。この演習は、正規に署名され、ブロックリスト(HVCI、LOLBIN...)に存在しないドライバーに対してリバースエンジニアリングとエクスプロイトを行うというものです。 このカーネルモードドライバーを介してシステム上の任意のアクティブなプロセスを終了できるCプログラムも用意しています。その動作については、この後詳しく説明します。

POC-BYOD

📃 使用方法: DriverKiller.exe <プロセス名.exe> [-d]

オプション -d : エクスプロイト後にサービスとドライバーをシステムから削除します。

ドライバーの証明書が期限切れのため、ターゲットマシンでテスト署名モードを有効にする必要があります。


パート1 - リバースエンジニアリング:

演習では、SHA-256ハッシュを名前とする.sysファイルが提供されます。 最初のステップは、このファイルをIDAで開くことです。
IDAは無料で利用できます。Hex-Raysのサイトにアクセスしてライセンスを生成し、ソフトウェアをダウンロードするだけです。

まず、ドライバーのIAT(Import Address Table)を一覧表示し、目的のAPIへの呼び出しを探します: ZwTerminateProcess。

screen1-git

ZwTerminateProcess をダブルクリックすると、IDAはこの関数のコンパイル済みコードに移動します。エントリを選択してクロスリファレンスを表示すると、それを呼び出すドライバーの関数のリストが得られます。

screen2-git

ZwTerminateProcess を使用しているのは、オフセット 1CE の関数 sub_12EF4 であることがわかります。ダブルクリックすると、IDAはそのコンパイル済みコードを表示します。

screen11-git

逆コンパイルされたコードには、ZwOpenProcess(ターゲットプロセスへのハンドルを開く)と ZwTerminateProcess(そのハンドルを介してプロセスを終了する)への呼び出しが示されています。

ZwOpenProcess のドキュメント(https://learn.microsoft.com/fr-fr/windows-hardware/drivers/ddi/ntddk/nf-ntddk-zwopenprocess)を参照すると、ClientID パラメータが対象プロセスのPIDを示すポインタであることがわかります。

その上の行では、ClientId.UniqueProcess が変数 v22 で初期化されています。これはその直前に定義されています:

v22 = (void )((_QWORD *)i + 10);

この代入を理解するには、変数 i と +10 フィールドを特定する必要があります。

screen3-git

この関数のさらに上では、SYSTEM_PROCESS_INFORMATION パラメータを指定した ZwQuerySystemInformation への呼び出しがあります。また、i が変数 v6 とともにこの構造体のエントリを反復するイテレータであることもわかります。

ZwQuerySystemInformation のドキュメント(https://learn.microsoft.com/en-us/windows/win32/sysinfo/zwquerysysteminformation)によると、この関数はシステム上のアクティブなプロセスごとに1エントリを含む配列を返します。

SYSTEM_PROCESS_INFORMATION 構造体は、https://learn.microsoft.com/en-us/windows/win32/api/winternl/nf-winternl-ntquerysysteminformation で説明されています。

typedef struct _SYSTEM_PROCESS_INFORMATION {
    ULONG NextEntryOffset;
    ULONG NumberOfThreads;
    BYTE Reserved1[48];
    UNICODE_STRING ImageName;
    KPRIORITY BasePriority;
    HANDLE UniqueProcessId;
    PVOID Reserved2;
    ULONG HandleCount;
    ULONG SessionId;
    PVOID Reserved3;
    SIZE_T PeakVirtualSize;
    SIZE_T VirtualSize;
    ULONG Reserved4;
    SIZE_T PeakWorkingSetSize;
    SIZE_T WorkingSetSize;
    PVOID Reserved5;
    SIZE_T QuotaPagedPoolUsage;
    PVOID Reserved6;
    SIZE_T QuotaNonPagedPoolUsage;
    SIZE_T PagefileUsage;
    SIZE_T PeakPagefileUsage;
    SIZE_T PrivatePageCount;
    LARGE_INTEGER Reserved7[6];
} SYSTEM_PROCESS_INFORMATION;

参考: Windows x64 におけるいくつかの型のサイズ

  • ULONG = 4オクテット
  • USHORT = 2オクテット
  • HANDLE = 8オクテット
  • PWSTR = 8オクテット
  • KPRIORITY (LONGのtypedef) = 4オクテット
  • UNICODE_STRING = 16オクテット(構造体は以下のとおり):
  typedef struct _UNICODE_STRING {
    USHORT Length;        -> 2      
    USHORT MaximumLength; -> + 2 = 4
    PWSTR  Buffer;        -> + 8 = 12 (12 n'est pas un multiple de 8 donc padding de 4 ajouté en amont de Buffer) = 16
} UNICODE_STRING;

UniqueProcessId のオフセットの計算:

    ULONG NextEntryOffset;        -> 4
    ULONG NumberOfThreads;        -> + 4 = 8
    BYTE Reserved1[48];           -> + 48 = 56
    UNICODE_STRING ImageName;     -> + 16 = 72
    KPRIORITY BasePriority;       -> + 4 = 76 (76 n'est pas un multiple de 8 donc padding de 4 ajouté) = 80
    HANDLE UniqueProcessId;       -> + 8 = 88

したがって、UniqueProcessId メンバーはオフセット 0x50(10進数の80)にあります。

変数 v22 の代入を見ると、i が QWORD(8オクテット)ポインタにキャストされていることがわかります:

v22 = (void )((_QWORD *)i + 10);
つまり、v22 は i + 10 * 8 = 80オクテットのアドレスに対応します。したがって、この変数には SYSTEM_PROCESS_INFORMATION 構造体から取得したPIDが含まれています。

どのPIDが ZwTerminateProcess に渡されるかを知るには、この代入を取り巻く条件を分析する必要があります。

screen4-git

最初にプロセスイメージ名が取得されていることがわかります:

v9 = (wchar_t )((_QWORD *)i + 8);
v9 = i + 8 × 8 = 64オクテットのアドレスだからです。これは、ImageName メンバーの Buffer に対応します。このメンバーはオフセット 56 + 2 (USHORT) + 2 (USHORT) + 4 (padding) = 64 にあるためです。

以下の操作とループを考慮すると、引数として渡されたプロセス名(a2)とシステム上のアクティブなプロセス v9/String の間で比較が行われているという仮説を立てることができます。

sub_1C078(String, v9, (int)v13);
v17 = strupr(a2);
v18 = strupr(String);

つまり、ZwTerminateProcess で終了するプロセス名を保持することになっているのはパラメータ a2 です。 a2 は関数 sub_12EF4 のパラメータであることに注目してください。さらに進めるには、この関数の参照を調べる必要があります(読みやすくするために ZwTerminateProcessCaller と改名しました)。

screen5-git

ZwTerminateProcessCaller はオフセット 61A の関数 sub_13624 によって呼び出されていることがわかります。

screen6-git

この逆コンパイル済みコードを分析する前に、関数 sub_13624(ZwTerminateProcessCallerCaller と改名)の参照を調べます。このコードがUserModeからの DeviceIoControl API呼び出しの後に実際に使用されていることを確認するためです。

screen§-git

ZwTerminateProcessCallerCaller は関数 sub_14130(ZwTerminateProcessCallerCallerCaller と改名... 幸いなことに、これはエントリポイントの前の最後の関数です 😅)によって呼び出されていることがわかります。

screen7-git

ZwTerminateProcessCallerCallerCaller はオフセット 306 の関数 sub_1A4A8 によって呼び出されていることがわかります。

screen8-git

ZwTerminateProcessCallerCallerCaller の代入が見つかります:

memset64(DriverObject->MajorFunction, (unsigned __int64)ZwTerminateProcessCallerCallerCaller, 0x1Cu);
これは、この関数が MajorFunction テーブルのすべてのエントリ(0x1B = 27、および28個の主要IRPが存在)に割り当てられていることを意味します。

screen9-git
ツールをダウンロード