Skip to content

Commit

Permalink
Merge pull request #469 from CAPESandbox/MACO
Browse files Browse the repository at this point in the history
MACO
  • Loading branch information
doomedraven authored Nov 2, 2024
2 parents 98f506d + 780b8f4 commit 571fcad
Show file tree
Hide file tree
Showing 74 changed files with 2,275 additions and 0 deletions.
63 changes: 63 additions & 0 deletions modules/parsers/MACO/AgentTesla.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import os

from maco.extractor import Extractor
from maco.model import ExtractorModel as MACOModel
from cape_parsers.CAPE.community.AgentTesla import extract_config


def convert_to_MACO(raw_config: dict) -> MACOModel:
if not raw_config:
return

protocol = raw_config.get("Protocol")
if not protocol:
return

parsed_result = MACOModel(family="AgentTesla", other=raw_config)
if protocol == "Telegram":
parsed_result.http.append(MACOModel.Http(uri=raw_config["C2"], password=raw_config["Password"], usage="c2"))

elif protocol in ["HTTP(S)", "Discord"]:
parsed_result.http.append(MACOModel.Http(uri=raw_config["C2"], usage="c2"))

elif protocol == "FTP":
parsed_result.ftp.append(
MACOModel.FTP(
username=raw_config["Username"],
password=raw_config["Password"],
hostname=raw_config["C2"].replace("ftp://", ""),
usage="c2",
)
)

elif protocol == "SMTP":
smtp = dict(
username=raw_config["Username"],
password=raw_config["Password"],
hostname=raw_config["C2"],
mail_to=[raw_config["EmailTo"]],
usage="c2",
)
if "Port" in raw_config:
smtp["port"] = raw_config["Port"]
parsed_result.smtp.append(MACOModel.SMTP(**smtp))

if "Persistence_Filename" in raw_config:
parsed_result.paths.append(MACOModel.Path(path=raw_config["Persistence_Filename"], usage="storage"))

if "ExternalIPCheckServices" in raw_config:
for service in raw_config["ExternalIPCheckServices"]:
parsed_result.http.append(MACOModel.Http(uri=service, usage="other"))

return parsed_result


class AgentTesla(Extractor):
author = "kevoreilly"
family = "AgentTesla"
last_modified = "2024-10-20"
sharing = "TLP:CLEAR"
yara_rule = open(os.path.join(os.path.dirname(__file__).split("/modules", 1)[0], f"data/yara/CAPE/{family}.yar")).read()

def run(self, stream, matches):
return convert_to_MACO(extract_config(stream.read()))
50 changes: 50 additions & 0 deletions modules/parsers/MACO/AsyncRAT.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import os

from maco.extractor import Extractor
from maco.model import ExtractorModel as MACOModel
from cape_parsers.CAPE.community.AsyncRAT import extract_config


def convert_to_MACO(raw_config: dict) -> MACOModel:
if not raw_config:
return

parsed_result = MACOModel(family="AsyncRAT", other=raw_config)

# Mutex
parsed_result.mutex.append(raw_config["Mutex"])

# Version
parsed_result.version = raw_config["Version"]

# Was persistence enabled?
if raw_config["Install"] == "true":
parsed_result.capability_enabled.append("persistence")
else:
parsed_result.capability_disabled.append("persistence")

# Installation Path
if raw_config.get("Folder"):
parsed_result.paths.append(MACOModel.Path(path=os.path.join(raw_config["Folder"], raw_config["Filename"]), usage="install"))

# C2s
for i in range(len(raw_config.get("C2s", []))):
parsed_result.http.append(MACOModel.Http(hostname=raw_config["C2s"][i], port=int(raw_config["Ports"][i]), usage="c2"))
# Pastebin
if raw_config.get("Pastebin") not in ["null", None]:
# TODO: Is it used to download the C2 information if not embedded?
# Ref: https://www.netskope.com/blog/asyncrat-using-fully-undetected-downloader
parsed_result.http.append(MACOModel.Http(uri=raw_config["Pastebin"], usage="download"))

return parsed_result


class AsyncRAT(Extractor):
author = "kevoreilly"
family = "AsyncRAT"
last_modified = "2024-10-26"
sharing = "TLP:CLEAR"
yara_rule = open(os.path.join(os.path.dirname(__file__).split("/modules", 1)[0], f"data/yara/CAPE/{family}.yar")).read()

def run(self, stream, matches):
return convert_to_MACO(extract_config(stream.read()))
28 changes: 28 additions & 0 deletions modules/parsers/MACO/AuroraStealer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import os

from maco.extractor import Extractor
from maco.model import ExtractorModel as MACOModel
from cape_parsers.CAPE.community.AuroraStealer import extract_config


def convert_to_MACO(raw_config: dict):
if not raw_config:
return None

parsed_result = MACOModel(family="AuroraStealer", other=raw_config)
if raw_config.get("C2"):
# IP related to C2
parsed_result.http.append(MACOModel.Http(hostname=raw_config["C2"], usage="c2"))

return parsed_result


class AuroraStealer(Extractor):
author = "kevoreilly"
family = "AuroraStealer"
last_modified = "2024-10-26"
sharing = "TLP:CLEAR"
yara_rule = open(os.path.join(os.path.dirname(__file__).split("/modules", 1)[0], f"data/yara/CAPE/{family}.yar")).read()

def run(self, stream, matches):
return convert_to_MACO(extract_config(stream.read()))
21 changes: 21 additions & 0 deletions modules/parsers/MACO/Azorult.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from maco.extractor import Extractor
from maco.model import ExtractorModel as MACOModel
from cape_parsers.CAPE.core.Azorult import extract_config, rule_source


def convert_to_MACO(raw_config: dict):
if not raw_config:
return None

return MACOModel(family="Azorult", http=[MACOModel.Http(hostname=raw_config["address"])], other=raw_config)


class Azorult(Extractor):
author = "kevoreilly"
family = "Azorult"
last_modified = "2024-10-26"
sharing = "TLP:CLEAR"
yara_rule = rule_source

def run(self, stream, matches):
return convert_to_MACO(extract_config(stream.read()))
32 changes: 32 additions & 0 deletions modules/parsers/MACO/BackOffLoader.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from maco.extractor import Extractor
from maco.model import ExtractorModel as MACOModel
from cape_parsers.CAPE.community.BackOffLoader import extract_config


def convert_to_MACO(raw_config: dict):
if not raw_config:
return None

parsed_result = MACOModel(family="BackOffLoader", other=raw_config)

# Version
parsed_result.version = raw_config["Version"]

# Encryption details
parsed_result.encryption.append(
MACOModel.Encryption(algorithm="rc4", key=raw_config["EncryptionKey"], seed=raw_config["RC4Seed"])
)
for url in raw_config["URLs"]:
parsed_result.http.append(MACOModel.Http(url=url))

return parsed_result


class BackOffLoader(Extractor):
author = "kevoreilly"
family = "BackOffLoader"
last_modified = "2024-10-26"
sharing = "TLP:CLEAR"

def run(self, stream, matches):
return convert_to_MACO(extract_config(stream.read()))
32 changes: 32 additions & 0 deletions modules/parsers/MACO/BackOffPOS.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from maco.extractor import Extractor
from maco.model import ExtractorModel as MACOModel
from cape_parsers.CAPE.community.BackOffPOS import extract_config


def convert_to_MACO(raw_config: dict):
if not raw_config:
return None

parsed_result = MACOModel(family="BackOffPOS", other=raw_config)

# Version
parsed_result.version = raw_config["Version"]

# Encryption details
parsed_result.encryption.append(
MACOModel.Encryption(algorithm="rc4", key=raw_config["EncryptionKey"], seed=raw_config["RC4Seed"])
)
for url in raw_config["URLs"]:
parsed_result.http.append(MACOModel.Http(url=url))

return parsed_result


class BackOffPOS(Extractor):
author = "kevoreilly"
family = "BackOffPOS"
last_modified = "2024-10-26"
sharing = "TLP:CLEAR"

def run(self, stream, matches):
return convert_to_MACO(extract_config(stream.read()))
28 changes: 28 additions & 0 deletions modules/parsers/MACO/BitPaymer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from maco.extractor import Extractor
from maco.model import ExtractorModel as MACOModel
from cape_parsers.CAPE.core.BitPaymer import extract_config, rule_source


def convert_to_MACO(raw_config: dict):
if not raw_config:
return None

parsed_result = MACOModel(family="BitPaymer", other=raw_config)

# Extracted strings
parsed_result.decoded_strings = raw_config["strings"]

# Encryption details
parsed_result.encryption.append(MACOModel.Encryption(algorithm="rsa", public_key=raw_config["RSA public key"]))
return parsed_result


class BitPaymer(Extractor):
author = "kevoreilly"
family = "BitPaymer"
last_modified = "2024-10-26"
sharing = "TLP:CLEAR"
yara_rule = rule_source

def run(self, stream, matches):
return convert_to_MACO(extract_config(stream.read()))
31 changes: 31 additions & 0 deletions modules/parsers/MACO/BlackDropper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import os

from maco.extractor import Extractor
from maco.model import ExtractorModel as MACOModel
from cape_parsers.CAPE.core.BlackDropper import extract_config


def convert_to_MACO(raw_config: dict):
if not raw_config:
return None

parsed_result = MACOModel(family="BlackDropper", campaign_id=[raw_config["campaign"]], other=raw_config)

for dir in raw_config.get("directories", []):
parsed_result.paths.append(MACOModel.Path(path=dir))

for url in raw_config.get("urls", []):
parsed_result.http.append(MACOModel.Http(uri=url))

return parsed_result


class BlackDropper(Extractor):
author = "kevoreilly"
family = "BlackDropper"
last_modified = "2024-10-26"
sharing = "TLP:CLEAR"
yara_rule = open(os.path.join(os.path.dirname(__file__).split("/modules", 1)[0], f"data/yara/CAPE/{family}.yar")).read()

def run(self, stream, matches):
return convert_to_MACO(extract_config(stream.read()))
65 changes: 65 additions & 0 deletions modules/parsers/MACO/BlackNix.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import os

from maco.extractor import Extractor
from maco.model import ExtractorModel as MACOModel
from cape_parsers.CAPE.community.BlackNix import extract_config


def convert_to_MACO(raw_config: dict):
if not raw_config:
return None

parsed_result = MACOModel(family="BlackNix", other=raw_config)

# Mutex
parsed_result.mutex.append(raw_config["Mutex"])

# Capabilities that are enabled/disabled
# TODO: Review if these are all capabilities set by a boolean flag
for capa in [
"Anti Sandboxie",
"Kernel Mode Unhooking",
"User Mode Unhooking",
"Melt Server",
"Offline Screen Capture",
"Offline Keylogger",
"Copy to ADS",
"Safe Mode Startup",
"Inject winlogon.exe",
"Active X Run",
"Registry Run",
]:
if raw_config[capa].lower() == "true":
parsed_result.capability_enabled.append(capa)
else:
parsed_result.capability_disabled.append(capa)

# Delay Time
parsed_result.sleep_delay = raw_config["Delay Time"]

# Password
parsed_result.password.append(raw_config["Password"])

# C2 Domain
parsed_result.http.append(MACOModel.Http(hostname=raw_config["Domain"], usage="c2"))
# Registry
parsed_result.registry.append(MACOModel.Registry(key=raw_config["Registry Key"]))

# Install Path
parsed_result.paths.append(
MACOModel.Path(path=os.path.join(raw_config["Install Path"], raw_config["Install Name"]), usage="install")
)

# Campaign Group/Name
parsed_result.campaign_id = [raw_config["Campaign Name"], raw_config["Campaign Group"]]
return parsed_result


class BlackNix(Extractor):
author = "kevoreilly"
family = "BlackNix"
last_modified = "2024-10-26"
sharing = "TLP:CLEAR"

def run(self, stream, matches):
return convert_to_MACO(extract_config(stream.read()))
35 changes: 35 additions & 0 deletions modules/parsers/MACO/Blister.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import os

from maco.extractor import Extractor
from maco.model import ExtractorModel as MACOModel
from cape_parsers.CAPE.core.Blister import extract_config


def convert_to_MACO(raw_config: dict):
if not raw_config:
return None

parsed_result = MACOModel(family="Blister", other=raw_config)

for capa in ["Persistence", "Sleep after injection"]:
if raw_config[capa]:
parsed_result.capability_enabled.append(capa)
else:
parsed_result.capability_disabled.append(capa)

# Rabbit encryption
parsed_result.encryption.append(
MACOModel.Encryption(algorithm="rabbit", key=raw_config["Rabbit key"], iv=raw_config["Rabbit IV"])
)
return parsed_result


class Blister(Extractor):
author = "kevoreilly"
family = "Blister"
last_modified = "2024-10-26"
sharing = "TLP:CLEAR"
yara_rule = open(os.path.join(os.path.dirname(__file__).split("/modules", 1)[0], f"data/yara/CAPE/{family}.yar")).read()

def run(self, stream, matches):
return convert_to_MACO(extract_config(stream.read()))
Loading

0 comments on commit 571fcad

Please sign in to comment.