Skip to content

Persistence

BITS jobs (qmgr database)

BITS jobs cheat sheet: qmgr0.dat/qmgr1.dat vs qmgr.db (ESE), Bits-Client events 3, 4, 59, 60, SetNotifyCmdLine persistence and BitsParser carving.

Location
C:\ProgramData\Microsoft\Network\Downloader\qmgr.db
Proves
A BITS job transferred a file from or to a URL, and may run a command on completion
Timestamps
Job creation/modification as FILETIME, UTC in qmgr.db; Bits-Client EVTX events in UTC; destination file NTFS times
Retention
Jobs deleted on completion or cancel (carvable until overwritten); inactive jobs dropped after 90 days; Bits-Client log rolls over by size
Access
Administrator; qmgr.db locked live: collect via raw copy (KAPE) or a shadow copy
Type
Database
Windows
Vista / 78 / 8.11011
KAPE target
BITSEventLogs
Velociraptor
Windows.Triage.Targets:BITSEventLogs

What it is

The Background Intelligent Transfer Service (BITS) downloads and uploads files in the background for Windows Update, Defender and many applications. Attackers use it through bitsadmin.exe or the PowerShell BitsTransfer module because transfers run inside a svchost.exe service process, resume after reboots and proxy through the system's settings, which makes BITS a handy LOLBin downloader.

BITS also supports a notify command line: a program that runs when a job completes or enters an error state. Combined with a download that is designed to fail, this gives persistence that lives only in the BITS job database, not in the registry.

Job state is kept in the queue manager (qmgr) database, and client activity is logged in the Bits-Client Operational channel.

Location

Windows versionJob databaseNotes
Vista / 7 / 8 / 8.1C:\ProgramData\Microsoft\Network\Downloader\qmgr0.dat and qmgr1.datCustom binary format; two copies, the second may hold older or unique records
10 / 11C:\ProgramData\Microsoft\Network\Downloader\qmgr.dbESE database with edb.log and older edb*.log transaction logs in the same folder
All (Vista+)Microsoft-Windows-Bits-Client/Operational event logMicrosoft-Windows-Bits-Client%4Operational.evtx

The folder is %ALLUSERSPROFILE%\Microsoft\Network\Downloader. On Windows 10 and later the BITS service opens the database without sharing, so it cannot be copied with a normal file copy while the service runs.

What it proves

  • A transfer was set up: job name, source URL, local destination file, bytes transferred, job owner (SID) and state.
  • A command was attached: the notify program and arguments that BITS runs on completion or error.
  • Client process and URLs in the event log: event 3 names the job and owner, events 59/60 give the URL.
  • It does not prove the downloaded file was executed; follow the destination path into Prefetch, Amcache or process events. Completed or cancelled jobs are removed from the active database.

Key fields

Field (BitsParser output)Meaning
JobName, JobDesc, JobIdName, description and GUID chosen by the creator (attackers often mimic "System update")
JobTypeDownload, upload or upload-reply
JobStateQueued, transferring, suspended, error, transferred…
OwnerSID, OwnerAccount that created the job
CommandExecuted, CommandArgumentsNotify command line set with /SetNotifyCmdLine
SourceURL, DestFile, TmpFileRemote URL, final local path and temporary BIT*.tmp file
DownloadByteSize, TransferByteSizeExpected and transferred sizes
CreationTime, ModifiedTimeJob times when present in the record
CarvedRecord recovered from free space or transaction logs

Timestamps

TimestampSet whenFormatPitfalls
Job creation / modificationJob created or changedFILETIME in the record, UTC (BitsParser prints ISO 8601)Not every record carries both times, especially carved ones
Event 3BITS created a new jobEVTX, UTCIncludes job name and owner, and on some versions the client process
Event 59 / 60Transfer started / stoppedEVTX, UTCContain the URL; 60 also carries the status code
Event 4Transfer job completedEVTX, UTCPair with 59/60 for the URL
Event 61 / 64Transfer error / notify program could not be launchedEVTX, UTC64 reveals the notify command even when the job is gone
Destination file $SI timesFile written by BITSNTFS, UTCWritten to a BIT*.tmp file first, renamed at completion

Retention and clearing

  • Jobs are deleted from the database when they complete or are cancelled, but records can survive in free pages of the database and in the ESE transaction logs until overwritten.
  • Inactive jobs are abandoned after a timeout of 90 days by default (policy JobInactivityTimeout), which bounds the life of a "failing download" persistence job unless it is refreshed.
  • bitsadmin /reset /allusers or Get-BitsTransfer -AllUsers | Remove-BitsTransfer clears jobs; the event log and carving may still show them.
  • The Bits-Client log is busy on Windows Update-heavy systems and rolls over by size.

Collection

  • KAPE target: BITS (the whole Downloader folder, using raw copy for locked files) and EventLogs for the Bits-Client channel.
  • Velociraptor (Windows.Triage.Targets): BITS, EventLogs. No built-in Velociraptor analysis artifact targets the qmgr database; collect the files and parse them offline.
  • Built-in: live enumeration needs administrator rights; the database itself should come from a shadow copy or a raw-copy tool.
bitsadmin /list /allusers /verbose
powershell -c "Get-BitsTransfer -AllUsers | Format-List *"
wevtutil epl Microsoft-Windows-Bits-Client/Operational E:\case\Bits-Client.evtx
vssadmin list shadows

Parsing tools

  • BitsParser (Mandiant, open source, Python 3): parses both the legacy qmgr format and the Windows 10+ ESE database, outputs JSON; --carvedb and --carveall recover deleted records from the database and transaction logs.
  • EvtxECmd (Eric Zimmerman): Bits-Client events to CSV for timelining.
  • ESE viewers (for example libesedb's esedbexport, open source) open qmgr.db, but job and file details sit in binary blobs, so BitsParser is the practical choice.

Investigation tips

  • Look for jobs with a notify command (CommandExecuted) that is not a known updater, and for jobs owned by user accounts pulling executables or scripts.
  • Pull every URL from events 59 and 60; unusual domains, raw IP addresses and non-Microsoft hosts stand out against Windows Update traffic.
  • A job in the error state with a notify command and an unreachable URL is the classic BITS persistence pattern.
  • Check the destination file in the $MFT and USN journal: BITS writes to a temporary BIT*.tmp file first, then renames it to the destination name.
  • bitsadmin.exe in Prefetch or PowerShell logs showing Start-BitsTransfer confirms who drove the transfer.
  • Match the URLs and job times with proxy, DNS or firewall logs to confirm the transfer left the host and to size it.

Related artifacts

Glossary terms

All artifacts on one page: cheat sheet