在接下来的这个系列中我们会以实例来说明Windows系统案例一般如何进行排查,包括一些常见工具的使用以及排查问题的思路。
这次我们遇到的一个有意思的的问题是这样的:用户在云上自建了Windows活动目录(AD),包括一台域控和几台域成员,当用户采用本地账户登录域成员时没有问题,但是当用户使用域账号登录时,登录进行到最后一步显示桌面时,突然自动注销了。于是导致用户一直无法登录域。
当然如果你非常熟悉Windows AD的话,可能会首先主动去查组策略,但是往往用户可能会设置众多的策略导致排查起来并不轻松,甚至在用户自建的域中可能会有各种各样的问题,比如组策略刷新问题从而扰乱了我们的视线。那么在这篇文章中,我们来介绍一下如何在Windows系统如果步步跟踪最后找出问题的原因。
首先,我们要下载一个Windows系统排查中经常会用到的一个工具 process monitor,该工具能够记录系统内对于文件和注册表的所有操作,不仅包括类似进程名字和ID,也包括了一些调试级别的信息如堆栈,其原理是通过向Windows Filter Manager注册filter driver在实现对所有文件和注册表操作的感知,并可以在其回调函数中实现信息记录。
由于出问题的用户是无法登录的,因此我们必须使用本地管理员账号来登录该机器并且运行process monitor工具,并抓取整个复现的过程。
然后我们就可以开始分析process monitor日志了,首先我们来看一下整个进程的运行情况 - 点击Tools->Process Tree...以后我们可以看到整个登录过程的进程运行情况:
我们注意到在userinit这个父进程下面运行了logoff.exe。我们通过点击该进程可以来看一下该进程可执行文件的位置:
他是存放在c:\windows\system32下的一个文件,因此我们可以确定其实Windows自带的命令行注销工具。但是为什么会出现在登录时候调用呢?我们如果此时去遍查所有的登录策略脚本并不会发现有脚本运行了这样一个程序,于是我们回过头来在观察一下日志:
我们可以发现该程序是由userinit.exe调用起来的,同时我们可以看看调用时的堆栈情况:
通过堆栈可以确认在程序是由userinit.exe进程通过函数ProcesRemoteSessionInitialCommand()调用起来的,而从该函数的名字判断应该是一种只会从terminal session中启动相关进程的行为。
此时我们可以来了解一下userinit.exe进程的信息:userinit是有Windows登录主进程winlogon.exe创建的,该程序主要负责运行登录脚本和启动shell UI程序 - explorer.exe。
研究到这里为止,我们几乎可以确定是某一个terminal登录相关的配置导致的问题,而Windows的绝大多数的此类配置是在注册表里,而注意process monitor同样抓取注册表的访问。于是我们可以耐心地在process monitor中寻找这方面的信息:
而访问该注册表的恰恰是运行在宿主进程svchost.exe中gpsvc(组策略服务)
通过该注册表我们可以查询到其对应如下组策略:
通过以上的实例我们可以知道,有时候process monitor这类工具一样可以提供一些调试信息,所以并不一定需要打开调试器才能进行调试。