windows7登录调试

  • 格式:pdf
  • 大小:377.78 KB
  • 文档页数:11

Windows7口令登录过程调试
boywhp@
基本原理
Windows7以后Winlogon进程是动态的,有用户登录就会创建一个Winlogon进程,因此系统中完全可能存在多个登录进程,注销后Winlogon进程也会随之结束。

Windbg断点NtCreateUserProcess观察Windows7启动流程:
我整理的基本进程树如下:
smss.exe
autochk.exe
smss.exe000000000000003c//session0
Csrss.exe
Wininit.exe
Services.exe
开机自启动服务进程
Lsass.exe
Lsm.exe
smss.exe000000010000003c//session1
Csrss.exe
Winlogon.exe
LogonUI.exe
LogonUI.exe负责用户认证界面,Windows7以后不再使用msgina.dll,而是使用多个进程配合,完成用户认证过程,大致过程为1、Winlogon启动LogonUI等待用户输入凭证2、Winlogon通过ALPC通知Lsass 用户登录3、Lsass依次查询认证模块【本地认证MSV1_0.dll】4、Lsass返回认证结果。

框图如下
调试过程
必须要吐槽下,windows7下windbg内核调试应用程序经常断不下了,害我浪费了很多功夫~~现总结了一个稳当可靠的办法:
1、!process00查看目标进程的基本情况,主要是Cid。

2、bp nt!KiFastCallEntry"j poi(@$teb+20)=0x1a0'';'gc'"把1a0替换成实际的Cid即可。

3、等断点命中后,bp winlogon!XXXXX
4、.reload/user下,bl看一下,确保函数解析成地址。

首先看Winlogon和LogonUI之间的交互,LogonUI.exe就是一个壳,类似svchost,真正的功能是通过authui.dll模块完成的,从《Windows Internals5》介绍,winlogon是通过ALPC的东西同Lsass通信的,但是LogonUI没怎么讲,我估计八成也是一样的,应该就是RPC调用。

RPC调用分服务端和客户端,客户端最终RPCRT4!NdrClientCall2执行调用,而服务端最终会执行RPCRT4!Invoke执行具体的函数。

我们断点winlogon!NdrClientCall2观察下【这里不bp RPCRT4!NdrClientCall2主要是避免其他进程干扰,因为RPC在系统中调用很频繁】,随便输入个密码,命中:
这里我们发现winlogon的确使用了RPC调用来执行进程交互,注意这个函数名是WluiDisplayStatus,其实很明确的告诉我们winlogonUIDisplayStatus,那么该RPC最终在哪里被执行呢?很显然是在authui.dll 下断点RPCRT4!Invoke命中,而后单步跑一下,如图:
直接从IDA 里面翻了下authui.dll 注册RPC 服务
从直接把所有的RPC 接口函数DUMP 出来,如下:
其中WluirRequestCredentials 很惹人关注,对应的winlogon!winlogon!WluirRequestCredentials
WluirRequestCredentials 函数如下:Winlogon 同logonUI 的authui.dll 中通过一一对应的RPC 函数完成接口调用,下面是一次错误密码测试过程时,依次命中的调用情况:
序号
函数名描述1winlogon!WluiRequestCredentials
请求用户输入凭证,注:该函数是阻塞函数,会
一直等待直到用户确认登录才返回。

2
winlogon!WluiDisplayStatus 显示状态?未细究。

3
winlogon!WluiReportResult 通报结果。

4winlogon!WluiDisplayRequestCredentialsError 显示登录错误提示。

我们发现基本上LogonUI 进程没干啥活,所以的动作都是winlogon 的WluiXXXXXX 接口消息驱动的,IDA 里面会发现大量的DirectUI 界面代码。

Winlogon 使用状态机来维护整个登录过程中的各种情况处理,通过Winlogon!Winlogon!StateMachineSetSigna StateMachineSetSigna StateMachineSetSignal
l 来完成状态切换,整个状态定义DUMP 如下【未截全】:
例如:断点Winlogon!Winlogon!StateMachineSetSignal
StateMachineSetSignal 点击登录界面残障人士按钮,命中如下:注意其中的参数二对应的是状态,查下状态9对应的正是g_xWinsrv_AccessNotify_Signal ,winlogon 和LogonUI 的交互基本上流程基本比较清晰了,下面我们重点研究下winlogon 同lsass 进程完成密码认证
的一些细节。

Winlogon 同样使用RPC 调用完成同lsass 的交互,不同的是windows 把这几个RPC 调用封装成了DLL 形式,分别是SspiCli 客户端和SspiSrv 服务端,最终还是调用了RPCRT4函数,证据如下:
直接从IDA 中DUMP 出SSPISRV 的RPC 调用接口如下:
根据《windows internals 5》一文,Winlogon 调用SspiCli!SspiCli!LsaLogonUser
LsaLogonUser 完成登录,该函数最终通过RPC 调用Lsass::SspiSrv!SspirLogonUser
其中AuthenticationInformation 参数里面包含了登录所需的信息,具体结构如下:
Windbg显示这里密码被加密了,哈哈,下内存写断点,命中堆栈如下:
WLGeneric_Request_Logon_Credz_Execute对应的代码如下:
Winlogon!WLGeneric_Request_Logon_Credz_Execute
Winlogon!
该函数首先通过RequestCredentials函数请求登录凭证,如果是本地登录模式,该函数最终会调用
WluiRequestCredentials,请求用户WluiRequestCredentials函数执行LogonUI进程的RPC服务函数authui!
authui!WluiRequestCredentials
输入登录凭证。

最终authui!CRequestCredentialsCallbackData::GetCredential获取用户登录凭证,数据结构为
_CRED_PROV_CREDENTIAL*可惜没有数据结构定义。

输入“qqqqqqqq”调试显示DUMP如下:
下内存断点:Ba w10027e5c8+3e,命中堆栈如下:
这里windbg函数显示的函数CRequestCredentialsCallbackData::GetShutdownChoice+0x63是错误的,实际是sub_7483CBE7函数:
查看一下内存数据,如下:
源地址是0027e510,长度是000000b0:
Ba w10027e510+3e,命中
查看源地址238df78:
继续跟踪内存Ba w1238df78+3e
查看内存如下:
函数KerbInteractiveUnlockLogonPack是一个可以google到的函数,很好。

02024df8fc024df924024df928authui!KerbInteractiveUnlockLogonPack+0x90
断点ba w1023888b8命中堆栈
CredProtect函数MSDN如下:
查看堆栈第二个参数,果然是明文密码:
对应的解密函数CredUnprotect
这些内容实际在lsass进程里面解密,断点ADVAPI32!CredUnprotectW命中堆栈如下:
最终的密码认证还是通过群众喜闻乐见的msv1_0!LsaApLogonUserEx2来完成,如下:。