仮想マシン上でWindowsデバイスドライバをデバッグする

2017年8月15日

はじめに

前回までは、簡単なデバイスドライバを作成し、DbgPrint関数によるログ出力だけでドライバの基本動作を確認するというものでしたが、今回は本格的なカーネルデバッグを行うための手順について紹介します。Windowsのカーネルデバッグは、
https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/getting-started-with-windows-debugging
に記載されているように、実際にドライバを動作させるターゲットPCと、デバッガを起動してデバッグ作業を行うホストPCとを接続し、PC間の通信によって行います。実ハードウェアを制御するデバイスドライバの開発においては、ターゲットPCはホストPCとは物理的に独立しており、外部インタフェース(例えば、シリアルケーブルやIEEE 1394、USBなど)を通して接続した構成でデバッグを行いますが、今回は仮想マシン環境でゲストOSをターゲットとしてホストOSと接続しながらデバッグを行います。

最新のWDKは、Visual Studioと連携した統合開発環境になっており、デバッグ作業もVisual Studio上で行うことができますが、ここでは前回までと同様Windows 7以前のWDKを使用していることから、Windows Debugger (以下、WinDbg) を用いてデバッグを行います。

環境設定

仮想マシン環境でカーネルデバッグを行うためには、仮想マシン上のゲストOSがホストOSと通信するために、以下のように名前つきパイプを用いた仮想的なシリアルポートを用意します。

シリアルポート設定

この設定により、ゲストOS側では名前つきパイプがシリアルポートとして見えるため、物理的なシリアルポートを用いた通常のカーネルデバッグと同様、以下の手順でカーネルデバッグを有効にします。ここで、具体的なシリアルポートの番号は環境に依存します。

C:\Windows\system32>bcdedit /set debug on
The operation completed successfully.

C:\Windows\system32>bcdedit /dbgsettings serial debugport:2 baudrate:115200
The operation completed successfully.

実行

WinDbgでカーネルデバッグを有効にするには「File」メニューの「Kernel Debug…」を選択し、以下のダイアログ上でカーネルデバッグの設定を行った上で、「OK」ボタンをクリックして実行します。「Port」には、仮想マシンのシリアルポート設定におけるパイプの名前を指定します。

WinDbg設定

WinDbgを実行してターゲットPCに接続されると、WinDbgのコマンドウィンドウ上にその旨を示すメッセージが出力されます。

WinDbg接続画面

ドライバのダウンロード

ホストPC側でドライバを修正して再ビルドすると、そのドライバファイルをターゲットPCにコピーしてドライバを再起動する必要がありますが、カーネルデバッグ環境を使えば、ホストPCとターゲットPC間の接続を通してドライバのファイル(.sysファイル)を自動的にダウンロードすることができます。
このためには、まず、対象のドライバファイル名 (ターゲットPC上のパス) と、ホストPC側のパスを以下のように関連づけて記述した.iniファイルを作成する必要があります。

map
\Systemroot\system32\drivers\sample1.sys
Z:\Projects\WinDrvSample\sample1\objchk_win7_x86\i386\sample1.sys

その後、WinDbgをターゲットPCに接続した後、作成した.iniファイルを読み込むことによって、ダウンロードが可能になります。

kd> .kdfiles z:\projects\WinDrvSample\mymap.ini
KD file assocations loaded from 'z:\projects\WinDrvSample\mymap.ini'

ターゲットPC上でドライバの起動が行われる際には、自動的にドライバファイルがホストPCからダウンロードされて実行されます。

KD: Accessing 'Z:\Projects\WinDrvSample\sample1\objchk_win7_x86\i386\sample1.sys' (\SystemRoot\system32\drivers\sample1.sys)
  File size 4KKdPullRemoteFile(841AED48): About to overwrite \SystemRoot\system32\drivers\sample1.sys and preallocate to e00
KdPullRemoteFile(841AED48): Return from ZwCreateFile with status 0
.

WinDbgのコマンド

WinDbgを用いたデバッグは、GUIのメニューを用いて行うこともできますが、今回はコマンドウィンドウ上のコマンド入力により行う方法をいくつか紹介します。

  1. BreakPointの設定
    kd> bp sample1!SampleUnload
  2. 設定済みBreakPointの表示
    kd> bl
     0 e 90f71010     0001 (0001) sample1!SampleUnload
  3. スタックトレースの表示
    kd> kb
    ChildEBP RetAddr  Args to Child              
    807e5cc4 829bd447 865ede78 92ba0a00 841aed48 sample1!SampleUnload [z:\projects\windrvsample\sample1\sample1.c @ 7]
    807e5d00 82889f2b 92ba0a00 00000000 841aed48 nt!IopLoadUnloadDriver+0x1e
    807e5d50 82a2a66d 00000001 90838d71 00000000 nt!ExpWorkerThread+0x10d
    807e5d90 828dc0d9 82889e1e 00000001 00000000 nt!PspSystemThreadStartup+0x9e
    00000000 00000000 00000000 00000000 00000000 nt!KiThreadStartup+0x19
  4. 構造体変数のメンバー表示
    kd> dt DriverObject
    Local var @ 0x807e5ccc Type _DRIVER_OBJECT*
    0x865ede78 
       +0x000 Type             : 0n4
       +0x002 Size             : 0n168
       +0x004 DeviceObject     : (null) 
       +0x008 Flags            : 0x13
       +0x00c DriverStart      : 0x90f70000 Void
       +0x010 DriverSize       : 0x6000
       +0x014 DriverSection    : 0x8654ec00 Void
       +0x018 DriverExtension  : 0x865edf20 _DRIVER_EXTENSION
       +0x01c DriverName       : _UNICODE_STRING "\Driver\sample1"
       +0x024 HardwareDatabase : 0x82b86250 _UNICODE_STRING "\REGISTRY\MACHINE\HARDWARE\DESCRIPTION\SYSTEM"
       +0x028 FastIoDispatch   : (null) 
       +0x02c DriverInit       : 0x90f7403e     long  sample1!GsDriverEntry+0
       +0x030 DriverStartIo    : (null) 
       +0x034 DriverUnload     : 0x90f71010     void  sample1!SampleUnload+0
       +0x038 MajorFunction    : [28] 0x828cd437     long  nt!IopInvalidDeviceRequest+0

おわりに

今回は、Windowsドライバのカーネルデバッグの基本手順を、前回の投稿で作成した簡単なドライバを用いて紹介しました。通常は、ドライバを動かすターゲットPCとデバッガを実行するホストPCとを物理的に接続した構成でデバッグを行いますが、名前つきパイプによりホストOSとゲストOSを接続することで、ホストPCと同一ハードウェア上の仮想マシンでデバッグを行えることを確認しました。

About Author

hiro.sakamoto

Leave a Comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください

Recent Comments

Social Media