Network connection history: the RegRipper networklist plugin
8 min read
When the question is "what networks has this machine joined, and when", the answer is in the SOFTWARE hive, and the RegRipper networklist plugin is the tool that reads it. Windows keeps a durable list of every network profile the machine has connected to: the wired LANs, the corporate domains, and crucially the wireless SSIDs. Each profile carries a created timestamp and a last-connected timestamp, and a parallel set of keys ties those profiles to the physical gateway MAC address that was on the wire at the time. That last detail is what turns the network profiles list from "an inventory" into "a geolocation and movement trail".
Where it lives
There are two cooperating locations under the SOFTWARE hive. The plugin's primary path is:
SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkList\Profiles\<GUID>
Each network the machine has connected to gets one subkey named with a profile GUID. Under that GUID the values that matter are ProfileName, Description, Category, DateCreated, and DateLastConnected. The networklist plugin enumerates those Profiles subkeys and pulls exactly those values for each one.
The second location is the signatures store:
SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkList\Signatures\Unmanaged
SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkList\Signatures\Managed
Unmanaged holds signatures for networks the machine joined on its own (home Wi-Fi, coffee-shop hotspots, anything not pushed by Group Policy). Managed holds the domain-pushed profiles. The signature subkeys cross-reference the Profiles GUIDs and add the field the Profiles key does not carry: the gateway MAC under a DefaultGatewayMac value, plus a FirstNetwork value that usually mirrors the human-readable name. The classic RegRipper plugin walks both stores and joins them on the GUID. Worth confirming against the plugin source for the exact value names your version reads, because the Signatures-side names have shifted across Windows builds.
What each profile records
For a single profile, the useful fields are:
ProfileName— the display name of the network. For a wireless network this is the SSID. For a wired or domain network it is the network name Windows assigned ("Network", "Network 2", or the AD domain name). This is the field that answers "which Wi-Fi did this laptop connect to".Description— usually a copy of the profile name, sometimes the adapter or domain description.Category— an integer firewall-profile classification:0= Public,1= Private,2= Domain. The category tells you how the machine treated the network, which in turn tells you something about where it was. A laptop that has aDomainprofile forcorp.example.comwas physically (or VPN-tunnelled) onto that domain network at least once.DateCreated— when this profile was first established, i.e. the first time the machine joined this network.DateLastConnected— the most recent time the machine connected to it.
The site's parser surfaces these as a table with columns Profile, Description, Category, First connected, Last connected, and the key's last-written time. The first/last-connected columns are derived from DateCreated and DateLastConnected, and that derivation is where most homegrown tools get it wrong.
The SYSTEMTIME gotcha
DateCreated and DateLastConnected are not FILETIMEs. Reach for the eight-byte little-endian FILETIME parse you use everywhere else and you will get garbage dates, or you will reject the value as malformed. These two values are 16-byte SYSTEMTIME structures.
A SYSTEMTIME is a struct of eight 16-bit fields, each stored little-endian:
Offset Field
0x00 wYear
0x02 wMonth
0x04 wDayOfWeek
0x06 wDay
0x08 wHour
0x0A wMinute
0x0C wSecond
0x0E wMilliseconds
So a correct decode reads wYear from offset 0, wMonth from offset 2, skips wDayOfWeek at offset 4, reads wDay from offset 6, then hour, minute, second from 8, 10, 12. That offset-4 skip is the single most common parsing bug: read the day from offset 4 instead of 6 and every date is off, because offset 4 is the day-of-week index, not the day of month.
This is exactly the layout the parser on this site implements: it pulls the year at offset 0 as a little-endian uint16, sanity-checks it falls between 1601 and 9999, then reads month at 2, day at 6, and hour/minute/second at 8/10/12. A year outside the valid range means the blob is not a SYSTEMTIME (or the value is absent), and the field is left blank rather than guessed.
Two consequences for your reporting:
- No timezone. A SYSTEMTIME carries no UTC flag. These timestamps are written in local time as the machine understood it at the moment of connection. If the machine moved across timezones (and a laptop with a Wi-Fi history almost certainly did), the local-time stamps were each written against whatever the box's timezone was set to then. Reconcile against the machine's
TimeZoneInformationin the SYSTEM hive, and remember that historical timezone changes are not recorded here. - Millisecond and day-of-week precision exists but is rarely useful. You can read
wMillisecondsandwDayOfWeekif you want a cross-check: compute the day-of-week from the parsed date and compare it to the storedwDayOfWeek. A mismatch is a strong signal the blob is corrupt or you parsed it at the wrong offset.
Contrast this with the key's own LastWrite time, which is a FILETIME in UTC, and which the parser reports separately as "Key last written". When DateLastConnected and the key's LastWrite disagree significantly, treat the SYSTEMTIME as authoritative for the connection event and the LastWrite as "last time anything in this key changed".
The gateway MAC: the part that geolocates
The Profiles key tells you the machine joined a network called "HOME-5G" on a given date. By itself that is weak: SSIDs are not unique, and an attacker who renames a hotspot to match a known SSID can muddy it. The Signatures store is what hardens it. Under Signatures\Unmanaged\<sig> (and the Managed equivalent) Windows stores the default gateway MAC address that was seen on that network — the physical layer-2 address of the router the machine talked to.
That MAC is a pivot in two directions:
- Geolocation. Wireless gateway MAC addresses (BSSIDs) are catalogued by the large Wi-Fi positioning databases used by every phone for location. A gateway MAC recovered from
Signatures\Unmanagedcan sometimes be resolved to a physical location via a BSSID lookup service. That converts "this laptop joined some network in March" into "this laptop was at this street address in March". Handle that capability with the legal care it deserves, but know it exists. - Correlation across machines. If two machines in your investigation both list the same gateway MAC for a network, they were on the same physical LAN. SSIDs can collide by accident; a full gateway MAC matching across hosts is strong evidence of co-location on the same network segment.
The MAC plus ProfileName plus DateLastConnected is the triple that answers the movement question. The category field adds context: a Public profile with a consumer-router gateway MAC and an SSID like "Starbucks" reads as "user took the laptop to a coffee shop". A Domain profile reads as "user was on the corporate network".
Reading it in practice
A profile row, assembled across the Profiles and Signatures keys, looks like:
ProfileName: CORP-WIFI
Category: Domain (2)
DateCreated: 2025-11-03 09:14:22 (local)
DateLastConnected: 2026-06-15 08:41:07 (local)
DefaultGatewayMac: 00:1A:2B:3C:4D:5E
That single row says: this machine first joined the network "CORP-WIFI" in early November, was treated as a domain-joined connection, last connected the morning before acquisition, and was talking to a specific router. Pull the matching SSID against the Unmanaged store for any non-domain networks, and you have the full join history.
The persistence of this data is the point. Profiles accumulate. Windows does not prune them on its own, so a multi-year-old laptop carries a DateCreated for networks it touched once years ago. Deleting a network profile through the GUI removes the Profiles subkey, but recovery of deleted cells from the hive's unallocated space (RegRipper's del plugin, or yarp's recovery) will often resurrect the GUID and its values.
One acquisition caveat: like every registry artifact, the live DateLastConnected updates whenever the machine reconnects, overwriting the prior value. Grab the SOFTWARE hive at a known time and treat it as a snapshot. If VSS is available, earlier snapshots give you a history of DateLastConnected changes — see which registry hive to grab for acquisition specifics.
Tools
- RegRipper's
networklistplugin. Enumerates the Profiles GUIDs, decodes theDateCreated/DateLastConnectedSYSTEMTIME blobs, reports the category, and joins to the Signatures store for the gateway MAC. The plugin source is the authoritative reference for which Signatures-side value names your Windows build uses. See the RegRipper plugins reference for the broader plugin set. - Eric Zimmerman's Registry Explorer / RECmd with a NetworkList batch file produces the same profile table in CSV, including the SYSTEMTIME decode.
- The parser on this site decodes
networklistdirectly in the browser — analyze a SOFTWARE hive in your browser and the network profiles surface as a table with first/last connected already parsed from the SYSTEMTIME fields, no upload required.
Whatever tool you use, verify it reads wDay from offset 6 and not offset 4. The fastest way to catch a broken SYSTEMTIME parser is to find a profile whose first-connected date you can corroborate from another artifact (a Wi-Fi event log, a VPN connection log) and check the day matches. If every date is internally consistent but off by a few days, the offset-4 day-of-week bug is the first suspect.
networklist will not tell you what the machine did on a network — that is for the event logs and the application artifacts. But for the questions "where has this machine physically been" and "what networks did it join, and when", it is the single best registry source, and the gateway MAC under Signatures is the value that makes it forensically heavy rather than merely informational.