问题
开发了一个服务 S,它偶尔需要做一些用户才能做的事情,所以创建了一个用户进程 U。后来开发自测时,发现用户进程 U 总是往 C:\Windows\system32\config 里写日志。设计上,明明是让进程 U 往用户的 %AppData% 目录写日志的。
分析
服务 S 使用 WTSQueryUserToken 获取用户的 Token,然后使用 CreateProcessAsUser 创建用户进程 U。
这一步是得到验证的,使用任务管理器查看进程 U 确实是当前登录的用户身份,而不是 Session 0 里的 SYSTEM 身份。
但是进程 U 去获取 %AppData% 时却依然拿到 SYSTEM 身份的目录。这点可以用 Process Explorer 验证,进程属性里有一页“环境”。这说明 CreateProcessAsUser 时,继承了服务 S 的环境。
1 | BOOL CreateProcessAsUserW( |
经过排查,确实 lpEnvironment 是传了 nullptr。
解决
先用 CreateEnvironmentBlock 创建用户身份的环境块,然后传给 CreateProcessAsUser。
1 | CreateEnvironmentBlock(&environment, user_token, FALSE); |
其中,第三个参数传 FALSE 是关键,表示不继承服务 S 的环境。