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")
})