本「
IT談話館」一般公開記事は、10年以上の実務経験を持つ上級Windowsエンジニアを想定しています。
本館は、Windowsカーネル深層を解析し、クラッシュ原因をはじめとするシステム内の「異様な動き」を検出・分析する
超高度な技術と実績を保有しています。
Windows 10 Active Memory Dumpとカーネルメモリダンプ
本「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 7や8.1からWindows 10へアップグレードすると、Active Dump Memoryという新しい種類のクラッシュダンプを作成できます。本稿では、このActive Dump Memoryと、従来から作成できるカーネルメモリダンプを比較しながら、これら2種類のダンプ間の相違を紹介します。
新種のダンプファイルの導入自体は歓迎すべきことですが、ダンプファイルに保存される情報の質と量が気になるところです。そこで、次のような視点から64ビットWindows 10 Professional環境で採取したカーネルメモリダンプとActive Memory Dumpを本「IT談話館」の独自解析コードで解析し、内容を比較してみることにします。
- ダンプに記録されているすべてのプロセスオブジェクトを列挙する
- すべてのプロセスオブジェクトのすべてのスレッドオブジェクトを列挙する
- すべてのスレッドオブジェクトの開始アドレスと開始ルーチン名を列挙する
- すべてのスレッドオブジェクトのトラップフレームとトラップされたコードを列挙する
- ユーザー空間からカーネル空間へのシステムサービス呼び出しの背景を分析する
まずはWindows 10環境で採取されたカーネルメモリダンプの解析結果を見てみましょう。
カーネルメモリダンプ
0xffffe0015246a840 ActiveThread->011 csrss.exe
No.001 Thread->0xffffe001522c9840 TrapFrame->0xffffd00158946c00
Start->00007ff9`a45a5310 Rip->00007ff9`a7c43d7a
No.002 Thread->0xffffe00150318080 TrapFrame->0xffffd00158dcdc00
Start->00007ff9`a45a5310 Rip->00007ff9`a7c43d7a
No.003 Thread->0xffffe0015220c840 TrapFrame->0xffffd001589f2c00
Start->00007ff9`a4547130 Rip->00007ff9`a4547a5a
No.004 Thread->0xffffe00152e56080 TrapFrame->0xffffd00020595c00
Start->00007ff9`a45a5310 Rip->00007ff9`a7c43d7a
No.005 Thread->0xffffe00152f65080 TrapFrame->0xffffd000208bfc00
Start->00007ff9`a45a5310 Rip->00007ff9`a7c43d7a
No.006 Thread->0xffffe00150eff040 TrapFrame->0xffffd00021a3bc00
Start->00007ff9`a7be9040 Rip->00007ff9`a7c4505a
0xffffe001549b65c0 ActiveThread->012 csrss.exe
No.001 Thread->0xffffe0015162f080 TrapFrame->0xffffd00021cefc00
Start->00007ff9`a45a5310 Rip->00007ff9`a7c43d7a
No.002 Thread->0xffffe0015165c080 TrapFrame->0xffffd0002231ec00
Start->00007ff9`a45a5310 Rip->00007ff9`a7c43d7a
No.003 Thread->0xffffe00154fdf080 TrapFrame->0xffffd000231cdc00
Start->00007ff9`a4547130 Rip->00007ff9`a4547a5a
No.004 Thread->0xffffe001539de080 TrapFrame->0xffffd00020375c00
Start->00007ff9`a4547130 Rip->00007ff9`a4547a5a
No.005 Thread->0xffffe00154dae080 TrapFrame->0xffffd00023157c00
Start->00007ff9`a45a5310 Rip->00007ff9`a7c43d7a
No.006 Thread->0xffffe00154a71080 TrapFrame->0xffffd000224fdc00
Start->00007ff9`a4547130 Rip->00007ff9`a4547a5a
No.007 Thread->0xffffe0015238c680 TrapFrame->0xffffd00021afbc00
Start->00007ff9`a7be9040 Rip->00007ff9`a7c4505a
この情報は本「IT談話館」の独自解析コードが返してくれた「csrss.exe」プロセスに関する情報です。実際には、すべてのプロセスの内部情報が返されていますが、ここでは、「csrss.exe」プロセスに関する情報だけを紹介しています。16進数値が並んでいるだけですから、これら2つのプロセスの特徴を瞬時に把握することはできません。その最大の原因は、ユーザー空間情報が記録されていないことです。次に紹介する情報は、同一の解析コードでActive Memory Dumpダンプを解析した結果です。
Active Memory Dump
0xffffe000fb83c240 ActiveThread->012 csrss.exe
No.001 Thread->0xffffe000fb80a080 TrapFrame->0xffffd001276a5c00
Start->00007ffd`aee15310 Rip->ntdll!NtAlpcSendWaitReceivePort+0xa (00007ffd`b24b3d7a)
No.002 Thread->0xffffe000fc417080 TrapFrame->0xffffd0012d2f7c00
Start->00007ffd`aee15310 Rip->ntdll!NtAlpcSendWaitReceivePort+0xa (00007ffd`b24b3d7a)
No.003 Thread->0xffffe000fc414480 TrapFrame->0xffffd00127aaec00
Start->00007ffd`aedb7130 Rip->00007ffd`aedb7a5a
No.004 Thread->0xffffe000fc4f8840 TrapFrame->0xffffd0012768cc00
Start->00007ffd`aedb7130 Rip->00007ffd`aedb7a5a
No.005 Thread->0xffffe000fca6d080 TrapFrame->0xffffd0012b3fcc00
Start->00007ffd`aee15310 Rip->ntdll!NtAlpcSendWaitReceivePort+0xa (00007ffd`b24b3d7a)
No.006 Thread->0xffffe000fce1a080 TrapFrame->0xffffd0012c1fcc00
Start->00007ffd`aee15310 Rip->ntdll!NtAlpcSendWaitReceivePort+0xa (00007ffd`b24b3d7a)
0xffffe000fa2a4080 ActiveThread->012 csrss.exe
No.001 Thread->0xffffe000fa2de180 TrapFrame->0xffffd0012b1bac00
Start->00007ffd`aee15310 Rip->ntdll!NtAlpcSendWaitReceivePort+0xa (00007ffd`b24b3d7a)
No.002 Thread->0xffffe000fc53e700 TrapFrame->0xffffd001294bec00
Start->00007ffd`aee15310 Rip->ntdll!NtAlpcSendWaitReceivePort+0xa (00007ffd`b24b3d7a)
No.003 Thread->0xffffe000fc537280 TrapFrame->0xffffd0012aa70c00
Start->00007ffd`aedb7130 Rip->00007ffd`aedb7a5a
No.004 Thread->0xffffe000fc535800 TrapFrame->0xffffd0012aa77c00
Start->00007ffd`aedb7130 Rip->00007ffd`aedb7a5a
No.005 Thread->0xffffe000fc5f4080 TrapFrame->0xffffd0012d139c00
Start->00007ffd`aee15310 Rip->ntdll!NtAlpcSendWaitReceivePort+0xa (00007ffd`b24b3d7a)
赤色のデータからは、これらのプロセスがAlpcを使用し、他のプロセスと通信していることが分かります。このため、「!alpc /lpp 0xffffe000fa2a4080」といったWinDbg拡張コマンドを実行すれば、プロセス間通信の概要をある程度その場で把握できます。Alpcに興味のある方は、本館の「この記事」が参考になるでしょう。
2つのクラッシュダンプを採取するために、今回は「NotMyfault.exe」を使用しましたから、そのプロセス情報を解析し、ユーザー空間とカーネル空間の関係を覗いてみます。
Active Memory Dump
0: kd> vertarget
Windows 10 Kernel Version 10240 MP (2 procs) Free x64
Product: WinNt, suite: TerminalServer SingleUserTS
Built by: 10240.16393.amd64fre.th1_st1.150717-1719
Machine Name:
Kernel base = 0xfffff803`15415000 PsLoadedModuleList = 0xfffff803`1573a030
Debug session time: Tue Aug 4 11:21:22.658 2015 (UTC + 9:00)
System Uptime: 0 days 18:04:16.257
0xffffe0007749f080 ActiveThread->003 NotMyfault.exe
No.001 Thread->0xffffe00075ea5840 TrapFrame->0xffffd00022fbde40
Start->NotMyfault+0x2f98 (00007ff7`cf1a2f98) Rip->ntdll!NtDeviceIoControlFile+0xa (00007ffa`3dab356a)
No.002 Thread->0xffffe000772b9840 TrapFrame->0xffffd00022a2ec00
Start->ntdll!TppWorkerThread (00007ffa`3da59040) Rip->ntdll!NtWaitForWorkViaWorkerFactory+0xa (00007ffa`3dab505a)
No.003 Thread->0xffffe00076aff5c0 TrapFrame->0xffffd000210eac00
Start->ntdll!TppWorkerThread (00007ffa`3da59040) Rip->ntdll!NtWaitForWorkViaWorkerFactory+0xa (00007ffa`3dab505a)
赤色のデータの背景は、次のようなコマンド操作で調査できます。
1: kd> u ntdll!NtDeviceIoControlFile ntdll!NtDeviceIoControlFile+a
ntdll!NtDeviceIoControlFile:
00007ffc`b04d3560 4c8bd1 mov r10,rcx
00007ffc`b04d3563 b807000000 mov eax,7
00007ffc`b04d3568 0f05 syscall
00007ffc`b04d356a c3 ret
「syscall」は、ユーザー空間からカーネル空間に存在するシステムサービステーブルへアクセスするコードです。一方、「7」という数値は、次のように、システムサービステーブル(SSDT)内のインデックスを示しています。
0: kd> ub ntdll!NtDeviceIoControlFile+a l0n20
ntdll!NtMapUserPhysicalPagesScatter+0xa:
00007ffa`3dab352a c3 ret
00007ffa`3dab352b 0f1f440000 nop dword ptr [rax+rax]
ntdll!NtWaitForSingleObject:
00007ffa`3dab3530 4c8bd1 mov r10,rcx
00007ffa`3dab3533 b804000000 mov eax,4
00007ffa`3dab3538 0f05 syscall
00007ffa`3dab353a c3 ret
00007ffa`3dab353b 0f1f440000 nop dword ptr [rax+rax]
ntdll!NtCallbackReturn:
00007ffa`3dab3540 4c8bd1 mov r10,rcx
00007ffa`3dab3543 b805000000 mov eax,5
00007ffa`3dab3548 0f05 syscall
00007ffa`3dab354a c3 ret
00007ffa`3dab354b 0f1f440000 nop dword ptr [rax+rax]
ntdll!NtReadFile:
00007ffa`3dab3550 4c8bd1 mov r10,rcx
00007ffa`3dab3553 b806000000 mov eax,6
00007ffa`3dab3558 0f05 syscall
00007ffa`3dab355a c3 ret
00007ffa`3dab355b 0f1f440000 nop dword ptr [rax+rax]
ntdll!NtDeviceIoControlFile:
00007ffa`3dab3560 4c8bd1 mov r10,rcx
00007ffa`3dab3563 b807000000 mov eax,7
00007ffa`3dab3568 0f05 syscall
「r10,rcx」部分は、システムサービスに渡す引数ですが、後ほど調査します。「7」をはじめとするインデックス値とシステムサービステーブル、および、システムサービスの関係は、次のようになっています。
0 nt!NtAccessCheck (fffff803`15505324)
1 nt!NtWorkerFactoryWorkerReady (fffff803`15508810)
2 nt!NtAcceptConnectPort (fffff803`1594366c)
3 nt!NtMapUserPhysicalPagesScatter (fffff803`15ab6c78)
4 nt!NtWaitForSingleObject (fffff803`15837420)
5 nt!NtCallbackReturn (fffff803`15564dd0)
6 nt!NtReadFile (fffff803`15834d10)
7 nt!NtDeviceIoControlFile (fffff803`15842a00)
8 nt!NtWriteFile (fffff803`15834100)
9 nt!NtRemoveIoCompletion (fffff803`1591d5b0)
10 nt!NtReleaseSemaphore (fffff803`159053a0)
11 nt!NtReplyWaitReceivePort (fffff803`15829b6c)
12 nt!NtReplyPort (fffff803`15927e04)
13 nt!NtSetInformationThread (fffff803`1582a400)
14 nt!NtSetEvent (fffff803`15840410)
15 nt!NtClose (fffff803`15835f90)
[---]
この情報も本館の独自解析コードで取り出していますが、ご覧のように、テーブル内にはシステムサービスが順序よく並んでいます。「7 nt!NtDeviceIoControlFile (fffff803`15842a00)」サービスは、「r10,rcx」経由で次のような引数を受け取っています。
NotMyfault.exe(0xffffe0007749f080) has 3 active threads
1: Thread: 0xffffe00075ea5840
Wait Reason: 27
State: 2
Trapframe: ffffd00022fbde40
Arg(448)
System Call Number: 7 ===> nt!NtDeviceIoControlFile (fffff803`15842a00)
2: Thread: 0xffffe000772b9840
Wait Reason: 15
State: 5
Trapframe: ffffd00022a2ec00
Arg(92)
System Call Number: 438 ===> nt!NtWaitForWorkViaWorkerFactory (fffff803`15457810)
3: Thread: 0xffffe00076aff5c0
Wait Reason: 15
State: 5
Trapframe: ffffd000210eac00
Arg(92)
System Call Number: 438 ===> nt!NtWaitForWorkViaWorkerFactory (fffff803`15457810)
0: kd> !handle 0n448 3 0xffffe0007749f080
PROCESS ffffe0007749f080
SessionId: 2 Cid: 141c Peb: 7ff7cee8d000 ParentCid: 1204
DirBase: 69225000 ObjectTable: ffffc001e0e2b2c0 HandleCount:
Image: NotMyfault.exe
Handle Error reading handle count.
01c0: Object: ffffe00076049f20 GrantedAccess: 0012019f (Protected) (Inherit) (Audit) Entry: ffffc001d3300700
Object: ffffe00076049f20 Type: (ffffe0007301fdc0) File
ObjectHeader: ffffe00076049ef0 (new version)
HandleCount: 1 PointerCount: 32770
ご覧のように、「7 nt!NtDeviceIoControlFile (fffff803`15842a00)」システムサービスは、Fileオブジェクトを受け取っています。本稿では、Fileオブジェクトの解析工程の説明は割愛します。Active Memory Dumpにはユーザー空間で動作していた「NotMyfault.exe」プロセスに関する情報が記録されており、たいへん便利です。このレベルの基本的な解析技術を身に着けておくと、Windows 10の最新のカーネル内部変更にも対応できるようになります。次の情報は、ビルド番号更新後のWindows 10の「ntdll!NtDeviceIoControlFile」の実装ロジックであり、セキュリティー向上の視点から、システム呼び出し工程が変更されたことを示しています。
1: kd> vertarget
Windows 10 Kernel Version 14393 MP (2 procs) Free x64
Product: WinNt, suite: TerminalServer SingleUserTS
Built by: 14393.103.amd64fre.rs1_release_inmarket.160819-1924
Machine Name:
Kernel base = 0xfffff800`e6e7e000 PsLoadedModuleList = 0xfffff800`e71830a0
Debug session time: Sat Sep 17 04:18:01.076 2016 (UTC + 9:00)
System Uptime: 2 days 16:42:08.801
1: kd> uf ntdll!NtDeviceIoControlFile
ntdll!NtDeviceIoControlFile:
00007ffe`61304f20 4c8bd1 mov r10,rcx
00007ffe`61304f23 b807000000 mov eax,7
00007ffe`61304f28 f604250803fe7f01 test byte ptr [SharedUserData+0x308 (00000000`7ffe0308)],1
00007ffe`61304f30 7503 jne ntdll!NtDeviceIoControlFile+0x15 (00007ffe`61304f35) Branch
ntdll!NtDeviceIoControlFile+0x12:
00007ffe`61304f32 0f05 syscall
00007ffe`61304f34 c3 ret
ntdll!NtDeviceIoControlFile+0x15:
00007ffe`61304f35 cd2e int 2Eh
00007ffe`61304f37 c3 ret
このレベルの内部変更は、「Windows As A Service」ビジネスモデルがすでに採用されている現在、カーネル内部のいたるところに見られます。「内部変更」の多くは、突然、あるいは、こっそり、行われる性格が強く、セキュリティー脅威の緩和対策のため、公に語られないのが時代の流れです。結果、これまで何の問題もなく動作していたアプリケーションが突然動作しなくなる、あるいは、(一見、正常そうに動作していても)正確な情報を返してこない。このような事態をもろ手を挙げて歓迎するわけにはいきませんが、現実的には、当面避けられない!、と覚悟したほうがよいでしょう。