本「
IT談話館」一般公開記事は、10年以上の実務経験を持つ上級Windowsエンジニアを想定しています。
本館は、Windowsカーネル深層を解析し、クラッシュ原因をはじめとするシステム内の「異様な動き」を検出・分析する
超高度な技術と実績を保有しています。
Idleプロセスと名無しのプロセス
本「IT談話館」の「一般公開記事」は、「Active Memory Dump とカーネルメモリダンプ」の解析結果を基に起草されています。「本館」主筆の「豊田孝」はDKOM(Direct Kernel Object Manipulation)ベースの解析手法の第一人者であり、Windowsカーネル空間の解析分野では世界の先頭を走っています。
現在、セキュリティー問題を無視することはできません。Microsoft社側の負担だけではなく、同社製品の利用者側の負担も増しています。困ったことではありますが、当面避けられません。セキュリティーの視点から「Windows10ソフトウェアセンサー」を見た場合、本「IT談話館」の確認範囲では、「カーネル層保護ロジック」に加え、次のような保護メカニズム階層が考案・実装されています。下記リンクはすべて本館記事を指しています。
- Silo/Server Silo
- Job
- Session
- Protected Process
- Mandatory Integrity Control(MIC)
- Windows API(+CPU)
- CPU
Windowsシステムには姿を見せずに動作するプロセスが存在します。そのようなプロセスは、「Active Memory Dump とカーネルメモリダンプ」をWinDbgにロードし、「!process」拡張コマンドを実行しても、表示されてきません。たとえば、次の図が示すように、分析ツールとして絶大な人気を誇るProcMonは「Idle」プロセスを起動するプロセスを検出することはできません。
本稿では、次の実物カーネルメモリダンプを本「IT談話館」の独自解析コードで解析し、表面に出てこないプロセスを紹介します。
4: kd> vertarget
Windows 7 Kernel Version 7601 (Service Pack 1) MP (8 procs) Free x64
Product: WinNt, suite: TerminalServer SingleUserTS
Built by: 7601.22616.amd64fre.win7sp1_ldr.140303-2307
Machine Name:
Kernel base = 0xfffff800`03a54000 PsLoadedModuleList = 0xfffff800`03c98890
Debug session time: Sat Sep 20 09:58:01.081 2014 (UTC + 9:00)
System Uptime: 0 days 2:46:44.174
この情報は、今回のカーネルメモリダンプの採取環境が8個のコアーを搭載したマシン上で動作する64ビットWindows 7 SP1であることを示しています。また、システム稼働後、2時間46分ちょっと過ぎにクラッシュが発生していることもわかります。まずは、本「IT談話館」の独自解析コードを実行し、どのようなプロセスがメモリに読み込まれたのかを調べてみます。
System(0xfffffa8006d0f740) Inserted->1
000 No.000 Inserted->1 smss.exe(0xfffffa800a763b30)
001 No.001 Inserted->1 csrss.exe(0xfffffa800bad1b30)
002 No.002 Inserted->1 psxss.exe(0xfffffa800bc35b30)
003 No.003 Inserted->1 csrss.exe(0xfffffa800bc50b30)
004 No.004 Inserted->1 wininit.exe(0xfffffa800adc3b30)
005 No.005 Inserted->1 services.exe(0xfffffa800c096060)
[---]
128 No.128 Inserted->1 iexplore.exe(0xfffffa800ef4b690)
129 No.129 Inserted->1 crypticError.e(0xfffffa800e514b30)
130 No.130 Inserted->1 GameClient.exe(0xfffffa80107d5b30)
131 No.131 Inserted->1 ArcOSOverlay.e(0xfffffa800d677060)
132 No.132 Inserted->0 (0xfffff80003c80ac0)
133 No.133 Inserted->0 Idle(0xfffff80003c54180)
システムクラッシュ発生当時動作していたプロセスを調査する場合、解析目的に応じて、次のような複数の視点を確保する必要があります。
- Process Manager
- Session Manager
- Security Manager
- Memory Manager
上の実行結果は、「Memory Manager」視点からの調査結果です。合計134個のプロセスは、赤色の「132」から、次のような順序でメモリにロードされます。
- (0xfffff80003c80ac0)
- Idle(0xfffff80003c54180)
- System(0xfffffa8006d0f740)
- smss.exe(0xfffffa800a763b30)
- csrss.exe(0xfffffa800bad1b30)
- その他
「132」の「(0xfffff80003c80ac0)」プロセスは「Idle」プロセスの前に起動されており、イメージ名が表示されていません。大変気になるプロセスであり、仮想アドレス「0xfffff80003c80ac0」から始まる領域に次のようにロードされています。
4: kd> dt nt!_eprocess 0xfffff80003c80ac0
nt!_EPROCESS
+0x000 Pcb : _KPROCESS
+0x160 ProcessLock : _EX_PUSH_LOCK
+0x168 CreateTime : _LARGE_INTEGER 0x2b80
+0x170 ExitTime : _LARGE_INTEGER 0x0
+0x178 RundownProtect : _EX_RUNDOWN_REF
+0x180 UniqueProcessId : 0x00000000`00000147 Void
+0x188 ActiveProcessLinks : _LIST_ENTRY [ 0x00000000`00000422 - 0x00000000`00000000 ]
+0x198 ProcessQuotaUsage : [2] 0
+0x1a8 ProcessQuotaPeak : [2] 0
+0x1b8 CommitCharge : 0x233
[---]
+0x2d8 Session : (null)
+0x2e0 ImageFileName : [15] "???"
+0x2ef PriorityClass : 0 ''
[---]
+0x328 ActiveThreads : 4
+0x32c ImagePathHash : 0
+0x330 DefaultHardErrorProcessing : 0
+0x334 LastThreadExitStatus : 0n0
+0x338 Peb : (null)
+0x340 PrefetchTrace : _EX_FAST_REF
+0x348 ReadOperationCount : _LARGE_INTEGER 0x0
+0x350 WriteOperationCount : _LARGE_INTEGER 0x0
+0x358 OtherOperationCount : _LARGE_INTEGER 0x0
+0x360 ReadTransferCount : _LARGE_INTEGER 0x0
+0x368 WriteTransferCount : _LARGE_INTEGER 0x0
+0x370 OtherTransferCount : _LARGE_INTEGER 0x0
+0x378 CommitChargeLimit : 0
+0x380 CommitChargePeak : 0
+0x388 AweInfo : 0x00000000`00000004 Void
+0x390 SeAuditProcessCreationInfo : _SE_AUDIT_PROCESS_CREATION_INFO
+0x398 Vm : _MMSUPPORT
+0x420 MmProcessLinks : _LIST_ENTRY [ 0xfffff800`03c545a0 - 0xfffffa80`0d677480 ]
+0x430 HighestUserAddress : 0x00000000`00003ea0 Void
[---]
4: kd> !validatelist poi(0xfffff80003c80ac0+420)
Found list end after 134 entries
このプロセス情報は次のような事実を示しています。
- 多くのフィールドが0となっている
- アクティブスレッド数が「4」と設定されているが実際にはスレッドは存在しない
- 「134」個のプロセスが存在することを示す情報を記録している
- 「134」という数値は調査の結果、正しい数値である
これらの事実と次の情報を総合すると、名前を持たないプロセス「(0xfffff80003c80ac0)」は必要な処理を(人知れず素早く)完了し、すでに動作を停止しているか、あるいは、特殊なプロセス、と考えられます。
4: kd> dt _object_header 0xfffff80003c80ac0-30
nt!_OBJECT_HEADER
+0x000 PointerCount : 0n0
+0x008 HandleCount : 0n0
+0x008 NextToFree : (null)
+0x010 Lock : _EX_PUSH_LOCK
+0x018 TypeIndex : 0 ''
+0x019 TraceFlags : 0 ''
+0x01a InfoMask : 0 ''
+0x01b Flags : 0 ''
+0x020 ObjectCreateInfo : (null)
+0x020 QuotaBlockCharged : (null)
+0x028 SecurityDescriptor : (null)
+0x030 Body : _QUAD
先ほどの実行結果をよく見ると、「132」と「133」以外のプロセスは「Inserted->1」というデータを持っていますが、これら2つのプロセスの対応するデータは「Inserted->0」となっています。「132」と「133」の2つのプロセスの存在は、Process ManagerやSession Managerなどに問い合わせても確認することはできません。この意味では、これら2つのプロセスは、マルウェア検出ツールなどから自分の存在を隠ぺいし、長期間システム内に潜む凶悪なルートキットの特徴を備えており、Microsoft社製純正ルートキットと呼べる存在です。
名前を持たないプロセス「・(0xfffff80003c80ac0)」はいったいどのような役割を担っているのでしょう?Windowsシステムには、次のような、「プライマリ(アイドル)プロセス+プライマリ(アイドル)スレッド」という考え方があります。
No.0 PrimaryProcess->0xFFFFF80003C54180 IdleThread->0xFFFFF80003C53CC0 State->02 Priority->16 WaitTime->0x9C906
No.1 PrimaryProcess->0xFFFFF80003C54180 IdleThread->0xFFFFF880009F30C0 State->02 Priority->16 WaitTime->0x0
No.2 PrimaryProcess->0xFFFFF80003C54180 IdleThread->0xFFFFF8800336F0C0 State->02 Priority->16 WaitTime->0x0
No.3 PrimaryProcess->0xFFFFF80003C54180 IdleThread->0xFFFFF880033E00C0 State->02 Priority->16 WaitTime->0x9B2F5
No.4 PrimaryProcess->0xFFFFF80003C54180 IdleThread->0xFFFFF880009BD0C0 State->02 Priority->16 WaitTime->0x0
No.5 PrimaryProcess->0xFFFFF80003C54180 IdleThread->0xFFFFF880034AF0C0 State->02 Priority->16 WaitTime->0x9C8FD
No.6 PrimaryProcess->0xFFFFF80003C54180 IdleThread->0xFFFFF880035200C0 State->02 Priority->16 WaitTime->0x0
No.7 PrimaryProcess->0xFFFFF80003C54180 IdleThread->0xFFFFF880035910C0 State->02 Priority->16 WaitTime->0x0
名前を持たないプロセス「・(0xfffff80003c80ac0)」が「Idle」プロセス(0xFFFFF80003C54180)の前に動作を開始している事実から、「プライマリ(アイドル)プロセス+プライマリ(アイドル)スレッド」を準備している、と解釈するのが自然でしょう。本稿では、Windows 7環境で採取されたカーネルメモリダンプの解析結果を紹介していますが、名前を持たないプロセスと「Idle」プロセスの関係はWindows 8.1やWindows 10にもそのまま引き継がれ、Windows 10からは、次のように、「Minimal Process」と呼ばれています。
***Windows 8.1***
2: kd> vertarget
Windows 8.1 Kernel Version 9600 MP (4 procs) Free x64
Product: WinNt, suite: TerminalServer SingleUserTS Personal
Built by: 9600.17238.amd64fre.winblue_gdr.140723-2018
Machine Name:
Kernel base = 0xfffff801`6868c000 PsLoadedModuleList = 0xfffff801`68956350
Debug session time: Thu Oct 9 00:34:44.270 2014 (UTC + 9:00)
System Uptime: 0 days 13:38:52.140
No.134 Inserted->0 0xfffff80168956540->
No.135 Inserted->0 0xfffff801689d9300->Idle
2: kd> dt _eprocess 0xfffff80168956540 mini*
nt!_EPROCESS
+0x67c Minimal : 0y0
***Windows 10 Creators Update***
1: kd> vertarget
Windows 10 Kernel Version 15063 MP (2 procs) Free x64
Product: WinNt, suite: TerminalServer SingleUserTS
Built by: 15063.0.amd64fre.rs2_release.170317-1834
Machine Name:
Kernel base = 0xfffff800`d5287000 PsLoadedModuleList = 0xfffff800`d55d35c0
Debug session time: Sat Aug 26 08:15:56.376 2017 (UTC + 9:00)
System Uptime: 4 days 0:30:14.078
No.137 Inserted->0 0xfffff800d55efb08->***
No.138 Inserted->0 0xfffff800d567e9c0->Idle
1: kd> dt _eprocess 0xfffff800d55efb08 mini*
ntdll!_EPROCESS
+0x6cc Minimal : 0y1
本稿で紹介した名前を持たない不思議なプロセスは、Windows 7の時代から存在していました。時代が進みWindows 10の時代に入ると、Minimal Process、という種類の特殊なプロセスであることが公にされました。ところが、同じWindows 10といっても、次のようにビルド番号が上がると、Minimalビットはリセットされています。
1: kd> vertarget
Windows 10 Kernel Version 17134 MP (2 procs) Free x64
Product: WinNt, suite: TerminalServer SingleUserTS
Built by: 17134.1.amd64fre.rs4_release.180410-1804
Machine Name:
Kernel base = 0xfffff802`b820d000 PsLoadedModuleList = 0xfffff802`b85bb170
Debug session time: Thu Aug 16 12:02:05.563 2018 (UTC + 9:00)
System Uptime: 0 days 3:54:33.418
No.178 Inserted->1 Sequence->781 Minimal->0 Pico->0 0xffffaa81eb670580->svchost.exe
No.179 Inserted->0 Sequence->000 Minimal->0 Pico->8011 0xfffff802b85d9090->
No.180 Inserted->0 Sequence->000 Minimal->0 Pico->0 0xfffff802b86749c0->Idle