Windows artifacts · Lesson 8 of 9
SRUM and other activity databases
10 min read
Windows keeps several databases that were built for performance reporting, search and user convenience, not for auditing, yet they record which programs ran, how much data they moved, which files existed and what messages appeared on screen. This lesson covers the System Resource Usage Monitor (SRUM), the Windows Search index, the Timeline database and the notifications database on Windows 10 and 11: where each one sits in a triage collection, how to open it safely and how to state what it proves.
SRUM: what it is and where it lives
SRUM was introduced in Windows 8 to feed the battery, app history and data usage views in Settings and Task Manager. It is hosted by the Diagnostic Policy Service and samples, per application and per user, how much CPU time, disk I/O, network traffic and energy each program consumed.
The data is stored in C:\Windows\System32\sru\SRUDB.dat, an Extensible Storage Engine (ESE) database. ESE, also called JET Blue, is the transactional database engine behind Active Directory, the Windows Search index and Microsoft Exchange. Like any ESE database it works with companion files in the same folder: a checkpoint file SRU.chk, transaction logs SRU.log and SRUnnnnn.log, SRUtmp.log and reserved logs SRUres*.jrs. Changes are written to the logs first and applied to the database later.
Two consequences follow for a triage collection, where files are copied with their original paths rather than imaged:
- Copy the whole
srufolder, not onlySRUDB.dat. The file is locked while Windows runs, so collectors use raw NTFS access to copy it. - Expect a "dirty" database. A database copied from a running system is usually in the Dirty Shutdown state because log records have not been applied. Check with
esentutl /mh SRUDB.datand read theState:line. To bring it to a clean state, work on a copy of the folder on a Windows analysis workstation and runesentutl /r sru /iinside it, wheresruis the log base name and/iignores mismatched attached databases. Never useesentutl /p(repair) as a first step: it discards data it cannot reconcile. Some parsers recover the database themselves; others refuse a dirty file.
SRUM also has a buffer stage. Recent measurements are kept in memory and in the SOFTWARE hive under SOFTWARE\Microsoft\Windows NT\CurrentVersion\SRUM\Extensions, and are written to SRUDB.dat roughly once an hour. The last hour or so before collection may therefore be absent from the database. Typical retention in the main tables is about 30 to 60 days; older rows are purged, so the earliest record shows how far back the evidence reaches on that system.
SRUM tables
Each SRUM data table is named by a GUID. Each row carries an AutoIncId, a TimeStamp, an AppId and a UserId. The last two are integers, not names: they resolve through SruDbIdMapTable, whose columns are IdType (the kind of entry: application, service or user SID), IdIndex (the integer referenced by other tables) and IdBlob (the value). Application paths are often stored in device form such as \device\harddiskvolume3\users\ana\appdata\local\microsoft\onedrive\onedrive.exe, and user IDs resolve to a binary SID that tools render as S-1-5-21-…-1001. Lesson 2.2 covers mapping a SID to an account and profile.
| Table | GUID | Key columns | Typical question |
|---|---|---|---|
| Application Resource Usage | {D10CA2FE-6FCF-4F6D-848E-B2E99266FA89} | ForegroundCycleTime, BackgroundCycleTime, ForegroundBytesRead, ForegroundBytesWritten, Background equivalents | Did this program run under this user, and how heavily? |
| Network Data Usage | {973F5D5C-1D90-4944-BE8E-24B94231A174} | InterfaceLuid, L2ProfileId, BytesSent, BytesRecvd | How much did this program send or receive, and over which network? |
| Network Connectivity | {DD6636C4-8929-4683-974E-22C046A43763} | InterfaceLuid, L2ProfileId, ConnectedTime, ConnectStartTime | When and how long was the machine connected to a network? |
| Energy Usage | {FEE4E14F-02A9-4550-B5CE-5FA2DA202E37} (and a long-term "LT" variant) | Charge levels, cycle count, AC/battery state | Was the laptop on battery or charging at a given time? |
Cycle times are CPU cycles, not seconds, so compare them between applications rather than converting them to a duration. InterfaceLuid is a 64-bit value whose top 16 bits hold the IANA interface type: 6 is Ethernet and 71 is IEEE 802.11 wireless. L2ProfileId identifies the wireless or wired profile and can be matched to a network name using the WLAN profile data in the SOFTWARE hive; parsers such as SrumECmd accept the SOFTWARE hive for this reason (for example SrumECmd -f SRUDB.dat -r SOFTWARE --csv out). Mark Baggett's srum-dump is another free parser that produces a spreadsheet.
What a SRUM timestamp means
TimeStamp is stored as an ESE date-time value (an OLE Automation date: days since 1899-12-30 as a floating-point number) in UTC. It marks the end of a collection interval, not the moment of activity, and every counter in the row is a total for that interval. A row with TimeStamp 10:00:00Z, where the previous row for the same table ended at 09:00:00Z, says the activity happened somewhere between 09:00 and 10:00. It does not say when within that hour, in how many sessions, to which destination, or which files were involved. Always look up the previous TimeStamp in the same table, because intervals are not guaranteed to be exactly 60 minutes, for example after a restart.
Worked example: a possible exfiltration
A case asks whether a user uploaded a large volume of data on 14 March 2026. After replaying the logs, the Network Data Usage table contains this row:
| Field | Value |
|---|---|
| TimeStamp | 2026-03-14T10:00:00Z (previous row for this table: 09:00:00Z) |
| AppId → IdBlob | \device\harddiskvolume3\users\ana\appdata\local\microsoft\onedrive\onedrive.exe |
| UserId → IdBlob | S-1-5-21-…-1001 (profile C:\Users\ana) |
| InterfaceLuid | 0x0047000004000000 (top 16 bits 0x0047 = 71, wireless) |
| BytesSent | 1,288,490,188 |
| BytesRecvd | 41,936,212 |
Converting the volume. In binary units, 1,288,490,188 / 1,073,741,824 = 1.20 GiB, and 1,288,490,188 / 1,048,576 = 1,228.8 MiB. In decimal units it is 1,288.49 MB, or 1.29 GB. State which convention you use, or give the exact byte count, because reports and exam questions depend on exact values.
Reading the interval. The bytes were sent between 09:00:00Z and 10:00:00Z. Spread evenly over the hour, that is 1,288,490,188 × 8 / 3,600 = about 2.86 Mbit/s; the real transfer could have been shorter and faster. The ratio of sent to received bytes (about 30:1) fits an upload, not a download or a sync from the cloud.
Stating the finding. "SRUM records that onedrive.exe, running under the account with SID S-1-5-21-…-1001 (profile ana), sent 1,288,490,188 bytes (about 1.2 GiB) over a wireless interface in the collection interval ending 2026-03-14T10:00:00Z; the preceding interval ended at 09:00:00Z." This wording claims nothing about destination, content or who was physically at the keyboard.
Corroborating. Look for the same transfer elsewhere: the sync client's own logs in the user profile, the browser history if a web upload is suspected (Module 4), firewall, proxy or cloud tenant audit logs that show destination and file names, the NTFS USN journal for files created or moved into the synced folder before 10:00 (Lesson 1.4), and the Application Resource Usage row for the same AppId and interval, which should show matching activity. Lesson 2.3 covers execution artifacts that place the program on the system.
Windows Search index
The Windows Search service indexes file names, paths, metadata such as size, dates and author, and for many file types extracted text. On Windows 10 the index is C:\ProgramData\Microsoft\Search\Data\Applications\Windows\Windows.edb, another ESE database with its own MSS*.log files, so the same collection and recovery rules apply. Recent Windows 11 builds replaced it with SQLite files, such as Windows.db and companion .db files, in the same folder.
The index can answer "did a file with this name exist in this user's folders, and what did it contain?". Properties such as the auto-summary can hold a text snippet of the document. Entries for deleted files may remain until the indexer processes the deletion, and deleted ESE or SQLite records can sometimes be carved. The index covers only indexed locations, by default the user profiles and Start menu, plus indexed mail.
Windows Timeline: ActivitiesCache.db
From Windows 10 version 1803, the Timeline feature recorded user activity in %LOCALAPPDATA%\ConnectedDevicesPlatform\<id>\ActivitiesCache.db, a SQLite database. The <id> folder is named after the account, for example L.ana for a local account. The Activity table holds AppId (JSON listing the application identifiers), Payload (JSON with details such as a displayed file or page name, and for focus records the active duration), ActivityType, and StartTime, EndTime, LastModifiedTime and ExpirationTime as Unix epoch seconds. Zimmerman's WxTCmd parses it.
Microsoft stopped syncing activity history to the cloud and Windows 11 does not include Timeline. Treat this database mainly as a Windows 10 artifact: on Windows 11 it may be absent or contain little.
Notifications database
%LOCALAPPDATA%\Microsoft\Windows\Notifications\wpndatabase.db is a SQLite database of toast notifications. The Notification table stores each toast's XML Payload, which often contains message or email previews, with ArrivalTime and ExpiryTime as FILETIME values; NotificationHandler maps the handler to the application. A preview can show a message that was later deleted from the application itself.
For every SQLite database in this lesson, collect the -wal and -shm files next to it. Recent changes may exist only in the write-ahead log, and opening the database without it shows an older state.
Summary of the databases
| Database | Path | Format | What it answers | Retention and caveats |
|---|---|---|---|---|
| SRUM | C:\Windows\System32\sru\SRUDB.dat | ESE | App and user resource use, network bytes, connectivity, energy | About 30–60 days; hourly flush; often dirty; interval totals |
| Search index (Win 10) | C:\ProgramData\Microsoft\Search\Data\Applications\Windows\Windows.edb | ESE | Names, paths, metadata and text of indexed files | Indexed locations only; often dirty |
| Search index (recent Win 11) | Same folder, Windows.db and companions | SQLite | As above | Collect all companion files |
| Timeline | %LOCALAPPDATA%\ConnectedDevicesPlatform\<id>\ActivitiesCache.db | SQLite | Apps and documents used, with start and end times | Mainly Windows 10 (1803+); expires after about 30 days |
| Notifications | %LOCALAPPDATA%\Microsoft\Windows\Notifications\wpndatabase.db | SQLite | Toast previews and arrival times | Short-lived; collect WAL |
Exam focus: Expect to resolve a SRUM AppId or UserId through SruDbIdMapTable, report BytesSent or BytesRecvd for a given application and interval, and convert bytes to MiB or GiB. Know that the SRUM TimeStamp is the end of an interval in UTC and that the database may need log replay before parsing. You may also be asked which database would hold a deleted file's name or a notification preview on a given Windows version.
Key points
- SRUDB.dat is an ESE database; copy the whole
srufolder and replay the logs on a copy (esentutl /r sru /i) when it is dirty. - Data reaches SRUDB.dat from the SOFTWARE hive about hourly, so the last hour may be missing; retention is typically 30 to 60 days.
- AppId and UserId are integers resolved through SruDbIdMapTable; Network Data Usage gives BytesSent and BytesRecvd per app, user and interface.
- A SRUM TimeStamp marks the end of the collection interval and values are interval totals; state findings as "in the interval ending at T".
- The Search index (Windows.edb, or SQLite in recent Windows 11 builds) can hold names and content of deleted files; ActivitiesCache.db is mainly Windows 10; wpndatabase.db holds notification previews.