Cisco Japan Blog
Share

悪意のある Windows ドライバに関する分析(パート 1):カーネルとドライバの概要


2024年2月5日


ドライバはずっと以前から攻撃者の関心を集めてきました。脆弱なドライバが悪用されたり、悪意のあるドライバが作成されたりしています。悪意のあるドライバの検出は容易ではないため、うまく利用できさえすれば、システムへの完全なアクセスが可能になります。実際の事例が、ドライバベースのブラウザハイジャッカー RedDriver と署名タイムスタンプ偽造ツール HookSignTool についての以前の Talos の調査で報告されています。

悪意のあるドライバが存在するからには、特定されたサンプルを分析できる人材が必要です。分析には Windows オペレーティングシステムに関する特別な知識が必要ですが、こうした知識は簡単に習得できるものではありません。Windows ドライバとカーネルというトピックは膨大で非常に複雑なので、圧倒されるほど大変に感じることでしょう。これらのテーマについて入手可能なドキュメントに目を通すのは、初心者にとってはもちろん、プログラミング経験者にとっても気が遠くなる作業になるはずです。この初めのハードルがあるだけでなく、最初に多くのことを習得する必要があるので、このテーマに足を踏み入れる障壁が高くなっています。多くの人にとって、カーネル空間とはオペレーティングシステムの難解で隠された要素のようです。

このシリーズでは、悪意のあるドライバの研究に関心はあるものの、まったく経験がない方に向けて、ドライバと Windows カーネルの概要を大まかに紹介します。ただし、プロセス、スレッド、レジストリ、一般的なシステムファイルなどの Windows の基本概念に関する経験のほか、逆アセンブラと C または C++ プログラミングの経験か知識があることが望ましいでしょう。Microsoft 社は Windows 11 カーネルの一部を徐々に Rust に移行し始めているので、将来的には Rust プログラミング言語の経験を積むことが有利になる可能性があります。

このシリーズは、悪意のあるドライバについて学習する出発点となり、このテーマに足を踏み入れる障壁を低くすることを目的としています。シリーズの各パートはその前に説明した内容に基づいて構成していきますが、まずは、ドライバ、Windows カーネル、I/O システムの基本概念を紹介します。

次に、I/O システムとドライバの動作について詳しく説明します。最後に、ドライバを取り巻くセキュリティの概念、悪意のある状況でドライバがどのように使用される可能性があるのか、基本的なドライバの分析、悪意のあるドライバを特定する方法、といったトピックを取り上げる予定です。

このブログ記事の補足として、重要なテーマに外部技術情報へのリンクを貼って詳細を確認できるようにしています。このブログシリーズは、詳細に説明するというよりも、概念について幅広く紹介することを意図したものなので、ぜひリンク先の情報をご覧ください。さらに学習したい方のために推薦書籍のリストも提供します。

Windows カーネル

カーネルモードとユーザーモード

Windows オペレーティングシステム(OS)は 2 つのレイヤ(モード)に分かれています。1 つは、ユーザーが操作するファイルとアプリケーションが動作するユーザーモードです。もう 1 つがカーネルモードで、カーネルモードドライバと Windows の基盤は、システムを稼働させるための機能をこのモードで実行します。オペレーティングシステムを 2 つのモードに分割することにより、一般ユーザーと Windows カーネルの間に高度に制御された論理的な境界が作成されます。カーネルは非常に複雑かつ脆弱な環境なので、システムの完全性とセキュリティを維持するためにはこの境界が必要です。

メモリ内では、2 つのモードは論理的に 2 つの「仮想」アドレス空間に分けられます。ユーザーモードのアドレス空間内では、アプリケーションの実行時にプロセスが開き、それぞれが専用の仮想メモリ空間で実行されます。ユーザーモードのプロセスがクラッシュしても、専用のメモリ空間でプロセスが実行されているのでシステムは動作を継続し、クラッシュしたプロセスを適切に処理できます。一方カーネルモードでは、すべてのドライバがオペレーティングシステム自体と同じ仮想アドレス空間で実行されます。ドライバが誤って別のドライバまたはオペレーティングシステムのアドレスに書き込むと、損傷を防ぐためにシステム全体がクラッシュし、その結果、一般に「ブルースクリーン」(BSOD)として知られる現象が発生します。つまり、ドライバによってシステムが簡単にクラッシュしてしまうため、ドライバの作成は慎重に行う必要があります。

カーネルの概念

Windows カーネルは非常に複雑なテーマであり、その機能のさまざまな側面に特化した書籍やコースが完備されています。カーネルは、たった 1 本のブログ記事で完全に説明できるものではありません。とはいえ、基本を確認するために、ドライバとドライバがオペレーティングシステムとやり取りする方法について説明していきます。これは、カーネルとドライバについてより詳しく学習するプロセスを開始する足がかりとなります。

カーネルモードレイヤは、システムを実行するために連動するさまざまなコンポーネントの配列で構成されています。この図に示しているように、カーネルモードはさらにさまざまなレイヤに分けられます。

重要事項:上の図は、Windows カーネルを簡略化して表したものです。多くのコンポーネントはこのブログ記事の対象外なので、ここには示していません。

ご覧のとおり、ドライバはアプリケーションのユーザーモードではなく、カーネルモードで実行されます。カーネルモードは OS の基盤となるインフラストラクチャとみなすことができ、一般ユーザーが直接操作することはありません。レイヤは論理的に分離されていますが、レイヤ間の情報交換は高度に制御されたチャネルを通じて行われます。

最新のオペレーティングシステムでは、システム権限モデルは通常、一般に「リング」として表される論理レイヤに分割されています。各リングは権限のレベルを表します。一番外側のリングは最も権限が低く、中央のリング(カーネル)は最も権限が高くなります。外側のリング内のアプリケーションは、内側のリングの権限を必要とするアクションを直接実行できません。このモデルは「階層型保護ドメイン」または単に「保護リング」と呼ばれます。

保護リングモデルは、システムリソースへの直接アクセスを制限することで障害や悪意のあるアクティビティを防ぐように設計されています。外側のリングから何らかのアクションを行うにはより高い権限が必要となるので、「システムコール」(syscall とも呼ばれる)を実行する必要があります。syscall を実行すると一連の関数が開始され、最終的にリング 0 のカーネルで意図したアクションが実行されます。たとえば、アプリケーションが Windows API 関数 OpenProcess を実行する場合、x64 システムでは実行フローは次のようになります。

リング 3 では、実行フロー内の各関数がチェーン内の次の関数のラッパーとして事実上機能し、それぞれが次の関数に実行を渡します。ただし、ntdll.dll の NtOpenProcess が呼び出されると、次のステップではカーネルに対して実際の syscall が実行され、その結果としてカーネルが KiSystemCall64(システム サービス ディスパッチャ)を実行します。

syscall を受け取ると、KiSystemCall64 は要求された関数のアドレスをシステムサービス記述子テーブル(SSDT)から取得します。SSDT は、syscall で使用するためにマップされているカーネル関数のアドレスを格納したテーブルです。適切なアドレスが見つかると、要求された関数が実行されます。

エグゼクティブレイヤ

カーネルモード内には「エグゼクティブレイヤ」と呼ばれる別のレイヤがあり、これにはドライバに以下の機能とサービスを提供するコンポーネントが含まれています。

これらは「マネージャ」と呼ばれ、ドライバが使用できるさまざまな機能へのインターフェイスを提供します。各マネージャの管理対象は特定の機能領域(オブジェクト管理やメモリ管理など)です。マネージャ名を見れば一目瞭然ですが、必要に応じてこのブログシリーズでそれぞれの役割について説明します。個々のマネージャについてさらに理解を深めるには、上記リストの MSDN のリンクをご覧ください。

悪意のあるドライバの分析中に観察される動作の大部分は、エグゼクティブレイヤのマネージャインターフェイスによって提供される機能に関連しています。このシリーズの後半では、悪意のあるドライバを含むドライバの操作において I/O マネージャがどのように大きな役割を果たすかについて説明します。

ハードウェア抽象化レイヤ(HAL)

カーネルの下には、ハードウェアと OS の残りの部分との中間レイヤとも言えるハードウェア抽象化レイヤ(HAL)があります。Windows では、HAL は「hal.dll」という名前で実装されており、OS と物理ハードウェア間の通信を容易にし、プロセッサリソースへの標準インターフェイスを提供します。HAL の重要な機能の 1 つは、アーキテクチャに応じて異なるバージョンの HAL を実装することで、Windows が異なる CPU アーキテクチャで動作できるようにすることです。

多くの DLL とは対照的に、hal.dll によってエクスポートされる関数popup_iconのほとんどは、アプリケーションやドライバを介してプログラマが直接呼び出すことを意図したものではなく、システム内の他のモジュールやコンポーネントによって使用されるようになっています。hal.dll がエクスポートする関数の大部分は文書化されておらず、その多くは以前の Windows バージョンから引き継がれたもので今では使用されていません。

ドライバ

ドライバの役割

ドライバは Windows オペレーティングシステムのバックグラウンドで重要な役割を果たしており、ほとんどのユーザーは、最初のインストールまたは不定期のアップデートを除けば、ドライバを直接操作することはありません。ファイル構造はユーザーモードの実行ファイルと似ているかもしれませんが、機能はまったく異なります。ユーザーモードの実行ファイルとは違って、ドライバは標準の Win32 API ルーチンを使用せず、カーネルモードライブラリのセットとエグゼクティブレイヤ内のマネージャコンポーネントのインターフェイスによって提供される「ドライバサポートルーチン」を使用します。

一般に、ドライバはカーネルモードで動作し、オペレーティングシステムとハードウェアまたは接続されたデバイス間の通信を可能にします。ただし、ドライバにはフィルタドライバやソフトウェアドライバなど多くの種類があり、すべてがハードウェアと直接やり取りするわけではないので、この説明はあまりにも単純すぎます。ユーザーモードで動作するドライバもありますが、このブログシリーズではカーネルモードドライバだけに焦点を当てます。ドライバの種類の詳細については、Microsoft 社のドキュメントを参照することをお勧めします。

簡単に言えば、ドライバはクライアントから要求を受け取って、クライアント自体は直接実行できないようになっているシステム内のさまざまなアクションを実行します。具体的には、ハードウェアとのやり取り、スレッドやプロセスの操作、ネットワークのフィルタリングなどであり、他にもカーネルレベルのアクセスを必要とする多くの操作をドライバが実行します。つまりドライバは、カーネルモードとユーザーモードのギャップを埋めることで、オペレーティングシステムに与えられる命令のパイプ役として機能します。

ドライバファイル

表面的には、ドライバは基本的に「.sys」ファイル拡張子を持つダイナミック リンク ライブラリ(DLL)に見えますが、一般的な DLL ファイルとは大きく異なります。ドライバは他の実行ファイルと同じ方法では実行できず、ドライバがインポートする関数やライブラリはユーザーモードのアプリケーションでは使用できません。ドライバを実行するには、まず、このシリーズで後ほど説明する特定のプロセスを経てドライバをオペレーティングシステムにロードする必要があります。

多くの場合、.sys ファイルは、セットアップ情報(INF)ファイル、カタログ(.cat)ファイル、その他ドライバが必要とするファイルとともに、最初から「ドライバパッケージ」内に格納されています。INF(.inf)ファイルは、バージョン情報、デバイス ID、ドライバファイル、.cat ファイルなど、ドライバのインストールに必要なすべての情報を Windows に提供するテキストファイルです。INF ファイルの例と概要については、こちらから Microsoft 社のドキュメントを参照してください。カタログファイルには、ドライバパッケージの内容のファイルハッシュが含まれており、Windows はこれを使用して、パッケージ内のファイルの完全性を検証します。

ドライバの機能

Windows Driver Model とフレームワーク

Windows 98 および Windows 2000 のリリースに伴い、Microsoft 社はデバイスドライバの基本モデルである Windows Driver Model(WDM)をリリースしました。さまざまな機能がありますが、特にドライバ開発プロセスが容易になりました。この新しいモデルにより、バージョンごとに個別のドライバを作成する必要がなくなり、異なるバージョンの Windows 間でドライバのソースコードを簡単に移植できるようになりました。この移植性により、リリース前には不可能だった上位互換性が実現しています。WDM ドライバでは下位互換性は保証されておらず、古いバージョンの Windows では同じ機能であっても利用できない場合があります。

WDM の欠点の 1 つは、ハードウェアでますます一般的になっているプラグアンドプレイ(PNP)や電源管理 I/O 要求を本質的に扱えないことです。このため開発者のほとんどは、これらの要求を処理できる定型コードをコピーしてドライバで使用するようになったのですが、これはかなり非効率なプロセスです。

ドライバの作成プロセスをさらに合理化するために Microsoft 社が導入したのが Windows Driver Frameworks(WDF)(以前の Windows Driver Foundation)です。開発者に WDF を提供することで、ドライバごとに必要だった定型コードが不要になりました。ただし、WDF 自体は単一のフレームワークではありません。実際には、KMDF(カーネルモード ドライバ フレームワーク)と UMDF(ユーザーモード ドライバ フレームワーク)という 2 つの異なるフレームワークが含まれています。WDF は WDM を直接置き換えるものではありませんが、より複雑なタスクの一部を簡素化する、より効率的なインターフェイスを WDM に提供します。

この記事の執筆時点では、Microsoft 社はカーネルモードドライバの開発に KMDF を使用することを推奨していますが、WDM は依然として有効な選択肢であり、Windows ドライバのベースとなるコアモデルであることに変わりありません。WDF は開発に抽象化レイヤを追加し、ドライバの作成でより手間のかかる側面の一部を処理します。とは言え、WDM を学習することは有益です。WDF がバックグラウンドで実行するアクションのいくつかをより明確に把握できるからです。このため、このブログシリーズのコード例では WDM を利用します。さらに、今でも WDM を使用して悪意のあるドライバが作成されることは一般的なので、研究や防御の観点からも WDM の知識は貴重です。製品のドライバを開発する際は、Microsoft 社のガイダンスと標準的なプラクティスに従うことを強くお勧めします。

ドライバコード

一般に、Windows ドライバは C で書かれていますが、Microsoft 社は Visual Studio 2012 と Windows Driver Kit(WDK)8 で C++ のサポートを開始しました。ドライバ開発者の中には、Resource Acquisition is Initializationpopup_icon(RAII)と呼ばれる概念を使用することでリソース管理が容易になるので C++ を好む人もいます。RAII はこのブログ記事の範囲外ですが、概要を理解しておくと、後でドライバについて学習する際に役立つ可能性があります。

ドライバの作成とユーザーモードの実行ファイルの作成の重要な違いは、ドライバのメモリ操作の多くは手動で実行する必要があることです。ユーザーモード アプリケーションでは、プロセスが終了すると、割り当てられた専用メモリが解放されます。逆に、ドライバを作成する際には、メモリを手動で割り当てて適宜解放しなければなりません。そうしないとメモリリークが発生し、予期しない問題を引き起こす可能性があります。ドライバの開発中は、すべてのメモリが適切に処理されるように特別な注意を払う必要があります。

基本的な操作を実行するには、まず必要な「標準ルーチン」をドライバに実装しなければなりません。これらの標準ルーチンを個々に実装しないとドライバが機能しません。

Windows 内のオブジェクト

ドライバがどのように機能するかを詳しく紹介する前に、まず Windows カーネルの重要な概念の 1 つである「オブジェクト」について説明しておく必要があります。

Windows OS はオブジェクトベースです。つまり、システム内のファイル、スレッド、実行ファイル、および各種コンポーネントのすべてが特定のオブジェクト型として定義され、表現されます。

概念的には、定義された型の構造体はやり取りする対象に関係なく常に同じなので、定義された型としてオブジェクトを表現することによって標準化と移植性が実現します。構造体内部のデータは変更できますが、構造体自体の定義は変更できません。なぜなら、定義上では異なるオブジェクト型になってしまうからです。

注:オブジェクトベースをオブジェクト指向プログラミングpopup_iconOOP)と混同しないようにしてください。Windows OS OOP の原則を一部導入してはいますが、この 2 つの用語を一緒くたにはできません。

一例を挙げると、システムはロードされたドライバのイメージを DRIVER_OBJECT と呼ばれるオブジェクト型として表現し、構造体の異なるメンバーは DriverSize や DriverName といった対応する属性を表現し、格納します。

DRIVER_OBJECT 構造体(MSDN から引用)

ドライバやカーネルについて学習する際は、さまざまな型のオブジェクトに遭遇することになりますが、MSDN Web サイトに多くのドキュメントが掲載されています。MSDN は、Windows オペレーティングシステムについて学習する際に利用できる最も重要な技術情報です。また、文書化されていない関数やデータ型がいくつかあるため、検索エンジンでオブジェクト型または関数名を検索すると役立つ情報が得られることがあります。

DriverEntry

ドライバのコードにとって最も基本的な要件は、通常は DriverEntry という名前のエントリルーチンが必要なことです。これは、ドライバがロードされると最初に呼び出されるルーチンです。DriverEntry が実行しなければならない必須の処理が複数あります。

  • 他の標準ルーチンの実装
  • ディスパッチルーチンの実装と、そのエントリポイントの割り当て
  • 必要なリソース、オブジェクト、デバイスの作成と初期化
  • 不要になったメモリの解放
  • NTSTATUSpopup_icon 戻りの指定

DriverEntry は、DriverObject と RegistryPath という 2 つのパラメータを取ります。

DriverEntry プロトタイプ(MSDN から引用)

RegistryPath パラメータは、レジストリ内のドライバの「parameters」キーへのレジストリパスを含む Unicode 文字列へのポインタです。このパスは、ドライバがシステムに最初にインストールされるときに作成されます。通常、このキーには、ドライバの作成方法に応じて、ドライバが必要とする構成情報が含まれています。

DriverObject パラメータは、DRIVER_OBJECT として定義された構造体へのポインタです。DRIVER_OBJECT はカーネルモードドライバ自体を表し、そのメンバー内にドライバに関する情報が含まれています。DRIVER_OBJECT は部分的に不透明であり、すべてのメンバーがユーザーに表示されるわけではありません。

以下は、C++ で記述された一般的な DriverEntry 関数の例です。

この例では、DriverEntry は実行が完了すると、単純に NTSTATUSpopup_icon 値 STATUS_SUCCESS を返します。

前述したように、DriverEntry は、ドライバに必要なリソース、オブジェクト、またはデバイスの作成と初期化を行う必要もあります。デモの場合は、デバイスオブジェクトシンボリックリンクの初期化と作成が必要です。

ドライバがクライアントから要求を受け取るには、DEVICE_OBJECT 構造体として表されるデバイスオブジェクトを作成する必要があります。

DEVICE_OBJECT 構造体は、デバイスオブジェクトを表すためにオペレーティングシステムによって使用されます。デバイスオブジェクトは、ドライバが I/O 要求を処理する論理、仮想、または物理デバイスを表します」(MSDN より)

デバイスオブジェクトは、クライアントとドライバ間の要求を処理するインターフェイスと考えることができます。要求を直接ドライバに送る代わりに、デバイスオブジェクトがクライアントの通信ポイントとして機能します。デバイスオブジェクトの作成は、PDEVICE_OBJECT 構造体を初期化し、DeviceObject パラメータとして IoCreateDevice 関数に渡すことで行います。Unicode 文字列で表されるデバイス名も指定し、DeviceName パラメータとして渡します。

IoCreateDevice プロトタイプ(MSDN から引用)

IoCreateSymbolicLink 関数を呼び出すことで、デバイスオブジェクト名を使用してシンボリックリンクを初期化し、作成できるようになりました。シンボリックリンク(symlink)とは、デバイスオブジェクト名を、ユーザーが表示できる指定された名前にリンクする機能です。

デバイスオブジェクトとシンボリックリンクの作成。

デバイスオブジェクトとシンボリックリンクを設定すると、ドライバはディスパッチルーチン(ドライバが受け取る可能性のあるさまざまな要求を処理する関数)を実装する準備が整います。

アンロードルーチン

コードのもう 1 つの必須セクションが DriverUnload ルーチンです。この関数は、ドライバがアンロードされた後にどのような操作が実行されるかを決定します。通常は、ドライバによって作成されたデバイスオブジェクトとシンボリックリンクの削除か、必要なクリーンアップの実行になります。

DriverEntry では、アンロードルーチンを DriverObject 構造体の DriverUnload メンバーに割り当てて宣言する必要があります。この例では、デバイスオブジェクトとシンボリックリンクが削除されます。

ディスパッチルーチンと関数コード

DRIVER_OBJECT 構造体で理解しておく必要のある重要なメンバーが MajorFunction です。このメンバーは PDRIVER_DISPATCH(DRIVER_DISPATCH 構造体へのポインタ)として定義され、ドライバのディスパッチルーチンのエントリポイントの配列を含んでいます。事実上、特定のドライバがサポートする操作のリストです。ディスパッチルーチンは、ドライバがシステム定義の「関数コード」(「MajorFunction コード」とも呼ばれる)を受け取ったときに呼び出されるドライバ内の関数です。以下のリストでわかるように、それぞれのプレフィックスは「IRP_MJ_」です。

一般的な MajorFunction コード:

関数コードの大半は「IRP_MJ_」で始まりますが、「IRP_MN_」を使用するものもあります。このプレフィックスは、その関数コードが MinorFunction で、関連する MajorFunction の下位であることを示しています。たとえば、IRP_MN_SET_POWERIRP_MJ_POWER の下位になります。MajorFunction コードと MinorFunction コードの完全なリストについては、Microsoft 社のドキュメントを参照してください。

関数コードは基本的に、要求を受けてドライバが特定のアクションを実行するための命令として機能します。関数コードを処理できるようにするには、ドライバは、DriverObject 構造体の適切な MajorFunction コードにディスパッチルーチンのエントリポイントを割り当てる必要があります。この割り当ては DriverEntry ルーチンで行われ、以下に示すように、特定の関数コードに各ディスパッチルーチンが割り当てられます。

たとえば、上記の例のドライバが関数コード IRP_MJ_CREATE を含む要求を受け取ると、ディスパッチルーチン TestDriverCreate が実行されます。以下は、TestDriverCreate ルーチンの例です。

IRP_MJ_CREATE は、使用するかどうかに関係なく、すべてのドライバで処理する必要がある重要な関数コードです。上に示した TestDriverCreate 関数では、何も実行せずに関数コードが処理され、IoCompleteRequest を呼び出して要求を完了します。要求の処理についての詳細な説明は、このブログシリーズの後半で説明します。デモを目的としたものなのでこの例では意図的に機能を含めていませんが、実際のドライバでは、この関数コードを処理するときにアクションが実行される可能性があります。

TestDriverCreate 関数の 2 番目のパラメータである「PIRP Irp」は、ドライバの操作に使用される重要な構造体である I/O 要求パケット(「IRP」とも呼ばれる)を指します。

I/O システムと I/O 要求パケット(IRPS)

ドライバへの要求フローを管理するために、Windows はいわゆる I/O(入力/出力)システムを実装しています。このシステムは、ドライバ、周辺デバイス、およびドライバに要求を行うクライアント間のデータフローを処理します。主要な関数コードを含むデータは、「IRP」(「I/O 要求パケット」の略)と呼ばれるものにカプセル化され、_IRP として定義される構造体として表されます。

_IRP 構造体(MSDN から引用)

I/O システムの一部である I/O マネージャは、IRP を作成してドライバに送ることにより、カーネルモードドライバへのインターフェイスとして機能します。IRP には、要求を受け取ったドライバがアクションを実行するための関数コードを含めることができます。ただし、I/O マネージャだけが IRP の送信元というわけではありません。エグゼクティブレイヤの他のマネージャや、場合によってはドライバによって IRP が作成されることがあります。IRP の作成だけが I/O マネージャの機能ではなく、インストールされているドライバごとにドライバオブジェクトを作成する役割もあります。

前述したように、I/O システムはドライバの操作に大きな役割を果たしているため、そのコンポーネントについてよく理解しておくことが重要です。このシリーズの次のパートでは、IRP と I/O システム、それらとドライバとの関係について詳しく説明します。デバイススタックと IOCTL についても触れる予定です。シリーズ後半では、ドライバのロードとデバッグのプロセスも説明し、最終的には悪意のあるドライバの動作と分析について取り上げます。

このシリーズの次のパートがリリースされるまでに、このブログ全体で提供されているリンクを参照することをお勧めします。ドライバとカーネル環境を取り巻く基本概念は、それらの概念に触れたり、ドキュメントや関連する研究を読んだりすることで理解できるようになります。以下は、ドライバの作成方法とその動作方法に関する貴重な情報が得られる推薦書籍のリストです。

書籍

  • Windows カーネルプログラミング(Pavel Yosifovich 著)
    • Windows カーネルプログラミングの詳細についてわかりやすく説明されています。
  • Windows NT デバイスドライバの開発(Peter Viscarole、W. Anthony Mason 著)
    • 古い Windows デバイスドライバの開発に関する書籍ですが、現在でも重要な情報が盛りだくさんです。
  • Windows Internals:パート 1 とパート 2(Pavel Yosifovich、Mark E. Russinovich、Alex Ionescu、David A. Solomon 著)
    • Windows の内部について説明した Microsoft 社のオフィシャルブック。カーネルには焦点を当てていませんが、所有しておいたほうがよい良書です。

 

本稿は 2024 年 01 月 18 日に Talos Grouppopup_icon のブログに投稿された「Exploring malicious Windows drivers (Part 1): Introduction to the kernel and driverspopup_icon」の抄訳です。

 

Tags:
コメントを書く