top of page
Search

Detecting and Removing Malware using VirusTotal Integration on Windows Endpoints with Wazuh

  • Writer: Sean Nanty (z3tssu)
    Sean Nanty (z3tssu)
  • Nov 8, 2024
  • 4 min read

This is a continuation to my first post, on how to setup Wazuh.


In this guide, I will show you how to configure Wazuh to remove malware that a user may download on their machines with the use of VirusTotal API integration.

Objectives

  1. Configure Windows Endpoints

  2. Create a Python Script and Convert it to Exe

  3. Configure Wazuh Server

  4. Integrate VirusTotal

  5. Protect the Downloads folder


Seems Easy enough right?


1. Configure Windows Endpoint

The instruction requires you to manually configure each individual endpoint’s agent which is located in C:\Program Files (x86)\ossec-agent\ossec.conf


However I am not going to be doing that, rather I want the lazy and fast method, so I will configure the shared agent.conf file which is located on the wazuh-server, which will affect all Wazuh agent’s configurations.


  • On the Wazuh server access the agent.conf

cd /var/ossec/etc/shared/default/agent.conf
nano agent.conf
  • add the following:

This will check the Downloads folder of the particular user.


2. Create a Python Script and Convert it to EXE

This will be used to remove malicious downloaded files.

  1. Download the Python executable installer from the official Python website.

  2. Run the Python installer once downloaded. Make sure to check the following boxes:

  3. Install launcher for all users

  4. Add Python 3.X to PATH (This places the interpreter in the execution path)

3. Once Python completes the installation process, open an administrator PowerShell terminal and use pip it to install PyInstaller:

> pip install pyinstaller
> pyinstaller --version

4. The next step will be to create the active response script remove-threat.py to remove a file from the Windows endpoint

Python Script

#!/usr/bin/python3
# Copyright (C) 2015-2022, Wazuh Inc.
# All rights reserved.

import os
import sys
import json
import datetime

if os.name == 'nt':
    LOG_FILE = "C:\\Program Files (x86)\\ossec-agent\\active-response\\active-responses.log"
else:
    LOG_FILE = "/var/ossec/logs/active-responses.log"

ADD_COMMAND = 0
DELETE_COMMAND = 1
CONTINUE_COMMAND = 2
ABORT_COMMAND = 3

OS_SUCCESS = 0
OS_INVALID = -1

class message:
    def __init__(self):
        self.alert = ""
        self.command = 0

def write_debug_file(ar_name, msg):
    with open(LOG_FILE, mode="a") as log_file:
        log_file.write(str(datetime.datetime.now().strftime('%Y/%m/%d %H:%M:%S')) + " " + ar_name + ": " + msg +"\n")

def setup_and_check_message(argv):

    # get alert from stdin
    input_str = ""
    for line in sys.stdin:
        input_str = line
        break


    try:
        data = json.loads(input_str)
    except ValueError:
        write_debug_file(argv[0], 'Decoding JSON has failed, invalid input format')
        message.command = OS_INVALID
        return message

    message.alert = data

    command = data.get("command")

    if command == "add":
        message.command = ADD_COMMAND
    elif command == "delete":
        message.command = DELETE_COMMAND
    else:
        message.command = OS_INVALID
        write_debug_file(argv[0], 'Not valid command: ' + command)

    return message


def send_keys_and_check_message(argv, keys):

    # build and send message with keys
    keys_msg = json.dumps({"version": 1,"origin":{"name": argv[0],"module":"active-response"},"command":"check_keys","parameters":{"keys":keys}})

    write_debug_file(argv[0], keys_msg)

    print(keys_msg)
    sys.stdout.flush()

    # read the response of previous message
    input_str = ""
    while True:
        line = sys.stdin.readline()
        if line:
            input_str = line
            break

    # write_debug_file(argv[0], input_str)

    try:
        data = json.loads(input_str)
    except ValueError:
        write_debug_file(argv[0], 'Decoding JSON has failed, invalid input format')
        return message

    action = data.get("command")

    if "continue" == action:
        ret = CONTINUE_COMMAND
    elif "abort" == action:
        ret = ABORT_COMMAND
    else:
        ret = OS_INVALID
        write_debug_file(argv[0], "Invalid value of 'command'")

    return ret

def main(argv):

    write_debug_file(argv[0], "Started")

    # validate json and get command
    msg = setup_and_check_message(argv)

    if msg.command < 0:
        sys.exit(OS_INVALID)

    if msg.command == ADD_COMMAND:
        alert = msg.alert["parameters"]["alert"]
        keys = [alert["rule"]["id"]]
        action = send_keys_and_check_message(argv, keys)

        # if necessary, abort execution
        if action != CONTINUE_COMMAND:

            if action == ABORT_COMMAND:
                write_debug_file(argv[0], "Aborted")
                sys.exit(OS_SUCCESS)
            else:
                write_debug_file(argv[0], "Invalid command")
                sys.exit(OS_INVALID)

        try:
            os.remove(msg.alert["parameters"]["alert"]["data"]["virustotal"]["source"]["file"])
            write_debug_file(argv[0], json.dumps(msg.alert) + " Successfully removed threat")
        except OSError as error:
            write_debug_file(argv[0], json.dumps(msg.alert) + "Error removing threat")


    else:
        write_debug_file(argv[0], "Invalid command")

    write_debug_file(argv[0], "Ended")

    sys.exit(OS_SUCCESS)

if __name__ == "__main__":
    main(sys.argv)

You can create this with a simple notepad or the Python IDE (pycharm)

Store it somewhere that's easy to find


5. Convert the created Python script into an EXE

  • Run the following as an administrator

pyinstaller -F \path_to_remove-threat.py

Keep track of where it created the application.


6. Move the executable file remove-threat.exe to the C:\Program Files (x86)\ossec-agent\active-response\bin directory.


7. Now restart the Wazuh agent


Restart-Service -Name wazuh

Configuring the Wazuh Server

The following steps will involve adding your VirusTotal API key to the Wazuh server ossec.conf file.

  1. Integrating VirusTotal

cd /var/ossec/etc
nano ossec.conf

Now access your VirusTotal and find your API key, then replace<YOUR_VIRUS_TOTAL_API_KEY> with your VirusTotal API key. This allows to trigger a VirusTotal query whenever any of the rules in the FIM syscheck the group is triggered:

<ossec_config>
  <integration>
    <name>virustotal</name>
    <api_key><YOUR_VIRUS_TOTAL_API_KEY></api_key> <!-- Replace with your VirusTotal API key -->
    <group>syscheck</group>
    <alert_format>json</alert_format>
  </integration>
</ossec_config>

2. Enabling Active Response

Within ossec.conf, add the following that will enable active response and will trigger the created remove-threat.exe when VirusTotal queries a positive malware match.

<ossec_config>
  <command>
    <name>remove-threat</name>
    <executable>remove-threat.exe</executable>
    <timeout_allowed>no</timeout_allowed>
  </command>

  <active-response>
    <disabled>no</disabled>
    <command>remove-threat</command>
    <location>local</location>
    <rules_id>87105</rules_id>
  </active-response>
</ossec_config>

I added it to the bottom of my ossec.conf

3. Add the detection and removal rules

navigate to:

cd /var/ossec/etc/rulesnano local_rules.xml
<group name="virustotal,">
  <rule id="100092" level="12">
      <if_sid>657</if_sid>
      <match>Successfully removed threat</match>
      <description>$(parameters.program) removed threat located at $(parameters.alert.data.virustotal.source.file)</description>
  </rule>

  <rule id="100093" level="12">
    <if_sid>657</if_sid>
    <match>Error removing threat</match>
    <description>Error removing threat located at $(parameters.alert.data.virustotal.source.file)</description>
  </rule>
</group>

Add it to the local_rules.xml as below


4. Restart the wazuh-manager

sudo systemctl restart wazuh-manager

Attack emulation

  1. Download an EICAR test file to the C:\Users\<USER_NAME>\Downloads directory on the Windows endpoint.

  2. > Invoke-WebRequest -Uri https://secure.eicar.org/eicar.com.txt -OutFile eicar.txt > cp .\eicar.txt C:\Users\<USER_NAME>\Downloads

  3. This triggers a VirusTotal query and generates an alert. In addition, the active response script automatically removes the file.

Visualize the alerts

You can visualize the alert data in the Wazuh dashboard. To do this, go to the Security Events module and add the filters in the search bar to query the alerts.

  • Windows — rule.id: is one of 554,100092,553,87105

Comments


Subscribe for new posts
  • GitHub
  • X
  • Linkedin

Thanks for submitting!

Sean Nanty (z3tssu)
Naruto_edited.jpg
Cybersecurity/IT Researcher/Practioner

© 2035 by DO IT YOURSELF. Powered and secured by Wix

bottom of page