Chapter 14

BAM, DAM, and SRUM

Background Activity Moderator (BAM), Desktop Activity Moderator (DAM), and System Resource Usage Monitor (SRUM) are modern Windows artifacts that record execution evidence and resource usage — often providing timestamps and details not available from Prefetch or Amcache.

Scenario

An attacker ran a data collection tool as a background process (no visible window, running under a service account) over a weekend. Prefetch wasn't capturing it (disabled on Server OS). Amcache.hve has the entry but only records the first run. You need to know the exact dates the tool ran. BAM has the answer: it records the last execution time of every executable per user account, including service accounts and system processes. SRUM adds network and CPU usage by application — you can see exactly how much data the collection tool transmitted to an external IP.

Background Activity Moderator (BAM)

BAM is a Windows 10 (version 1709+) feature that throttles background applications. As a side effect, it maintains a registry record of every executable that was run in the background, per user account.

  BAM Registry Location
  ═══════════════════════════════════════════════════════════════════

  HKLM\SYSTEM\CurrentControlSet\Services\bam\State\UserSettings\{SID}

  One subkey per user SID, containing:
    ├── Value name:  full path of the executable
    └── Value data:  binary data containing last execution timestamp
                     (FILETIME format — 8 bytes)

  Coverage:
    ✓ Background processes (services, scheduled tasks)
    ✓ Processes running under any user account
    ✓ Executables from removable media (full original path preserved)
    ✗ Only last run time per executable (not run count, not all runs)
    ✗ Windows 10 version 1709+ and Windows Server 2016+ only

  Retention: BAM entries persist across reboots.
             They are flushed periodically (~7 days idle on some versions)
             but in practice often contain months of history.
PowerShellbam-extract.ps1
# Extract BAM entries from live system or offline SYSTEM hive
# For offline hive, load it first or use RECmd with a batch file

$bamBase = "HKLM:\SYSTEM\CurrentControlSet\Services\bam\State\UserSettings"

Get-ChildItem $bamBase | ForEach-Object {
    $sid = $_.PSChildName
    # Resolve SID to username
    try {
        $username = ([System.Security.Principal.SecurityIdentifier]$sid).Translate([System.Security.Principal.NTAccount]).Value
    } catch {
        $username = $sid
    }

    # Each value is a file path with binary timestamp data
    $_.GetValueNames() | Where-Object { $_ -match "\\" } | ForEach-Object {
        $exePath = $_
        $rawBytes = $_.PSProvider.GetValue($null, $exePath, $null)

        # First 8 bytes are FILETIME — convert to datetime
        if ($rawBytes -and $rawBytes.Length -ge 8) {
            $fileTime = [BitConverter]::ToInt64($rawBytes[0..7], 0)
            $dt = [DateTime]::FromFileTimeUtc($fileTime)

            [PSCustomObject]@{
                User      = $username
                SID       = $sid
                ExePath   = $exePath
                LastRun   = $dt
            }
        }
    }
} | Sort-Object LastRun -Descending | Format-Table -AutoSize

System Resource Usage Monitor (SRUM)

SRUM is an ESE (Extensible Storage Engine) database at C:\Windows\System32\SRU\SRUDB.dat that records hourly summaries of resource usage by application — CPU time, RAM, network bytes sent/received, per user account.

  SRUM Database — Key Tables
  ═══════════════════════════════════════════════════════════════════

  {D10CA2FE-...} — Network Connectivity table:
    ├── App (application path)
    ├── UserId (user SID)
    ├── TimeStamp (hour boundary)
    ├── BytesSent
    ├── BytesRecvd
    ├── InterfaceLuid (which network interface)
    └── ProfileName (WiFi network name, if applicable)

  {5C8CF1C7-...} — Network Usage table:
    ├── App
    ├── UserId
    ├── TimeStamp
    ├── BytesSent, BytesRecvd
    └── L2ProfileId (network profile)

  {97C2CE28-...} — Application Resource Usage:
    ├── App
    ├── UserId
    ├── TimeStamp
    ├── ForegroundCycleTime
    ├── BackgroundCycleTime
    ├── ForegroundContextSwitches
    └── BackgroundContextSwitches

  Forensic value: per-hour network bandwidth by application
    → Large BytesSent by an unusual process = exfiltration evidence
    → Even if the process is deleted, SRUM records its historical usage
    → App paths preserved exactly — reveals original paths of deleted tools
Batchsrum-parse.bat
:: Parse SRUM database with SrumECmd (Eric Zimmermann)

:: SRUM must be copied while live or shadow-copied — it's locked during use
:: KAPE automatically handles the locked file via VSS or raw copy

SrumECmd.exe ^
  -f "D:\evidence\C\Windows\System32\SRU\SRUDB.dat" ^
  --csv "D:\analysis\srum" ^
  -r "D:\evidence\C\Windows\System32\config\SOFTWARE"

:: -r: path to SOFTWARE registry hive (needed to resolve app names/SIDs)
:: Output CSVs:
::   srum_NetworkConnections.csv  — hourly network usage per app
::   srum_NetworkUsages.csv
::   srum_AppResourceUseInfo.csv  — CPU/memory usage per app
PowerShellsrum-exfil-hunt.ps1
# Hunt for data exfiltration evidence in SRUM network data
$srum = Import-Csv "D:\analysis\srum\srum_NetworkConnections.csv"

# Find applications with abnormally high outbound data
$srum | Where-Object {
    [int64]$_.BytesSent -gt 100MB  # > 100 MB in a single hour period
} | Select-Object TimeStamp, ExeInfo, UserId, BytesSent, BytesRecvd |
  Sort-Object BytesSent -Descending |
  Format-Table -AutoSize

# Look for known attacker tool paths in SRUM
$srum | Where-Object {
    $_.ExeInfo -match "\\Temp\\" -or
    $_.ExeInfo -match "\\AppData\\Roaming\\" -or
    $_.ExeInfo -match "\\Users\\Public\\"
} | Select-Object TimeStamp, ExeInfo, BytesSent, BytesRecvd |
  Sort-Object TimeStamp |
  Format-Table -AutoSize

# Cross-reference: executables with large BytesSent that no longer exist
$srum | Where-Object { [int64]$_.BytesSent -gt 10MB } |
  ForEach-Object {
    $path = $_.ExeInfo
    if ($path -match "^[A-Z]:\\" -and !(Test-Path $path)) {
        $_ | Select-Object TimeStamp, ExeInfo, BytesSent
    }
  } | Format-Table -AutoSize

Combining BAM + SRUM + Prefetch for a Complete Picture

ArtifactWhat it adds
BAMLast run time for each executable, per-user. Works on servers where Prefetch is disabled. Captures service accounts and background processes Prefetch misses.
SRUM NetworkHourly network bandwidth by application. Quantifies exfiltration. Persists even after the executable is deleted.
SRUM App UsageCPU/memory usage by application. Confirms execution (process actually consumed resources, not just launched and killed). Background vs foreground split reveals stealth.
PrefetchAll run timestamps (up to 8), run count, loaded DLL list. Most complete for workstation execution history.
AmcacheSHA-1 hash — links the execution to a specific binary for VT lookup and attribution.

Q & A

Q: How far back does SRUM data typically go? Can you use it for a historical investigation?

SRUM retains data for approximately 30-60 days depending on system activity and database size limits (default max 500 MB). After that, older entries are purged to make room for new ones. For investigations where the attack happened more than 60 days ago, SRUM data may be gone or incomplete. The best source for older SRUM data is VSS — Volume Shadow Copies may contain older versions of SRUDB.dat from before the purge cycle. If the organization runs regular VSS snapshots (e.g., weekly), you may be able to access a SRUM database from 2-3 months prior by mounting an older shadow copy. For very old historical investigations, SRUM likely won't be available, and you'll need to rely on SIEM logs, EDR telemetry history, and alternative artifacts like Amcache (which has longer retention in some configurations).