MENASEC

Hunting malicious BITS jobs in 2026, and the log most people never turned on

The Background Intelligent Transfer Service is still a quiet way to download a payload, run a command on job completion, and survive a reboot without dropping an obvious autorun. Here is where the telemetry lives, the three event IDs that actually help, and how to tune out Windows Update.

MENASEC Published 9 Aug 2026

The Background Intelligent Transfer Service is one of those Windows components that was built for a genuinely good reason and turned out to be almost perfectly shaped for abuse. It exists so Windows Update and enterprise software can pull large files in the background, throttling to spare your bandwidth, resuming across reboots, retrying on its own. Every one of those properties is also exactly what an attacker wants from a download primitive, which is why BITS abuse, T1197, has outlived most of the tricks it shared a stage with in 2021. I still find it on assessments in 2026, and the reason it keeps working is that most shops never enabled the log that would have caught it.

Why it is still worth an attacker’s time

Think about what a BITS job gives you if you are the one running it. The transfer happens under the service host, not under your process, so a naive rule watching your malware make outbound connections sees nothing. The job persists in the queue across reboots, so a download that fails tonight quietly completes after the user logs in tomorrow, no scheduled task required. And the traffic blends into the same service that legitimately talks to Microsoft all day. On top of the download, BITS has a feature called a notify command, set with bitsadmin /SetNotifyCmdLine, that runs a program of your choice when the job finishes. That is a download and an execution trigger and a reboot-survivable queue in one native binary, with no file dropped that a casual autorun sweep would flag.

So this is not a legacy technique I am covering out of nostalgia. It is a live one, and the detection story is better than it was, if you know which telemetry to turn on.

The log most people never enabled

Here is the part that decides whether you can hunt this at all. BITS writes a rich operational log at Microsoft-Windows-Bits-Client/Operational, and on a default endpoint it is enabled but rarely forwarded anywhere. If your SIEM is only ingesting Security, System, and Application, you do not have BITS telemetry, full stop, and the first move is to add that channel to your collection. Once it flows, three event IDs carry most of the weight.

Event ID 3 fires when a new job is created, and it records the job name, the owner, and, crucially, the process that created it. Event ID 59 fires when BITS starts a transfer and logs the URL it is reaching for. Event ID 60 logs the transfer stopping, with the URL and the byte counts. The pairing of “which process asked for this job” from 3 and “where it went” from 59 is the whole hunt in two fields. Job names are attacker-controlled and often left as a default or something bland, so I do not lean on the name; I lean on the process and the destination.

The process trail on top of the log

The BITS log is the primary source, but the process telemetry corroborates it and sometimes catches the cases where the log was not forwarded. Two entry points dominate. The first is bitsadmin.exe, the legacy command-line tool, invoked as bitsadmin /transfer to create and run a job, or with /SetNotifyCmdLine for the persistence variant. Microsoft has formally deprecated the tool, which is good news for defenders: a bitsadmin.exe process on a modern workstation is already unusual enough to be a hunt lead, and you can read the exact switch surface in the bitsadmin reference. The second is PowerShell, through the Start-BitsTransfer cmdlet in the BitsTransfer module, documented here. That one is stealthier because PowerShell is everywhere, so you pivot on the module load and the cmdlet in script-block logging rather than the image name.

Look, the strongest single signal is not any one of these in isolation, it is the join. A bitsadmin or Start-BitsTransfer invocation from a process whose parent is a document handler, a mail client, or a freshly spawned shell, followed by an EID 59 to a URL nobody recognizes, is a very different thing from the same cmdlet run by your patch-management agent. This is the same lineage logic behind tracing a macro-laden document that invokes a downloader: the BITS call is rarely the beginning of the story, and the parentage tells you where the story started.

Tuning out the noise, because there is a lot of it

BITS is busy on a healthy endpoint, and that is the honest catch with this hunt. Windows Update, Microsoft Store, Defender signature pulls, Office click-to-run, and half the enterprise agents you run all use BITS legitimately, and they will bury a naive rule instantly. The way I tune it is to stop trying to alert on BITS activity in general and start alerting on BITS activity that does not look like those known producers. The job owner and creating process are your allowlist axis: transfers created by svchost.exe, the update stack, and your signed management agents are expected. Transfers created by anything else, especially a user-context process or an interactive shell, are the residue worth reading on your Tuesday triage. Then a second filter on the destination in EID 59, dropping the Microsoft and vendor domains you can enumerate, and what remains is a short list. In my last environment that short list was three or four jobs a week, all explainable in under a minute, which is exactly where you want a hunt to sit.

The notify-command persistence variant deserves its own watch. A job configured with a notify command line is genuinely rare in normal operations, so an EID 3 whose associated job has a SetNotifyCmdLine set, or a bitsadmin command line containing that switch, is close to a standalone alert rather than a hunt input. Rare.

A hunt you can run this week

If you want a concrete starting point, do three things in order. Confirm Microsoft-Windows-Bits-Client/Operational is being collected, because everything else is theater without it. Pull every EID 3 for a week and group by creating process, then set aside svchost.exe and your known agents and read what is left. For each survivor, join to the matching EID 59 and look at the URL and the owner. You are looking for a transfer created by something that has no business creating one, heading somewhere that is not a vendor. It pairs naturally with how you already reason about early execution evidence during initial access, because a suspicious BITS job is almost always downstream of something else you would have wanted to catch first. This will not find a patient attacker who mimics your update stack perfectly. It finds the common case, which is most of them, and it costs you one log channel and an afternoon.

threat-huntingbitspersistencedetection-engineering