Windowsメモリ内部解析サービス
豊田孝の「IT談話館」 Windowsメモリダンプ解析を依頼する WinDbgとシステム分析




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



WinDbgとWindowsレジストリ解析(基礎)


 WindowsはSaaSとして提供される時代に入り、その内部は頻繁に更新されています。更新内容の多くは、いろいろな事情から、公にされることはほとんどありません。最新のユーザー空間とカーネル空間に関する信頼できる情報を取得するには、インターネットなどでは語られることのない高度な内部解析技術が必須とされています。

 本稿では、Windows 10環境で採取した「Active Memory Dump」内に保存されているWindowsレジストリ情報を本「IT談話館」の独自解析コードで解析します。

  Windowsレジストリ情報は、オブジェクト名前空間にKeyオブジェクトして記録されます。まずは、独自の解析コードを実行し、解析対象プロセスの「ハンドルテーブル」からオブジェクト名前空間へアクセスし、数あるオブジェクトの中からKeyオブジェクトを検出します。古いWindows 10ビルド環境で採取したメモリダンプを解析すると、次のようなレジストリ情報を取得することができます。なお、解析コードの開発知識の習得には、「時間と予算の投資」が必要です。
No.029	Object->0xffffc70ebe079c60	ObjectType->0xffffd88dfb31dd10	Name->Key
		Index->0x02b	Handle->0x074

0: kd> !object 0xffffc70ebe079c60
Object: ffffc70ebe079c60  Type: (ffffd88dfb31dd10) Key
    ObjectHeader: ffffc70ebe079c30 (new version)
    HandleCount: 1  PointerCount: 28875
    Directory Object: 00000000  Name: \REGISTRY\MACHINE
 Keyオブジェクトを検出した後は、WinDbg付属の「!reg」コマンドで次のように調査します。
0: kd> !reg kbody 0xffffc70ebe079c60
Type        : KEY_BODY_TYPE
KCB         : ffffc70ebc83c138
NotifyBlock : 0000000000000000
KeyBodyList : 0xffffc70ec8580e90 0xffffc70ebc83c1a8

0: kd> !reg kcb ffffc70ebc83c138
Key              : \REGISTRY\MACHINE
RefCount         : d4
Flags            : CompressedName,
ExtFlags         :
Parent           : 0xffffc70ebc83c008
KeyHive          : 0xffffc70ebc823000
KeyCell          : 0x170 [cell index]
TotalLevels      : 2
LayerHeight      : 0
MaxNameLen       : 0x16
MaxValueNameLen  : 0x0
MaxValueDataLen  : 0x0
LastWriteTime    : 0x 1d39e07:0x3f20c700
KeyBodyListHead  : 0xffffc70ebe079c80 0xffffc70ecef327f0
SubKeyCount      : 6
ValueCache.Count : 0
Owner            : 0x0000000000000000
KCBLock          : 0xffffc70ebc83c228
KeyLock          : 0xffffc70ebc83c238
 このコマンド操作では、上位概念から解析を開始する必要から、「kbody」と「kcb」という2つの引数を「!reg」コマンドに渡しています。上の実行結果を見ると、希望する情報が返されています。ところが、比較的新しいWindows 10ビルド環境で採取したメモリダンプ上で同じコマンド操作を行うと、次のようなエラーが返されてしまいます。
0: kd> !reg kbody 0xffff8d8c493159a0

Type        : KEY_BODY_TYPE
KCB         : ffff8d8c47d43520
NotifyBlock : 0000000000000000
KeyBodyList : 0xffff8d8c47d43598 0xffff8d8c506c1100

0: kd> !reg kcb ffff8d8c47d43520
Not enough space to read nt!_CM_KEY_CONTROL_BLOCK-RefCount
c0000005 Exception in kdexts.reg debugger extension.
      PC: 00007ff9`5ca7a839  VA: 00000012`07d7e30a  R/W: d98f8ef8  Parameter: 00000000`00000000

0: kd> dt nt!_CM_KEY_CONTROL_BLOCK ffff8d8c47d43520 ref*
   +0x000 RefCount : 0x7f
 この例外発生の背景には、次のような内部変更の影響が推察されます。
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`9ea1b000 PsLoadedModuleList = 0xfffff802`9edc9150
Debug session time: Sun Mar 10 06:57:53.854 2019 (UTC + 9:00)
System Uptime: 2 days 22:17:18.721

1: kd> dt nt!_CM_KEY_CONTROL_BLOCK ref*
   +0x000 RefCount : Uint4B


0: kd> vertarget
Windows 10 Kernel Version 18362 MP (2 procs) Free x64
Product: WinNt, suite: TerminalServer SingleUserTS
Built by: 18362.1.amd64fre.19h1_release.190318-1202
Machine Name:
Kernel base = 0xfffff804`59a00000 PsLoadedModuleList = 0xfffff804`59e480b0
Debug session time: Sun Nov  3 09:56:47.110 2019 (UTC + 9:00)
System Uptime: 0 days 1:42:54.949

0: kd> dt nt!_CM_KEY_CONTROL_BLOCK ref*
   +0x000 RefCount : Uint8B
 この情報は、kdexts.regの開発担当者が必要とされるメモリ量が4バイトから8バイトに変更されたことをうっかり忘れていたことを示唆しています。同じWindows 10と一口に言ってもビルド番号が異なれば、このような細かな内部変更も発生しており、米Microsoft社内の上級エンジニアでさえも、すべての変更内容を把握することは難しいと推測されます。

 本館はこの例外に興味を引かれたため、本館独自の解析コードを開発し、上の「Built by: 18362.1」メモリダンプに適応し、Keyオブジェクト自体の設計上の変更を確認してみることにしました。

 次のような結果が返されてきます。
ObjectTable->0xffff8d8c4c8e8000	HandleCount->0235	ffffc489264e2080->notmyfault64.e

kbody->0xffff8d8c493159a0	kcb->0xffff8d8c47d43520
	FullKeyName->\REGISTRY\MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options	RefCount->0127
Found list end after 122 entries
	Length->28	ShrtKeyName->IMAGE FILE EXECUTION OPTIONSME)E10318}

kbody->0xffff8d8c4d710940	kcb->0xffff8d8c43e857f0
	FullKeyName->***
	RefCount->0113
Found list end after 106 entries
	Length->15	ShrtKeyName->SESSION MANAGER

kbody->0xffff8d8c4d70f980	kcb->0xffff8d8c44246d40
	FullKeyName->***
	RefCount->0123
Found list end after 119 entries
	Length->8	ShrtKeyName->VERSIONSAPPING

kbody->0xffff8d8c4d7103a0	kcb->0xffff8d8c43e58ad0
	FullKeyName->***
	RefCount->0171
Found list end after 161 entries
	Length->7	ShrtKeyName->MACHINE

kbody->0xffff8d8c4d710700	kcb->0xffff8d8c43e58ad0
	FullKeyName->***
	RefCount->0171
Found list end after 161 entries
	Length->7	ShrtKeyName->MACHINE

kbody->0xffff8d8c4d710820	kcb->0xffff8d8c47e653f0
	FullKeyName->\REGISTRY\MACHINE\SOFTWARE\Microsoft\Ole	RefCount->0124
Found list end after 120 entries
	Length->3	ShrtKeyName->OLE
	
[---]
 この情報には2箇所のデータが赤色で表示されています。2番目の赤色の「SESSION MANAGER」のFullKeyName欄は「***」となっており、希望する文字列が返されていません。この背景に興味のある方は「WinDbgとWindowsレジストリ解析(応用)」を一読していただくとし、ここでは赤色の数値「122」のみを解析します。この数値はKeyBodyListを構成する要素数を示している思われます。本館はさらに、この数値は該当キーを参照しているプロセスオブジェクトの数をも示しているのではないか?と仮定し、なら、プロセス名を取得してみようと思い立ちました。そこで、新規に解析コードを開発し、次のような情報を取得してみました。
	Kbody->0xffff8d8c493159a0	ProcessId->0x1514
Found list end after 122 entries
0000: 0xffffc489241113c0	ProcessId->0x0270	csrss.exe
0001: 0xffffc48924130080	ProcessId->0x02ac	services.exe
0002: 0xffffc48924131080	ProcessId->0x02b4	lsass.exe
0003: 0xffffc489241d5080	ProcessId->0x0314	svchost.exe
0004: 0xffffc4892481c080	ProcessId->0x032c	svchost.exe
0005: 0xffffc48924843080	ProcessId->0x0374	fontdrvhost.ex
0006: 0xffffc4892486e0c0	ProcessId->0x03b8	fontdrvhost.ex
0007: 0xffffc489227730c0	ProcessId->0x03e0	svchost.exe
0008: 0xffffc489248c4080	ProcessId->0x01b0	svchost.exe
0009: 0xffffc48924879080	ProcessId->0x02d0	dwm.exe
0010: 0xffffc4892494f080	ProcessId->0x0220	svchost.exe
0011: 0xffffc48924991280	ProcessId->0x0428	svchost.exe
0012: 0xffffc48924997080	ProcessId->0x0430	svchost.exe
0013: 0xffffc489249ca080	ProcessId->0x0470	svchost.exe
0014: 0xffffc489249e90c0	ProcessId->0x0490	svchost.exe
0015: 0xffffc489249f1080	ProcessId->0x04a0	svchost.exe
0016: 0xffffc48924a30080	ProcessId->0x0508	svchost.exe
0017: 0xffffc48924ac03c0	ProcessId->0x0540	svchost.exe
0018: 0xffffc48924af7080	ProcessId->0x056c	WUDFHost.exe
0019: 0xffffc48924a890c0	ProcessId->0x058c	svchost.exe
0020: 0xffffc48924b18080	ProcessId->0x05dc	svchost.exe
0021: 0xffffc48924b1c080	ProcessId->0x05e4	svchost.exe
0022: 0xffffc48924b5a080	ProcessId->0x062c	svchost.exe
0023: 0xffffc48924b2d080	ProcessId->0x0610	svchost.exe
0024: 0xffffc48924b2f080	ProcessId->0x0620	svchost.exe

[---]
 今回は、「\REGISTRY\MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options」キーを参照しているプロセスを検出しました。他のキーも同じように解析することができます。使用した解析コードは「ハンドルテーブル」をはじめとする複数の概念の上に実装されています。各概念は論理的に関連付けられており、その関連付け論理(考え方)はWindows 10ビルド間でかなり安定しています。

 レジストリ情報はメモリフォレンジックなどの作業では極めて重要な調査対象とされています。実務作業では「kbody」と「kcb」などの上位概念の解析から入り、その後、作業目的に応じて下位概念の解析に進むことになります。必要以上にレジストリ深層を解析する必要はありませんが、現在のソフトウェアの更新と提供状況を考えると、”そこはどういう意味だろう?”という疑問を解消する技術は独自に習得しておく必要があります。この姿勢を堅持していれば、たとえば、今回のようなWinDbgコマンドのエラー発生時に対処できる知識が自然と身に付きます。

WinDbgとWindowsレジストリ解析(応用)



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




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

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