Get-ScheduledTask: detecta tareas programadas sospechosas en Windows

Get-ScheduledTask: detecta tareas programadas sospechosas en Windows

Un malware que se ejecuta una vez y desaparece preocupa menos que el que vuelve después del reinicio. Una de las formas más baratas de asegurar ese regreso es crear una tarea programada: se dispara al iniciar sesión, cada hora o todos los lunes, sin pedirle nada al usuario. Si nunca has mirado la lista de tareas de tu Windows, probablemente no sabes qué hay ahí. PowerShell lo resuelve en una línea.

¿Por qué importan las tareas programadas para la seguridad?

El Programador de tareas es una función legítima de Windows y se ejecuta con los privilegios que defina la tarea, incluido SYSTEM. Por eso aparece como técnica de persistencia y ejecución en MITRE ATT&CK, catalogada como T1053.005 (Scheduled Task). La tarea maliciosa suele tener un nombre parecido al de algo del sistema, y lo que ejecuta es un powershell.exe con argumentos largos, un script en %APPDATA% o un binario en una carpeta temporal.

El cmdlet Get-ScheduledTask forma parte del módulo ScheduledTasks, disponible desde Windows 8 y Windows Server 2012, según la documentación de Microsoft. Devuelve la definición de las tareas registradas en el equipo, y los datos de ejecución (último resultado, próxima hora) vienen de otro cmdlet, Get-ScheduledTaskInfo.

¿Cómo listar todas las tareas programadas con PowerShell?

¿Cómo ver las tareas programadas de Windows con PowerShell?

Ejecuta Get-ScheduledTask en un PowerShell con privilegios elevados. Lista nombre, ruta, estado y descripción de todas las tareas registradas. Sin filtro, el resultado pasa de cien líneas, casi todas de la propia Microsoft.

# Todas las tareas, ordenadas por estado
Get-ScheduledTask | Sort-Object State | Format-Table TaskName, TaskPath, State -AutoSize

# Solo las habilitadas y listas para ejecutarse
Get-ScheduledTask | Where-Object State -eq 'Ready'

El campo TaskPath es el que más ayuda. Las tareas nativas viven en \Microsoft\Windows\.... Lo que queda fuera de ahí es software de terceros (Chrome, Office, drivers) o algo que merece una mirada.

# Tareas fuera de la carpeta de Microsoft
Get-ScheduledTask |
    Where-Object { $_.TaskPath -notlike '\Microsoft\*' } |
    Format-Table TaskName, TaskPath, State -AutoSize

Ojo: un atacante puede registrar la tarea dentro de \Microsoft\Windows\ justamente para camuflarse. Filtrar por ruta es un primer corte, no una garantía.

Qué ejecuta realmente cada tarea

El nombre de la tarea no dice nada. Lo que importa es la acción: qué programa se ejecuta y con qué argumentos. Esa información está en la propiedad Actions, y la cuenta usada está en Principal.

Get-ScheduledTask | ForEach-Object {
    [PSCustomObject]@{
        Tarefa    = $_.TaskName
        Caminho   = $_.TaskPath
        Executa   = ($_.Actions | ForEach-Object { "$($_.Execute) $($_.Arguments)" }) -join ' | '
        Conta     = $_.Principal.UserId
        Elevacao  = $_.Principal.RunLevel
    }
} | Where-Object { $_.Caminho -notlike '\Microsoft\*' } | Format-List

Fíjate en estas señales en la columna Executa (los nombres de las propiedades están en portugués en este script; cámbialos si quieres):

  • powershell.exe o cmd.exe con argumentos codificados (-enc, -EncodedCommand) o con -WindowStyle Hidden;
  • binarios en carpetas escribibles por el usuario: %TEMP%, %APPDATA%, C:\Users\Public, C:\ProgramData;
  • mshta.exe, wscript.exe, regsvr32.exe, rundll32.exe llamando a algo remoto o a un archivo extraño;
  • cuenta SYSTEM con RunLevel Highest en una tarea que no reconoces;
  • un nombre que imita al del sistema con un error sutil, o una descripción vacía.

¿Cuándo se ejecutó la tarea por última vez?

Combínalo con Get-ScheduledTaskInfo para ver el historial reciente. La documentación del cmdlet describe que devuelve la información de la última ejecución, y acepta la entrada por canalización directamente desde Get-ScheduledTask.

Get-ScheduledTask |
    Where-Object { $_.TaskPath -notlike '\Microsoft\*' } |
    Get-ScheduledTaskInfo |
    Select-Object TaskName, LastRunTime, LastTaskResult, NextRunTime |
    Sort-Object LastRunTime -Descending

Un LastTaskResult igual a 0 significa que la última ejecución terminó sin errores. Una tarea desconocida que se ejecuta con éxito cada hora es más sospechosa que una que nunca se ejecutó.

¿Cómo saber cuándo se creó una tarea?

Windows registra la creación de tareas en el registro de Seguridad con el Event ID 4698, siempre que la auditoría de "Otros eventos de acceso a objetos" esté activada. Sin esa política no hay registro y solo descubres la tarea mirando la lista.

# Creación de tareas programadas en los últimos 30 días
Get-WinEvent -FilterHashtable @{
    LogName   = 'Security'
    Id        = 4698
    StartTime = (Get-Date).AddDays(-30)
} | Select-Object TimeCreated, Message

El campo de mensaje trae el nombre de la tarea, la cuenta que la creó y el XML completo con la acción. Si ese comando no devuelve nada, vale la pena activar la auditoría. El post sobre auditoría de registros de seguridad con PowerShell muestra cómo, y el de Get-WinEvent explica los filtros usados arriba.

Desactivar, exportar y eliminar con seguridad

¿Encontraste una tarea rara? Antes de borrarla, conserva la evidencia. Export-ScheduledTask devuelve el XML de la definición, y lo guardas en un archivo:

# 1. Guardar la definición (evidencia)
Export-ScheduledTask -TaskName "NombreDeLaTarea" -TaskPath "\" | Out-File "$env:USERPROFILE\Desktop\tarea-sospechosa.xml"

# 2. Desactivar sin borrar
Disable-ScheduledTask -TaskName "NombreDeLaTarea" -TaskPath "\"

# 3. Solo después de investigar: eliminar
Unregister-ScheduledTask -TaskName "NombreDeLaTarea" -TaskPath "\" -Confirm:$false

Borrar la tarea no resuelve el problema si el archivo que ejecuta sigue en el disco, ni si existen otras formas de persistencia. Calcula el hash del binario con Get-FileHash, consúltalo en VirusTotal y revisa también los servicios con Get-Service. Si el equipo es importante, trátalo como un incidente: aíslalo de la red y cambia las contraseñas usadas en él.

Checklist de auditoría rápida

  1. Lista las tareas fuera de \Microsoft\ e identifica cada una.
  2. Revisa el Execute y los Arguments de todas, incluso las que están dentro de la carpeta de Microsoft.
  3. Desconfía de cualquier acción que apunte a una carpeta escribible por el usuario.
  4. Cruza con el LastRunTime y con el Event ID 4698.
  5. Exporta el XML, desactiva, investiga y solo entonces elimina.

Conclusión

Una tarea programada es persistencia barata, silenciosa y legítima a los ojos del sistema, y justamente por eso conviene revisar la lista de vez en cuando. Tres cmdlets (Get-ScheduledTask, Get-ScheduledTaskInfo y Export-ScheduledTask) cubren toda la auditoría. Si quieres el otro lado de la moneda, crear tareas legítimas desde la terminal, lee la guía de schtasks para programar tareas en Windows.

Comentarios