用户进程狂写日志到 system32 目录?

问题

开发了一个服务 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
2
3
4
5
6
7
8
9
10
11
12
13
BOOL CreateProcessAsUserW(
[in, optional] HANDLE hToken,
[in, optional] LPCWSTR lpApplicationName,
[in, out, optional] LPWSTR lpCommandLine,
[in, optional] LPSECURITY_ATTRIBUTES lpProcessAttributes,
[in, optional] LPSECURITY_ATTRIBUTES lpThreadAttributes,
[in] BOOL bInheritHandles,
[in] DWORD dwCreationFlags,
[in, optional] LPVOID lpEnvironment,
[in, optional] LPCWSTR lpCurrentDirectory,
[in] LPSTARTUPINFOW lpStartupInfo,
[out] LPPROCESS_INFORMATION lpProcessInformation
);

经过排查,确实 lpEnvironment 是传了 nullptr。

解决

先用 CreateEnvironmentBlock 创建用户身份的环境块,然后传给 CreateProcessAsUser

1
CreateEnvironmentBlock(&environment, user_token, FALSE);

其中,第三个参数传 FALSE 是关键,表示不继承服务 S 的环境。