TL;DR

The host reads clean because Windows rebuilt the evidence, not because nothing happened.

A Windows feature update installed from media builds a new operating system, moves part of the old one into it and rebuilds the rest. Prefetch, BAM, PCA, every event log on the measured hosts, the scheduled task files and the live USB keys start on the upgrade day, and Amcache did on two of three hosts. All of them parse without error, so a laptop upgraded during the period of interest has nothing before it. Per-user registry content is replayed into new hives with its write times reset. Jump lists, LNK files, browser stores, SRUM, the Recycle Bin and two registry stores, DeviceMigration and NetworkList, carry history across.

Four things decide whether an examiner reads that correctly. The kind of update, because the enablement package measured here rebuilt nothing. The Setup path, because on one path the offline phase wrote local time as UTC and shifted those timestamps by the host's offset. The install image, which stamps the system files and makes the usual $SI-before-$FN timestomping rule fire on tens of thousands of them. And Windows.old, the only complete pre-upgrade copy, which lasted 12 days on one host here and 42 on another. Measured on three hosts, one of them a real investigation.

A host upgraded during the period of interest reads as clean. I met this on a case. The subject's laptop had no Prefetch, no Amcache, no event log and no USB history older than one particular morning a few weeks before collection, and every one of those sources parsed without error. Every EVTX file, the NTUSER.DAT and UsrClass.dat of every profile, and the profile folders themselves had been created that morning.

My first reading was a reinstallation, with the user's data put back from a backup afterwards. A closer look showed an in-place Windows 11 feature update instead, and three things separated the two:

  • The SYSTEM hive held a Source OS key. Setup writes one at the start of every upgrade, as a copy of the old system's CurrentVersion key; a clean install has no old system to copy.
  • The user's LNK files, jump lists, documents and DPAPI keys were the original MFT records, created up to 17 months before that morning. A restore from backup writes new records whose $FILE_NAME creation time is the day of the restore, whatever $STANDARD_INFORMATION says.
  • The new system's own folders carried the signature of Setup's swap: an install-image creation time, and $FILE_NAME values left by a rename into the volume root (both explained below).

What the published DFIR material says about upgrades fits in four sentences: the install date resets, the event logs are recreated, USB keys are cleared, and the old system sits in Windows.old for a while. All four are true. None of them tells an examiner which sources can still answer a question about the time before the upgrade, how far back each one reaches, or which timestamps the upgrade itself has falsified.

This Field Note answers those three questions with measurements. It covers every file, folder and registry location my timeline collection reads, plus the ones investigators reach for by hand, measured record by record on the MFT and key by key inside the hives, with the mechanism behind each effect.

The short version

The loss is selective and predictable. Setup builds a new operating system, moves selected parts of the old one into it, and rebuilds the rest. On the hosts measured, three fates cover almost every source:

  • Rebuilt, so empty before the upgrade: Prefetch, PCA, BAM, every EVTX log, the setupapi device logs, the live USBSTOR, USB and MountPoints2 keys, scheduled task files and their TaskCache keys, and the WMI repository.
  • Replayed into new hive files, with write times reset: UserAssist, RecentDocs, ShellBags and the Office MRU. Their content survives, and so do the timestamps stored inside UserAssist and Office MRU values.
  • Moved across with history intact: jump lists, LNK files, Office MRU caches, browser history and cookies, SRUM, the Search index, Windows Timeline, the notifications database, DPAPI keys, Credential Manager, Outlook stores, the Recycle Bin and user data.

Two registry stores keep device and network history that the rebuilt keys lost: DeviceMigration and NetworkList. On the case host, DeviceMigration still listed four USB storage devices that the live USBSTOR key had forgotten.

The upgrade also plants two timestamp traps. Operating system files carry a creation time copied from the install image, identical to 100 ns on unrelated hosts, which makes the usual $SI-before-$FN timestomping rule fire. And on the case host the offline phase wrote local time as if it were UTC, which placed the rebuilt user profile before the system it runs on.

What was measured

Three hosts, all upgraded into Windows 11. The sources inventory comes from the 48 artifacts of my Velociraptor timeline collection, extended with the locations investigators check by hand: PSReadLine history, thumbnail caches, the RDP bitmap cache, the WMI repository, BITS, Defender history and quarantine, DPAPI, Credential Manager and shadow copies.

HostUpgradeWhat makes it useful
Host A, the caseWindows 11 in-place upgrade from installation media; UTC+3; NVMe SSD with BitLocker; forensic image acquired about six weeks laterA real investigation. 506,576 in-use MFT records classified; 14 records checked against raw bytes with an independent parser.
Host B, the controlWindows 10 22H2 in-place upgrade from media to Windows 11 25H2 (build 26200); UTC+3; collected 20 minutes after Setup finishedEvery effect dated against Setup's own log, and every rebuilt source compared with its copy in Windows.old.
Host CWindows 11 in-place upgrade from media to 24H2; UTC+1 at the time of the swap; later the 25H2 and 26H2 enablement packages; measured liveA second full swap from the same install image as Host A, 21 months old. The 26H2 enablement package was measured with snapshots and controls.

Dates in this Field Note are relative to each host's upgrade, which I call the swap. Times of day are given only where an order of events depends on them.

Each finding below is measured on these three hosts. Where the text says every event log or every hive, it means every .evtx file under System32\winevt\Logs and every registry hive file on the system volume of these hosts. Logs that products keep elsewhere, and other builds, editions, architectures and upgrade routes, were not measured.

What happens to each source

Every classification comes from the MFT records a source consists of. A record created by the upgrade cannot hold history from before it; a record that existed before it can. The column "reaches back" gives the oldest surviving record on Host A, which bounds how far that source can still answer questions. Where Host B behaved differently, the row says so.

Execution evidence

Every execution artifact except SRUM starts on the upgrade day on Host A. Amcache is the one source whose fate differed between hosts.

SourceFateReaches backWhat it means
PrefetchRebuiltSwap dayNo .pf file predates the swap; run counts and last-run times restart. 78 files were created in the first minutes of the new system.
Amcache.hveHost A: new, 2 days later. Host B: carriedHost A: nothing. Host B: five yearsOn Host B the original hive moved across with 1,183 file inventory entries written before the upgrade. Do not assume either outcome; check the record.
PCA launch dictionaryRebuiltSwap dayGUI launch records start at the upgrade.
BAMRebuiltSwap day0 of 47 execution times predate the swap on Host A; 0 of 18 on Host B.
ShimCacheValue rewrittenNot establishedWhether entries from before the upgrade were carried inside the value is still open.
SRUM databaseCarriedOriginal databaseThe database moved into the new tree, so its 30 to 60 day usage window is unaffected. Only its transaction logs were recreated.

Event and text logs

All 241 EVTX files on Host A were created at the new system's first boot or later. 199 of them share one second, the moment the new event log service started.

SourceFateReaches backWhat it means
EVTX event logsRebuiltSwap dayNo logon, service install, PowerShell or RDP event survives from before the upgrade.
setupapi device logsRebuiltSwap dayDevice installation history restarts.
Defender detection historyCarriedOriginal installationDetection records moved across. On Host B the quarantine (193 items) and MPLog files moved too.
Panther, CBS and DISM logsRebuiltSwap daySetup's own logs of the swap were removed on Host A; on Host B they survive inside Windows.old.
PSReadLine historyCarriedOriginal fileOn Host B the console history file moved with the profile.

Machine registry

On the full-swap hosts, every hive file on the volume is a new record created by the upgrade. Inside them, the device and execution keys start at the swap, while two stores carry older history in timestamps stored inside their values.

Key familyFateWhat it means
USBSTOR, USB, WPDBUSENUMRebuiltNo key predates the swap. On Host A the live USBSTOR key lists one device, and every key under it was written about six weeks after the upgrade.
MountedDevicesCarried, time resetThe mappings survive; their key time does not date them.
DeviceMigrationRewritten, old values kept579 LastPresentDate values reaching 20 months back on Host A, including four USB storage devices USBSTOR no longer lists. On Host B the values are identical, device for device, to those in Windows.old.
NetworkList profilesCarried, times reset117 of 124 profiles keep a creation date from before the upgrade. On Host B DateCreated is identical for 28 of 28 profiles.
TaskCacheRe-registeredAll 335 task registrations on Host A were written at or after the swap.
Services, Uninstall, ProfileListImage dates or rewrittenKeys that predate the upgrade carry install-image dates, not host history (see the traps section).
Setup\Source OSNewA copy of CurrentVersion taken at the start of each upgrade. Its name records the date; it is the first key to read.

For a removable media case, DeviceMigration is the surviving record. The four USB storage devices it holds on Host A (a WD Elements drive, a SanDisk 3.2Gen1 stick and two generic mass-storage instances) appear nowhere else on the live system. The key sits at HKLM\SYSTEM\Setup\Upgrade\Pnp\CurrentControlSet\Control\DeviceMigration. Its key write times belong to Setup; only the LastPresentDate values date the devices.

File access and user activity

File-based user activity survived in every profile that had it. The subject's profile directory and both hives on Host A are records created at the swap, yet 386 Recent LNK files, 57 jump lists and 133 Office MRU cache files moved into it, reaching back about 17 months.

SourceFateWhat it means
Recent LNK files and jump listsCarriedThe strongest surviving evidence of file and folder access. Their internal times are untouched.
Office MRU cachesCarriedaggmru, MruServiceCache, the usage store and Office Recent moved with the profile.
Windows Search indexCarriedCan hold file and mail metadata from before the upgrade.
Windows Timeline, notifications databaseCarriedActivitiesCache.db and wpndatabase.db moved in every profile that had them.
Browser history and cookiesCarriedChrome, Edge and Firefox stores moved with the profile's data folders. On Host B the Chromium caches and WebCacheV01.dat moved too.
Thumbnail caches, RDP bitmap cacheLeft in Windows.oldOn Host B the live files are new. The old ones exist only while Windows.old does.
User Temp folderLeft in Windows.oldOn Host B 7,814 files stayed behind. Tools staged in Temp before an upgrade are visible only in Windows.old.
User foldersCarriedDownloads, Documents, Desktop and OneDrive moved with their MFT records and timestamps, so file-system timelines of user data span the swap.

Persistence and credentials

SourceFateWhat it means
Scheduled task XML filesRebuilt476 of 497 task files on Host A were created at the swap. A task planted before the upgrade looks as if it was created on the upgrade day.
WMI repositoryRebuiltNew files. Whether event subscriptions from before the upgrade were migrated into them is not established.
BITS job databaseCarriedMoved with its history.
DPAPI, Credential ManagerCarriedSecrets protected before the upgrade stay decryptable.
$MFT, $LogFile, $UsnJrnl, Recycle BinStay in placeVolume structures the upgrade does not replace. The journals are circular, so their window after an upgrade depends on activity.

The registry replay: content kept, write times reset

On the full-swap hosts, per-user activity keys were copied into brand new hive files, and every copied key got the time of the copy. On Host A every BagMRU key in the subject's UsrClass.dat carries the same LastWriteTime, six minutes after the new kernel started. A timeline built on key write times shows a burst of user activity at the moment of the upgrade that never happened.

Host B proves the mechanism, because Windows.old kept the old hives. I read each key family from both hives with the raw registry accessor and compared entries.

Key familyOld hiveNew hiveVerdict
UserAssist278280Carried. 274 values byte-identical; the rest changed by use after the upgrade.
Office MRU9494Carried. All 71 item values byte-identical, with open times reaching back nearly five years.
RecentDocs430430Carried, write times reset
RunMRU1717Carried, write times reset
ShellBags (UsrClass)1,3131,313Carried, write times reset
FeatureUsage232232Carried, write times reset
Terminal Server Client77Carried, write times reset
ComDlg32 (Open/Save)2590Not carried
TypedPaths170Not carried
WordWheelQuery20Not carried
MountPoints2472Not carried; the 2 are new

UserAssist and the Office MRU are the two registry sources that still date activity before an upgrade. Their values embed their own run and open times, and the copy is byte for byte. On Host A the subject's UserAssist keeps 64 values whose last-run time falls before the image was applied at 07:08 UTC on the swap day, reaching back 17 months, and the subject's Office MRU keeps 108 of 115. Every other replayed key tells you what was used, not when.

The list of dropped families matters as much as the carried one. Open and Save dialog history, typed Explorer paths and Explorer search terms are the keys that show a user deliberately navigating to something, and they are the ones the migration does not carry.

Four timeline traps

1. The install image stamps its own creation times

The $STANDARD_INFORMATION birth of an operating system file identifies the install image, not the host. C:\Windows and C:\Users carry the $SI birth 2024-04-01T07:21:16.1844348Z on all three hosts, identical to 100 ns, and on Host B so do System32, WinSxS and the config folder. A value that precise, on unrelated machines, can only come from the media.

The bulk of the files carry their own stored times. On Host B, 115,875 of 117,356 new files under C:\Windows have an $SI birth that differs from their $FN birth, spread over 177 distinct seconds on two days: 1 April 2024 and 6 June 2026, the two build dates inside a 25H2 image. A timeline sorted by $SI birth places the upgrade's files two years in the past.

WIM images store per-entry timestamps at 100 ns, and the open reference implementation, wimlib, restores them on apply. No Microsoft page states that Setup does the same; the measurements say it does.

2. The usual timestomping rule fires

On Host A, 56,958 records have an $SI birth earlier than their $FN birth. That is the pattern the usual timestomping detectors flag, and it is consistent with Setup creating each file and then restoring the image time through the API. Exclude image-stamped records from anomaly rules on any upgraded host, or the one real case of timestomping will sit under fifty thousand false ones.

The inverse rule fails too. 2,335 new records on Host B carry the image time in their $FN birth as well, C:\Windows among them, because they were renamed after being stamped. "$FN birth before the upgrade" is therefore not proof that a record is old. On Host B the two image days never occur on the Windows 10 side (0 of 388,246 Windows.old records), which is what makes them usable as a marker.

3. The offline phase wrote local time as UTC

On Host A, every record written during the Safe OS phase is three hours ahead of true UTC, which is exactly the host's offset. Four measurements establish it:

  1. The host runs at UTC+3 with its hardware clock in local time: the TimeZoneInformation key has a bias of -180 and no RealTimeIsUniversal value.
  2. The new system logged its first kernel start (Kernel-General event 12) and its event log service start (EventLog 6005) with correct UTC times.
  3. No record carries a stored time later than the kernel start plus three hours. System32 has to exist before the new kernel can boot, so its stored creation time, 2 h 45 min after the kernel start, cannot be true UTC.
  4. No record carries a true-clock time in the 15 minutes that the shifted cluster fills. The last true-clock write is SRUM's final update of the old system.

The only clock change logged around the swap is a two-second adjustment the next day, so the clock was never wrong. The offset comes from how the offline environment read it. Microsoft's WinPE team documented the mechanism in 2007: Windows keeps the hardware clock in local time, and NTFS computes UTC "by subtracting the timezone offset from the local time in the BIOS clock", so a WinPE image with the wrong time zone writes wrong NTFS times.

Uncorrected, Host A's timeline shows the user profile being rebuilt 2 h 45 min before the system files it depends on. Corrected, every step falls into Microsoft's documented phase order. On a host west of UTC the offline records would read earlier than true UTC, not later.

Before subtracting an offset, establish five things.

  1. That Setup actually booted into Safe OS. Host B's log shows it can skip it.
  2. Which records the offline phase wrote. On Host A they form one cluster of stored times that, once corrected, ends before the new kernel's first start.
  3. The time zone and daylight-saving state in force on the upgrade day, from the TimeZoneInformation key and that day's event logs, not today's setting.
  4. Whether the hardware clock held local time or UTC. A RealTimeIsUniversal value of 1, a hypervisor clock or a dual-boot system changes the answer.
  5. Whether the host crossed a time zone or daylight-saving boundary between the last write of the old system and the first write of the new one.

The shift is measured on one host, at UTC+3 with no daylight saving. Hosts at negative offsets, on a daylight-saving changeover or with a UTC hardware clock have not been measured. Treat the correction as a bounded rule for the records it covers, not a transform for the whole timeline.

Host B has no shift, and Setup's own log explains why. It reads "Got SafeOS boot removal OneSetting: TRUE". Setup skipped the Safe OS boot and ran every offline step while Windows 10 was still running, so no record was written by WinPE. On the hosts here the shift follows the Setup path, on one host each: Host C applied its image under the running system at UTC+1 and Host A in Safe OS at UTC+3, so path and offset cannot be separated yet. Setup's log is where the path is recorded.

4. "The upgrade time" is not one moment

On Host B the new operating system was laid down 45 minutes before the reboot, while Windows 10 was still running. 128,995 records, the new C:\Windows tree, the Windows components of Program Files and the new hives, were born in a 13-minute window long before the machine restarted. The user profiles were recreated in the offline apply, also before the reboot. A timeline that anchors "upgrade" on the reboot misplaces all of it.

A second full-swap host: the same verdict, a different path

Host C made the same upgrade as Host A, and every source received the same verdict. Both left Windows 11 23H2 (build 22631) by full OS swap into the 24H2 platform (build 26100), and both volumes were first installed from the same Windows 11 22H2 image. Host C was measured live 21 months after its swap; Host A from a disk image six weeks after its own. On both, every event log, Prefetch file, scheduled task file, PCA file, Windows Error Reporting report and thumbnail cache was recreated, and no file survives from before the swap. The machine hives and the WMI repository are new files dated to the install image. SRUM, jump lists, browser stores, Office caches, the Recycle Bin and Defender detection history were kept. The losses belong to the upgrade and not to one machine.

Each source was measured twice, once as files and once as content. Every in-use MFT record was classed by its $SI and $FN births against the swap window as kept, re-parented, image-stamped, swap-created or after. The timeline feeders were then run on each host with a cut-off two days after the swap, so a row dated before the swap is pre-upgrade content that survived. Neither host has a pre-upgrade copy: both Windows.old folders are gone.

One install image, dated in three places

Both hosts received the same install image, and the image dates itself three ways. Among the records born in the swap, 44,593 on Host C and 44,903 on Host A carry an $SI birth on 1 April 2024, and the five most frequent exact values are identical on the two hosts to the 100 ns tick, with identical counts. HKLM\SYSTEM\Setup!CloneTag reads Mon Apr 01 07:29:24 2024 on both. And the volume root keeps the $SI birth 2022-05-07T05:17:22.4911263Z of the Windows 11 22H2 image that first installed each machine, through every later upgrade, although the two volumes were formatted in November 2023 and April 2024.

The machine hives keep the image's key write times as well. 7,344 HKLM keys on Host C and 5,926 on Host A carry a write time on 1 April 2024, and 0 and 3 carry a write time from the host's own life before the upgrade, so a machine-hive key time older than the swap is almost always the image build. The root $SI birth (the original install media), the $MFT birth (the format) and the oldest Source OS InstallDate (the first system still on record) give three independent points in a host's install history. That reading rests on two hosts.

Two Setup paths, two corrections

Setup ran the same upgrade along two paths, and the path decides which timestamps need correcting. Host C received its image while 23H2 was still running. The lay-down preceded the new kernel's first write by 16 hours 14 minutes, where Host A's Safe OS lay-down preceded it by 15 minutes. Files born hours after the lay-down sit in the new tree, and only a running system creates them. The user's new profile and hives were born 15.4 hours before the first event log of the new system. Host C's offline stamps carry no time-zone shift: shifted back by the host's offset, the lay-down would fall before the Panther folder and before the start time the Source OS key records, both written by the old system when Setup began. The three-hour shift on Host A belongs to its Safe OS phase.

The path also changes how the MFT allocates the new records. On Host A all 130,367 records born in the swap window sit in reused slots (sequence 2 or higher), because the deleted staging tree had freed them. On Host C 44,490 of 44,545 lay-down records sit in first-use slots (sequence 1). A rule that reads sequence 2 as the mark of a new record holds on a Safe OS upgrade and misses almost every new record on a downlevel one.

Read the path before correcting a timeline. A user hive born before the first event log of the new system marks an image applied under the running old system: offline stamps are true UTC and the profile predates the reboot. A user hive born minutes after the new kernel started marks a Safe OS apply: subtract the host's offset from the records laid down before the kernel start, after the checks in the offline-time trap above.

Retention explains the other differences

The two hosts differ in how much pre-upgrade content survives, and the cause is time since the swap and not Setup. UserAssist and Recent LNK counts cover every user profile on the host, with a cutoff of midnight UTC on the swap day. SRUM is one database for all users and the system.

Surviving pre-upgrade contentHost C, 21 months afterHost A, 6 weeks after
UserAssist values with a run time before the swap1112
Recent LNK files kept0401
SRUM rows dated before the swap3,14814,500

Ordinary use replaced the stores the upgrade had kept. A source classed as new on an old swap may have been kept by the upgrade and replaced later, so the youngest swap is the cleaner witness for what Setup preserves.

How Setup swaps the operating system, seen from the MFT

Microsoft documents four phases: Downlevel, SafeOS, First boot and Second boot. It does not document how the new system replaces the old one on the volume. The MFT records it, once you apply the rules for when NTFS rewrites $FILE_NAME times.

The rules come from two peer-reviewed studies, Galhuber and Luh (2021) and Bouma et al. (2023): NTFS writes $FN only when an object is created, renamed or moved, and a rename or move copies the $SI values from just before the operation into $FN. Renaming a parent never rewrites its children's $FN, because a child refers to its parent by record number. With those rules, Host A's volume reconstructs the swap in five steps.

  1. Staging, 12 to 13 days before the swap. Downlevel built a staging tree in fresh MFT entries above the old high-water mark; 431,641 of those records are now deleted. The Source OS key dates the start of this phase.
  2. Lay-down, 15 minutes. SafeOS created 121,792 records. C:\Windows sits in an MFT slot the staging deletion freed, with sequence number 2, so it is a new allocation, not the old folder.
  3. Stamping. Setup overwrote the $SI birth of most new records with the time stored in the image (trap 1).
  4. Rename into the root. C:\Windows, C:\Users, C:\Program Files and C:\ProgramData carry the image time in their $FN birth and swap-day times in their other $FN fields. Under the rename rule that combination arises only when an object is created, stamped, then renamed or moved. The top-level folders were built elsewhere and renamed into the root, while their children kept their creation-time $FN. On Host C an undocumented value, HKLM\SYSTEM\Setup!UPGOldOsPieces, lists the old pieces moved aside: Windows, Program Files, Program Files (x86), Users, ProgramData, inetpub, SkyDriveTemp and $WinREAgent.
  5. First and second boot. The new kernel started 26 seconds after the last rename. The event logs appeared 24 seconds later, the new profile and hives under a minute after that, the per-user registry apply six minutes in, and the install date was written nine and a half minutes after the kernel start.

Host B records the same sequence with Setup's log as the clock:

Setup phaseRecords bornWhere
Setup start and download1,164Setup's working folder
Image applied downlevel128,995New Windows tree, Program Files, the new hives
Gather103Windows.old and Setup's working folder
Offline apply, old system still running1,9291,668 under Users: the rebuilt profiles
Recovery image and finalize604Setup's working folder
First boot and online apply3,643Windows, Program Files, ProgramData

Nothing was written in the 32 seconds between the last record of the old system and the first record of the new kernel.

Enablement packages leave the volume alone

Microsoft describes an enablement package as "a small, quick-to-install 'master switch'" over features already installed, and states that 24H2 "is a full OS swap so it isn't available as an enablement package". Host C's 25H2 enablement package left no trace on the volume: its top-level folders still carry the 24H2 image time, BuildLabEx still names the 24H2 build while CurrentBuild reads 26200, and its only Source OS key dates the earlier media upgrade. The effects in this Field Note apply to in-place feature updates that swap the operating system, not to enablement packages or monthly cumulative updates. The next section gives the measurement behind that statement.

An enablement package, measured live

An enablement package is a label and servicing event, and it sets no evidence floor. Host C received the Windows 11 25H2 to 26H2 package (KB5121794) on 2 October 2026 and was measured around it. Eight live snapshots each walked about 860,000 registry keys, recording the path, the last write time and a hash of the values, together with the event log inventory, the servicing store and the update history. Two controls stayed out of the update window: an idle interval of 4.6 hours, and a plain restart. A display driver update was installed and restarted first, so its effects belong to the baseline. The NTFS change journal on C: was enlarged from 32 MiB to 1 GiB beforehand, and its identifier did not change at either restart or at the update.

Nothing was rebuilt. Prefetch, Amcache, every hive, every event log, the scheduled task files, the WMI repository, the restore points and the Source OS and DeviceMigration stores were written in place or not at all. The host had 557 event log channels and 485 .evtx files before and after, with no System 104 or Security 1102 event. The record count fell on 37 channels during the update against 43 in the plain-restart control, so the ring-buffer wrap came from the restart. Three registry values changed in the build key. The restart explains 62,299 of the 64,055 registry keys that changed, and 1,099 are attributable to the update.

The update in time

The servicing session ran for 57 seconds, and the label changed about seven minutes later at the first boot. All times are UTC.

TimeEventSource
16:24:23Event 41: an update was downloadedWindows Update client log
16:24:28KB5121794 from Absent to Staged (Servicing event 1)Setup log
16:25:04Staged to Installed begun; RebootPending key createdSetup log, registry
16:30:51Restart requested from the Start menu (System event 1074)System log
16:31:51OS start (System event 12), after shutdown event 13 at 16:31:36System log
16:32:18.687CurrentVersion key written: the label becomes 26300 and 26H2Registry
16:32:28KB5121794 Installed (Servicing event 2)Setup log

The Windows Update client log records the download and no installation event: event 41 appears and no event 19, 43 or 44 follows, so a detection keyed to those installation events does not see an enablement package. The Windows Update history does hold a row for "Windows 11, version 26H2", with result code 2 and client MoUpdateOrchestrator.

Three builds on one host

After the update the host reports three different builds, and only the registry reports the new one. The registry says 26300.9550, the kernel file and the System log say 26100.9549, and the build lab string says 26100.1. System event 12 reported build 26100 at every boot, the 26H2 boot included, because the kernel file did not change. A timeline that infers the Windows version from event 12 reads 25H2 and 26H2 as the same system, and one keyed on the wrong source misdates or misses the update. The Setup log and the servicing store carry the dates. Get-HotFix reports a date without a time, as local midnight.

Telling the two update types apart

The update type is readable from the live host without a baseline. A media upgrade leaves a new Source OS key and a reset InstallDate for the life of the installation, and a Windows.old for the uninstall window only, so the first two markers decide the question once Windows.old is gone.

MarkerMedia upgradeEnablement package
Source OS key under HKLM\SYSTEM\SetupA new key dated at the start of the updateNone added
InstallDateReset at the end of OOBEUnchanged
Windows.oldCreated, kept for the uninstall windowNot created
Setup logssetupact.log and setuperr.log under PantherUpdateAgent.log under Logs\MoSetup
Prefetch, Amcache, BAM, EVTXRebuilt at the swapWritten in place
Per-user registryReplayed into new hives, write times resetNot touched
Restore pointsA removal step is logged; its effect was not measuredKept
BootsSafe OS boot, or an offline apply while the old system runsOne shutdown and one start

An enablement package therefore sets no floor for Prefetch, Amcache, BAM or EVTX. Applying the media-upgrade rules to one discards evidence that exists.

Collection tools need checking against new builds. Of fifteen stock Windows artifacts collected live on Host C after the update, at build 26300, 14 finished; the fifteenth failed with the same two parser messages it had produced before the update. A static review of my own Velociraptor artifact library found 13 artifacts with a version-dependent branch, and one shipped notebook dropped 26200 and 26300 hosts without raising an error, since fixed. Parsers that dispatch on structure work unchanged; code that keys on a build number is where a new build disappears from a collection.

Measuring the two full-swap hosts exposed two collection defects that would each have read as missing evidence. A SRUM collection through the raw NTFS accessor returned 0 rows and no error, because the file search did not pass the accessor on. The raw NTFS reader returned Host A's 2.47 GB Search index database as 392 MB followed by a hole, so every copy failed to open. A collection that returns nothing has to be tested against a source known to hold data before its silence counts.

Where this design comes from

The swap measured above is a design Microsoft has refined for almost twenty years, and it was last described in public in 2011. Each generation changed where the old system goes and how much of it comes back, and each change moved evidence.

Vista: setup becomes an image

Windows Vista replaced the old file-copy installer with image-based setup: a new setup program "performs the installation, applying a Windows Vista image" from a WIM file, and WIM images "are file-based, enabling them to be applied to an existing partition non-destructively" (Michael Niehaus, TechNet Magazine, 2006). Windows.old existed from this era, created by a custom install over an older Windows on the same drive.

Windows 7: a transport, and a gather in Windows PE

Microsoft's own account of the Windows 7 upgrade comes from the Building Windows 8 team in 2011. Setup preserved applications and user files "by moving each file to a transport location", two folders named Windows.~q and Windows.~tr, then moving them back. Registry values were gathered while the old system was still running, and file content "was then gathered offline during the Windows Pre-Installation Environment (Windows PE) phase". Upgrade time grew with the number of files: Microsoft's own chart timed a PC with 1.44 million files at 513 minutes.

Windows 8: Windows.old becomes the transport

The same post describes the redesign that still shapes the volume today. Microsoft "repurposed the 'Windows.old' naming convention" as the single transport, and instead of copying files out, Setup moves whole folders into Windows.old: Windows, Program Files, Program Files (x86), Users and ProgramData. Files were linked rather than moved ("in upgrades to Windows 8, we use hard link operations instead"), the downlevel gather was dropped because "everything we need to preserve can be extracted from the Windows.old folder", and Windows.old was deleted automatically four weeks after a successful install.

That is the folder list Host C's UPGOldOsPieces value still records, and it is why the top-level folders on an upgraded volume carry rename signatures in their $FN attributes. The design is fourteen years old; the MFT on a 2026 Windows 11 host still shows it.

Windows 10: feature updates, shorter windows, less time offline

  • Every feature update became a full in-place upgrade in four phases, with a SafeOS phase in which the PC "is booted into Windows PE" and "an OS rollback is prepared if needed".
  • Version 1607 cut the rollback window from 30 days to 10; Microsoft said it "changed the setting to 10 days to free storage space".
  • Version 1803 added the DISM commands that set that window, and moved "portions of the work done during the offline phases" to the online phase. Microsoft's figures reported at the time put average offline time at 83 minutes for 1703, 51 for 1709 and 30 for 1803.

Windows 11: full swaps and switches

Windows 11 alternates between the two paths. 24H2 "is a full OS swap", while 22H2 to 23H2 and 24H2 to 25H2 are enablement packages that share "an identical set of system files" and need "a single restart". Setup can also skip the Safe OS boot entirely: Anoop Nair documented physical machines that "skipped the Safe OS phase" under a setting called NEO, and Host B's log records the same decision. Microsoft has not documented it.

Two things this history does not settle. No current Microsoft page says whether Windows 10 and 11 still link files into Windows.old or move them. Host B answers it for its end state: collected 20 minutes after Setup finished, the control records show carried files with no copy left inside Windows.old, and rebuilt files with their old copy there. And no source describes how the per-user registry is replayed into new hives; the measurements in the registry section are, as far as I can find, the first public description of what that replay keeps and drops.

Windows.old, and what outlives it

Windows.old holds the old copy of the sources the upgrade rebuilt, for 10 days by default. The window is configurable from 2 to 60 days with DISM /Set-OSUninstallWindow. On Host B, collected inside the window, it returned 233 Prefetch files reaching back five years, 398 event logs, 14 setupapi logs, the five machine hives and each profile's old NTUSER.DAT and UsrClass.dat.

The Windows.old hives are the state at shutdown, not a snapshot from before Setup started. Windows 10 kept running for 46 minutes of the upgrade and kept writing: 68 of 83 BAM entries in the old hive were written during the upgrade window. Setup also wrote the DeviceMigration store into the old SYSTEM hive during its gather phase, so that store, read from Windows.old, was created by the upgrade too.

On Host B Setup moved its own working folder, including the Panther logs of the upgrade, into Windows.old. The upgrade's own record there lasts exactly as long as Windows.old. Setup's log also records a step named "Remove System Restore checkpoints"; what that step deletes was not measured.

After the window, the old system survived only as deleted MFT records. On Host A no pre-upgrade copy remained: Windows.old was gone, and the oldest Volume Shadow Copy store was created four days after the swap. A complete whole-volume carve, 2 h 38 min on a 931 GiB NVMe drive, recovered no Prefetch file or event log from before the upgrade. Every carved Prefetch run time postdates the swap. The E01 set was 194 GiB for 244 GiB allocated, so the unallocated space was stored as zeros, which is the signature of blocks the drive had discarded through TRIM.

The MFT is the exception, because TRIM does not touch it. Recycle Bin $I records are small enough to live inside the MFT record, and the carve's MFT phase returned 63 of the subject's deletions from before the upgrade, each with its original path, size and deletion time, reaching back 17 months. 32 of them are Word AutoRecovery files deleted within the same two seconds.

How long Windows.old lasts

Windows.old lasts for the uninstall window plus the wait for the next cleanup run that acts, so its lifetime is a bound and never a date. Microsoft's default window is 10 days, configurable from 2 to 60 days with DISM /Set-OSUninstallWindow or with the policy Update/ConfigureFeatureUpdateUninstallPeriod. The window only makes the folder eligible: a cleanup run has to find it eligible and delete it, and that run can come days later.

The two full-swap hosts kept it for 12 and 42 days. Host C ran the 10-day default: its policy store holds only the shipped default entry, no applied policy overrides it, and Windows.old was gone about 12 days after the swap. Microsoft's server-side configuration can still change the window and leaves no trace on the host, so 10 days is the configured value and the deletion timing agrees with it. Host A ran a 30-day window set by policy: its cleanup task logged 30 on each of its 13 runs and named the policy store as the source, and the host carries device-management enrollment tasks, which is how such a policy arrives. Its folder lasted 42 days because the host was barely used. The cleanup task ran 13 times between 30 July and 12 August, the volume then gained at most 75 new files a day until 1 September, and the run that deleted the folder came on 6 September.

Two logs date the deletion, and both write local time without an offset marker, so subtract the host's UTC offset. The setup cleanup log records the move to Scratch Reserves and the deletion to the second, with the window and the source of the window. The Disk Cleanup session log brackets the deletion by the last session that found Windows.old and the first that reports it missing. The task that deletes the folder removes itself afterwards, so its definition is missing on every host examined, and disabling it would not protect the folder: Disk Cleanup, Storage Sense, the Temporary files page in Settings, DISM /Remove-OSUninstall, "Go back", a reset and the next feature upgrade each remove or replace Windows.old by another route. The supported way to keep it longer is a larger window, up to 60 days.

Observations against the literature

Eight observations were checked against published rules, and seven are explained or supported by them. The eighth, the apparent profile-before-system order, was resolved by measurement. The table gives each verdict and what the sources support. The NTFS rules are those of Bouma et al. and of Galhuber and Luh, listed in the references.

ObservationVerdictExplanation
The same $SI birth, identical to 100 ns (2024-04-01 07:21:16.1844348 UTC), on Host A and Host C, and later on Host B. On Host A, new records sit in reused MFT slots with sequence number 2 or higher (130,367); on Host C, which applied its image under the running system, 44,490 of 44,545 sit in first-use slots (sequence 1).Consistent, but unsourced for Windows; per-entry WIM timestamps are documented by wimlibThe image stores per-entry times at 100 ns and Setup restores them (inferred). On the Safe OS path, sequence 2 in the staging band marks a fresh allocation into slots the staging deletion freed; the test does not apply to an image applied under the running system.
$SI birth equals $FN birth at the swap: Prefetch, event logs, the profile, the hivesConfirmed by the create rule; the recreation of event logs was published by az4n6 and KobzarCreated at that instant, never stamped, never renamed.
All four $FN times at one instant, $SI birth from the image: System32, the SYSTEM hiveConfirmed as a rule by Bouma et al. and by FILE_BASIC_INFORMATION; Setup's use of it is unsourcedCreated, then $SI stamped through the API, never renamed afterwards.
$FN birth equals the image $SI birth, other $FN times on the swap day: C:\Windows, C:\Users, the SRUM databaseConfirmed by the rename ruleStamped or old, then renamed or moved; the $FN values are the last $SI state before the move.
Nine folders under the new profile with older $FN times; Desktop and Documents with swap-time $FNThe moves are confirmed by the move rule; Desktop and Documents are consistent with a create followed by SetFileTimeThe nine were moved while their $SI held the older values; the two were recreated with their birth time restored.
New hives at the swap; activity keys replayed with pre-upgrade times inside their values; MountPoints2 not carriedPartly confirmed: the MountPoints2 loss was published by Kobzar; the carrying of UserAssist, RecentDocs and ShellBags shows that Microsoft's USMT component list is not the in-place upgrade's listNew hive files populated by the migration engine's per-user apply: content carried, write times reset.
The rebuilt profile apparently created before the system files it runs onResolved by measurement: the offline phase wrote UTC+3 local time as UTCCorrected, the order matches Microsoft's documented phase order.
Whole-volume classes of new, moved and kept records; Setup logs absent; Source OS key present; no Windows.old on Host CConsistent with the move rule, Microsoft's log locations, Source OS behavior and the uninstall retentionFolders were moved rather than files copied. Why some new records were stamped from the image and others were not has no published explanation.

Eight rules for an examiner

  1. Establish whether and when the host was upgraded before reading any absence as a finding. The Source OS keys under HKLM\SYSTEM\Setup, InstallDate, BuildLabEx against CurrentBuild, and the $FN birth of each NTUSER.DAT answer it.
  2. Tell an enablement package from a media upgrade before setting any floor. A changed build label with no new Source OS key, no Windows.old and an InstallDate older than the change marks an enablement package, which sets no floor for Prefetch, Amcache, BAM or EVTX.
  3. Read the Setup path before correcting any offline timestamp. A user hive born before the first event log marks an image applied under the running old system, with true UTC stamps. A user hive born after the new kernel started marks a Safe OS apply, whose offline stamps run ahead by the host's UTC offset.
  4. Treat a media upgrade as a hard floor for Prefetch, PCA, BAM, EVTX, setupapi and scheduled tasks, and for the write time of every per-user registry key. Check Amcache, which was rebuilt on two hosts and carried on one. Report absences before the floor as "not recorded", not "did not happen", and date replayed keys by the timestamps stored inside UserAssist and Office MRU values.
  5. Take pre-upgrade USB and network history from DeviceMigration and NetworkList, dated by the values inside them, not by key write times.
  6. Reach behind the upgrade with the carried sources: jump lists, LNK files, browser stores, SRUM, the Search index, Windows Timeline, the Recycle Bin, and the embedded times in UserAssist and the Office MRU.
  7. Check for a recent upgrade before touching the machine, then collect Windows.old and $WINDOWS.~BT first, with the same artifact set as the live system. Check shadow copies for any store inside the retention window. When the copies are gone, carve deleted MFT records. Image a powered-off host write-blocked instead of booting it.
  8. Subtract the host's UTC offset from offline-phase records only when Setup booted into Safe OS and the hardware clock held local time, after confirming the time zone in force that day and which records the offline phase wrote. Exclude image-stamped $SI births from anomaly rules, and never read the $SI birth of a system file as a host event.

Key takeaways

  1. An upgrade is part of the case. A media update rebuilt Prefetch, BAM, PCA, every event log and the task files on the hosts measured, and Amcache on two of three, and every collector still parses them. They start on the upgrade day, so establish whether and when the host was upgraded before reading any absence.
  2. Classify the update before setting a floor. The 26H2 enablement package recreated no event log, hive, Prefetch or Amcache file on Host C. Applying the media-upgrade floors to it throws away evidence that exists.
  3. Ask which clock wrote each timestamp. The offline phase wrote local time as UTC on one Setup path and true UTC on the other. Install-image births are Microsoft's build dates, identical to 100 ns on unrelated hosts. A registry key's write time after an upgrade is the migration's, not the user's.
  4. Date replayed registry content from its values. 7,518 of 7,613 per-user key write times on Host C and 7,037 of 7,114 on Host A are the replay, counted across every profile hive, the Default and service-account hives included, while the times stored inside UserAssist, the Office MRU, DeviceMigration and NetworkList survive.
  5. Treat Windows.old as perishable evidence with an unknown deadline. It lasted 12 and 42 days, set by a default, a policy or a server-side value the host does not show, plus the wait for a cleanup run. Live triage, live imaging or a boot to look around can cost the only pre-upgrade copy. On an SSD that honors TRIM, carving free space returned nothing from before the swap, while deleted MFT records survived because TRIM does not touch the MFT.
  6. Read the evidence Setup writes about itself. DeviceMigration, the Source OS keys, CloneTag, the volume root's $SI birth and the cleanup logs outlive Windows.old. On Host A the surviving USB history came from DeviceMigration and not from USBSTOR.
  7. Check what your collection reads before trusting its silence. Most built-in artifacts and target sets read the live paths only, and as of October 2026, none of RECmd's batch files, RegRipper 4.0, Velociraptor's built-in and exchange artifacts, Plaso or ForensicArtifacts parses DeviceMigration, and KAPE only collects the hive. Code keyed on a build number can drop new-build hosts without an error.
  8. Separate the upgrade from ordinary ageing. The two full-swap hosts received the same verdict for every source measured. Their surviving content differs (1 against 112 UserAssist values with a run time before the swap, 0 against 401 kept Recent LNK files, counted across all profiles) because of 21 months against six weeks of use after the swap.
  9. An observation that fits both hypotheses decides nothing. Setup's removal of restore points was first read as proof that it takes no snapshot, which fits the opposite reading equally well. For every "X did not happen", ask what the evidence would look like if X had happened.
  10. Check that a source covers the window, and tell a zero from a tool that did not run. A Setup log extract that began 15 minutes into the upgrade and an MFT search that missed a file present on the host each produced a confident negative. A SRUM feeder returned 0 rows with no error. Each would have read as missing evidence.

References

Earlier DFIR work on upgrades documented the consequences. Credit where it is due: each of these was first to publish its finding.

Prior DFIR research

NTFS timestamp rules

History of the upgrade design

Microsoft