远程RDP时意识到服务端重启过,在sysdm.cpl中确认有内存转储,在管理员级cmd中复制转储文件,方便后续操作。

cd /d X:\<path>\crash
copy %SystemRoot%\MEMORY.DMP .

用windbgx加载MEMORY.DMP

.prompt_allow +reg +ea +dis

kd> !analyze -v
...
MEMORY_MANAGEMENT (1a)
    # Any other values for parameter 1 must be individually examined.
Arguments:
Arg1: 0000000000061941, The subtype of the BugCheck.
Arg2: 000001d8448a8000
Arg3: 000000000000000f
Arg4: ffffbc8a1122fa00
...
PROCESS_NAME:  svchost.exe

STACK_TEXT:
ffffbc8a`1122f858 fffff807`72834fe8     : 00000000`0000001a 00000000`00061941 000001d8`448a8000 00000000`0000000f : nt!KeBugCheckEx
ffffbc8a`1122f860 fffff807`72806a5e     : 00000063`60a7e4d0 000001d8`41149a50 ffffbc8a`1122fa80 ffffd48e`325f5dd0 : nt!MmAccessFault+0x1c8308
ffffbc8a`1122fa00 00007ffc`63264d51     : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : nt!KiPageFault+0x35e
00000063`60a7dfe0 00000000`00000000     : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : 0x00007ffc`63264d51
...

查看当前进程

kd> !process -1 0
PROCESS ffffd48e335670c0
    SessionId: 0  Cid: 1900    Peb: 635faa8000  ParentCid: 02e4
    DirBase: 3c2854000  ObjectTable: ffffe582035d58c0  HandleCount: 348.
    Image: svchost.exe
查看当前进程上下文

kd> !process -1 0xf
kd> !process -1 0x1f
(略)

查看当前线程及调用栈回溯

kd> !thread -p -1 0xf
kd> !thread -p -1 0x1f
PROCESS ffffd48e335670c0
    SessionId: 0  Cid: 1900    Peb: 635faa8000  ParentCid: 02e4
    DirBase: 3c2854000  ObjectTable: ffffe582035d58c0  HandleCount: 348.
    Image: svchost.exe

THREAD ffffd48e46fe5080  Cid 1900.6cbc  Teb: 000000635fbed000 Win32Thread: 0000000000000000 RUNNING on processor 7
...
Child-SP          RetAddr               Call Site
ffffbc8a`1122f858 fffff807`72834fe8     nt!KeBugCheckEx
ffffbc8a`1122f860 fffff807`72806a5e     nt!MmAccessFault+0x1c8308
ffffbc8a`1122fa00 00007ffc`63264d51     nt!KiPageFault+0x35e (TrapFrame @ ffffbc8a`1122fa00)
00000063`60a7dfe0 00000000`00000000     0x00007ffc`63264d51

调用栈里有未解析的地址,刷新kd维护的用户态加载模块列表使之匹配目标进程

kd> .reload /f /user
Loading User Symbols
PEB is paged out (Peb.Ldr = 00000063`5faa8018).  Type ".hh dbgerr001" for details
报"PEB is paged out",可以利用!vad单独加载相应模块的符号信息。

kd> !vad 7ffc`63264d51 1
...
Reload command: .reload rpcrt4.dll=00007ffc`63250000,125000

kd> .reload rpcrt4.dll=00007ffc`63250000,125000

kd> kpn
 # Child-SP          RetAddr               Call Site
00 ffffbc8a`1122f858 fffff807`72834fe8     nt!KeBugCheckEx
01 ffffbc8a`1122f860 fffff807`72806a5e     nt!MmAccessFault+0x1c8308
02 ffffbc8a`1122fa00 00007ffc`63264d51     nt!KiPageFault+0x35e
03 00000063`60a7dfe0 00000000`00000000     rpcrt4+0x14d51
"!process -1 0xf"输出的调用栈回溯中还有一个地址未被解析,一并解决

kd> !vad 7ffc`63ff0994 1
...
Reload command: .reload ntdll.dll=00007ffc`63f50000,1f8000

kd> .reload ntdll.dll=00007ffc`63f50000,1f8000
kd> !process -1 0xf

但lmul发现rpcrt4、ntdll的符号并未找到并加载

kd> lmul
start             end                 module name
00007ffc`63250000 00007ffc`63375000   rpcrt4   T (no symbols)
00007ffc`63f50000 00007ffc`64148000   ntdll    T (no symbols)

起初以为是符号不匹配所致,手工更新单个符号

symchk.exe /v C:\Windows\System32\ntdll.dll
symchk.exe /v C:\Windows\System32\rpcrt4.dll

符号是匹配的,不是这个原因。

kd> !lmi rpcrt4
Loaded Module Info: [rpcrt4]
Cannot read Image header @ 00007ffc63250000
    Load Report: no symbols loaded

用!lmi时才意识到缺少用户态内存转储,MEMORY.DMP是缺省的自动内存转储。读不到PE头,无法寻找相应的符号文件。

用IDA反汇编rpcrt4.dll,Rebase后查看0x7ffc63264d51,这是

Ndr64ComplexArrayUnmarshall+0x651

kd> .frame /c 3
03 00000063`60a7dfe0 00000000`00000000     rpcrt4+0x14d51
rax=0000000000000000 rbx=0000006360a7e4d0 rcx=000001d8439d8028
rdx=000001d8439d8020 rsi=00007ffc63266e20 rdi=0000000000000008
rip=00007ffc63264d51 rsp=0000006360a7dfe0 rbp=00007ffc63264700
 r8=000001d8448a8000  r9=000001d8448a8000 r10=0000000000000010
r11=00007ffc63250000 r12=00007ffc63264ee0 r13=0000000000000000
r14=00007ffc3b0277dc r15=0000000000000001
iopl=0         nv up ei pl zr na po nc
cs=0010  ss=0000  ds=002b  es=002b  fs=0053  gs=002b             efl=00040246
rpcrt4+0x14d51:
00007ffc`63264d51 ??              ???

IDA中查看附近代码

00007FFC63264D4E mov     rax, [rax]
00007FFC63264D51 mov     [r8], rax

有个写访问违例,仅此而已,无法进一步分析,缺少用户态内存转储。

彼时PID是1900,死马当成活马医,看一下重启后的1900进程。

$ tasklist /svc /fi "pid eq 1900"

Image Name                     PID Services
========================= ======== ===========
svchost.exe                   1900 UserManager

services.msc中查看描述,用户管理器提供多用户交互所需要的运行时组件。猜测是RDP登录过程中触发了什么BUG,最终OS重启。