Windows Serviceのデバッグ

概略

Windows Serviceのデバッグを行いたい場合のためのメモ

自己責任で(VM推奨)

デバッグした後は元の環境に戻す(重要)

環境

Windows 7 x86 (VirtualBox)



手法 その1

サービスの初期状態からデバッグできるようにする

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Optionにプログラム名のレジストリキーを作成する.


    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution
    String Value
    Value name : Debugger
    Value data : <debugger path> -server npipe:pipe=<Session Name>

今回の場合は以下のようにした.


    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution
    String Value
    Value name : Debugger
    Value data : C:\Debuggers\x86\ntsd.exe -server npipe:pipe=hoge

セッション分離

Windows Vista以降はセッションが分離されているため上記の方法をとる.

それより前のOSだと直接WinDbgを指定してやれば良いらしい(未確認).

f:id:kmdnet:20180522162816p:plain

Let's Debug!

WinDbg → Connect to Remote Session(Ctrl+R)


npipe:server=localhost,pipe=hoge

タイムアウト時間の調整

サービスのタイムアウト時間を伸ばさないとすぐ終了してしまう. デフォルトで30000ミリ秒(30秒).


C:\Windows\System32>sc start MySrv
[SC] StartService FAILED 1053:

The service did not respond to the start or control request in a timely fashion.

f:id:kmdnet:20180522160852p:plain

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Controlでデフォルトのタイムアウト時間を伸ばす. → 再起動


    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control
    DWORD
    Value Name : ServicesPipeTimeout
    Value data : 86400000(Decimal)

※ 86400000(Decimal) = 24hours

※ 全てのサービスに影響するためデバッグ後は修正する



手法 その2(svchostと依存関係がある場合)

svchost.exeと依存関係がある場合, 孤立させる必要がある.

今回はBITS(Background Intelligent Transfer Service)を対象にする.


C:\Windows\System32>sc qc bits
[SC] QueryServiceConfig SUCCESS

SERVICE_NAME: bits
        TYPE               : 20  WIN32_SHARE_PROCESS
        START_TYPE         : 2   AUTO_START  (DELAYED)
        ERROR_CONTROL      : 1   NORMAL
        BINARY_PATH_NAME   : C:\Windows\System32\svchost.exe -k netsvcs
        LOAD_ORDER_GROUP   :
        TAG                : 0
        DISPLAY_NAME       : Background Intelligent Transfer Service
        DEPENDENCIES       : RpcSs
                           : EventSystem
        SERVICE_START_NAME : LocalSystem

見る箇所はBINARY_PATH_NAMEのグループ名(netsvcs). ちなみにsvchost -k (group).

新しいグループ(TempGrp)を作成する.


    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsNT\CurrentVersion\SvcHost 
    REG_MULTI_SZ
    Value Name : TempGrp
    Value data : 孤立させたいサービスのValue data

※ 作成したグループのValue dataにnetsvcsのValue dataを指定する.

f:id:kmdnet:20180522212132p:plain

元々のグループのsub keyを作成したグループにコピーする.

今回の場合はnetsvcsなのでAuthenticationCapabilities, CoInitializeSecurityParamを新しいグループにコピーすれば良い.

f:id:kmdnet:20180522213303p:plain

サービスのパスを修正する.


C:\Windows\System32>sc config BITS binPath= "C:\Windows\system32\svchost.exe -k TempGrp"
[SC] ChangeServiceConfig SUCCESS

※ 細かい所だけどbinPathはクオーテーションで囲む, binPath=の後のスペースは必要. ハマりやすい所なので注意.

必要に応じてサービスの再起動を行う. あとは手法 その1と同じ.



手法 その3(非推奨)

MSDNによると非推奨.

svchostを複製する.

%SystemRoot%\System32にsvchost.exeをコピーしてsvchost2.exeを作成する.


C:\Windows\System32>sc config BITS binPath= "C:\Windows\System32\svchost2.exe -k netsvcs"
[SC] ChangeServiceConfig SUCCESS

必要に応じてサービスの再起動を行う. あとは手法 その1と同じ.

所感

個人的には手法1と3(適当)

参考文献

Debugging a Service Application | Microsoft Docs