
🔥 个人主页: 杨利杰YJlio
❄️ 个人专栏: 《Sysinternals实战教程》 《Windows PowerShell 实战》 《WINDOWS教程》 《IOS教程》
《微信助手》 《锤子助手》 《Python》 《Kali Linux》
《那些年未解决的Windows疑难杂症》
🌟 让复杂的事情更简单,让重复的工作自动化


Windows Internals 10.2.8:以其他账户运行服务,为什么它改变的不只是登录名,而是整个安全上下文?
- [1. 写在前面:这节内容到底在讲什么?](#1. 写在前面:这节内容到底在讲什么?)
- [2. 为什么有些服务必须脱离内置账户体系?](#2. 为什么有些服务必须脱离内置账户体系?)
-
- [2.1 内置服务账户适合什么场景?](#2.1 内置服务账户适合什么场景?)
- [2.2 为什么某些服务需要真实用户账户?](#2.2 为什么某些服务需要真实用户账户?)
- [2.3 这节的核心判断](#2.3 这节的核心判断)
- [3. 如何配置以其他账户运行服务?](#3. 如何配置以其他账户运行服务?)
-
- [3.1 图形界面配置路径](#3.1 图形界面配置路径)
- [3.2 SCM 在这里扮演什么角色?](#3.2 SCM 在这里扮演什么角色?)
- [3.3 使用命令查看服务运行账户](#3.3 使用命令查看服务运行账户)
-
- [方法一:使用 sc.exe](#方法一:使用 sc.exe)
- [方法二:使用 PowerShell 查询](#方法二:使用 PowerShell 查询)
- 方法三:查看注册表配置
- [4. 用户没登录,服务为什么也能用该账户启动?](#4. 用户没登录,服务为什么也能用该账户启动?)
-
- [4.1 交互登录和服务登录不是一回事](#4.1 交互登录和服务登录不是一回事)
- [4.2 这个机制对排障有什么价值?](#4.2 这个机制对排障有什么价值?)
- [4.3 相关事件日志应该怎么看?](#4.3 相关事件日志应该怎么看?)
- [5. 为什么会连带改变 Profile 和注册表视图?](#5. 为什么会连带改变 Profile 和注册表视图?)
-
- [5.1 Profile 为什么重要?](#5.1 Profile 为什么重要?)
- [5.2 HKCU 到底是谁的 HKCU?](#5.2 HKCU 到底是谁的 HKCU?)
- [5.3 这类问题在现场怎么表现?](#5.3 这类问题在现场怎么表现?)
-
- 现象一:服务切换账户后突然能访问共享
- 现象二:服务改用指定用户后读取到不同配置
- [现象三:用户未登录,但 Profile 已经存在](#现象三:用户未登录,但 Profile 已经存在)
- [5.4 使用 ProcMon 怎么验证?](#5.4 使用 ProcMon 怎么验证?)
- [6. 这种模型的局限与风险:为什么会引出 User Services?](#6. 这种模型的局限与风险:为什么会引出 User Services?)
-
- [6.1 局限一:绑定的是静态用户,不是当前活跃用户](#6.1 局限一:绑定的是静态用户,不是当前活跃用户)
- [6.2 局限二:未登录用户的 Profile 可能被提前加载](#6.2 局限二:未登录用户的 Profile 可能被提前加载)
- [6.3 风险三:真实用户 Token 暴露面扩大](#6.3 风险三:真实用户 Token 暴露面扩大)
- [6.4 User Services 为什么出现?](#6.4 User Services 为什么出现?)
- [7. 企业桌面运维中应该怎么排查这类问题?](#7. 企业桌面运维中应该怎么排查这类问题?)
-
- [7.1 先固定问题边界](#7.1 先固定问题边界)
- [7.2 再看服务账户配置](#7.2 再看服务账户配置)
- [7.3 检查服务账户是否具备"作为服务登录"权限](#7.3 检查服务账户是否具备“作为服务登录”权限)
- [7.4 检查账号状态](#7.4 检查账号状态)
- [7.5 检查服务启动日志](#7.5 检查服务启动日志)
- [7.6 用 ProcMon 建证据链](#7.6 用 ProcMon 建证据链)
- [8. 一张流程图看懂替代账户服务的启动链路](#8. 一张流程图看懂替代账户服务的启动链路)
- [9. 常见问题与现场处理建议](#9. 常见问题与现场处理建议)
-
- [9.1 服务账号密码改了,服务会自动更新吗?](#9.1 服务账号密码改了,服务会自动更新吗?)
- [9.2 为什么服务账号会被锁定?](#9.2 为什么服务账号会被锁定?)
- [9.3 服务切换账户后为什么访问共享失败?](#9.3 服务切换账户后为什么访问共享失败?)
- [9.4 服务改用域账号后,本机权限够不够?](#9.4 服务改用域账号后,本机权限够不够?)
- [9.5 是否建议所有服务都使用域账号?](#9.5 是否建议所有服务都使用域账号?)
- [10. 总结提升:这节真正要带走的不是操作,而是安全上下文意识](#10. 总结提升:这节真正要带走的不是操作,而是安全上下文意识)

1. 写在前面:这节内容到底在讲什么?
在 Windows 服务机制里,我们经常会看到服务运行在不同账户下,比如:
LocalSystemNetwork ServiceLocal Service- 某个本地用户账户
- 某个域用户账户
- 某个专门创建的服务账户
很多人在配置服务时,只把它理解成一个很简单的动作:
把服务属性里的"登录身份"从一个账号换成另一个账号。
但从 Windows Internals 的视角看,这个理解太浅了。
服务以其他账户运行,本质上不是"换一个用户名",而是改变服务进程未来启动时的安全令牌、用户配置文件、注册表视图、资源访问边界和网络认证身份。
也就是说,服务账户不是一个显示字段,而是服务进程运行环境的根基。
如果只看界面,不理解背后的安全上下文,就很容易在服务无法启动、共享访问失败、域账号密码过期、用户配置异常、权限扩大等问题上反复踩坑。
本文结合 Windows Internals 第 10 章服务机制中的 10.2.8 Running services in alternate accounts,从企业桌面运维和排障角度,把"以其他账户运行服务"拆成几个关键问题:
- 为什么服务需要脱离内置账户体系?
- Services MMC 里的
This Account到底改变了什么? - 用户没有登录时,服务为什么也能用该用户身份启动?
- 为什么会连带加载 Profile 和注册表视图?
- 这种模型为什么会引出后面的 User Services?

2. 为什么有些服务必须脱离内置账户体系?

Windows 已经提供了几类常见的内置服务账户。比如 LocalSystem 权限非常高,适合系统级服务;Network Service 和 Local Service 则更适合低权限后台服务。
但是,并不是所有服务都适合放在这些内置身份下运行。
有些服务需要访问的资源,本身就不是授予机器账户或内置服务账户的,而是授予某个具体用户或域账号的。
2.1 内置服务账户适合什么场景?
内置服务账户通常更适合这类场景:
- 服务需要长期驻留后台
- 服务不依赖某个具体交互用户
- 服务只需要访问本机系统资源
- 服务使用机器身份访问网络资源
- 服务权限边界相对固定
这类账户的优势是稳定、标准化、易管理。
但它们也有明显边界:它们不代表某个真实业务用户。
2.2 为什么某些服务需要真实用户账户?
典型原因包括:
- 服务需要访问只授权给某个域用户的共享目录
- 服务需要用指定身份连接数据库、中间件或外部系统
- 服务需要读取某个用户配置文件下的专属配置
- 服务需要以业务身份完成网络认证
- 服务厂商设计时要求绑定一个服务专用账号
例如某些业务系统后台服务,需要访问:
text
\\fileserver\appdata
\\nas\department-share
SQL Server 指定登录身份
某个用户配置目录下的证书或配置文件
如果这些资源没有授权给机器账户,那么 LocalSystem 在本机看起来权限很高,但访问网络资源时可能并不好使。
这就是很多人容易误解的地方:LocalSystem 在本机很强,不代表它在网络上也能代表某个真实用户。
2.3 这节的核心判断
这一节真正想让我们建立的是一个判断框架:
当服务需要访问"绑定到真实用户身份"的资源时,Windows 允许它使用替代账户运行。
但这个能力不是免费的。
你得到的是资源访问能力,付出的代价是服务与真实用户安全上下文发生绑定。
这也是后面所有风险的源头。

3. 如何配置以其他账户运行服务?

从操作界面看,配置方式很简单。
打开服务管理器后,进入目标服务属性,在 Log On / 登录 选项卡中选择 This Account / 此账户,然后输入账号和密码。
3.1 图形界面配置路径
操作路径如下:
text
Win + R
输入 services.msc
找到目标服务
右键 Properties / 属性
切换到 Log On / 登录
选择 This Account / 此账户
输入账号和密码
应用并重启服务
这一步看起来只是 GUI 配置,实际上会影响后续 SCM 启动服务的方式。
3.2 SCM 在这里扮演什么角色?
SCM,全称是 Service Control Manager。
它可以理解为 Windows 服务的"总调度器"。服务什么时候启动、用什么账户启动、失败后怎么处理、依赖关系怎么拉起,背后都离不开 SCM。
当服务被配置为 This Account 后,后续服务启动时,SCM 不再直接使用内置服务账户模型,而是要使用你配置的账户凭据来创建服务进程运行所需的安全上下文。
也就是说:
服务属性里的 This Account,是未来服务进程安全令牌来源的根配置。
3.3 使用命令查看服务运行账户
现场排障时,不建议只看截图。可以直接用命令确认服务到底配置成了哪个账户。
方法一:使用 sc.exe
cmd
sc qc "服务名"
重点看输出中的:
text
SERVICE_START_NAME
例如:
text
SERVICE_START_NAME : .\ServiceUser
SERVICE_START_NAME : DOMAIN\ServiceUser
SERVICE_START_NAME : LocalSystem
方法二:使用 PowerShell 查询
powershell
Get-CimInstance Win32_Service |
Select-Object Name, DisplayName, StartName, State |
Sort-Object StartName
如果只想查某一个服务:
powershell
Get-CimInstance Win32_Service -Filter "Name='服务名'" |
Select-Object Name, DisplayName, StartName, State, PathName
方法三:查看注册表配置
服务配置通常位于:
text
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\<服务名>
PowerShell 可查看:
powershell
Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Services\服务名" |
Select-Object ObjectName, ImagePath, Start, Type
其中 ObjectName 通常对应服务登录账户。
注意:不要直接随意修改服务注册表项。现场排障可以读取确认,但修改服务账户优先使用 Services MMC、sc.exe 或 PowerShell 官方接口。

4. 用户没登录,服务为什么也能用该账户启动?

这一点是本节最容易被误解的地方。
很多人会以为:
服务跑在某个用户账户下,说明这个用户必须先登录系统。
这个理解不准确。
服务型登录并不等于用户交互登录。用户没有进入桌面,服务仍然可以由 SCM 使用该账户凭据拉起。
4.1 交互登录和服务登录不是一回事
可以先把两种登录区分开:
| 类型 | 典型场景 | 是否需要进入桌面 |
|---|---|---|
| 交互式登录 | 用户输入密码登录 Windows 桌面 | 需要 |
| 服务型登录 | SCM 使用指定账户启动服务 | 不需要 |
服务型登录的重点不是"用户坐在电脑前登录了",而是:
SCM 能使用该账户凭据,为服务创建一个非交互式的运行上下文。
这就是为什么某些服务启动后,你会看到相关用户 Profile 被加载,但用户本人并没有登录桌面。
4.2 这个机制对排障有什么价值?
在企业桌面支持场景里,经常会碰到这类现象:
- 某个域账号没有登录过桌面,但系统里出现了对应 Profile
- 某个服务启动后,用户目录被创建
- 某个服务账号密码过期后,服务启动失败
- 某个服务账号被锁定后,多台终端上的服务同时异常
- 某个用户注销了,但后台服务仍然在用该身份运行
如果只从"用户有没有登录桌面"理解,就会看不懂这些现象。
如果从"SCM 使用该账户进行服务型登录"理解,就很清楚:
服务跑在某个用户账户下,不等于这个用户正在桌面登录,而是 SCM 使用该账户凭据完成了服务型登录。
4.3 相关事件日志应该怎么看?
当服务因为账户问题启动失败时,优先看:
text
eventvwr.msc
Windows Logs
System
Source: Service Control Manager
常见方向包括:
- 服务登录失败
- 账号密码错误
- 账号没有"作为服务登录"的权限
- 服务启动超时
- 服务依赖项异常
可以重点关注:
text
7000 / 7009 / 7011 / 7038
其中 7038 常见于服务无法使用指定账户登录。
如果启用了安全审核,还可以在 Security 日志中关注服务型登录相关记录,例如登录类型为 Service 的事件。
现场排障时不要只看服务界面提示,Event Viewer 里的 Service Control Manager 才是更可靠的证据来源。

5. 为什么会连带改变 Profile 和注册表视图?

当服务以替代账户启动时,变化不止发生在"账户名"这一层。
更深一层的变化是:该用户的配置文件、环境变量、注册表用户配置视图,都可能被带入服务运行环境。
5.1 Profile 为什么重要?
Windows 用户 Profile 不是一个简单文件夹,它包含了大量用户级状态:
text
C:\Users\<用户名>
NTUSER.DAT
AppData
用户级配置
用户级证书
用户级注册表
用户环境变量
当服务使用某个真实用户账户运行时,它可能需要这个用户的配置文件支持,才能读取对应配置或访问相关资源。
这就是为什么有些服务改用域账号后,行为会和 LocalSystem 下完全不一样。
5.2 HKCU 到底是谁的 HKCU?
在普通用户登录桌面时,我们常说:
text
HKEY_CURRENT_USER
但要注意,HKCU 本身不是一个独立真实根,它本质上是当前用户上下文对应注册表配置的映射。
真实位置通常在:
text
HKEY_USERS\<SID>
所以问题来了:
当服务以某个用户账户运行时,服务看到的 HKCU 是谁的 HKCU?
答案是:服务运行账户对应用户的 HKCU 视图。
这意味着,服务账户一变,服务读取到的用户级注册表配置也会跟着变。
5.3 这类问题在现场怎么表现?
常见现象包括:
现象一:服务切换账户后突然能访问共享
原因可能是:
- 原账户没有共享权限
- 新账户具有共享访问权限
- 网络认证身份发生变化
现象二:服务改用指定用户后读取到不同配置
原因可能是:
- HKCU 指向发生变化
- AppData 下配置不同
- 用户级证书或环境变量不同
现象三:用户未登录,但 Profile 已经存在
原因可能是:
- 服务以该用户身份启动
- SCM 为服务加载了对应 Profile
- 系统创建或使用了该用户配置目录
所以排障时不要只问"用户有没有登录",还要问"有没有服务正在使用该用户账户"。
5.4 使用 ProcMon 怎么验证?
如果怀疑服务读取了某个用户配置,可以用 Process Monitor 建立证据链。
建议过滤条件:
text
Process Name is <服务进程名>
Operation is RegOpenKey / RegQueryValue / CreateFile
Path contains HKEY_USERS
Path contains C:\Users\<服务账户>
观察重点:
- 是否访问了
HKEY_USERS\<SID> - 是否读取了
C:\Users\<服务账户>\AppData - 是否访问了用户证书、配置文件、日志目录
- 是否出现
ACCESS DENIED - 是否出现
NAME NOT FOUND
这就是 Mark Russinovich 式排障思路:不要猜服务读了什么,用工具把它实际访问的对象抓出来。

6. 这种模型的局限与风险:为什么会引出 User Services?

以其他账户运行服务解决了资源访问问题,但它也带来了几个明显问题。
6.1 局限一:绑定的是静态用户,不是当前活跃用户
传统服务配置 This Account 后,绑定的是一个固定账户。
这对某些服务没有问题,比如:
text
DOMAIN\Service_App
DOMAIN\Service_SQL
DOMAIN\Service_Backup
但对多用户场景来说就不一定合适。
比如在远程桌面、多用户会话、共享终端环境里,你真正想要的可能不是"永远使用某个固定用户",而是:
当前谁登录,就为谁创建对应服务实例。
传统替代账户模型做不到这一点。
6.2 局限二:未登录用户的 Profile 可能被提前加载
如果某个服务使用指定账户运行,那么即使用户没有进入桌面,对应 Profile 也可能被加载。
这会带来一些状态管理问题:
- 用户配置被后台进程占用
- Profile 无法正常卸载
- 用户目录提前创建
- 某些配置被服务进程修改
- 排障时误以为该用户登录过
6.3 风险三:真实用户 Token 暴露面扩大
服务进程通常是长期运行的后台进程。
当它持有真实用户身份时,一旦该服务进程被注入、被劫持、被错误配置,就可能产生更大的安全风险。
风险包括:
- 利用该用户身份访问共享资源
- 利用该用户身份连接网络服务
- 读取该用户可访问的文件或注册表
- 在权限边界设计不清时扩大攻击面
把服务切到真实用户账户,不只是"让它能访问资源",也意味着把这个用户的身份暴露给一个长期驻留的后台进程。
6.4 User Services 为什么出现?
User Services 可以理解为更细粒度的用户服务模型。
它解决的核心问题是:
- 不再固定绑定某个静态用户
- 用户真正登录时才为该用户创建服务实例
- 用户注销后对应实例退出
- 更适合多用户和现代用户态服务场景
用一句话概括:
User Services 是为了让服务实例跟随真实登录用户生命周期,而不是长期绑定一个静态账户。

7. 企业桌面运维中应该怎么排查这类问题?
这一节虽然是 Windows Internals 的服务机制内容,但在企业桌面支持中非常实用。
只要遇到"服务启动失败、服务访问共享失败、域账号密码问题、用户 Profile 异常、服务账号锁定",都可以用下面这套思路。
7.1 先固定问题边界
先问清楚:
- 哪个服务异常?
- 服务原来用什么账户运行?
- 最近是否改过密码?
- 是否从 LocalSystem 改成了域账号?
- 是否访问网络共享、数据库或中间件?
- 是单台机器异常,还是多台机器同时异常?
- 是启动失败,还是启动后功能异常?
用户说"服务坏了"只是入口,真正要定位的是:哪个服务、哪个账户、哪个资源、哪个失败点。
7.2 再看服务账户配置
powershell
Get-CimInstance Win32_Service |
Select-Object Name, DisplayName, StartName, State |
Sort-Object StartName
如果知道服务名:
powershell
Get-CimInstance Win32_Service -Filter "Name='服务名'" |
Select-Object Name, DisplayName, StartName, State, PathName
7.3 检查服务账户是否具备"作为服务登录"权限
本地安全策略路径:
text
secpol.msc
Local Policies
User Rights Assignment
Log on as a service
如果是域环境,还要确认是否被域组策略覆盖。
命令查看策略结果:
cmd
gpresult /h C:\Temp\gpresult.html
打开报告后重点看:
text
Computer Configuration
Windows Settings
Security Settings
Local Policies
User Rights Assignment
7.4 检查账号状态
如果是域账号,需要确认:
- 密码是否过期
- 账户是否锁定
- 账户是否被禁用
- 是否限制登录计算机
- 是否被移出相关安全组
- 是否仍有访问共享、数据库或应用资源的权限
这一步通常需要 AD 管理员或域控侧配合。
7.5 检查服务启动日志
text
eventvwr.msc
Windows Logs
System
Source: Service Control Manager
重点看:
text
7000
7009
7011
7038
如果涉及账号锁定,还要结合域控安全日志和账号锁定来源分析。
7.6 用 ProcMon 建证据链
ProcMon 过滤建议:
text
Process Name is 服务进程名
Result is ACCESS DENIED
Path contains C:\Users
Path contains HKEY_USERS
Path contains \\共享服务器
最终要把结论落到具体对象上:
text
不是"系统异常"
而是"服务 A 使用 DOMAIN\ServiceUser 启动时,
访问 \\fileserver\share\config.json 返回 ACCESS DENIED,
导致服务初始化失败。"
这才是可复盘、可写进工单、可交给后端或域控同事继续处理的证据链。

8. 一张流程图看懂替代账户服务的启动链路
下面这张 Mermaid 图可以把 10.2.8 的主线串起来:
是
否
服务需要访问特定用户资源
配置服务 Log On 为 This Account
SCM 保存服务登录账户配置
服务启动时 SCM 使用该账户凭据
创建服务型登录上下文
加载该用户 Profile
映射该用户 HKCU / HKEY_USERS 视图
服务以该用户身份访问文件/注册表/网络资源
是否具备权限?
服务正常启动并访问资源
启动失败或功能异常
查看 SCM 日志 / ProcMon / 权限配置
风险:Token 暴露与静态用户绑定
引出 User Services 模型
这张图最关键的地方在于:
服务账户配置不是一个孤立设置,它会沿着 SCM → 登录上下文 → Profile → 注册表视图 → 资源访问链路一路传导。

9. 常见问题与现场处理建议
9.1 服务账号密码改了,服务会自动更新吗?
不会。
如果服务使用的是指定用户账户,密码变更后,服务配置里保存的凭据需要同步更新。
否则常见结果是:
text
服务无法启动
服务登录失败
账号被反复锁定
企业环境中,服务账号密码变更一定要纳入变更流程,否则很容易造成批量服务中断。
9.2 为什么服务账号会被锁定?
常见原因:
- 多台机器保存了旧密码
- 某个计划任务使用旧凭据
- 某个服务仍在使用旧密码
- 应用配置文件中写死了旧密码
- 第三方程序反复尝试登录
排查建议:
text
从域控账号锁定日志反查来源机器
再到来源机器检查服务、任务计划、凭据管理器、应用配置
9.3 服务切换账户后为什么访问共享失败?
优先检查三层权限:
| 层级 | 检查内容 |
|---|---|
| 共享权限 | 共享目录是否授权该账户 |
| NTFS 权限 | 文件系统 ACL 是否允许访问 |
| 网络认证 | 是否使用正确域账号身份访问 |
很多时候不是服务坏了,而是:
text
服务账户没有对应共享路径的有效权限
9.4 服务改用域账号后,本机权限够不够?
不一定。
域账号能访问网络资源,不代表它在本机有足够权限。
需要确认:
- 本地目录权限
- 注册表权限
- 服务依赖组件权限
- 是否需要加入本地特定组
- 是否需要"作为服务登录"权限
9.5 是否建议所有服务都使用域账号?
不建议。
更合理的原则是:
能用低权限内置账户解决,就不要滥用高权限域账号;必须使用域账号时,应使用专用服务账户,并控制权限范围。
推荐做法:
- 使用专用服务账号
- 禁止多人共用个人账号作为服务账户
- 避免使用域管理员账号运行普通服务
- 明确最小权限
- 建立密码轮换和变更记录
- 对关键服务做好启动验证

10. 总结提升:这节真正要带走的不是操作,而是安全上下文意识
10.2.8 这一节表面上讲的是:
如何让服务以其他账户运行。
但真正重要的是:
理解服务账户背后的安全上下文变化。
最后我用几句话收束全文:
- 以内置账户运行服务,适合系统级、低权限、标准后台服务场景。
- 以其他账户运行服务,适合需要真实用户身份访问资源的场景。
- This Account 不是显示层选项,而是服务进程安全令牌来源的根配置。
- 用户未登录桌面,服务也可以通过 SCM 使用该账户完成服务型登录。
- 服务账户变化会影响 Profile、HKCU、HKEY_USERS、AppData、网络认证和资源访问结果。
- 替代账户模型解决了资源访问问题,但也带来了静态用户绑定和 Token 暴露风险。
- User Services 的出现,本质上是为了让服务实例更贴近当前真实登录用户的生命周期。
所以,后续再看到服务的"登录身份"配置时,不要只把它当成一个账号字段。
它真正代表的是:这个服务未来以谁的身份存在、能访问谁的资源、暴露谁的权限、加载谁的配置。
这就是 Windows 服务机制中非常关键的一层底层理解。
发布建议
建议标题:
text
Windows Internals 10.2.8:以其他账户运行服务,为什么它改变的不只是登录名,而是整个安全上下文?
建议摘要:
text
本文围绕 Windows Internals 第 10 章服务机制中的 Running services in alternate accounts,解释服务为什么需要以其他账户运行、SCM 如何使用指定账户启动服务、用户未登录时服务为何仍能加载 Profile,以及这种模型在多用户和安全场景下的局限。适合 Windows 桌面运维、系统排障、服务账号治理和 Sysinternals 学习场景阅读。
建议关键词:
text
Windows Internals, Windows 服务, Service Control Manager, SCM, 服务账户, This Account, User Services, Sysinternals, ProcMon, Windows 桌面运维

🔝 返回顶部