「Windowsメモリダンプ解析サービス」のご案内
豊田孝の「IT談話館」 Windowsメモリダンプ解析を依頼する




「Windowsメモリダンプ解析サービス」のご案内



WinDbgとWindowsカーネルアーキテクチャー


 WindowsはSaaSとして提供される時代に入り、その内部は頻繁に更新されています。更新内容の多くは、いろいろな事情から、公にされることはほとんどありません。最新のユーザー空間とカーネル空間に関する信頼できる情報を取得するには、高度な内部解析技術が必須とされています。本稿では、Windowsカーネルアーキテクチャーを紹介します。まずは、次のようなWindowsカーネルアーキテクチャーをおさらいしておきます。



 このアーキテクチャー図にはALPCではなくLPCという旧式の用語が使用されています。
kd> !lpc ?
LPC is now emulated over ALPC. Use !alpc
 ALPCについては後程触れることになっています。また、図内ではSystem Service Descriptor Table(SSDT)ではなく、Trap Interfaceなる用語が使われています。次の情報は上図の2年後に当たる、2008年当時の32bit Windows XP SP2環境下で採取されたカーネルメモリダンプの割り込みテーブルの解析結果であり、Trapなる用語がテーブル内で使われています。
kd> vertarget
Windows XP Kernel Version 2600 (Service Pack 2) UP Free x86 compatible
Product: WinNt, suite: TerminalServer SingleUserTS
Built by: 2600.xpsp_sp2_gdr.070227-2254
Machine Name:
Kernel base = 0x804d9000 PsLoadedModuleList = 0x8055c620
Debug session time: Wed Jun  4 19:50:12.855 2008 (UTC + 9:00)
System Uptime: 0 days 0:09:06.425

 00    nt!KiTrap00 (804e1350)
 01	nt!KiTrap01 (804e14cb)
 03	nt!KiTrap03 (804e189d)
 04	nt!KiTrap04 (804e1a20)
 05	nt!KiTrap05 (804e1b81)
 06	nt!KiTrap06 (804e1d02)
 07	nt!KiTrap07 (804e236a)
 09	nt!KiTrap09 (804e278f)
 0a	nt!KiTrap0A (804e28ac)
 0b	nt!KiTrap0B (804e29e9)
 0c	nt!KiTrap0C (804e2c42)
 0d	nt!KiTrap0D (804e2f38)
 0e	nt!KiTrap0E (804e364f)
 0f	nt!KiTrap0F (804e397c)
 10	nt!KiTrap10 (804e3a99)
 11	nt!KiTrap11 (804e3bce)
 12	nt!KiTrap0F (804e397c)
 13	nt!KiTrap13 (804e3d34)
 14	nt!KiTrap0F (804e397c)
 15	nt!KiTrap0F (804e397c)
 16	nt!KiTrap0F (804e397c)
 17	nt!KiTrap0F (804e397c)
 18	nt!KiTrap0F (804e397c)
 19	nt!KiTrap0F (804e397c)
 1a	nt!KiTrap0F (804e397c)
 1b	nt!KiTrap0F (804e397c)
 1c	nt!KiTrap0F (804e397c)
 1d	nt!KiTrap0F (804e397c)
 1e	nt!KiTrap0F (804e397c)
 1f	nt!KiTrap0F (804e397c)
 2a	nt!KiGetTickCount (804e0b92)
 2b	nt!KiCallbackReturn (804e0c95)
 2c	nt!KiSetLowWaitHighThread (804e0e34)
 2d	nt!KiDebugService (804e177c)
 2e	nt!KiSystemService (804e0631)
 2f	nt!KiTrap0F (804e397c)
 30	hal!HalpClockInterrupt (806f4d50)
 31	fede47a4
 32	nt!KiUnexpectedInterrupt2 (804dfd04)
 33	nt!KiUnexpectedInterrupt3 (804dfd0e)
 34	nt!KiUnexpectedInterrupt4 (804dfd18)
 35	812e0044
 36	nt!KiUnexpectedInterrupt6 (804dfd2c)
 37	nt!KiUnexpectedInterrupt7 (804dfd36)
 38	hal!HalpProfileInterrupt (806eeef0)
 39	8131383c
 3a	nt!KiUnexpectedInterrupt10 (804dfd54)
 3b	feff55c4
 
 [---]
 
 Trap Interfaceという表現は2000年代初頭の一般的な技術水準、つまり、ソフト割り込みとハード割り込みがそれほど区別されない当時の雰囲気を反映しているものと推察されます。いわゆる、不意に発生する割り込みに対してはTrap(罠)を仕掛けておく、といった認識でしょう。なお、SSDT(System Service Description Table)の機能や役割については、本館の「WinDbgとWindows XP/7/8/10割り込みテーブル(IDT)の内部解析」や「Windows 10 Active Memory Dumpとカーネルメモリダンプ」の記事が参考になるかもしれません。

 上のアーキテクチャー図は時代の流れを感じさせますが、当時の考え方や概念は繰り返し再考され、その姿を変えて現在でも存在しています。Windows 10システム環境で採取した「Active Memory Dump」をWinDbgで解析すると、次のようなWindowsカーネルアーキテクチャー内部情報を取得することができます。
Pcr->0xfffff8005a350000	Prcb->0xfffff8005a350180	Process->0xffffd88dffb3c080	Thread->0xffffd88dfef55080	notmyfault64.exe
 この情報は、上のWindowsアーキテクチャー図でいえば、最下位層のKernel run-time/Hardware Abstraction Layer(HAL)から最上位層のApplicationに相当します。Device、Device Driver、VAD、Session、Section、Token、Job、VM、あるいは、IRPなどの下位概念の多くを捨象し、まさに、Windowsカーネルアーキテクチャーの中心概念のみを示しています。下位概念に興味のある方は、本館の「応用編」に目を通すとよろしいかもしれません。本「IT談話館」は、Windowsカーネルアーキテクチャーを構成する各種オブジェクト間の微妙な関係性を解析し、Windowsシステムの健康度を診断したり、システムクラッシュ発生原因を特定する高度な技術力を保有しています。

 上のWindowsアーキテクチャー図には、System ServicesやCritical servicesという概念が含まれています。System ServicesはServices.exe(SCM)プロセスの子プロセスですから、その特定は容易ですが、Critical servicesとはいったいなんでしょう?正直に言えば、本「IT談話館」も確かなことは分かりません。しかし、次のような仮説を設定し、その仮説を自力で実証することにより、それらしい情報を取得することができます。  これらの仮説を組み入れた解析コードを独自に作成し、Windows 10 Professional環境で採取した「Active Memory Dump」を解析してみると、次のような情報が返されてきます。
No.001: Parent: 0x002ac	Child: 0x00378	SessionId->0	Critical->1	svchost.exe(0xffffd88dfe647080)
No.002: Parent: 0x002ac	Child: 0x003a0	SessionId->0	Critical->1	svchost.exe(0xffffd88dfd92a080)
No.003: Parent: 0x002ac	Child: 0x004e0	SessionId->0	Critical->1	svchost.exe(0xffffd88dfe9a7080)

TotalProcesses->160
 すべての条件をクリアーしたのは、160個のプロセス中、3個だけです。3個のプロセスはすべて「svchost.exe」サービスプロセスですから、なんとなく納得できそうな感じですが、実務解析作業では、「0xffffd88dfe647080」などのプロセス識別情報を頼りにさらに解析作業を進め、”なんとなく納得”ではなく、”事実”を知る必要があります。たとえば、とりあえず、上記3個の「svchost.exe」プロセスが受け取っているコマンドラインパラメータを調査してみるのも一案です。

+0xFFFFD88DFE647080	svchost.exe
	CommandLine->C:\WINDOWS\system32\svchost.exe -k DcomLaunch -p

+0xFFFFD88DFD92A080	svchost.exe
	CommandLine->c:\windows\system32\svchost.exe -k rpcss -p

+0xFFFFD88DFE9A7080	svchost.exe
	CommandLine->C:\WINDOWS\system32\svchost.exe -k LocalServiceNoNetwork -p
 赤色で強調されている引数はそれぞれの「svchost.exe」サービスプロセスの役割(Service)を指定しています。DcomはDistributed COM、rpcはRemote Procedure Callをそれぞれ示していますから、これらのサービスプロセスが動作を停止した場合、Windowsシステムの運用に深刻(Critical)な影響が出ます。逆に、この2つのプロセスの動作は実質的に停止することはできませんから、内外からのシステム侵入者に「横展開」され、セキュリティー面での危険性が残されていることになります。便利な機能は誰にとっても便利なわけです。

 最後のLocalServiceNoNetworkは依然意味不明ですが、次のような「プロセスとオブジェクト名前空間」の間に成立している関係を解析してみると、LRPC(Local rpc)であることがはっきりします。
HandleCount->0502	svchost.exe	ffffd88dfe9a7080
	015: Object->0xffffc70ebd13a640	Name->KnownDlls
	046: Object->0xffffc70ebcfc9ea0	Name->BaseNamedObjects
	061: Object->0xffffd88dfd10adb0	Name->Service-0x0-3e5$
	062: Object->0xffffd88dfcf41260	Name->Default
	063: Object->0xffffd88dfd10adb0	Name->Service-0x0-3e5$
	105: Object->0xffffd88dfe7b64d0	Name->LRPC-1e04123d1c6dafcb51
	108: Object->0xffffd88dfe7cda20	Name->CoreMessagingRegistrar
	110: Object->0xffffd88dfe7cd550	Name->CoreUISystemWindowIDManager
	174: Object->0xffffd88dfdf50970	Name->LRPC-0478b56f5966a113be
	184: Object->0xffffd88dfdf28fe0	Name->BFE_Notify_Event_{f53b9da8-b2b0-4953-ae43-04e69107a58c}
	187: Object->0xffffd88dfdf958c0	Name->BFE_Notify_Event_{0cafbc46-b5ab-4c15-8971-dfda7deb763f}
	191: Object->0xffffd88dfdf98a20	Name->BFE_Notify_Event_{5a40686c-db98-416e-aa26-2f12369eed56}
	193: Object->0xffffd88dfdf95550	Name->BFE_Notify_Event_{7ec53fd7-a69f-4f72-a8f8-be819f2dca7b}
	195: Object->0xffffd88dfdf98400	Name->BFE_Notify_Event_{646dbf31-a7c9-48f1-b3c5-1c9b46d4f9e0}
	212: Object->0xffffc70ec8662fc0	Name->__ComCatalogCache__
	229: Object->0xffffd88dfeaf7b40	Name->BFE_Notify_Event_{bc107dad-a0b3-4993-8525-3244e00dcbf5}
	230: Object->0xffffd88dfb2f6de0	Name->MaximumCommitCondition
	233: Object->0xffffd88dfeaf7b40	Name->BFE_Notify_Event_{bc107dad-a0b3-4993-8525-3244e00dcbf5}
	247: Object->0xffffd88dfdee66c0	Name->BFE_Notify_Event_{3aab5344-00d6-4166-8201-552775602cb5}
	248: Object->0xffffd88dfdee66c0	Name->BFE_Notify_Event_{3aab5344-00d6-4166-8201-552775602cb5}

0: kd> !object 0xffffd88dfe7b64d0
Object: ffffd88dfe7b64d0  Type: (ffffd88dfb31acf0) ALPC Port
    ObjectHeader: ffffd88dfe7b64a0 (new version)
    HandleCount: 1  PointerCount: 32768
    Directory Object: ffffc70ebd466520  Name: LRPC-1e04123d1c6dafcb51
 この解析結果は、ALPCがRPCの応用メカニズムであることを示していますから、LocalServiceNoNetworkの意味がここではっきりします。LRPCは、ローカルシステム上のユーザー空間/カーネル空間やプロセス/スレッド間に適応される相互通信メカニズムであり、ネットワークサービスは提供していません(NoNetwork)。このALPCポートオブジェクトを調査したい場合には、たとえば、「!alpc /p 0xffffd88dfe7b64d0」などのWinDbgコマンドを次のように実行します。
0: kd> !alpc /p 0xffffd88dfe7b64d0
Port  ffffd88dfe7b64d0
  Type                      : ALPC_CONNECTION_PORT
  CommunicationInfo         : ffffc70ec8a08c30
    ConnectionPort          : ffffd88dfe7b64d0 (LRPC-1e04123d1c6dafcb51)
    ClientCommunicationPort : 0000000000000000
    ServerCommunicationPort : 0000000000000000
  OwnerProcess              : ffffd88dfe9a7080 (svchost.exe)
  SequenceNo                : 0x00000000 (0)
  CompletionPort            : ffffd88dfe9cf3c0
  CompletionList            : 0000000000000000
  ConnectionPending         : No
  ConnectionRefused         : No
  Disconnected              : No
  Closed                    : No
  FlushOnClose              : Yes
  ReturnExtendedInfo        : No
  Waitable                  : No
  Security                  : Static
  Wow64CompletionList       : No

  10 thread(s) are registered with port IO completion object:

    THREAD ffffd88dfd842080  Cid 04e0.1984  Teb: 00000007c7d36000 Win32Thread: 0000000000000000 WAIT
    THREAD ffffd88dfffc0700  Cid 04e0.1b3c  Teb: 00000007c7dbe000 Win32Thread: 0000000000000000 WAIT
    THREAD ffffd88dfe850080  Cid 04e0.1e68  Teb: 00000007c7c04000 Win32Thread: 0000000000000000 WAIT
    THREAD ffffd88dfc469040  Cid 04e0.1c10  Teb: 00000007c7c18000 Win32Thread: 0000000000000000 WAIT
    THREAD ffffd88e00161080  Cid 04e0.1ff8  Teb: 00000007c7c3e000 Win32Thread: 0000000000000000 WAIT
    THREAD ffffd88dffc22340  Cid 04e0.18ec  Teb: 00000007c7c40000 Win32Thread: 0000000000000000 WAIT
    THREAD ffffd88dff5bc1c0  Cid 04e0.177c  Teb: 00000007c7c42000 Win32Thread: 0000000000000000 WAIT
    THREAD ffffd88e00127200  Cid 04e0.199c  Teb: 00000007c7c44000 Win32Thread: 0000000000000000 WAIT
    THREAD ffffd88dff868080  Cid 04e0.1d7c  Teb: 00000007c7c46000 Win32Thread: 0000000000000000 WAIT
    THREAD ffffd88dff89a700  Cid 04e0.048c  Teb: 00000007c7c48000 Win32Thread: 0000000000000000 WAIT

  Main queue is empty.


  Direct message queue is empty.


  Large message queue is empty.


  Pending queue is empty.


  Canceled queue is empty.
 この出力情報を見ると、ほとんどのキューは「空」ですが、IO完了キューには10個のスレッドが入っています。ここで示されている「10個」という数値は正しいでしょうか?キューが破損している可能性はないでしょうか?次のようなコマンド操作をすると、これらの疑問への回答を探すことができます。
0: kd> !thread ffffd88dff89a700
THREAD ffffd88dff89a700  Cid 04e0.048c  Teb: 00000007c7c48000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
    ffffd88dfe9cf3c0  QueueObject
Not impersonating
DeviceMap                 ffffc70ec7468e30
Owning Process            ffffd88dfe9a7080       Image:         svchost.exe
Attached Process          N/A            Image:         N/A
Wait Start TickCount      4947807        Ticks: 13689 (0:00:03:33.890)
Context Switch Count      1              IdealProcessor: 1             
UserTime                  00:00:00.000
KernelTime                00:00:00.000
Win32 Start Address ntdll!TppWorkerThread (0x00007fff20c642c0)
Stack Init ffffd70a80e0cd90 Current ffffd70a80e0c540
Base ffffd70a80e0d000 Limit ffffd70a80e07000 Call 0000000000000000
Priority 8 BasePriority 8 PriorityDecrement 0 IoPriority 2 PagePriority 5
Child-SP          RetAddr           : Args to Child                                                           : Call Site
ffffd70a`80e0c580 fffff800`5b4b1070 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : nt!KiSwapContext+0x76
ffffd70a`80e0c6c0 fffff800`5b4b09ee : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : nt!KiSwapThread+0x190
ffffd70a`80e0c780 fffff800`5b4af87f : ffffd88d`ff89a700 00000000`00000000 ffffd88d`fe9a7000 ffffd88d`fe9cf3c0 : nt!KiCommitThreadWait+0x10e
ffffd70a`80e0c820 fffff800`5b4af379 : 00000000`00000000 00000000`00000001 00000000`00000001 00000000`00000000 : nt!KeRemoveQueueEx+0x24f
ffffd70a`80e0c8c0 fffff800`5b4aef05 : 00000000`00000000 00000000`00000000 000004e8`fffffb30 000004d0`fffffb30 : nt!IoRemoveIoCompletion+0x99
ffffd70a`80e0c9e0 fffff800`5b596203 : 00000000`00000000 fffff800`5b52062b ffffd88d`fe9cf190 00000000`00000000 : nt!NtWaitForWorkViaWorkerFactory+0x305
ffffd70a`80e0cb90 00007fff`20cd3784 : 00007fff`20c649dd 00000007`c7c9b000 00000000`00000000 00000000`00000000 : nt!KiSystemServiceCopyEnd+0x13 (TrapFrame @ ffffd70a`80e0cc00)
00000007`d107f4e8 00007fff`20c649dd : 00000007`c7c9b000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!NtWaitForWorkViaWorkerFactory+0x14
00000007`d107f4f0 00007fff`201d1fe4 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!TppWorkerThread+0x71d
00000007`d107f880 00007fff`20c9efb1 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : KERNEL32!BaseThreadInitThunk+0x14
00000007`d107f8b0 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!RtlUserThreadStart+0x21

0: kd> dt _kqueue ffffd88dfe9cf3c0
ntdll!_KQUEUE
   +0x000 Header           : _DISPATCHER_HEADER
   +0x018 EntryListHead    : _LIST_ENTRY [ 0xffffd88d`fe9cf3d8 - 0xffffd88d`fe9cf3d8 ]
   +0x028 CurrentCount     : 0
   +0x02c MaximumCount     : 4
   +0x030 ThreadListHead   : _LIST_ENTRY [ 0xffffd88d`fd842288 - 0xffffd88d`ff89a908 ]

0: kd> !validatelist ffffd88dfe9cf3c0+30
Found list end after 10 entries
 10個のスレッド数を確認するだけでしたら、このコマンド操作で十分ですが、実務解析作業では次のようなコマンド操作を行い、さらにカーネル深層に踏み込むこともあります。
0: kd> dt _io_workitem ffffd88dfe9cf3c0
nt!_IO_WORKITEM
   +0x000 WorkItem         : _WORK_QUEUE_ITEM
   +0x020 Routine          : 0xffffd88d`fe9cf3d8     void  +ffffd88dfe9cf3d8
   +0x028 IoObject         : 0x00000004`00000000 Void
   +0x030 Context          : 0xffffd88d`fd842288 Void
   +0x038 WorkOnBehalfThread : 0xffffd88d`ff89a908 _ETHREAD
   +0x040 Type             : 0
   +0x044 ActivityId       : _GUID {00000000-1000-8948-7c24-184c0e000d02}

0: kd> dt _WORK_QUEUE_ITEM ffffd88dfe9cf3c0
ntdll!_WORK_QUEUE_ITEM
   +0x000 List             : _LIST_ENTRY [ 0x00000000`00100204 - 0xffffd88d`ff5bc300 ]
   +0x010 WorkerRoutine    : 0xffffd88d`ff89a840     void  +ffffd88dff89a840
   +0x018 Parameter        : 0xffffd88d`fe9cf3d8 Void

0: kd> !validatelist poi(0xffffd88dff89a840)
Found list end after 10 entries
 このコマンド操作は、Windowsカーネルアーキテクチャー知識、C++のポインター、および、キャスト(型変換)を応用しています。

 本稿で取り上げたALPCは名前付きパイプとともに、プロのWindows内部解析技術者にとっては避けて通れない技術概念の一つです(参照)。従来はこのレベルの技術の習得には海外の資料や人材に頼る必要がありましたが、本「IT談話館」主筆の「豊田孝」はBlackHatなどのカンファレンスでプレゼンする海外の先端技術者に助言を与えています。時代が求める人材の育成と技術の習得には、「時間と予算の投資」が必要です。



「Windowsメモリダンプ解析サービス」のご案内




ビジネス
Windows内部解析専門家を目指す人向けの技術資料

Copyright©豊田孝 2004- 2019
本日は2019-12-16です。