Windows Registry Forensics: The Registry as Narrative
The Windows Registry is one of those artefact sources that can be more useful than almost anything else. It contains a huge amount of information about the system, the user, installed software, policy, hardware, services, persistence, application behaviour, shell interaction, and a dozen other things you might care about during an investigation. Microsoft describes it as a system-defined database where applications and system components store and retrieve configuration data, which is a long way of saying that Windows and its applications store a lot of their state there.
During DFIR investigations, that state needs interpretation. A Registry key might show something was configured, a value might show the command line Windows expected to run, and a LastWrite timestamp tells you when that key or one of its values last changed. Those details can’t, on their own, automatically tell you who made the change, why they made it, whether the configured thing actually executed, or whether it was material to the incident. That’s the point to keep in mind for the rest of this article.
The Registry is Configuration Before it’s Evidence
The Registry sits in close proximity to how Windows makes decisions, which is why it’s useful in DFIR. It usually shows the conditions Windows or an application used or required before some later behaviour happened.
When a service starts, Windows is reading service configuration. When an application remembers a user preference, it might be reading from a user hive. When shell behaviour changes, COM objects are registered, file associations are altered, or a user’s RDP client remembers previous destinations, the Registry might be involved. The Registry can show the conditions in place when Windows or an application decided how to operate.
Earlier articles in this series covered artefacts like Prefetch, Shimcache, Amcache, services, scheduled tasks, Jump Lists, and file system metadata. Those artefacts help answer questions like whether a program ran, whether a file was present, what a user or application interacted with, and what changed around that time. The Registry usually answers a slightly different set of questions:
- What Windows was configured to do
- Whether that configuration was system-wide or user-specific
- What path, command, class, service, policy, or application setting existed
- Whether that setting was present before or after the activity we care about
It can also help explain the execution, persistence, or user behaviour you’re seeing elsewhere.
Hives Tell You Whose Story You’re Reading
The main hives you’ll care about in an incident response investigation are SYSTEM, SOFTWARE, SAM, SECURITY, NTUSER.DAT, and USRCLASS.DAT. That isn’t an exhaustive list, and it doesn’t need to be. Junior analysts get into trouble when they try to memorise endless key paths without first understanding whose context they’re looking at.
The SYSTEM hive is about the machine. Services, drivers, control sets, mounted devices, hardware-related configuration, networking, and boot-relevant state all tend to live here. If you’re looking at service persistence, driver loading, certain lateral movement artefacts, or configuration that applies before any particular user logs on, SYSTEM is often where you’ll start.
The SOFTWARE hive is also machine-level, but it’s more application and operating system configuration than boot and driver state. Installed software, Windows configuration, application settings, policy-backed locations, and many machine-wide autorun locations live here. Run and RunOnce keys, for example, can be set at both machine and user scope, which is one reason you need to pay attention to whether you’re looking under HKLM (HKEY_LOCAL_MACHINE) or HKCU (HKEY_CURRENT_USER). Microsoft’s documentation is explicit that Run keys make a program run when a user logs on, while RunOnce keys are intended to run once and then be deleted.
SAM and SECURITY are different. They’re not usually the first hives you open when you’re chasing a user’s recent file access or a Run key, but they’re relevant for local accounts, local groups, security policy, LSA-related material, and parts of the security model that help explain authority. In a domain environment, you might spend more time looking at domain controller evidence, event logs, and Active Directory data, but local SAM and SECURITY data can still be relevant on workstations and servers, especially when local accounts, cached secrets, or local policy form part of the incident.
NTUSER.DAT is the user’s primary registry hive. It can contain user-specific application settings, Explorer state, Run keys, typed paths, RDP client artefacts, and other per-user context. HKEY_CURRENT_USER isn’t a separate standalone hive on disk in the way people often imagine. Microsoft describes it as a predefined key that maps to the current user’s branch under HKEY_USERS, with that mapping established according to the process/thread security context. Some per-user registry data, particularly HKCU\Software\Classes, might be backed by USRCLASS.DAT rather than NTUSER.DAT.
USRCLASS.DAT is also user-specific. Shell, COM, file association, and class registration context often show up there, which is why ShellBags and shell-adjacent artefacts lead you into user profile data rather than only system hives. HKEY_CLASSES_ROOT adds another layer because it presents a merged view of machine-wide class registration under HKLM and user-specific class registration under HKCU, with user-specific settings taking priority.
Before interpreting a key, decide whether the evidence is system-level, user-level, application-level, or policy/configuration state. A machine-wide Run key doesn’t mean the same thing as a user Run key, a service configured to run as LocalSystem doesn’t mean the same thing as an application preference stored under one user’s profile, and a shell extension registered per-user doesn’t mean the same thing as one registered for the whole machine. The path tells you whose context you’re in. Don’t skip that part.
Persistence is Configuration with Conditions Attached
Registry-backed persistence is usually described as a list of keys: Run keys, services, shell extensions, COM hijacking, AppInit DLLs, Winlogon keys, Image File Execution Options, Windows Management Instrumentation (WMI)-adjacent configuration, and policy-backed startup behaviour. That catalogue can make the mechanism look more self-explanatory than the evidence actually is.
A Run key value under a user hive might show that a command was configured to run when that user logs on. It doesn’t prove the user logged on after the value was created, that the target executable still existed at logon, that the process ran successfully, or that the user knowingly created the value. It’s still useful because it tells you a persistence path existed, the user scope, and sometimes the command line. It might also give you a key LastWrite time and a concrete path to pivot on, and then you can ask better investigative questions.
You still need to check whether that user logged on after the value appeared. Look for Prefetch entries and Amcache records that recorded the binary. Use logon records and process telemetry to establish the sequence. Shimcache can show the path was observed, although it isn’t a clean execution timestamp. Event logs or endpoint detection and response (EDR) telemetry can help confirm process creation, and file system artefacts might show the payload being written shortly before the Registry change. Jump Lists, LNK files, browser downloads, or archive extraction records often explain how the file got there. That’s the Registry doing its job: not proving the whole event, but explaining why the rest of the event is plausible.
Services work the same way. A service key under SYSTEM tells you configuration: service name, ImagePath, start type, account context, dependencies, and other settings. Microsoft documents that the Service Control Manager starts auto-start services during boot, and that load ordering and last-known-good behaviour are tied to Registry-backed service and control set configuration (ControlSet001, ControlSet002, etc.). But a service key alone isn’t the whole finding. If the service was installed by an adversary, you want the service creation event, the file creation, the logon that provided administrative authority, the process or command that created the service, the first service start, any crash events, etc.
LastWrite is Useful, but it Isn’t a Diary
Registry timestamps are another place where analysts overestimate what they have. A Registry key has a LastWrite timestamp, but values don’t each have their own independent LastWrite timestamp in the way you need them to. Microsoft’s RegQueryInfoKey documentation describes the returned FILETIME as the last time the key or any of its value entries was modified.
That gives you a useful timestamp, but not always the timestamp you want. If a key contains 10 values, and one of them changed, the key LastWrite updates. If a value was created and then another value under the same key was modified later, the key LastWrite reflects the later modification. If an installer, updater, EDR product, configuration management agent, or Group Policy refresh touched the key after the adversary did, the timestamp might now describe that later activity.
Treat the timestamp carefully. Keep each finding tied to the thing the Registry can actually prove:
- “The key
LastWritetime was…” - “The value was present when collected…”
- “The key was last modified after…”
- “The timestamp is consistent with the configuration changing during the incident window.”
“The attacker created this Run key at 09:42” is a much bigger claim than the data might support. The timestamp tells you when the configuration changed; it doesn’t prove who did it or why. You might be able to support that, but not from the Registry alone.
The Registry also isn’t static while Windows is running. Hives are loaded into memory. Changes might be written through transaction logs before being fully reflected in the hive file you collected. Microsoft’s hive documentation notes that hive supporting files can include transaction logs of changes to keys and values, and if a hive is dirty and you didn’t collect or replay the logs, you might not have all the data.
That’s an issue in IR because triage collections are often fast and sometimes live. If your collection grabs SYSTEM but misses SYSTEM.LOG1 and SYSTEM.LOG2, your parser might still produce output from the primary hive. That output might look clean while still being incomplete. Treat parser output as derived evidence: preserve the hives and transaction logs, and be ready to explain what the parser read.
CurrentControlSet is a Live Convenience, Not an Offline Certainty
On a live system, HKLM\SYSTEM\CurrentControlSet is the active control set, and it’s where analysts are used to looking for services, control configuration, and other system state. Offline, though, you usually don’t have a literal CurrentControlSet key in the same way. You have ControlSet001, ControlSet002, and possibly others, and the Select key tells you which control set was current, which was default, which failed, and which represented last-known-good.
That’s not just trivia. If a tool only parses the active control set, it might miss historical or alternate configurations. If an artefact appears in ControlSet002 but not ControlSet001, that doesn’t automatically mean it was active at the time you care about, and it also doesn’t mean it’s irrelevant. It might represent a difference introduced by boot behaviour, rollback, or system change. So you need to ask:
Which control set did the artefact come from, which control set was current, and do the control sets agree?
If they don’t agree, the difference itself might be meaningful rather than noise. That’s especially important for services and driver configuration. You don’t want to miss a malicious service because it only appears in a control set your tool ignored or otherwise didn’t capture. You also don’t want to claim active persistence based on a control set that wasn’t active without explaining that nuance.
Volatile keys are another consideration. Some Registry data is memory-backed and not saved to disk. Microsoft’s RegCreateKeyEx documentation describes volatile keys as stored in memory and not preserved when the corresponding hive is unloaded, and it separately notes that non-volatile keys are stored in a file and preserved across restarts. For DFIR, that means a dead-box image and a memory image might not tell you the same thing.
The Registry is Strongest When it Explains Adjacent Artefacts
A good Registry finding should create pivots. A suspicious Run key points straight at persistence. You need to check the file path it references against all the other data at your disposal. For services, look for creation events, control actions, the ImagePath target, file system metadata, Shimcache, Amcache, and Prefetch where applicable. Ideally, you also want a process tree showing services.exe launching that payload.
If you find RDP client destinations under a user profile, pivot to Terminal Services logs, Security logon events, Jump Lists for mstsc.exe, ShellBags, network telemetry, and destination host artefacts. The source and destination sides of remote activity often show different artefacts, so don’t expect the same executable names, Registry paths, or event IDs on both systems.
If you find shell or COM-related configuration, pivot carefully. COM registration, file associations, shell extensions, and per-user class registrations can explain why a DLL or executable could be loaded by another process. They usually need strong corroboration before you describe actual execution, and even stronger corroboration before you describe intent.
This is where timelines are helpful, but not magical. A supertimeline can show Registry modification, file creation, user logon, program execution, event log entries, and application artefacts in temporal proximity. That proximity helps you understand what happened when, but it doesn’t remove the need to understand each artefact individually. Timelines are another tool in the toolbox, and they can be overwhelming unless you follow pivots rather than scrolling through millions of rows hoping the case solves itself.
The Registry contributes a lot to that timeline because it often records state changes, but state change isn’t always user action. Context is the difference between “interesting” and “meaningful.”
Absence is Also Evidence, but Only Sometimes
Analysts also get into trouble in the opposite direction. If a key is present, they overstate it. If a key is absent, they dismiss the activity. Registry absence can mean several different things: the artefact was never created, the user profile wasn’t loaded, the action used a different mechanism, or the data lived somewhere else for that Windows version. It can also mean a 32-bit application wrote to a redirected location, the hive wasn’t collected, transaction logs weren’t replayed, the key was deleted, the relevant data only existed in memory, or the parser didn’t support the artefact, the Windows build, or the key path variant.
In enterprise environments, there are more complications. Group Policy, Intune, SCCM, security baselines, login scripts, EDR products, VPN clients, browser management, application control, and software deployment tools can each write Registry data or cause Registry changes. Some of those changes look exactly like persistence if you only look at the key path. Some adversary changes look boring because they use the same locations administrators and installers use every day. Baselining is useful; it won’t give you a perfect answer, but it helps separate normal management activity from something that needs investigation.
Ask whether the value is common across the fleet, whether the same key is present on clean systems, and whether a known management tool introduced it. Then look at the path: signed enterprise application, user-writable directory, temporary directory, or recently created binary. A value that appears on one host means something different from one that appears on three adjacent hosts or every workstation after a policy deployment, and those questions turn Registry analysis from lookup into investigation.
Writing Registry Findings Without Overstating Them
The wording of a Registry finding changes the claim you’re making. Start by writing what the Registry actually showed, then add corroboration only when the rest of the evidence supports it. For a Run key, a careful statement might be:
A value under the user’s Run key configured
update.exein the user profile to run at logon. The keyLastWritetime places the most recent modification at approximately 09:42 UTC. The same executable path appears in Amcache, and Prefetch indicates the executable ran after the user’s next recorded logon.
The same discipline applies to service findings, where the Registry gives you configuration and the rest of the evidence has to prove activity:
A service configuration existed under the
SYSTEMhive with anImagePathpointing toC:\ProgramData\...\svc.exe. The service was configured for automatic start and to run under a privileged account. Event logs and EDR telemetry should be used to confirm service creation time, account context, and successful execution.
Again, the Registry tells you configuration. The rest of the evidence tells you whether that configuration translated into activity. This kind of wording can feel slow when you’re trying to close an investigation, but it keeps your conclusions defensible. It also helps the next analyst. They can see what the artefact proves, what it suggests, and what still needs corroboration.
The Registry Explains Why the Story Makes Sense
The Registry can be noisy, stale, incomplete, misleading, and easy to over-interpret. It’s also one of the best sources we have for understanding how Windows and its applications were configured at a point in time. The Registry isn’t where you go to memorise suspicious keys. It’s where you go to understand state, configuration, scope, and possibility. Then you test that interpretation against the rest of the Windows artefact ecosystem: execution evidence, file system metadata, event logs, user activity, application artefacts, memory where available, and EDR telemetry. Used carefully, the Registry often sits in the middle of the narrative. It doesn’t usually tell you everything that happened, but it can explain why Windows was willing to let it happen.
