作者:陆麟
转载请征得作者同意.如有BUG,请汇报.
2000.5.1
最近太忙.简直疯了.居然一直没空.但是无论如何,在到北京前要更新一下主页.
当LsaApLogonUser(Ex/Ex2)被调用时,验证包就获得了用户名和密码等信息.我们可以看到,在AuthenticationInformation指针处其实乃是一个关键的结构.通常我们执行的是MSV1_0_INTERACTIVE_LOGON,指针则指向
typedef struct _MSV1_0_INTERACTIVE_LOGON {
MSV1_0_LOGON_SUBMIT_TYPE MessageType;
UNICODE_STRING LogonDomainName;
UNICODE_STRING UserName;
UNICODE_STRING Password;
} MSV1_0_INTERACTIVE_LOGON;
结构.MessageType用来表明这次LOGON是什么样的LONON.这里的一切都是以明文形式存在,包括用户名,密码,域名/机器名.:)
现在,MS的验证包就开始登录验证.从SAM里找出用户名,并验证密码.然后返回用户的令牌.
对于登录目标不是本机,而是网络主域,那么LOGON调用NETLOGON SERVICE完成登录.对于LSA来说,NETLOGN则比LOGON进程差不多.因为他们都调用LSA来完成登录.而NETLOGON比LOGON多调用几次LsaApLogonUser(Ex/Ex2).因为需要完成对主域控制器和后备服务器的登录同步.
调用LSA的LsaLogonUser时.MS的验证包判断机器名是否为本机,如果不是本机,则执行一个PASS-THROUGH验证.
也就是说,验证由目标机验证包完成.本机验证包负责传送数据到目标机.
我们讲述一下PASS-THROUGH验证.
本机将登录请求发送到本机所属的域控制器.然后域控制器检查是否域名和自己的域名相同.如果相同,则验证于域控制器继续进行.完成验证后返回数据给本机.并且允许访问本机和域资源.如果域名不同于控制器的域名,域控制器检查是否该域是自己的信任域.如果是,域控制器将验证PASS到该信任域的域控制器.由信任域的域控制器验证.验证完毕后,数据返回到域控制器,由域控制器返回数据到本机.而验证的具体步骤则仍如上所述.
验证完成后.一个令牌被返回.验证包填写的令牌信息为:
typedef struct _LSA_TOKEN_INFORMATION_V1 {
LARGE_INTEGER ExpirationTime;
TOKEN_USER User;
PTOKEN_GROUPS Groups;
TOKEN_PRIMARY_GROUP PrimaryGroup;
PTOKEN_PRIVILEGES Privileges;
TOKEN_OWNER Owner;
TOKEN_DEFAULT_DACL DefaultDacl;
} LSA_TOKEN_INFORMATION_V1, *PLSA_TOKEN_INFORMATION_V1;
而实际LsaLogonUser获得的是根据这些信息合成的TOKEN HANDLE.TOKEN本身的数据结构是不公开的.尽管我认为了解该结构似乎没有很大的意义.但是通过KD的!tokenfields命令我们可以看到数据结构.
另外还返回了用户的LOGON脚本于ProfileBuffer:
typedef struct _MSV1_0_INTERACTIVE_PROFILE {
MSV1_0_PROFILE_BUFFER_TYPE MessageType;
USHORT LogonCount;
USHORT BadPasswordCount;
LARGE_INTEGER LogonTime;
LARGE_INTEGER LogoffTime;
LARGE_INTEGER KickOffTime;
LARGE_INTEGER PasswordLastSet;
LARGE_INTEGER PasswordCanChange;
LARGE_INTEGER PasswordMustChange;
UNICODE_STRING LogonScript;
UNICODE_STRING HomeDirectory;
UNICODE_STRING FullName;
UNICODE_STRING ProfilePath;
UNICODE_STRING HomeDirectoryDrive;
UNICODE_STRING LogonServer;
ULONG UserFlags;
} MSV1_0_INTERACTIVE_PROFILE, *PMSV1_0_INTERACTIVE_PROFILE;
好了.今天就说到这里.作为出游前的一篇文章.