有时在我们编写的前台程序需要开机运行,当有后台程序时可以注册服务方式进行启动(system权限),前台程序的启动需要等待用户登录到桌面后运行(涉及界面交互等),前台程序的启动主要有几种方式:
1. 写入启动项注册表进行自动启动,这时启动的程序是以当前用户权限运行,弊端是权限低且不安全,用户可人为或被其他安全软件禁用;
2. 创建计划任务方式启动,计划任务属性中可设置以最高权限运行,相当于管理员权限运行前台程序,可设置任何时间段运行程序,弊端也是不安全,人为或其他安全软件可禁用计划任务;
3. 通过后台服务拉前台程序,这种是最安全的方式(后台服务也可实时守护该程序运行),也是大多数安装软件所使用的,主要有两种方式启动:
(1) 绕过UAC以最高权限启动
自Vista操作系统之后,微软考虑到安全因素,在系统管理员账户和标准用户之间创出了UAC(用户账户控制)。当标准用户启动需管理员权限的操作时要弹框让用户确认,这样可防止恶意软件或间谍软件随意修改系统造成破坏。
但对于必须要通过最高权限运行交互进程来说就造成问题,微软API接口提供CreateProcessAsUser函数用于在后台服务程序中启动前台进程,但启动时要请求UAC权限(由于后台服务是最高权限启动,其创建的子进程也继承最高权限),这时后台UAC窗口无法显示在前台界面上,造成程序永远等待无法启动。
vista之后,微软会为每个登录用户分配一个会话,后台服务在系统启动时最先启动,分配的会话ID为0,其后每登录一个用户会话ID加1:
问题来了,由于有会话隔离,我们无法在一个会话程序中直接启动另一会话的程序。但微软有一个特殊的进程,对于每个会话会有一个对应的进程,这个进程就是winlogin.exe:
winlogin进程的作用
Winlogon.exe进程是微软公司为其Windows操作系统定义的一个非常重要的系统核心进程,被称为“Windows登陆应用程序”,它会随着系统启动而启动并一直运行。通常情况下此进程应该是安全的,并且只占用很少的CPU及内存资源,如果资源占用过多则很有可能被病毒“劫持”。
请不要尝试将本进程终止(也无法在任务管理器将其终止)或将此进程从系统中删除,这会导致你的系统无法正常运行。因为Winlogon.exe进程为系统提供了有以下4项重要的功能:
- 在登录系统时加载的用户配置文件,以及执行注销用户与锁定计算机;
- 负责处理Ctrl+Alt+Del快捷键(SAS)的功能;
- 监控键盘和鼠标使用情况来决定什么时候启动屏幕保护程序;
- 检验Windows操作系统激活密钥是否为合法许可;
可以发现winlogin进程是后台服务进程,但所属登录用户会话,那是不是可以通过这个进程来达到我们绕过UAC的限制启动前台交互程序呢?没错!!!
有了winlogin进程,我们可以在后台服务中先查询到winlogin进程信息,获取其访问令牌,最后通过CreateProcessAsUser将进程启动到活动登录用户当前活动会话。由于和前台界面所属同一会话,启动后的程序便可以进行交互。Exciting!!!
好了,来看看代码吧:
1. C++代码
BOOL LaunchAppIntoDifferentSession()
{
PROCESS_INFORMATION pi;
STARTUPINFO si;
BOOL bResult = FALSE;
DWORD dwSessionId,winlogonPid;
HANDLE hUserToken,hUserTokenDup,hPToken,hProcess;
DWORD dwCreationFlags;
// Log the client on to the local computer.
dwSessionId = WTSGetActiveConsoleSessionId();
//
// Find the winlogon process
PROCESSENTRY32 procEntry;
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap == INVALID_HANDLE_VALUE)
{