如何通过WinAPI读取/复制已登录用户被锁定的NTUSER.DAT文件
问题场景
- 运行前提:程序持有
SeDebugPrivilege、SeBackupPrivilege等特权,以管理员权限运行 - 预期操作:加载本地用户的
NTUSER.DAT注册表配置单元,读取对应注册表键值 - 异常现象:目标用户为注销状态时操作可正常执行;目标用户处于登录状态时操作失败,返回错误码32,对应提示为进程无法访问文件,因为该文件正被其他进程占用
- 排除方案:整盘卷影复制因需要拷贝整个驱动器,不具备可行性
- 待确认方向:是否存在无需依赖第三方库的Win32 API或原生方案,可在用户登录状态下复制或读取
NTUSER.DAT文件;是否可先卸载对应用户的注册表配置单元,再调用RegLoadKeyA()等API完成加载读取
方案说明
不可行操作说明
不要尝试在用户登录状态下强制卸载其正在使用的注册表配置单元:
- 已登录用户的
NTUSER.DAT会被内核态组件、用户会话下所有进程持续持有句柄,就算持有全部相关特权,调用RegUnLoadKey()也会直接返回ERROR_ACCESS_DENIED - 若通过驱动等非常规手段强制卸载配置单元,会直接导致对应用户会话崩溃、所有用户进程触发访问异常,甚至造成用户配置文件永久损坏。
可行原生方案
方案1:直接读取已挂载的活跃用户注册表(优先选择)
所有处于登录状态的用户,其注册表配置单元默认已经由系统挂载在HKEY_USERS\<用户SID>路径下,完全不需要操作磁盘上的NTUSER.DAT文件:
- 持有管理员权限+
SeDebugPrivilege的前提下,可直接调用RegOpenKeyEx()打开对应用户SID下的任意子键,读取实时的注册表键值 - 可通过
WTSQuerySessionInformation枚举当前活跃会话,结合LookupAccountSid类API匹配会话对应的用户SID,无需遍历所有磁盘文件。
方案2:利用备份权限直接读取锁定的NTUSER.DAT文件
如果确实需要读取磁盘上存储的NTUSER.DAT原始内容(例如需要获取未被加载的历史键值),无需做整盘卷影复制,利用已持有的SeBackupPrivilege即可绕过文件共享锁读取:
- 调用
CreateFileW()打开目标路径下的NTUSER.DAT文件,参数配置如下:dwDesiredAccess传入GENERIC_READdwShareMode传入FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETEdwCreationDisposition传入OPEN_EXISTINGdwFlagsAndAttributes必须传入FILE_FLAG_BACKUP_SEMANTICS,该标志会触发系统的备份权限校验逻辑,绕过常规文件锁限制
- 拿到有效文件句柄后,调用
ReadFile()逐块读取文件内容,写入本地临时文件副本,读取完成后关闭源文件句柄 - 对生成的临时副本文件调用
RegLoadKeyA()/RegLoadKeyW()加载到临时注册表路径,完成键值读取后调用RegUnLoadKey()卸载临时配置单元,删除临时文件即可。
注意:通过备份语义直接读取磁盘上的
NTUSER.DAT,获取的是文件落盘的静态版本,不会包含用户登录后驻留在内存中、尚未写入磁盘的注册表修改内容,若需要读取实时生效的注册表配置,必须使用方案1直接读取HKEY_USERS下的已挂载路径。
内容的提问来源于stack exchange,提问作者fin
相关产品推荐
相关产品推荐

