Windows之会话ID
Posted w1ng
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Windows之会话ID相关的知识,希望对你有一定的参考价值。
现在做的项目有一个用服务起的后台常驻程序,服务是一个守护进程,然后拉起一后台常驻进程。这个时候守护进程用户是system,会话ID是0,后台常驻的进程的会话ID是1。第一次接触到了会话的概念,借此了解一番。
Win7开发文档里边写到:
服务是整合在Microsoft Windows操作系统中的结构。服务与用户的应用程序不同,因为你可以对他们进行配置,不需要一个激活的用户登录,就可以使这些服务在系统启动的时候运行,直到系统关闭。Windows中的服务,负责所有种类的后台活动,但不包括从远程过程调用(RPC)服务到网络位置服务的用户。
一些服务可能会试图显示一些用户界面对话框,或者与用户的应用程序进行通信。这些服务都将面临与Windows 7 的兼容性问题。这个就是Windows 7的服务的Session 0隔离机制。
在Windows XP, Windows Server 2003或者更早期的Windows操作系统中,所有的服务和应用程序都是运行在与第一个登录到控制台的用户得Session中。这个Session叫做Session 0。在Session 0 中一起运行服务和用户应用程序,由于服务是以高权限运行的,所以会造成一些安全风险。这些因素使得一些恶意代理利用这点,来寻找提升他们自身权限的结构。
在Windows Vista中,服务在一个叫做Session 0 的特殊Session中承载。由于应用程序运行在用户登录到系统后所创建的Session 0 之后的Session中,所以应用程序和服务也就隔离开来:第一个登录的用户在Session 1中,第二个在Session 2中,以此类推。事实上运行在不同的Session中,如果没有特别将其放入全局命名空间(并且设置了相应的访问控制配置),是不能互相传递窗体消息,共享UI元素或者共享kernel对象。
上面这张图片看起来就比较清楚了。
所以,在Vista之前,服务和应用程序在同一Session中,没有太多问题,服务进程创建一个新的用户进程只需要调用CreateProcess即可。在Vista之后,由于Session 0隔离机制的存在,服务进程创建新的用户进程需要调用CreateProcessAsUser,在这之前还要进行一下权限的操作
获取当前活动会话ID DWORD dwSessionID = WTSGetActiveConsoleSessionId(); 获取当前活动会话的令牌 HANDLE hToken = NULL; WTSQueryUserToken(dwSessionID, &hToken); 创建一个当前用户进程 CreateProcessAsUser(hDuplicatedToken, lpszClientPath, NULL, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE |CREATE_UNICODE_ENVIRONMENT, lpEnvironment, NULL, &si, &pi);
但是这样创建的只是普通用户进程,有些时候我们需要更高的权限,比如现在的项目,后台进程是system用户。
参见MSDN中SetTokenInformation 和 TOKEN_INFORMATION_CLASS的说明,进程所属的Session由进程令牌中的TokenSessionId来决定,我们就可以复制服务进程的Token令牌,修改其中的TokenSessionId,从而在用户桌面创建一个system进程。
HANDLE hToken = NULL; HANDLE hTokenDup = NULL; 获得服务进程句柄 HANDLE hProcess = GetCurrentProcess(); 获取进程令牌 OpenProcessToken(hProcess, TOKEN_ALL_ACCESS, &hToken); 复制进程令牌 HANDLE hDuplicatedToken = NULL; DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, NULL, SecurityIdentification, TokenPrimary, &hDuplicatedToken); 创建环境快 LPVOID lpEnvironment = NULL; CreateEnvironmentBlock(&lpEnvironment, hDuplicatedToken, FALSE);
然后调用CreateProcessAsUser,就使用服务进程创建了一个system进程。
还有跨Session的内核对象要以“Global”进行命名,这样内核对象属于全局Session空间中。例如在之前创建的system进程和服务进程使用事件进行通信时,事件命名为“GlobalEventName”。
以上是关于Windows之会话ID的主要内容,如果未能解决你的问题,请参考以下文章