Registry key last write time, explained
8 min read
The registry last write time is the single most-used timestamp in registry forensics, and the single most-misread. It is one 8-byte field per key, and an enormous amount of timeline work — when a service was installed, when a USB device was first seen, when a persistence entry was planted, which item in an MRU list is newest — rests on reading it correctly. This post explains what the key last modified time actually records, what moves it, what it cannot tell you, and the assumptions that quietly turn it from evidence into error.
Every key has one. No value does.
Start with the fact that decides everything else: the timestamp belongs to the key, not to any value under it. On disk, every key is a nk key-node record, and at offset 0x04 of that record sits an 8-byte FILETIME — the LastWritten field. That is the registry's only per-key timestamp, and there is exactly one of them per key.
Values do not have this. The vk value record that stores a value's name, type, and data carries no timestamp at all. There is no "this value was last written at" field anywhere in the hive. So when you need to know when something in the registry changed, the only temporal handle the format gives you is the LastWritten time of the key that contains it — and that handle is shared by every value and every immediate subkey under that key.
This is not a parser limitation or a quirk of one tool. It is the on-disk structure. Any tool that appears to show you a per-value timestamp is either showing you the parent key's LastWritten time relabeled, or reading a timestamp that the data itself happens to store inside a value (UserAssist's last-run FILETIME, for example, lives in the value data — it is not registry metadata). The registry layer itself stamps keys, and only keys.
What updates it
The kernel rewrites a key's LastWritten time whenever the key is structurally modified. "Structurally modified" is broader than most people assume, and that breadth is the root of most mistakes. The timestamp moves when you:
- Add a value to the key, or delete one.
- Add a subkey, or delete one.
- Change an existing value — set its data, change its type, or rename it.
- Change the key's security descriptor or class.
In short: almost any change to the key or its contents bumps the timestamp to the current time. Renaming a key, changing one value's data, deleting an unrelated subkey — all of them rewrite the same single field on the same nk record.
There are documented edge cases where in-place value-data updates behave inconsistently across Windows versions and write paths, which is precisely why you should not lean on LastWritten to assert that a specific value changed. But the safe operating model is simple: treat LastWritten as "the most recent moment this key's structure or contents were touched," and do not try to attribute it to any one value.
What it does not tell you
This is where careful analysts and careless ones part ways. The LastWritten time tells you when the key was last touched. It does not tell you:
- Which value changed. The field is a single timestamp for the whole key. If a key holds twenty values and one of them was modified, the timestamp moves, and there is nothing in the hive to say which of the twenty it was. You get "something here changed at 14:22," not "the
Debuggervalue changed at 14:22." - Anything per-value. Values have no age. A value that was set the day the OS was installed and one that was set five minutes ago sit under the same key with the same
LastWrittentime, and the registry preserves no way to distinguish them. - The previous time. The field is one slot, not a log. Each write overwrites it. The live hive keeps only the most recent
LastWritten; every earlier write time is gone unless you recover it from a transaction log or VSS snapshot. - Creation time. There is no separate per-key creation timestamp.
LastWrittenis the last write, full stop.
The mistakes analysts make
Three assumptions cause most of the damage.
Mistake 1: "This value's data is recent, so it was set at the key's LastWrite time." No. The key's timestamp reflects the last structural change to the key, which may have nothing to do with the value you care about. Add an unrelated subkey today and the parent key's LastWritten jumps to today, even though the value you are looking at has not been touched since 2021. Reading a value's age off the key timestamp is the most common error in registry timeline work, and it produces confidently wrong conclusions.
Mistake 2: "LastWrite equals when the key was created." There is no creation time in the nk record. A Run key that has existed since install will show a LastWritten time of whenever its contents last changed — which, for an attacker who added a persistence value last week, is last week, not install day. The timestamp dates the modification, and you cannot recover the creation moment from it.
Mistake 3: "The key was untouched, so nothing happened." A stable LastWritten time only means no structural change has been flushed to this hive since then. It says nothing about reads, about in-memory volatile keys, or about activity recorded elsewhere. Absence of a recent write is not absence of activity.
How it is used forensically — correctly
Used within its limits, LastWritten is genuinely powerful.
Recency of the most-recent change. When a key holds a single logical artifact — a USBSTOR device subkey, a service's parameters, a per-device entry — the key's LastWritten time is a clean answer to "when was this last modified." The narrower the key's contents, the more precisely the timestamp dates the thing you care about. A device subkey that holds only that device's metadata gives you a tight bound on when that device was last enumerated.
Ordering an MRU. Many "most recently used" lists are implemented as subkeys, one per item, or as keys whose ordering is reconstructed from their write times. Sorting the relevant keys by LastWritten descending puts the most recent activity at the top. This is how you establish MRU #1 — the newest entry — without trusting any value-stored ordering that might be stale or tampered. The key that was written last is the one touched most recently.
Dating a persistence entry. When you find a suspicious value under ...\CurrentVersion\Run, Image File Execution Options, a service ImagePath, or a Winlogon hook, the containing key's LastWritten time is your best single estimate of when the persistence was established — provided nothing else under that key has been modified since. Cross-check it against transaction logs and any sibling artifacts before you state it as the planting time, but as a first anchor it is exactly the right field to read.
In each case the discipline is the same: tie the timestamp to a key whose contents are narrow enough that "the key changed" and "the thing I care about changed" mean nearly the same thing, then corroborate.
The timezone caveat
The LastWritten field is a FILETIME: 100-nanosecond intervals since 1601-01-01, and it is stored in UTC. It is not in the machine's local time, and the hive does not record what the local time zone was. If you report a registry timestamp in local time without saying so, you have introduced an ambiguity that can be hours wide and will not survive cross-examination.
If you need local-time context — to line a registry event up against a user's stated working hours, or against another local-time log — you have to apply the machine's configured offset yourself, which you can recover from the system time zone settings in the SYSTEM hive. Read the raw FILETIME as UTC, then convert deliberately and label it. Never assume a tool's displayed timestamp is the one you think it is; confirm whether it shows UTC or local, because the two will disagree and only one of them is what the hive actually stored.
What to take away
The registry gives you one timestamp per key and none per value. That LastWritten FILETIME moves on any structural change to the key — a value added, a subkey deleted, the security descriptor rewritten — and it keeps only the latest write, overwriting all history. It does not identify which value changed, it does not date individual values, and it is not a creation time. Used on narrow keys it precisely dates a device, a service, or a persistence entry, and sorting keys by it reconstructs MRU order. Read it as UTC, convert deliberately, and corroborate with transaction logs and VSS before you call it proof. You can analyze a hive in your browser and see the LastWritten time on every key in the tree, with nothing uploaded — but the value of understanding the field is that you will read it for what it is, not for what it is convenient to assume.