InvisibleFerret is a Python-based backdoor malware that affects both Windows and Linux endpoints. It is used in targeted campaigns by North Korean threat actors, particularly the notorious Lazarus Group. This malware is deployed through advanced social engineering tactics, often disguised as part of legitimate job recruitment processes. Threat actors impersonate recruiters, luring victims, primarily professionals in the technology, financial, and cryptocurrency sectors, into downloading malicious files. These files are cleverly masked as coding challenges, video conferencing software, or dependency packages, making them appear harmless and credible.

InvisibleFerret is delivered as a second-stage payload by BeaverTail, a JavaScript-based loader and stealer. Once installed, it exhibits a wide range of malicious capabilities, including geolocation tracking, file exfiltration via FTP and Telegram Bots, keylogging, and clipboard monitoring. 

In this blog post, we demonstrate how Wazuh can be configured to detect and mitigate the threat posed by InvisibleFerret on Linux endpoints.

InvisibleFerret malware behavior

Below are some of the behaviors observed when the InvisibleFerret malware is successfully executed on a Linux endpoint:

  • The malware identifies the internal IP address of the infected endpoint to understand the system’s network environment.
  • The malware gathers geolocation and system details, such as the OS version, hostname, and username, then generates a unique ID for the infected endpoint.
  • The malware creates three temporary files with 8-character obfuscated names in /tmp/, then removes them after execution to cover its tracks.
  • The malware categorizes its targets into structured lists, identifying specific file types, extensions, and directories to prioritize for data theft and exfiltration.
  • It downloads and executes legitimate remote desktop software like AnyDesk to maintain persistence on infected endpoints and give attackers more control.

Analyzed sample

Hash typeValue
MD530ee0cc21753e27dd45a7cedc1271cda
SHA1989252de0be3253c5cfd4b68bc84aae0a6fd6c9c
SHA2562012f6f7d8add86ebbc6629815832554fca37cc3e1edab68a51f57e345365f85

Infrastructure

We use the following infrastructure to demonstrate the detection of InvisibleFerret with Wazuh:

  • A pre-built, ready-to-use Wazuh OVA 4.11.2 which includes the Wazuh central components (Wazuh server, Wazuh indexer, and Wazuh dashboard). Follow this guide to download and set up the Wazuh virtual machine.
  • An Ubuntu 22.04 victim endpoint with the Wazuh agent 4.11.2  installed and enrolled to the Wazuh server.

Detection with Wazuh

In this blog post, we demonstrate how to use custom Wazuh detection rules to identify InvisibleFerret malware activity. We also use the CDB lists and Active Response capabilities to detect and automatically remove the InvisibleFerret malware files.

Ubuntu endpoint

We install SysmonForLinux to enrich the event logs generated on the Linux endpoints. This approach provides detailed information about events such as process creations, network connections, and changes to the file system. Then we create custom rules on the Wazuh server to detect the malicious behavior of the InvisibleFerret malware.

Note

Execute all the commands below as root. If you are using a non-root (normal) user, prepend sudo to each command.

  1. Install SysmonForLinux. SysmonForLinux can be installed in various ways depending on the Linux distribution and OS version. Installation steps can be found here.
  2. Download the SysmonForLinux configuration file after installation:
# wget https://wazuh.com/resources/blog/detecting-sysjoker-backdoor-malware-with-wazuh/sysmonforlinux-config.xml
  1. Use the SysmonForLinux configuration file:
# sysmon -accepteula -i# sysmon -i sysmonforlinux-config.xml
  1. Enable Sysmon to run at startup: 
# systemctl enable sysmon# systemctl start sysmon
  1. Add the following configuration within the <ossec_config> block of the /var/ossec/etc/ossec.conf file to forward Sysmon events to the Wazuh server for analysis:
<localfile>
    <log_format>syslog</log_format>
    <location>/var/log/syslog</location>
</localfile>
  1. Restart the Wazuh agent to apply the changes:
# systemctl restart wazuh-agent

Wazuh server

Decoders

Wazuh utilizes decoders to extract information from received log messages. Follow these steps to download the decoders that can extract information from SysmonforLinux logs.

  1. Download the SysmonForLinux decoders:
# wget https://wazuh.com/resources/blog/detecting-sysjoker-backdoor-malware-with-wazuh/sysmonforlinux-decoders.xml.txt
  1. Copy the content to the /var/ossec/etc/decoders/local_decoder.xml file:
# cat sysmonforlinux-decoders.xml.txt >> /var/ossec/etc/decoders/local_decoder.xml

Rules

Wazuh uses rules to analyze decoded log data and trigger alerts. Follow these steps to download the rules that can trigger alerts from the SysmonforLinux log.

  1. Download the SysmonForLinux base rules detecting generic Sysmon events: 
# wget https://wazuh.com/resources/blog/detecting-sysjoker-backdoor-malware-with-wazuh/sysmonforlinux-base-rules.xml
  1. Add the rules to the /var/ossec/etc/rules/local_rules.xml file. Since these are base rules, the rule levels are set to 1 to generate alerts that will not be shown on the dashboard.
# cat sysmonforlinux-base-rules.xml >> /var/ossec/etc/rules/local_rules.xml
  1. Add the rules below to the /var/ossec/etc/rules/local_rules.xml file to detect InvisibleFerret behavior:
<group name="invisibleferret,">

  <rule id="100501" level="7">
    <if_sid>200155</if_sid>
    <field name="eventdata.image" type="pcre2">\/usr\/bin\/python(\d+\.\d+).*?</field>
    <field name="eventdata.targetFilename" type="pcre2">\/tmp\/([a-zA-Z0-9]{8}).*?</field>
    <description>Suspicious file created: "$(eventdata.targetFilename)"- Possible InvisibleFerret malware activity detected.</description>
    <mitre>
      <id>T1044</id>
    </mitre>
  </rule>

  <rule id="100502" level="7">
    <if_sid>200157</if_sid>
    <field name="eventdata.image" type="pcre2">\/usr\/bin\/python(\d+\.\d+).*?</field>
    <field name="eventdata.targetFilename" type="pcre2">\/tmp\/([a-zA-Z0-9]{8}).*?</field>
    <description>Suspicious file deleted: "$(eventdata.targetFilename)" - Possible InvisibleFerret malware activity detected.</description>
    <mitre>
      <id>T1107</id>
      <id>T1485</id>
    </mitre>
  </rule>
   
  <rule id="100503" level="7">
    <if_sid>200152</if_sid>
    <field name="eventdata.image" type="pcre2">\/usr\/bin\/python(\d+\.\d+).*?</field>
    <field name="eventdata.destinationIp" type="pcre2">(127\.0\.0\.1)</field>
    <field name="eventdata.sourceIp" type="pcre2">(127\.0\.0\.53)</field>
    <field name="eventdata.sourcePort" type="pcre2">(53)</field>
    <description>Suspicious query of DNS - Possible InvisibleFerret malware activity detected.</description>
    <mitre>
      <id>T1043</id>
    </mitre>
  </rule>

  <rule id="100504" level="12">
    <if_sid>200152</if_sid>
    <field name="eventdata.image" type="pcre2">\/usr\/bin\/python(\d+\.\d+).*?</field>
    <field name="eventdata.sourceIp" type="pcre2">(\d+\.\d+\.\d+\.\d+)</field>
    <field name="eventdata.destinationIp" type="pcre2">(151\.101\.\d+\.\d+)</field>
    <field name="eventdata.destinationPort" type="pcre2">443</field>
    <description>Suspicious download request to "$(eventdata.destinationIp)" for remote access - InvisibleFerret malware activity detected.</description>
    <mitre>
      <id>T1043</id>
    </mitre>
  </rule>

 <rule id="100505" level="12">
    <if_sid>200152</if_sid>
    <field name="eventdata.image" type="pcre2">\/usr\/bin\/python(\d+\.\d+).*?</field>
    <field name="eventdata.sourceIp" type="pcre2">(\d+\.\d+\.\d+\.\d+)</field>
    <field name="eventdata.destinationIp" type="pcre2">(208\.95\.\d+\.\d+)</field>
    <field name="eventdata.destinationPort" type="pcre2">80</field>
    <description>Suspicious download request to "$(eventdata.destinationIp)" for data exfiltration - InvisibleFerret malware activity detected.</description>
    <mitre>
      <id>T1043</id>
    </mitre>
  </rule>

</group>

Where:

  • Rule ID 100501 is triggered when the malware creates suspicious files in the /tmp directory.
  • Rule ID 100502 is triggered when the malware immediately deletes suspicious files in the /tmp directory to maintain its legitimacy.
  • Rule ID 100503 is triggered when the malware queries the DNS to map the network and detect the virtualized environment.
  • Rule ID 100504 is triggered when the InvisibleFerret malware makes a request to download AnyDesk and connect to the C2 server for remote access.
  • Rule ID 100505 is triggered when  InvisibleFerret makes a second request for data exfiltration.
  1. Restart the Wazuh manager for the changes to take effect:
# systemctl restart wazuh-manager

Detection results

Follow the steps below to view the alerts generated on the Wazuh dashboard when the InvisibleFerret malware is executed on the Linux endpoint.

  1. Navigate to Threat intelligence > Threat Hunting and click the Events tab.
  2. Click + Add filter. Then filter by rule.id.
  3. In the Operator field, select is one of.
  4. Search and select the rule IDs 100501, 100502 , 100503, 100504, and 100505 in the Values field.
  5. Click Save.

Removing InvisibleFerret malware using Wazuh CBD lists and Active Response

We configure Wazuh to detect malicious files by comparing their signatures against a CDB list of known malware signatures. A CDB list is a text file that stores key:value pairs, allowing you to track users, file hashes, IP addresses, or domain names, or other relevant data. The Active Response module triggers automated countermeasures such as file deletion, process termination, to contain the threat immediately after detection. 

Detecting InvisibleFerret using file hashes in a CDB list

To detect the InvisibleFerret malware, you must add its known hashes to a CDB list. The Wazuh File Integrity Monitoring (FIM) module tracks file changes within monitored directories, generating alerts when files are created, modified, or deleted. These alerts include the MD5, SHA1, and SHA256 checksums of the file. By comparing the SHA256 checksums from the FIM module against the entries in the CDB list, Wazuh identifies the presence of the malware.

Follow the steps below to set up FIM, create a CDB list and set up the detection mechanism.

Ubuntu endpoint

  1. Add the configuration below within the <syscheck> block of the /var/ossec/etc/ossec.conf file to monitor the Downloads directory of all regular users in real-time.
<directories check_all="yes" report_changes="yes" realtime="yes">/home/*/Downloads</directories>

Note

In this blog post, we monitored only the Downloads directory of all regular users. However, you can configure Wazuh to monitor any directory of your choice. 

  1. Restart the Wazuh agent to apply the changes:
# systemctl restart wazuh-agent

Wazuh server

  1. Create a file malware-hashes in the /var/ossec/etc/lists directory. This is the CDB list that will contain the known file hashes associated with the InvisibleFerret malware. 
# touch /var/ossec/etc/lists/malware-hashes
  1. Add the known hashes of InvisibleFerret to the /var/ossec/etc/lists/malware-hashes file as key:value pairs: 
2012f6f7d8add86ebbc6629815832554fca37cc3e1edab68a51f57e345365f85:invisbleferret
a2de54fbfbca6e1715b2621ab382e9c1c645fdb0723a410e8775d2ac026897c8:invisbleferret
11dde438e1a636073e79c81d4c2543708cc0a2922e7c42c38b1b588e17545f96:invisbleferret
  1. Edit the /var/ossec/etc/ossec.conf file and include the /etc/lists/malware-hashes list within the <ruleset> configuration block:
  <list>etc/lists/malware-hashes</list>
  1. Add the custom rule below to the /var/ossec/etc/rules/local_rules.xml file to trigger alerts on the Wazuh dashboard whenever a SHA256 hash from the CDB list is detected: 
<group name="invisbleferret,">
  <rule id="100510" level="13">
    <if_sid>554</if_sid>
    <list field="sha256" lookup="match_key">etc/lists/malware-hashes</list>
    <description>A known InvisibleFerret malware hash detected: $(file)</description>
    <mitre>
      <id>T1204.002</id>
    </mitre>
  </rule>
</group>
  1. Restart the Wazuh manager to apply the changes:
# systemctl restart wazuh-manager

Visualizing alerts on the Wazuh dashboard

Perform the following on the Wazuh dashboard to view the alerts generated when the InvisibleFerret malware files are added to the Downloads directory.

  1. Navigate to Threat intelligence > Threat Hunting and click the Events tab.
  2. Click + Add filter. Then filter by rule.id.
  3. In the Operator field, select is.
  4. Search and select 100510 in the Values field.
  5. Click Save.

Removing InvisibleFerret malware files using Active Response

The Wazuh Active Response module helps mitigate threats by executing scripts on monitored endpoints when specific triggers occur.

In this guide, we demonstrate how to set up a Python script on a Linux endpoint to automatically delete InvisibleFerret malware files upon detection by Wazuh.

Follow the steps below to configure the active response script to remove InvisibleFerret malware files as soon as they are detected.

 Ubuntu endpoint

  1. Create a remove-threat.py script file in the /var/ossec/active-response/bin using the command below:
touch /var/ossec/active-response/bin/remove-threat.py
  1. Copy the below script into the /var/ossec/active-response/bin/remove-threat.py file:
#!/usr/bin/python3
# Copyright (C) 2015-2022, Wazuh Inc.
# All rights reserved.

# This program is free software; you can redistribute it
# and/or modify it under the terms of the GNU General Public
# License (version 2) as published by the FSF - Free Software
# Foundation.

import os
import sys
import json
import datetime
from pathlib import PureWindowsPath, PurePosixPath

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:
        ar_name_posix = str(PurePosixPath(PureWindowsPath(ar_name[ar_name.find("active-response"):])))
        log_file.write(str(datetime.datetime.now().strftime('%Y/%m/%d %H:%M:%S')) + " " + ar_name_posix + ": " + msg +"\n")


def setup_and_check_message(argv):

    # get alert from stdin
    input_str = ""
    for line in sys.stdin:
        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')
        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:

        """ Start Custom Key
        At this point, it is necessary to select the keys from the alert and add them into the keys array.
        """

        alert = msg.alert["parameters"]["alert"]
        keys = [alert["rule"]["id"]]

        """ End Custom Key """

        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"]["syscheck"]["path"])
            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)
  1. Change the script permissions and ownership as shown below:
# chmod 750 /var/ossec/active-response/bin/remove-threat.py
# chown root:wazuh /var/ossec/active-response/bin/remove-threat.py 
  1. Restart the Wazuh agent to apply the changes:
# systemctl restart wazuh-agent

Wazuh server

  1. Add the following configuration within the <ossec_config> block of the /var/ossec/etc/ossec.conf file to trigger an Active Response to rule ID 100510:
<command>
  <name>remove-threat</name>
  <executable>remove-threat.py</executable>
  <timeout_allowed>yes</timeout_allowed>
</command>

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

Where:

  • <name> specifies that remove-threat is the name of the command being called in the active response section.
  • <executable> specifies that remove-threat.py is the executable file to run.
  • <command> specifies the command that the active response will use.
  • The <active response> block calls the <command> block when the rule ID 100510 is triggered.
  • <location> specifies where the active response script is executed.
  1. Create custom rules in the /var/ossec/etc/rules/local_rules.xml to generate alerts when response actions are taken:
<group name="invisbleferret,">
  <rule id="100511" level="12">
   <if_sid>657</if_sid>
    <match>Successfully removed threat</match>
    <description>$(parameters.program): Successfully removed threat $(parameters.alert.syscheck.path) whose hash appears in a malware blacklist.</description>
  </rule>

  <rule id="100512" level="12">
   <if_sid>657</if_sid>
    <match>Error removing threat</match>
    <description>$(parameters.program): Error removing threat $(parameters.alert.syscheck.path) whose hash appears in a malware blacklist.</description>
  </rule>
</group>

Where:

  • Rule ID 100511 is triggered when the threat is successfully removed by the Wazuh Active Response module.
  • Rule ID 100512  is triggered when the threat is not successfully removed by the Wazuh active response module.
  1. Restart the Wazuh manager to apply the changes:
# systemctl restart wazuh-manager

Visualizing alerts on the Wazuh dashboard

Perform the following steps on the Wazuh dashboard to view the alerts of the removal of the malicious file by the Wazuh Active Response module:

  1. Navigate to Threat intelligence > Threat Hunting and click the Events tab.
  2. Click + Add filter. Then filter by rule.id.
  3. In the Operator field, select is one of.
  4. Search and select rule IDs 100511 and 100512 in the Values field.
  5. Click Save.

Conclusion

In this blog post, we demonstrated how to detect InvisibleFerret malware activities on monitored Linux endpoints. We enriched logs from the victim endpoint by integrating Sysmon and creating Wazuh detection rules to trigger alerts once they are associated with InvisibleFerret malware. We also illustrated how to remove the known malicious files using the Wazuh CDB lists and Active Response module.

Wazuh is a free, open source security platform providing a wide range of capabilities to monitor and safeguard your infrastructure against malicious activities. If you have any questions about this blog post or Wazuh, we invite you to join our community, where our team is available to assist you.

References