Windows.Registry.NTUser

This artifact searches for keys or values within the user’s NTUser.dat registry hives.

When a user logs into a windows machine the system creates their own “profile” which consists of a registry hive mapped into the HKEY_USERS hive. This hive file is locked as long as the user is logged in. If the user is not logged in, the file is not mapped at all.

This artifact bypasses the locking mechanism by parsing the raw NTFS filesystem to recover the registry hives. We then parse the registry hives to search for the glob provided.

This artifact is designed to be reused by other artifacts that need to access user data.

Any artifacts that look into the HKEY_USERS registry hive should be using the Windows.Registry.NTUser artifact instead of accessing the hive via the API. The API only makes the currently logged in users available in that hive and so if we rely on the windows API we will likely miss any settings for users not currently logged on.


name: Windows.Registry.NTUser
description: |
  This artifact searches for keys or values within the user's
  NTUser.dat registry hives.

  When a user logs into a windows machine the system creates their own
  "profile" which consists of a registry hive mapped into the
  HKEY_USERS hive. This hive file is locked as long as the user is
  logged in. If the user is not logged in, the file is not mapped at
  all.

  This artifact bypasses the locking mechanism by parsing the raw NTFS
  filesystem to recover the registry hives. We then parse the registry
  hives to search for the glob provided.

  This artifact is designed to be reused by other artifacts that need
  to access user data.

  
Any artifacts that look into the HKEY_USERS registry hive should
be using the `Windows.Registry.NTUser` artifact instead of
accessing the hive via the API. The API only makes the currently
logged in users available in that hive and so if we rely on the
windows API we will likely miss any settings for users not
currently logged on.
precondition: SELECT OS From info() where OS = 'windows' parameters: - name: KeyGlob default: Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\** - name: userRegex default: . type: regex export: | -- HivePath: The path to the hive on disk -- RegistryPath: The path in the registry to mount the hive -- RegMountPoint: The path inside the hive to mount (usually /) LET _map_file_to_reg_path(HivePath, RegistryPath, RegMountPoint, Accessor, Description) = dict( type="mount", description=Description, `from`=dict(accessor='raw_reg', prefix=pathspec( Path=RegMountPoint, DelegateAccessor=Accessor, DelegatePath=HivePath), path_type='registry'), `on`=dict(accessor='registry', prefix=RegistryPath, path_type='registry')) -- This needs to always be mapped because it is normally denied through the API LET _required_mappings = ( _map_file_to_reg_path( HivePath="C:/Windows/System32/Config/SECURITY", RegistryPath="HKEY_LOCAL_MACHINE\\Security", RegMountPoint="/", Accessor='ntfs', Description="Map SECURITY Hive to HKEY_LOCAL_MACHINE"), ) LET _standard_mappings = ( _map_file_to_reg_path( HivePath="C:/Windows/System32/Config/SYSTEM", RegistryPath="HKEY_LOCAL_MACHINE\\System\\CurrentControlSet", RegMountPoint="/ControlSet001", Accessor='ntfs', Description="Map SYSTEM Hive to CurrentControlSet"), _map_file_to_reg_path( HivePath="C:/Windows/System32/Config/SOFTWARE", RegistryPath="HKEY_LOCAL_MACHINE\\Software", RegMountPoint="/", Accessor='ntfs', Description="Map Software hive to HKEY_LOCAL_MACHINE"), _map_file_to_reg_path( HivePath="C:/Windows/System32/Config/System", RegistryPath="HKEY_LOCAL_MACHINE\\System", RegMountPoint="/", Accessor='ntfs', Description="Map System hive to HKEY_LOCAL_MACHINE") ) LET _make_ntuser_mappings(Accessor, Hive, Subpath) = SELECT _map_file_to_reg_path( HivePath=NTUserPath, RegMountPoint="/", Accessor=Accessor, Description=format(format="Map NTUSER.dat from User %v to HKEY_USERS", args=NTUserPath[2]), -- This is technically the SID but it is clearer to just use the username RegistryPath="HKEY_USERS\\" + NTUserPath[2] + Subpath) AS Mapping FROM foreach(row={ SELECT pathspec(parse=expand(path=Directory), path_type="windows") + Hive AS NTUserPath FROM Artifact.Windows.Sys.Users() }, query={ -- Verify the file actually exists SELECT NTUserPath FROM stat(filename=NTUserPath) }) LET _user_mappings = _make_ntuser_mappings(Accessor='auto', Hive="NTUser.dat", Subpath="").Mapping + _make_ntuser_mappings(Accessor='auto', Hive="\\AppData\\Local\\Microsoft\\Windows\\UsrClass.dat", Subpath="\\Software\\Classes", Subpath="\\Software\\Classes").Mapping // Use this like `LET _ <= MapRawRegistryHives` LET MapRawRegistryHives =remap(config=dict( remappings=_user_mappings + _standard_mappings + _required_mappings)) sources: - query: | LET UserProfiles = SELECT Uid, Gid, Name || "" as Username, Description, UUID, { SELECT OSPath FROM glob( root=expand(path=Directory), globs="/NTUSER.DAT", accessor="auto") } as OSPath, expand(path=Directory) as Directory FROM Artifact.Windows.Sys.Users() WHERE Directory and OSPath AND Username =~ userRegex SELECT * FROM foreach( row={ SELECT * FROM UserProfiles }, query={ SELECT OSPath, OSPath, Data, Mtime AS Mtime, Username, Description, Uid, Gid, UUID, Directory FROM glob( globs=KeyGlob, root=pathspec( DelegateAccessor="ntfs", DelegatePath=OSPath, Path="/"), accessor="raw_reg") })