Release ER Production RTAs to DR (#2270)

(cherry picked from commit 0358ec9d9a)
This commit is contained in:
Mika Ayenson
2022-09-08 12:50:39 -04:00
committed by github-actions[bot]
parent 6c9881027b
commit 1dfc8ca817
308 changed files with 9859 additions and 367 deletions
+28
View File
@@ -17,7 +17,9 @@ from uuid import uuid4
import click
from .cli_utils import rule_prompt, multi_collection
from .mappings import build_coverage_map, get_triggered_rules, print_converage_summary
from .misc import add_client, client_error, nested_set, parse_config, load_current_package_version
from .rule import TOMLRule, TOMLRuleContents
from .rule_formatter import toml_write
@@ -425,3 +427,29 @@ def prep_rule(author: str):
updated_rule.write_text(json.dumps(template_rule, sort_keys=True))
click.echo(f'Rule saved to: {updated_rule}. Import this to Kibana to create alerts on all dnstwist-* indexes')
click.echo('Note: you only need to import and enable this rule one time for all dnstwist-* indexes')
@root.group('rta')
def rta_group():
"""Commands related to Red Team Automation (RTA) scripts."""
# create command to show rule-rta coverage
@rta_group.command('coverage')
@click.option("-o", "--os-filter", default="all",
help="Filter rule coverage summary by OS. (E.g. windows) Default: all")
def rta_coverage(os_filter: str):
"""Show coverage of RTA / rules by os type."""
# get all rules
all_rules = RuleCollection.default()
# get rules triggered by RTA
triggered_rules = get_triggered_rules()
# build coverage map
coverage_map = build_coverage_map(triggered_rules, all_rules)
# # print summary
all_rule_count = len(all_rules.rules)
print_converage_summary(coverage_map, all_rule_count, os_filter)
+80 -1
View File
@@ -7,10 +7,14 @@
import os
from collections import defaultdict
from rta import get_available_tests
from .rule import TOMLRule
from .schemas import validate_rta_mapping
from .utils import load_etc_dump, save_etc_dump, get_path
from .utils import get_path, load_etc_dump, save_etc_dump
RTA_DIR = get_path("rta")
RTA_PLATFORM_TYPES = ["windows", "linux", "macos"]
class RtaMappings:
@@ -73,3 +77,78 @@ class RtaMappings:
rta_files.add(rta_path)
return list(sorted(rta_files))
def get_triggered_rules() -> dict:
"""Get the rules that are triggered by each RTA."""
triggered_rules = {}
for rta_test in list(get_available_tests().values()):
for rule_info in rta_test.get("siem", []):
rule_id = rule_info.get("rule_id")
for platform in rta_test.get("platforms", []):
triggered_rules.setdefault(platform, []).append(rule_id)
return triggered_rules
def get_platform_list(rule: TOMLRule) -> list:
"""Get the list of OSes for a rule."""
os_list = []
if rule.contents.metadata.os_type_list:
os_list = [r.lower() for r in rule.contents.metadata.os_list]
elif rule.contents.data.tags:
tags = [t.lower() for t in rule.contents.data.tags]
os_list = [t for t in RTA_PLATFORM_TYPES if t in tags]
return os_list
def build_coverage_map(triggered_rules: dict, all_rules) -> dict:
"""Get the rules that are not covered by each rta."""
# avoid a circular import
from .rule_loader import RuleCollection
all_rules: RuleCollection
coverage_map = {"all": 0}
for rule in all_rules.rules:
rule_covered = False
os_list = get_platform_list(rule)
for os_type in os_list:
prefix = ""
if rule.contents.metadata.maturity == "development":
prefix = "DIAG : "
elif rule.contents.metadata.maturity == "deprecated":
prefix = "DEPR : "
if rule.id in triggered_rules[os_type]:
coverage_map.setdefault(os_type, {}).setdefault("supported", []).append(f"- [x] {prefix}{rule.name}")
rule_covered = True
else:
coverage_map.setdefault(os_type, {}).setdefault("unsupported", []).append(f"- [ ] {prefix}{rule.name}")
if rule_covered:
coverage_map["all"] += 1
return coverage_map
def print_converage_summary(coverage_map: dict, all_rule_count: int, os_filter: str):
"""Print the coverage summary."""
print("\n\nCoverage Report\n")
supported_count = coverage_map["all"]
print(f"{supported_count} / {all_rule_count} unique detection rules are supported by RTAs for all OS types")
for os_type, results in coverage_map.items():
if os_type != "all" and (os_type == os_filter or os_filter == "all"):
supported = results["supported"]
unsupported = results["unsupported"]
print(f"\n{os_type} coverage: {len(supported)} / {len(supported) + len(unsupported)}")
print("Supported:")
for rule in sorted(set(supported)):
print(f"\t{rule}")
print("Unsupported:")
for rule in sorted(set(unsupported)):
print(f"\t{rule}")
+58 -24
View File
@@ -4,41 +4,75 @@
# 2.0.
import importlib
import inspect
from dataclasses import asdict, dataclass, field
from pathlib import Path
from typing import List, Optional
from typing import Dict, List, Optional
from . import common
CURRENT_DIR = Path(__file__).resolve().parent
def get_ttp_list(os_types: Optional[List[str]] = None) -> List[str]:
scripts = []
if os_types and not isinstance(os_types, (list, tuple)):
os_types = [os_types]
@dataclass
class RtaMetadata:
"""Metadata associated with all RTAs."""
for script in CURRENT_DIR.glob("*.py"):
base_name = script.stem
if base_name not in ("common", "main") and not base_name.startswith("_"):
if os_types:
# Import it and skip it if it's not supported
importlib.import_module(__name__ + "." + base_name)
if not any(base_name in common.OS_MAPPING[os_type] for os_type in os_types):
continue
uuid: str
platforms: List[str]
scripts.append(str(script))
path: Path = field(init=False)
name: str = field(init=False)
endpoint: Optional[List[dict]] = None
siem: Optional[List[dict]] = None
techniques: Optional[List[str]] = None
return scripts
def __post_init__(self):
"""Set the path and name based on the callee and check for platforms."""
# set the path of the callee
for frame in inspect.stack():
self.path = Path(frame.filename)
self.name = self.path.name
if frame.function == "<module>" and valid_rta_file(self.path):
break
# check for valid platforms
if not self.platforms and (self.endpoint or self.siem):
raise ValueError(f"RTA {self.name} has no platforms specified but has rule info provided.")
def get_ttp_names(os_types: Optional[List[str]] = None) -> List[str]:
names = []
for script in get_ttp_list(os_types):
basename = Path(script).stem
names.append(basename)
return names
def valid_rta_file(file_path: str) -> bool:
return file_path.stem not in ["init", "common", "main"] and not file_path.name.startswith("_")
__all__ = (
"common"
)
def get_available_tests(print_list: bool = False, os_filter: str = None) -> Dict[str, dict]:
"""Get a list of available tests."""
test_metadata = {}
for file in CURRENT_DIR.rglob("*.py"):
if valid_rta_file(file):
module = importlib.import_module(f"rta.{file.stem}")
if os_filter and os_filter not in module.metadata.platforms and os_filter != "all":
continue
test_metadata[file.stem] = asdict(module.metadata)
if print_list:
longest_test_name = len(max(test_metadata.keys(), key=len))
header = f"{'name':{longest_test_name}} | {'platforms':<30}"
print("Printing available tests")
print(header)
print("=" * len(header))
for test in test_metadata.values():
print(f"{test['name']:<{longest_test_name}} | {', '.join(test['platforms'])}")
return test_metadata
__all__ = "common"
+28 -12
View File
@@ -4,25 +4,27 @@
# 2.0.
import argparse
import difflib
import importlib
import subprocess
import sys
import time
from pathlib import Path
from . import get_ttp_list, get_ttp_names
from . import get_available_tests
from .common import CURRENT_OS
DELAY = 1
RTA_PLATFORM_TYPES = ["windows", "linux", "macos"]
def run_all():
"""Run a single RTA."""
errors = []
for ttp_file in get_ttp_list(CURRENT_OS):
for ttp_file in get_available_tests(os_filter=CURRENT_OS):
print(f"---- {Path(ttp_file).name} ----")
p = subprocess.Popen([sys.executable, ttp_file])
p = subprocess.Popen([sys.executable, "-m", "rta", "-n", ttp_file])
p.wait()
code = p.returncode
@@ -37,25 +39,39 @@ def run_all():
def run(ttp_name: str, *args):
"""Run all RTAs compatible with OS."""
if ttp_name not in get_ttp_names():
raise ValueError(f"Unknown RTA {ttp_name}")
ttp_names = sorted(get_available_tests())
if ttp_name not in ttp_names:
suggestion = ', '.join(difflib.get_close_matches(ttp_name, ttp_names, n=3))
if suggestion:
suggestion = f"Did you mean {suggestion}?"
raise ValueError(f"Unknown RTA {ttp_name}. {suggestion}")
module = importlib.import_module("rta." + ttp_name)
return module.main(*args)
if __name__ == '__main__':
if __name__ == "__main__":
parser = argparse.ArgumentParser("rta")
parser.add_argument("--ttp-name")
parser.add_argument("-n", "--name", dest="name", nargs='+',
help="Name(s) of test(s) to execute. E.g. bitsadmin_execution adobe_hijack")
parser.add_argument("-l", "--list", dest="list", action="store_true", help="Print a list of available tests")
parser.add_argument("-o", "--os-filter", dest="os_filter", default="all", choices=RTA_PLATFORM_TYPES,
help="Filter rule coverage summary by OS. (E.g. windows) Default: all",)
parser.add_argument("--run-all", action="store_true")
parser.add_argument("--delay", type=int, help="For run-all, the delay between executions")
parsed_args, remaining = parser.parse_known_args()
if parsed_args.ttp_name and parsed_args.run_all:
raise ValueError(f"Pass --ttp-name or --run-all, not both")
if parsed_args.name:
if parsed_args.run_all:
raise ValueError(f"Pass ttp --name or --run-all, not both")
else:
for rta_test in parsed_args.name:
rta_name = Path(rta_test).stem
exit(run(rta_name, *remaining))
if parsed_args.run_all:
elif parsed_args.list:
get_available_tests(print_list=True, os_filter=parsed_args.os_filter)
elif parsed_args.run_all:
exit(run_all())
else:
rta_name = Path(parsed_args.run).stem
exit(run(rta_name, *remaining))
print("Execute 'python -m rta -h' to see available options")
+11 -1
View File
@@ -11,9 +11,19 @@
import os
from . import common
from . import RtaMetadata
@common.requires_os(common.WINDOWS)
metadata = RtaMetadata(
uuid="2df08481-31db-44a8-b01d-1c0df827bddb",
platforms=["windows"],
endpoint=[],
siem=[{"rule_id": "2bf78aa2-9c56-48de-b139-f169bf99cf86", "rule_name": "Adobe Hijack Persistence"}],
techniques=["T1574"],
)
@common.requires_os(metadata.platforms)
def main():
rdr_cef_dir = "C:\\Program Files (x86)\\Adobe\\Acrobat Reader DC\\Reader\\AcroCEF"
rdrcef_exe = os.path.join(rdr_cef_dir, "RdrCEF.exe")
+39
View File
@@ -0,0 +1,39 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="e5d376ae-d634-41fa-903c-42f35736a615",
platforms=["macos"],
endpoint=[],
siem=[
{
"rule_name": "Suspicious Child Process of Adobe Acrobat Reader Update Service",
"rule_id": "f85ce03f-d8a8-4c83-acdc-5c8cd0592be7",
}
],
techniques=["T1068"],
)
@common.requires_os(metadata.platforms)
def main():
masquerade = "/tmp/com.adobe.ARMDC.SMJobBlessHelper"
common.create_macos_masquerade(masquerade)
# Execute command
common.log("Launching fake com.adobe.ARMDC.SMJobBlessHelper commands to adobe mimic privesc")
common.execute([masquerade, "childprocess", masquerade], timeout=10, kill=True)
# cleanup
common.remove_file(masquerade)
if __name__ == "__main__":
exit(main())
+47
View File
@@ -0,0 +1,47 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="ea7c50ad-5736-48c7-bf39-50f708710826",
platforms=["macos"],
endpoint=[
{
"rule_name": "Script Execution via macOS Application Bundle",
"rule_id": "94a891a9-3771-4a8c-a6ca-82fa66cfd7e2",
}
],
siem=[],
techniques=["T1553", "T1059"],
)
@common.requires_os(metadata.platforms)
def main():
# create masquerades
masquerade = "/tmp/launchd"
masquerade2 = "/tmp/bash"
masquerade3 = "/tmp/curl"
common.create_macos_masquerade(masquerade)
common.create_macos_masquerade(masquerade2)
common.create_macos_masquerade(masquerade3)
# Execute command
common.log("Launching fake macOS application bundler commands")
command = f"{masquerade2} test.app/Contents/MacOS/test-psntest"
common.execute([masquerade, "childprocess", command], timeout=10, kill=True)
common.execute([masquerade2, "childprocess", masquerade3], timeout=10, kill=True)
# cleanup
common.remove_file(masquerade)
common.remove_file(masquerade2)
if __name__ == "__main__":
exit(main())
+14 -1
View File
@@ -11,11 +11,24 @@
import time
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="a4a8608e-d94f-4eb1-b500-738328307bbc",
platforms=["windows"],
endpoint=[],
siem=[
{"rule_id": "fd4a992d-6130-4802-9ff8-829b89ae801f", "rule_name": "Potential Application Shimming via Sdbinst"}
],
techniques=["T1546"],
)
SHIM_FILE = common.get_path("bin", "CVE-2013-3893.sdb")
@common.requires_os(common.WINDOWS)
@common.requires_os(metadata.platforms)
@common.dependencies(SHIM_FILE)
def main():
common.log("Application Compatibility Shims")
+24 -13
View File
@@ -14,44 +14,55 @@ import re
import sys
from . import common
from . import RtaMetadata
@common.requires_os(common.WINDOWS)
metadata = RtaMetadata(uuid="961d7a1f-7bad-41d5-a3d9-8e8a2f59a824", platforms=["windows"], endpoint=[], siem=[], techniques=[])
@common.requires_os(metadata.platforms)
def main(target_host=None):
target_host = target_host or common.get_ip()
host_str = '\\\\%s' % target_host
host_str = "\\\\%s" % target_host
# Current time at \\localhost is 11/16/2017 11:25:50 AM
code, output = common.execute(['net', 'time', host_str])
match = re.search(r'Current time at .*? is (\d+)/(\d+)/(\d+) (\d+):(\d+):(\d+) (AM|PM)', output)
code, output = common.execute(["net", "time", host_str])
match = re.search(r"Current time at .*? is (\d+)/(\d+)/(\d+) (\d+):(\d+):(\d+) (AM|PM)", output)
groups = match.groups()
m, d, y, hh, mm, ss, period = groups
now = datetime.datetime(month=int(m), day=int(d), year=int(y), hour=int(hh), minute=int(mm), second=int(ss))
if period == 'PM' and hh != '12':
now = datetime.datetime(
month=int(m),
day=int(d),
year=int(y),
hour=int(hh),
minute=int(mm),
second=int(ss),
)
if period == "PM" and hh != "12":
now += datetime.timedelta(hours=12)
# Add one hour
task_time = now + datetime.timedelta(hours=1)
# Round down minutes
time_string = '%d:%d' % (task_time.hour, task_time.minute)
time_string = "%d:%d" % (task_time.hour, task_time.minute)
# Enumerate all remote tasks
common.execute(['at.exe', host_str])
common.execute(["at.exe", host_str])
# Create a job 1 hour into the future
code, output = common.execute(['at', host_str, time_string, 'cmd /c echo hello world'])
code, output = common.execute(["at", host_str, time_string, "cmd /c echo hello world"])
if code == 1 and 'deprecated' in output:
if code == 1 and "deprecated" in output:
common.log("Unable to continue RTA. Not supported in this version of Windows")
return common.UNSUPPORTED_RTA
if code == 0:
job_id = re.search('ID = (\d+)', output).group(1)
job_id = re.search("ID = (\d+)", output).group(1)
# Check status and delete
common.execute(['at.exe', host_str, job_id])
common.execute(['at.exe', host_str, job_id, '/delete'])
common.execute(["at.exe", host_str, job_id])
common.execute(["at.exe", host_str, job_id, "/delete"])
if __name__ == "__main__":
+39
View File
@@ -0,0 +1,39 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from pathlib import Path
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="72c2470b-c96e-4b44-88ec-1a67c4ec091c",
platforms=["macos"],
endpoint=[],
siem=[
{
"rule_name": "Potential Persistence via Atom Init Script Modification",
"rule_id": "b4449455-f986-4b5a-82ed-e36b129331f7",
}
],
techniques=["T1037"],
)
@common.requires_os(metadata.platforms)
def main():
atom_dir = Path.home().joinpath(".atom")
atom_dir.mkdir(parents=True, exist_ok=True)
atom_path = atom_dir.joinpath("init.coffee")
common.log(f"Executing file modification on {atom_path} to mimic malicious Atom init file.")
common.temporary_file_helper("testing", file_name=atom_path)
# cleanup
common.remove_directory(str(atom_dir))
if __name__ == "__main__":
exit(main())
+27
View File
@@ -0,0 +1,27 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="96c3cc10-7f86-428c-b353-e9de52472a96",
platforms=["macos"],
endpoint=[],
siem=[{"rule_name": "Authorization Plugin Modification", "rule_id": "e6c98d38-633d-4b3e-9387-42112cd5ac10"}],
techniques=["T1547"],
)
@common.requires_os(metadata.platforms)
def main():
common.log("Executing file modification on test.plist to mimic authorization plugin modification")
common.temporary_file_helper("testing", file_name="/Library/Security/SecurityAgentPlugins/test.plist")
if __name__ == "__main__":
exit(main())
+41
View File
@@ -0,0 +1,41 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="6294e8bd-a82e-4d60-9de7-cceb639e91d9",
platforms=["macos"],
endpoint=[
{"rule_name": "Suspicious Automator Workflows Execution", "rule_id": "e390d36d-c739-43ee-9e3d-5a76fa853bd5"}
],
siem=[{"rule_name": "Suspicious Automator Workflows Execution", "rule_id": "5d9f8cfc-0d03-443e-a167-2b0597ce0965"}],
techniques=["T1059"],
)
@common.requires_os(metadata.platforms)
def main():
# create masquerades
masquerade = "/tmp/automator"
masquerade2 = "/tmp/com.apple.automator.runner"
common.create_macos_masquerade(masquerade)
common.copy_file("/usr/bin/curl", masquerade2)
# Execute command
common.log("Launching fake commands to launch Automator workflows")
common.execute([masquerade], timeout=10, kill=True)
common.execute([masquerade2, "portquiz.net"], timeout=10, kill=True)
# cleanup
common.remove_file(masquerade)
common.remove_file(masquerade2)
if __name__ == "__main__":
exit(main())
+36
View File
@@ -0,0 +1,36 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="057f2c1b-28cc-4286-92ce-75e789aa8e74",
platforms=["macos"],
endpoint=[
{"rule_name": "Potential Kerberos Attack via Bifrost", "rule_id": "fecebe4f-2d28-46e7-9bc1-71cdd8ecdd60"}
],
siem=[{"rule_name": "Potential Kerberos Attack via Bifrost", "rule_id": "16904215-2c95-4ac8-bf5c-12354e047192"}],
techniques=["T1558", "T1550"],
)
@common.requires_os(metadata.platforms)
def main():
masquerade = "/tmp/bifrost"
common.create_macos_masquerade(masquerade)
# Execute command
common.log("Launching fake bifrost attack with kerberoast commands")
common.execute([masquerade, "-action", "-kerberoast"], timeout=10, kill=True)
# cleanup
common.remove_file(masquerade)
if __name__ == "__main__":
exit(main())
Binary file not shown.
+27
View File
@@ -0,0 +1,27 @@
function Invoke-ImageLoad {
[CmdletBinding()]
param(
[Parameter(Position=0,Mandatory=$True)]
[String]
$DllPath
)
$type=@"
using System;
using System.Runtime.InteropServices;
public class ImportIt
{
public const string DLLPath = @"$DLLPath";
[DllImport(DLLPath, EntryPoint = "GetClassNameW", CharSet = CharSet.Unicode)]
public static extern int MessageBox(IntPtr hWnd, String text, String caption, uint type);
public static void Main()
{
MessageBox(new IntPtr(0), "Hello RTA!", "Hello Dialog", 0);
}
}
"@
Add-Type -TypeDefinition $type;
[ImportIt]::Main();
}
-1
View File
@@ -2,4 +2,3 @@
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
+9
View File
@@ -0,0 +1,9 @@
[version]
Signature=$chicago$
AdvancedINF=2.5
[DefaultInstall_SingleUser]
UnRegisterOCXs=UnRegisterOCXSection
[UnRegisterOCXSection]
%11%\scrobj.dll,NI,C:\Users\Administrator\Desktop\rta\bin\notepad.sct
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+37
View File
@@ -0,0 +1,37 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
import platform
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="62eb4521-cfb8-4fb8-bc6d-792fe57273b7",
platforms=["macos"],
endpoint=[
{
"rule_name": "Potential Binary Masquerading via Invalid Code Signature",
"rule_id": "4154c8ce-c718-4641-80db-a6a52276f1a4",
}
],
siem=[],
techniques=["T1036"],
)
@common.requires_os(metadata.platforms)
def main():
if platform.processor() == "arm":
name = "com.apple.sleep_arm"
else:
name = "com.apple.sleep_intel"
path = common.get_path("bin", name)
common.execute([path, "5"], kill=True)
if __name__ == "__main__":
exit(main())
+13 -3
View File
@@ -13,9 +13,19 @@ import os
import subprocess
from . import common
from . import RtaMetadata
@common.requires_os(common.WINDOWS)
metadata = RtaMetadata(
uuid="aee48793-01ec-428f-9890-c5db9df07830",
platforms=["windows"],
endpoint=[],
siem=[{"rule_id": "a624863f-a70d-417f-a7d2-7a404638d47f", "rule_name": "Suspicious MS Office Child Process"}],
techniques=["T1566"],
)
@common.requires_os(metadata.platforms)
def main():
common.log("Running Windows BitsAdmin to Download")
server, ip, port = common.serve_web()
@@ -26,9 +36,9 @@ def main():
common.log("Emulating parent process: {parent}".format(parent=fake_word))
common.copy_file("C:\\Windows\\System32\\cmd.exe", fake_word)
command = subprocess.list2cmdline(['bitsadmin.exe', '/Transfer', '/Download', url, dest_path])
command = subprocess.list2cmdline(["bitsadmin.exe", "/Transfer", "/Download", url, dest_path])
common.execute([fake_word, "/c", command], timeout=15, kill=True)
common.execute(['taskkill', '/f', '/im', 'bitsadmin.exe'])
common.execute(["taskkill", "/f", "/im", "bitsadmin.exe"])
common.remove_files(dest_path, fake_word)
+42
View File
@@ -0,0 +1,42 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
import subprocess
from pathlib import Path
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="e7a55d39-37b4-4f37-9519-3779b3c23bfa",
platforms=["windows"],
endpoint=[
{"rule_name": "Suspicious Bitsadmin Activity", "rule_id": "676ac66c-4899-498f-ae21-ed5620af5477"},
{"rule_name": "Suspicious Microsoft Office Child Process", "rule_id": "c34a9dca-66cf-4283-944d-1800b28ae690"},
],
siem=[],
techniques=["T1197", "T1566"],
)
ROOT_DIR = Path(__file__).parent
EXE_FILE = common.get_path("bin", "renamed.exe")
@common.requires_os(metadata.platforms)
def main():
fake_word = ROOT_DIR / "winword.exe"
common.log(f"Copying {EXE_FILE} to {fake_word}")
common.copy_file(EXE_FILE, fake_word)
command = subprocess.list2cmdline(["bitsadmin.exe", "/Transfer", "/Download"])
common.execute([fake_word, "/c", command], timeout=15, kill=True)
common.execute(["taskkill", "/f", "/im", "bitsadmin.exe"])
common.remove_files(fake_word)
if __name__ == "__main__":
exit(main())
+41
View File
@@ -0,0 +1,41 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from pathlib import Path
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="ea187b1f-4aa0-4ffc-bac9-9ee1d55552fd",
platforms=["macos"],
endpoint=[
{
"rule_name": "Suspicious Access to Stored Browser Credentials",
"rule_id": "cea870d6-e6ee-4435-bc80-2c80e834c5d1",
}
],
siem=[{"rule_name": "Access of Stored Browser Credentials", "rule_id": "20457e4f-d1de-4b92-ae69-142e27a4342a"}],
techniques=["T1539", "T1555"],
)
@common.requires_os(metadata.platforms)
def main():
masquerade = "/tmp/bash"
common.create_macos_masquerade(masquerade)
# Execute command
common.log("Launching fake commands to aquire browser creds")
cookie_path = f"{Path.home()}/Library/Application Support/Google/Chrome/Default/Cookies"
common.execute([masquerade, cookie_path], timeout=10, kill=True)
# cleanup
common.remove_file(masquerade)
if __name__ == "__main__":
exit(main())
+69
View File
@@ -0,0 +1,69 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
import platform
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="e061a96e-4c31-4f67-9745-6ff873f7829e",
platforms=["windows", "macos", "linux"],
endpoint=[
{
"rule_name": "Potential Cookies Theft via Browser Debugging",
"rule_id": "5d7328aa-973b-41e7-a6b3-6f40ea3094f1",
}
],
siem=[
{
"rule_name": "Potential Cookies Theft via Browser Debugging",
"rule_id": "027ff9ea-85e7-42e3-99d2-bbb7069e02eb",
}
],
techniques=["T1539"],
)
EXE_FILE = common.get_path("bin", "renamed_posh.exe")
@common.requires_os(metadata.platforms)
def main():
param1 = "--remote-debugging-port=9222"
param2 = "--user-data-dir=remote-profile"
if platform.system() == "Darwin":
if platform.processor() == "arm":
name = "com.apple.ditto_and_spawn_arm"
else:
name = "com.apple.ditto_and_spawn_intel"
source = common.get_path("bin", name)
chrome = "/tmp/google-chrome"
common.copy_file(source, chrome)
common.log("Starting browser on debug mode")
common.execute([chrome, param1, param2], timeout=10, kill=True)
elif common.CURRENT_OS == "linux":
name = "linux.ditto_and_spawn"
source = common.get_path("bin", name)
chrome = "/tmp/google-chrome"
common.copy_file(source, chrome)
common.log("Starting browser on debug mode")
common.execute([chrome, param1, param2], timeout=10, kill=True)
else:
chrome = "C:\\Users\\Public\\chrome.exe"
common.copy_file(EXE_FILE, chrome)
# Execute command
common.log("Mimicking the start of a browser on debug mode")
common.execute([chrome, "/c", "echo", param1, param2], timeout=10)
common.remove_file(chrome)
if __name__ == "__main__":
exit(main())
+29 -9
View File
@@ -15,23 +15,39 @@ import sys
import time
from . import common
from . import RtaMetadata
@common.requires_os(common.WINDOWS)
metadata = RtaMetadata(
uuid="35bb73a9-cafa-4b2c-81f0-a97e2afa5e1c",
platforms=["windows"],
endpoint=[],
siem=[
{"rule_id": "e08ccd49-0380-4b2b-8d71-8000377d6e49", "rule_name": "Attempts to Brute Force an Okta User Account"}
],
techniques=["T1110"],
)
@common.requires_os(metadata.platforms)
def main(username="rta-tester", remote_host=None):
if not remote_host:
common.log('A remote host is required to detonate this RTA', '!')
common.log("A remote host is required to detonate this RTA", "!")
return common.MISSING_REMOTE_HOST
common.enable_logon_auditing(remote_host)
common.log('Brute forcing login with invalid password against {}'.format(remote_host))
ps_command = '''
common.log("Brute forcing login with invalid password against {}".format(remote_host))
ps_command = """
$PW = ConvertTo-SecureString "such-secure-passW0RD!" -AsPlainText -Force
$CREDS = New-Object System.Management.Automation.PsCredential {username}, $PW
Invoke-WmiMethod -ComputerName {host} -Class Win32_process -Name create -ArgumentList ipconfig -Credential $CREDS
'''
command = ['powershell', '-c', ps_command.format(username=username, host=remote_host)]
"""
command = [
"powershell",
"-c",
ps_command.format(username=username, host=remote_host),
]
# fail 4 times - the first 3 concurrently and wait for the final to complete
for i in range(4):
@@ -39,12 +55,16 @@ def main(username="rta-tester", remote_host=None):
time.sleep(1)
common.log('Password spraying against {}'.format(remote_host))
common.log("Password spraying against {}".format(remote_host))
# fail 5 times - the first 4 concurrently and wait for the final to complete
for i in range(5):
random_user = ''.join(random.sample(string.ascii_letters, 10))
command = ['powershell', '-c', ps_command.format(username=random_user, host=remote_host)]
random_user = "".join(random.sample(string.ascii_letters, 10))
command = [
"powershell",
"-c",
ps_command.format(username=random_user, host=remote_host),
]
common.execute(command, wait=i == 4)
# allow time for audit event to process
+36
View File
@@ -0,0 +1,36 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from pathlib import Path
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="44345dc0-883f-41b7-ad34-1d84cfd57129",
platforms=["macos"],
endpoint=[],
siem=[{"rule_name": "Suspicious Calendar File Modification", "rule_id": "cb71aa62-55c8-42f0-b0dd-afb0bb0b1f51"}],
techniques=["T1546"],
)
@common.requires_os(metadata.platforms)
def main():
cal_dir = Path(f"{Path.home()}/Library/Calendars/")
cal_calendar = cal_dir.joinpath("test.calendar", "Events")
cal_calendar.mkdir(parents=True, exist_ok=True)
cal_path = str(cal_calendar.joinpath("test.ics"))
common.log(f"Executing file modification on {cal_path} to mimic suspicious calendar file modification")
common.temporary_file_helper("testing", file_name=cal_path)
# cleanup
common.remove_directory(str(cal_calendar))
common.remove_directory(str(cal_dir))
if __name__ == "__main__":
exit(main())
+21 -4
View File
@@ -12,14 +12,31 @@
import os
from . import common
from . import RtaMetadata
@common.requires_os(common.WINDOWS)
metadata = RtaMetadata(
uuid="7b2c1b3e-2097-4e2f-bf5c-e157a91b8001",
platforms=["windows"],
endpoint=[],
siem=[{"rule_id": "fd70c98a-c410-42dc-a2e3-761c71848acf", "rule_name": "Suspicious CertUtil Commands"}],
techniques=["T1140"],
)
@common.requires_os(metadata.platforms)
def main():
common.log("Encoding target")
encoded_file = os.path.abspath('encoded.txt')
decoded_file = os.path.abspath('decoded.exe')
common.execute(["c:\\Windows\\System32\\certutil.exe", "-encode", "c:\\windows\\system32\\cmd.exe", encoded_file])
encoded_file = os.path.abspath("encoded.txt")
decoded_file = os.path.abspath("decoded.exe")
common.execute(
[
"c:\\Windows\\System32\\certutil.exe",
"-encode",
"c:\\windows\\system32\\cmd.exe",
encoded_file,
]
)
common.log("Decoding target")
common.execute(["c:\\Windows\\System32\\certutil.exe", "-decode", encoded_file, decoded_file])
+12 -1
View File
@@ -9,11 +9,22 @@
# Description: Uses certutil.exe to download a file.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="10609a63-0013-4fd0-9322-66c86c1c9501",
platforms=["windows"],
endpoint=[],
siem=[{"rule_id": "3838e0e3-1850-4850-a411-2e8c5ba40ba8", "rule_name": "Network Connection via Certutil"}],
techniques=["T1105"],
)
MY_DLL = common.get_path("bin", "mydll.dll")
@common.requires_os(common.WINDOWS)
@common.requires_os(metadata.platforms)
@common.dependencies(MY_DLL)
def main():
# http server will terminate on main thread exit
+34
View File
@@ -0,0 +1,34 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="be6619a2-324a-443b-9f23-2dc84733c847",
platforms=["windows"],
endpoint=[
{"rule_name": "Suspicious Microsoft IIS Worker Descendant", "rule_id": "89c9c5a0-a136-41e9-8cc8-f21ef5ad894b"}
],
siem=[],
techniques=["T1190", "T1059"],
)
EXE_FILE = common.get_path("bin", "renamed_posh.exe")
@common.requires_os(metadata.platforms)
def main():
w3wp = "C:\\Users\\Public\\w3wp.exe"
common.copy_file(EXE_FILE, w3wp)
# Creating a high entropy file, and executing the rename operation
common.execute([w3wp, "/c", "cmd.exe"], timeout=10)
common.remove_file(w3wp)
if __name__ == "__main__":
exit(main())
+42
View File
@@ -0,0 +1,42 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
import os
metadata = RtaMetadata(
uuid="9bf3622b-dd76-4156-a89c-6845dca46b1f",
platforms=["windows"],
endpoint=[
{"rule_name": "Execution from Unusual Directory", "rule_id": "16c84e67-e5e7-44ff-aefa-4d771bcafc0c"},
{
"rule_name": "Managed .NET Code Execution via Windows Script Interpreter",
"rule_id": "5a898048-d98c-44c6-b7ba-f63a31eb3571",
},
],
siem=[],
techniques=["T1220", "T1218", "T1055", "T1059"],
)
EXE_FILE = common.get_path("bin", "renamed_posh.exe")
@common.requires_os(metadata.platforms)
def main():
msxsl = "C:\\Users\\Public\\msxsl.exe"
fake_clr_path = "C:\\Users\\Administrator\\AppData\\Local\\Microsoft\\CLR_v4.0\\UsageLogs"
fake_clr_logs = fake_clr_path + "\\msxsl.exe.log"
common.copy_file(EXE_FILE, msxsl)
os.makedirs(fake_clr_path, exist_ok=True)
common.log("Creating a fake clr log file")
common.execute([msxsl, "-c", f"echo RTA > {fake_clr_logs}"], timeout=10)
common.remove_files(msxsl, fake_clr_logs)
if __name__ == "__main__":
exit(main())
+38
View File
@@ -0,0 +1,38 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="6c399694-d21c-4a19-9e58-8fa24eb399b9",
platforms=["windows"],
endpoint=[
{
"rule_name": "Windows Command Shell Spawned via Microsoft Office",
"rule_id": "2a396a3c-b343-42a9-b74b-c5b9925b6ee2",
}
],
siem=[],
techniques=["T1566", "T1059"],
)
EXE_FILE = common.get_path("bin", "renamed.exe")
@common.requires_os(metadata.platforms)
def main():
binary = "winword.exe"
common.copy_file(EXE_FILE, binary)
# Execute command
common.execute([binary, "/c", "cmd.exe /c 'echo comspec'"], timeout=5, kill=True)
common.remove_files(binary)
if __name__ == "__main__":
exit(main())
+50
View File
@@ -0,0 +1,50 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="aa6bf766-db74-4db5-8eec-f91386b1285b",
platforms=["windows"],
endpoint=[
{"rule_name": "Execution from Unusual Directory", "rule_id": "16c84e67-e5e7-44ff-aefa-4d771bcafc0c"},
{"rule_name": "Binary Masquerading via Untrusted Path", "rule_id": "35dedf0c-8db6-4d70-b2dc-a133b808211f"},
{"rule_name": "Scriptlet Execution via CMSTP", "rule_id": "8adfa9ad-0ed2-4b1b-bdad-f2c52e1d2a00"},
],
siem=[],
techniques=["T1218", "T1036", "T1059"],
)
EXE_FILE = common.get_path("bin", "renamed_posh.exe")
PS1_FILE = common.get_path("bin", "Invoke-ImageLoad.ps1")
RENAMER = common.get_path("bin", "rcedit-x64.exe")
@common.requires_os(metadata.platforms)
def main():
cmstp = "C:\\Users\\Public\\cmstp.exe"
user32 = "C:\\Windows\\System32\\user32.dll"
dll = "C:\\Users\\Public\\scrobj.dll"
ps1 = "C:\\Users\\Public\\Invoke-ImageLoad.ps1"
rcedit = "C:\\Users\\Public\\rcedit.exe"
common.copy_file(EXE_FILE, cmstp)
common.copy_file(user32, dll)
common.copy_file(PS1_FILE, ps1)
common.copy_file(RENAMER, rcedit)
# Execute command
common.log("Modifying the OriginalFileName attribute")
common.execute([rcedit, cmstp, "--set-version-string", "OriginalFilename", "CMSTP.EXE"])
common.log("Loading scrobj.dll into fake cmstp")
common.execute([cmstp, "-c", f"Import-Module {ps1}; Invoke-ImageLoad {dll}"], timeout=10)
common.remove_files(cmstp, dll, ps1, rcedit)
if __name__ == "__main__":
exit(main())
+36 -9
View File
@@ -11,6 +11,7 @@ import functools
import getpass
import inspect
import os
import platform
import re
import shutil
import socket
@@ -181,7 +182,7 @@ def temporary_file(contents, file_name=None):
def temporary_file_helper(contents, file_name=None):
if not (file_name and os.path.isabs(file_name)):
file_name = os.path.join(tempfile.gettempdir(), file_name or "temp{:d}".format(hash(contents)))
file_name = os.path.join(tempfile.gettempdir(), file_name or f"temp{hash(contents):d}")
with open(file_name, "wb" if isinstance(contents, bytes) else "w") as f:
f.write(contents)
@@ -302,6 +303,16 @@ def copy_file(source, target):
shutil.copy(source, target)
def create_macos_masquerade(masquerade: str):
if platform.processor() == "arm":
name = "com.apple.ditto_and_spawn_arm"
else:
name = "com.apple.ditto_and_spawn_intel"
source = get_path("bin", name)
copy_file(source, masquerade)
def link_file(source, target):
log("Linking %s -> %s" % (source, target))
execute(["ln", "-s", source, target])
@@ -323,7 +334,7 @@ def remove_file(path):
def remove_directory(path):
if os.path.exists(path):
if os.path.isdir(path):
log("Removing directory {:s}".format(path), log_type="-")
log(f"Removing directory {path:s}", log_type="-")
shutil.rmtree(path)
else:
remove_file(path)
@@ -361,7 +372,7 @@ def serve_web(ip=None, port=None, directory=BASE_DIR):
pass
def server_thread():
log("Starting web server on http://{ip}:{port:d} for directory {dir}".format(ip=ip, port=port, dir=directory))
log(f"Starting web server on http://{ip}:{port:d} for directory {directory}")
os.chdir(directory)
server.serve_forever()
@@ -505,13 +516,21 @@ def run_system(arguments=None):
return code
def write_reg(hive, key, value, data, data_type=None, restore=True, pause=False, append=False):
# type: (str, str, str, str|int, str|int|list, bool, bool, bool) -> None
def write_reg(
hive: str,
key: str,
value: str,
data: Union[str, int],
data_type: Union[str, int, list],
restore=True,
pause=False,
append=False,
) -> None:
with temporary_reg(hive, key, value, data, data_type, restore, pause, append):
pass
def read_reg(hive, key, value): # type: (str, str, str) -> (str, str)
def read_reg(hive: str, key: str, value: str) -> (str, str):
winreg = get_winreg()
if isinstance(hive, str):
@@ -537,8 +556,16 @@ def read_reg(hive, key, value): # type: (str, str, str) -> (str, str)
@contextlib.contextmanager
def temporary_reg(hive, key, value, data, data_type="sz", restore=True, pause=False, append=False):
# type: (str, str, str, str|int, str|int|list, bool, bool, bool) -> None
def temporary_reg(
hive: str,
key: str,
value: str,
data: Union[str, int],
data_type: Union[str, int, list] = "sz",
restore=True,
pause=False,
append=False,
) -> None:
winreg = get_winreg()
if isinstance(hive, str):
@@ -618,7 +645,7 @@ def temporary_reg(hive, key, value, data, data_type="sz", restore=True, pause=Fa
def enable_logon_auditing(host="localhost", verbose=True, sleep=2):
"""Enable logon auditing on local or remote system to enable 4624 and 4625 events."""
if verbose:
log("Ensuring audit logging enabled on {}".format(host))
log(f"Ensuring audit logging enabled on {host}")
auditpol = "auditpol.exe /set /subcategory:Logon /failure:enable /success:enable"
enable_logging = "Invoke-WmiMethod -ComputerName {} -Class Win32_process -Name create -ArgumentList '{}'".format(
+31 -3
View File
@@ -12,14 +12,42 @@ import os
import time
from . import common
from . import RtaMetadata
@common.requires_os(common.WINDOWS)
metadata = RtaMetadata(
uuid="413cf7ef-0fad-46fd-ab67-e94c4e3e0f0b",
platforms=["windows"],
endpoint=[],
siem=[
{
"rule_id": "c5c9f591-d111-4cf8-baec-c26a39bc31ef",
"rule_name": "Potential Credential Access via Renamed COM+ Services DLL",
},
{"rule_id": "208dbe77-01ed-4954-8d44-1e5751cb20de", "rule_name": "LSASS Memory Dump Handle Access"},
{
"rule_id": "00140285-b827-4aee-aa09-8113f58a08f3",
"rule_name": "Potential Credential Access via Windows Utilities",
},
],
techniques=["T1003"],
)
@common.requires_os(metadata.platforms)
def main():
common.log("Memory Dump via Comsvcs")
pid = os.getpid()
common.execute(["powershell.exe", "-c", "rundll32.exe", "C:\\Windows\\System32\\comsvcs.dll",
"MiniDump", "{} dump.bin full".format(pid)])
common.execute(
[
"powershell.exe",
"-c",
"rundll32.exe",
"C:\\Windows\\System32\\comsvcs.dll",
"MiniDump",
"{} dump.bin full".format(pid),
]
)
time.sleep(1)
common.remove_file("dump.bin")
+34
View File
@@ -0,0 +1,34 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="775ffaa8-7a44-490b-b13d-1bfa2100b1ae",
platforms=["windows"],
endpoint=[
{"rule_name": "CrashDump Disabled via Registry Modification", "rule_id": "77ca3fcc-f607-45e0-837e-e4173e4ffc2a"}
],
siem=[],
techniques=["T1112"],
)
@common.requires_os(metadata.platforms)
def main():
common.log("Temporarily disabling CrashDump...")
key = "System\\CurrentControlSet\\Control\\CrashControl"
value = "CrashDumpEnabled"
data = "0"
with common.temporary_reg(common.HKLM, key, value, data):
pass
if __name__ == "__main__":
exit(main())
@@ -0,0 +1,31 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="0a6fcfaa-db5e-498f-9253-0f76b8a18687",
platforms=["macos"],
endpoint=[
{"rule_name": "Dumping Account Hashes via Built-In Commands", "rule_id": "2ed766db-e0b0-4a07-8ec1-4e41dd406b64"}
],
siem=[
{"rule_name": "Dumping Account Hashes via Built-In Commands", "rule_id": "02ea4563-ec10-4974-b7de-12e65aa4f9b3"}
],
techniques=["T1003"],
)
@common.requires_os(metadata.platforms)
def main():
common.log("Executing defaults commands to dump hashes.")
common.execute(["defaults", "ShadowHashData", "-dump"])
if __name__ == "__main__":
exit(main())
+35
View File
@@ -0,0 +1,35 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="374718be-d841-4381-a75f-ef54f0d5eb18",
platforms=["windows"],
endpoint=[
{"rule_name": "Credential Access via Known Utilities", "rule_id": "3c44fc50-2672-48b3-af77-ff43b895ac70"}
],
siem=[],
techniques=["T1003"],
)
EXE_FILE = common.get_path("bin", "renamed.exe")
@common.requires_os(metadata.platforms)
def main():
binary = "ProcessDump.exe"
common.copy_file(EXE_FILE, binary)
# Execute command
common.execute([binary], timeout=5, kill=True)
common.remove_files(binary)
if __name__ == "__main__":
exit(main())
@@ -0,0 +1,36 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="cc7b01f9-852c-4232-8c70-ada3fb5cc515",
platforms=["macos"],
endpoint=[
{"rule_name": "Potential Credentials Phishing via OSASCRIPT", "rule_id": "318d3d9d-ba60-40e3-bc8c-3d3304209a3c"}
],
siem=[{"rule_name": "Prompt for Credentials with OSASCRIPT", "rule_id": "38948d29-3d5d-42e3-8aec-be832aaaf8eb"}],
techniques=["T1056"],
)
@common.requires_os(metadata.platforms)
def main():
masquerade = "/tmp/osascript"
common.create_macos_masquerade(masquerade)
# Execute command
common.log("Launching fake osascript commands to display passwords")
common.execute([masquerade, "osascript*display dialog*password*"], timeout=10, kill=True)
# cleanup
common.remove_file(masquerade)
if __name__ == "__main__":
exit(main())
+40
View File
@@ -0,0 +1,40 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
import os
metadata = RtaMetadata(
uuid="d12e0abb-017f-4321-adf2-20843f62b55d",
platforms=["windows"],
endpoint=[
{
"rule_name": "Potential Discovery of Windows Credential Manager Store",
"rule_id": "cc60be0e-2c6c-4dc9-9902-e97103ff8df9",
}
],
siem=[],
techniques=["T1555"],
)
@common.requires_os(metadata.platforms)
def main():
appdata = os.getenv("LOCALAPPDATA")
credmanfile = f"{appdata}\\Microsoft\\Credentials\\a.txt"
powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe"
# Execute command
common.execute([powershell, "/c", "echo AAAAAAAAAA >", credmanfile], timeout=10)
common.log("Cat the contents of a sample file in credman folder")
common.execute([powershell, "/c", "cat", credmanfile], timeout=10)
common.remove_file(credmanfile)
if __name__ == "__main__":
exit(main())
+45
View File
@@ -0,0 +1,45 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="5a2a5c20-73f6-4a08-a767-95d242b52708",
platforms=["windows"],
endpoint=[
{"rule_name": "Suspicious Windows Script Process Execution", "rule_id": "ffbab5db-73ae-42fd-a33f-36bf649f41cc"},
{"rule_name": "Execution from Unusual Directory", "rule_id": "16c84e67-e5e7-44ff-aefa-4d771bcafc0c"},
{"rule_name": "Binary Masquerading via Untrusted Path", "rule_id": "35dedf0c-8db6-4d70-b2dc-a133b808211f"},
],
siem=[],
techniques=["T1218", "T1036", "T1059"],
)
EXE_FILE = common.get_path("bin", "renamed_posh.exe")
RENAMER = common.get_path("bin", "rcedit-x64.exe")
@common.requires_os(metadata.platforms)
def main():
cscript = "C:\\Users\\Public\\cscript.exe"
rcedit = "C:\\Users\\Public\\rcedit.exe"
common.copy_file(EXE_FILE, cscript)
common.copy_file(RENAMER, rcedit)
# Execute command
common.log("Modifying the OriginalFileName attribute")
common.execute([rcedit, cscript, "--set-version-string", "OriginalFilename", "cscript.exe"])
cmd = "echo {16d51579-a30b-4c8b-a276-0ff4dc41e755}; iwr google.com -UseBasicParsing"
common.log("Simulating a suspicious command line and making a web request")
common.execute([cscript, "-c", cmd], timeout=10)
common.remove_files(cscript, rcedit)
if __name__ == "__main__":
exit(main())
+39
View File
@@ -0,0 +1,39 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="bf7645b2-d0cf-428d-a158-b1479160e60c",
platforms=["macos"],
endpoint=[
{
"rule_name": "Payload Downloaded by Process Running in Suspicious Directory",
"rule_id": "04d124d4-2be7-405e-b830-9494f927a51e",
}
],
siem=[],
techniques=["T1105"],
)
@common.requires_os(metadata.platforms)
def main():
masquerade = "/tmp/testfile"
common.create_macos_masquerade(masquerade)
# Execute command
common.log("Launching fake curl commands to download payload")
common.execute([masquerade, "childprocess", "curl", "portquiz.net"], timeout=5, kill=True)
# cleanup
common.remove_file(masquerade)
if __name__ == "__main__":
exit(main())
+38
View File
@@ -0,0 +1,38 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="4843eb25-3579-473a-b309-76d02eda3085",
platforms=["macos", "linux"],
endpoint=[{"rule_name": "DARKRADIATION Ransomware Infection", "rule_id": "33309858-3154-47a6-b601-eda2de62557b"}],
siem=[],
techniques=["T1486"],
)
@common.requires_os(metadata.platforms)
def main():
masquerade = "/tmp/xargs"
if common.CURRENT_OS == "linux":
source = common.get_path("bin", "linux.ditto_and_spawn")
common.copy_file(source, masquerade)
else:
common.create_macos_masquerade(masquerade)
# Execute command
common.log("Launching fake xargs command to execute DARKRADIATION infection")
common.execute([masquerade, "openssl", "enc", "test.☢test"], timeout=10, kill=True)
# cleanup
common.remove_file(masquerade)
if __name__ == "__main__":
exit(main())
+14 -2
View File
@@ -11,9 +11,19 @@
import sys
from . import common
from . import RtaMetadata
@common.requires_os("windows")
metadata = RtaMetadata(
uuid="7f4cfcf6-881b-48b0-864d-21eba06e57cc",
platforms=["windows"],
endpoint=[],
siem=[{"rule_id": "51ce96fb-9e52-4dad-b0ba-99b54440fc9a", "rule_name": "Incoming DCOM Lateral Movement with MMC"}],
techniques=["T1021"],
)
@common.requires_os(metadata.platforms)
def main(remote_host=None):
remote_host = remote_host or common.get_ip()
common.log("DCOM Lateral Movement with MMC")
@@ -29,7 +39,9 @@ def main(remote_host=None):
$dcom.Document.ActiveView.ExecuteShellCommand('C:\\Windows\\System32\\cmd.exe',$null,'whoami','7');
$dcom.Document.ActiveView.ExecuteShellCommand('C:\\Windows\\System32\\calc.exe',$null,$null,'7');
$dcom.quit();
""".format(remote_host=remote_host)
""".format(
remote_host=remote_host
)
command = ["powershell", "-c", ps_command]
+37
View File
@@ -0,0 +1,37 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="95d34e55-789d-40bf-9988-dbb803c2d066",
platforms=["windows"],
endpoint=[
{
"rule_name": "Connection to Dynamic DNS Provider by a Signed Binary Proxy",
"rule_id": "fb6939a2-1b54-428c-92a2-3a831585af2a",
}
],
siem=[],
techniques=["T1218", "T1071"],
)
@common.requires_os(metadata.platforms)
def main():
powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe"
# Execute command
common.log("Using PowerShell to connect to a DDNS provider website")
common.execute(
[powershell, "/c", "iwr", "https://www.noip.com", "-UseBasicParsing"],
timeout=10,
)
if __name__ == "__main__":
exit(main())
+38
View File
@@ -0,0 +1,38 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="9e85eb9f-ee9e-4c73-8a83-14dd29a5aa80",
platforms=["windows"],
endpoint=[
{
"rule_name": "Connection to Dynamic DNS Provider by an Unsigned Binary",
"rule_id": "75b80e66-90d0-4ab6-9e6b-976f7d690906",
}
],
siem=[],
techniques=["T1071"],
)
EXE_FILE = common.get_path("bin", "renamed_posh.exe")
@common.requires_os(metadata.platforms)
def main():
posh = "C:\\Users\\Public\\posh.exe"
common.copy_file(EXE_FILE, posh)
# Execute command
common.log("Using PowerShell to connect to a DDNS provider website")
common.execute([posh, "/c", "iwr", "https://www.noip.com", "-UseBasicParsing"], timeout=10)
common.remove_file(posh)
if __name__ == "__main__":
exit(main())
@@ -0,0 +1,29 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="b023cf4b-2856-4170-9ea0-884041904159",
platforms=["macos"],
endpoint=[
{"rule_name": "MacOS Monterey Reflective Code Loading", "rule_id": "16fba7a9-f8f6-43ce-ae24-6a392a48e49c"}
],
siem=[],
techniques=["T1620", "T1106"],
)
@common.requires_os(metadata.platforms)
def main():
common.log("Executing deletion on /private/tmp/NSCreateObjectFileImageFromMemory-test file.")
common.temporary_file_helper("testing", file_name="/private/tmp/NSCreateObjectFileImageFromMemory-test")
if __name__ == "__main__":
exit(main())
@@ -0,0 +1,44 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="9d02871f-6338-47aa-84c4-7d622692319f",
platforms=["macos"],
endpoint=[
{
"rule_name": "Modification of Safari Settings via Defaults Command",
"rule_id": "396e1138-243c-4215-a8ed-be303204710d",
}
],
siem=[
{
"rule_name": "Modification of Safari Settings via Defaults Command",
"rule_id": "6482255d-f468-45ea-a5b3-d3a7de1331ae",
}
],
techniques=["T1562"],
)
@common.requires_os(metadata.platforms)
def main():
masquerade = "/tmp/defaults"
common.create_macos_masquerade(masquerade)
# Execute command
common.log("Launching commands to mimic defaults modifying safari configurations.")
common.execute([masquerade, "write", "com.apple.Safari", "JavaScript"], timeout=10, kill=True)
# cleanup
common.remove_file(masquerade)
if __name__ == "__main__":
exit(main())
+11 -1
View File
@@ -13,9 +13,19 @@
import os
from . import common
from . import RtaMetadata
@common.requires_os(common.WINDOWS)
metadata = RtaMetadata(
uuid="eaf71384-2e38-4970-b170-9645ccde1d2b",
platforms=["windows"],
endpoint=[],
siem=[{"rule_id": "69c251fb-a5d6-4035-b5ec-40438bd829ff", "rule_name": "Modification of Boot Configuration"}],
techniques=["T1490"],
)
@common.requires_os(metadata.platforms)
def main():
# Messing with the boot configuration is probably not a great idea so create a backup:
common.log("Exporting the boot configuration....")
+11 -1
View File
@@ -11,9 +11,19 @@
import time
from . import common
from . import RtaMetadata
@common.requires_os(common.WINDOWS)
metadata = RtaMetadata(
uuid="8ffd2053-c04a-435a-84b3-a8403a5395db",
platforms=["windows"],
endpoint=[],
siem=[{"rule_id": "581add16-df76-42bb-af8e-c979bfb39a59", "rule_name": "Deleting Backup Catalogs with Wbadmin"}],
techniques=["T1490"],
)
@common.requires_os(metadata.platforms)
def main():
warning = "Deleting the backup catalog may have unexpected consequences. Operational issues are unknown."
common.log("WARNING: %s" % warning, log_type="!")
+11 -1
View File
@@ -12,9 +12,19 @@
import time
from . import common
from . import RtaMetadata
@common.requires_os(common.WINDOWS)
metadata = RtaMetadata(
uuid="5d049893-b5ca-4482-a9ea-c38c6d01c171",
platforms=["windows"],
endpoint=[],
siem=[{"rule_id": "f675872f-6d85-40a3-b502-c0d2ef101e92", "rule_name": "Delete Volume USN Journal with Fsutil"}],
techniques=["T1070"],
)
@common.requires_os(metadata.platforms)
def main():
message = "Deleting the USN journal may have unintended consequences"
common.log("WARNING: %s" % message, log_type="!")
+11 -1
View File
@@ -11,9 +11,19 @@
# Description: Uses both vssadmin.exe and wmic.exe to delete volume shadow copies.
from . import common
from . import RtaMetadata
@common.requires_os(common.WINDOWS)
metadata = RtaMetadata(
uuid="ae6343cc-3b56-4f60-854f-7102db519ec4",
platforms=["windows"],
endpoint=[],
siem=[{"rule_id": "dc9c1f74-dac3-48e3-b47f-eb79db358f57", "rule_name": "Volume Shadow Copy Deletion via WMIC"}],
techniques=["T1490"],
)
@common.requires_os(metadata.platforms)
def main():
common.log("Deleting volume shadow copies...")
common.execute(["vssadmin.exe", "delete", "shadows", "/for=c:", "/oldest", "/quiet"])
+32
View File
@@ -0,0 +1,32 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="ff744c89-20cb-4be0-9725-2430d0be7f6a",
platforms=["macos"],
endpoint=[],
siem=[
{
"rule_name": "Persistence via DirectoryService Plugin Modification",
"rule_id": "89fa6cb7-6b53-4de2-b604-648488841ab8",
}
],
techniques=["T1547"],
)
@common.requires_os(metadata.platforms)
def main():
common.log("Executing file modification on test.dsplug to mimic DirectoryService plugin modification")
common.temporary_file_helper("testing", file_name="/Library/DirectoryServices/PlugIns/test.dsplug")
if __name__ == "__main__":
exit(main())
+56
View File
@@ -0,0 +1,56 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="f4e4a28e-c845-4b26-bfdf-24128e73ef21",
platforms=["macos"],
endpoint=[
{"rule_name": "Operating System Security Updates Disabled", "rule_id": "741ad90d-e8d0-4d29-b91b-3d68108cb789"}
],
siem=[{"rule_name": "SoftwareUpdate Preferences Modification", "rule_id": "f683dcdf-a018-4801-b066-193d4ae6c8e5"}],
techniques=["T1562"],
)
@common.requires_os(metadata.platforms)
def main():
masquerade = "/tmp/defaults"
common.create_macos_masquerade(masquerade)
# Execute command
common.log("Launching fake commands for system discovery with builtin cmds")
# ER
common.execute(
[
masquerade,
"write",
"-bool",
"com.apple.SoftwareUpdate",
"CriticalUpdateInstall",
"NO",
],
timeout=10,
kill=True,
)
# DR
common.execute(
[masquerade, "write", "-bool", "com.apple.SoftwareUpdate", "NO"],
timeout=10,
kill=True,
)
# cleanup
common.remove_file(masquerade)
if __name__ == "__main__":
exit(main())
+11 -1
View File
@@ -12,9 +12,19 @@
import os
from . import common
from . import RtaMetadata
@common.requires_os(common.WINDOWS)
metadata = RtaMetadata(
uuid="75e14e5a-1188-47ea-9b96-2cf6e9443fc2",
platforms=["windows"],
endpoint=[],
siem=[{"rule_id": "4b438734-3793-4fda-bd42-ceeada0be8f9", "rule_name": "Disable Windows Firewall Rules via Netsh"}],
techniques=["T1562"],
)
@common.requires_os(metadata.platforms)
def main():
common.log("NetSH Advanced Firewall Configuration", log_type="~")
netsh = "netsh.exe"
+32
View File
@@ -0,0 +1,32 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="92407d57-e5ce-41b1-933a-7cad26158802",
platforms=["macos"],
endpoint=[
{
"rule_name": "Potential Virtual Machine Fingerprinting via Grep",
"rule_id": "e5c0963c-0367-4d24-bdf2-5af3a233e57b",
}
],
siem=[{"rule_name": "Virtual Machine Fingerprinting via Grep", "rule_id": "c85eb82c-d2c8-485c-a36f-534f914b7663"}],
techniques=["T1082", "T1497"],
)
@common.requires_os(metadata.platforms)
def main():
common.log("Executing egrep commands to fingerprint virtual machine.")
common.execute(["egrep", "-i", '"Manufacturer: (parallels|vmware|virtualbox)"'], shell=True)
if __name__ == "__main__":
exit(main())
+30
View File
@@ -0,0 +1,30 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from pathlib import Path
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="38c81994-958f-40c8-bb6a-20bc1b93d598",
platforms=["macos"],
endpoint=[],
siem=[
{"rule_name": "Persistence via Docker Shortcut Modification", "rule_id": "c81cefcb-82b9-4408-a533-3c3df549e62d"}
],
techniques=["T1543"],
)
@common.requires_os(metadata.platforms)
def main():
common.log("Executing file modification on com.apple.dock.plist to mimic dock plist modification")
common.temporary_file_helper("testing", file_name=f"{Path.home()}/Library/Preferences/com.apple.dock.plist")
if __name__ == "__main__":
exit(main())
+36
View File
@@ -0,0 +1,36 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="74d0c16a-8af1-4dbb-9202-cc4b25208ea6",
platforms=["windows"],
endpoint=[
{
"rule_name": "Untrusted Process Writing to Commonly Abused Persistence Locations",
"rule_id": "392b0c89-1427-4601-8b32-01e8e40600a6",
}
],
siem=[],
techniques=["T1547", "T1112"],
)
EXE_FILE = common.get_path("bin", "DoublePersist.exe")
@common.requires_os(metadata.platforms)
def main():
binary = "DoublePersist.exe"
common.copy_file(EXE_FILE, binary)
common.execute([binary])
common.remove_files(binary)
if __name__ == "__main__":
exit(main())
+36
View File
@@ -0,0 +1,36 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="b084e9dd-0c79-480c-b488-049ab8167b38",
platforms=["macos"],
endpoint=[],
siem=[
{"rule_name": "Potential Hidden Local User Account Creation", "rule_id": "41b638a1-8ab6-4f8e-86d9-466317ef2db5"}
],
techniques=["T1078"],
)
@common.requires_os(metadata.platforms)
def main():
masquerade = "/tmp/dscl"
common.create_macos_masquerade(masquerade)
# Execute command
common.log("Launching fake dscl commands to mimic creating a local hidden account.")
common.execute([masquerade, "IsHidden", "create", "true"], timeout=10, kill=True)
# cleanup
common.remove_file(masquerade)
if __name__ == "__main__":
exit(main())
+34
View File
@@ -0,0 +1,34 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="d5643e8a-c3f5-48a7-9f64-7255f603a24a",
platforms=["macos"],
endpoint=[],
siem=[{"rule_name": "Potential Admin Group Account Addition", "rule_id": "565c2b44-7a21-4818-955f-8d4737967d2e"}],
techniques=["T1078"],
)
@common.requires_os(metadata.platforms)
def main():
masquerade = "/tmp/dseditgroup"
common.create_macos_masquerade(masquerade)
# Execute command
common.log("Launching fake dseditgroup commands to mimic adding a user to an admin group")
common.execute([masquerade, "admin", "-append"], timeout=10, kill=True)
# cleanup
common.remove_file(masquerade)
if __name__ == "__main__":
exit(main())
+58
View File
@@ -0,0 +1,58 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
import time
metadata = RtaMetadata(
uuid="d8de8c03-d5d0-4118-8971-32439638d69f",
platforms=["windows"],
endpoint=[
{"rule_name": "Execution from Unusual Directory", "rule_id": "16c84e67-e5e7-44ff-aefa-4d771bcafc0c"},
{"rule_name": "Binary Masquerading via Untrusted Path", "rule_id": "35dedf0c-8db6-4d70-b2dc-a133b808211f"},
{"rule_name": "Dynwrapx Image Load via Windows Scripts", "rule_id": "4cd6f758-0057-4e8a-9701-20b6116c2118"},
{
"rule_name": "Suspicious Windows Script Interpreter Child Process",
"rule_id": "83da4fac-563a-4af8-8f32-5a3797a9068e",
},
],
siem=[],
techniques=["T1055", "T1218", "T1036", "T1059"],
)
EXE_FILE = common.get_path("bin", "renamed_posh.exe")
PS1_FILE = common.get_path("bin", "Invoke-ImageLoad.ps1")
RENAMER = common.get_path("bin", "rcedit-x64.exe")
@common.requires_os(metadata.platforms)
def main():
cscript = "C:\\Users\\Public\\cscript.exe"
user32 = "C:\\Windows\\System32\\user32.dll"
dll = "C:\\Users\\Public\\dynwrapx.dll"
ps1 = "C:\\Users\\Public\\Invoke-ImageLoad.ps1"
rcedit = "C:\\Users\\Public\\rcedit.exe"
common.copy_file(EXE_FILE, cscript)
common.copy_file(user32, dll)
common.copy_file(PS1_FILE, ps1)
common.copy_file(RENAMER, rcedit)
# Execute command
common.log("Modifying the OriginalFileName attribute")
common.execute([rcedit, dll, "--set-version-string", "OriginalFilename", "dynwrapx.dll"])
common.log("Loading dynwrapx.dll into fake cscript")
common.execute([cscript, "-c", f"Import-Module {ps1}; Invoke-ImageLoad {dll}"], timeout=10)
# No idea on why, but after a lot of headaches, I discovered that the dll.pe.original_file_name
# is only populated if I delay the removal of the dll file
time.sleep(5)
common.remove_files(cscript, dll, ps1, rcedit)
if __name__ == "__main__":
exit(main())
+34
View File
@@ -0,0 +1,34 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="58041706-c636-4043-b221-3d59f977b7e2",
platforms=["macos"],
endpoint=[{"rule_name": "Potential Persistence via Emond", "rule_id": "1cd247d8-00e8-4c62-b9ee-90cd1811460b"}],
siem=[{"rule_name": "Suspicious Emond Child Process", "rule_id": "3e3d15c6-1509-479a-b125-21718372157e"}],
techniques=["T1546"],
)
@common.requires_os(metadata.platforms)
def main():
masquerade = "/tmp/emond"
common.create_macos_masquerade(masquerade)
# Execute command
common.log("Launching bash from fake emond command")
common.execute([masquerade], timeout=10, kill=True)
# cleanup
common.remove_file(masquerade)
if __name__ == "__main__":
exit(main())
+38
View File
@@ -0,0 +1,38 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="be090f8e-dc7b-41eb-9c7e-74a0aed0dad1",
platforms=["macos", "linux"],
endpoint=[{"rule_name": "EggShell Backdoor Execution", "rule_id": "feed7842-34a6-4764-b858-6e5ac01a5ab7"}],
siem=[{"rule_name": "EggShell Backdoor Execution", "rule_id": "41824afb-d68c-4d0e-bfee-474dac1fa56e"}],
techniques=["T1059"],
)
@common.requires_os(metadata.platforms)
def main():
masquerade = "/tmp/eggshell"
if common.CURRENT_OS == "linux":
source = common.get_path("bin", "linux.ditto_and_spawn")
common.copy_file(source, masquerade)
else:
common.create_macos_masquerade(masquerade)
# Execute command
common.log("Launching fake commands for EggShell backdoor behavior")
common.execute([masquerade, "eyJkZWJ1ZyI6test"], timeout=10, kill=True)
# cleanup
common.remove_file(masquerade)
if __name__ == "__main__":
exit(main())
+46
View File
@@ -0,0 +1,46 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="086c6cae-22ac-47b6-bd24-85b33d8cf3a2",
platforms=["macos"],
endpoint=[
{
"rule_name": "Elevated Apple Script Execution via Unsigned Parent",
"rule_id": "f17c8dcf-d65f-479a-b047-3558233f774e",
}
],
siem=[
{
"rule_name": "Apple Scripting Execution with Administrator Privileges",
"rule_id": "827f8d8f-4117-4ae4-b551-f56d54b9da6b",
}
],
techniques=["T1078", "T1548", "T1059"],
)
@common.requires_os(metadata.platforms)
def main():
# create masquerades
masquerade = "/tmp/bash"
common.copy_macos_masquerade(masquerade)
# Execute commands
common.log("Launching fake osascript commands to mimic apple script execution")
command = "osascript with administrator privileges"
common.execute([masquerade, "childprocess", command], shell=True, timeout=5, kill=True)
# cleanup
common.remove_file(masquerade)
if __name__ == "__main__":
exit(main())
+38
View File
@@ -0,0 +1,38 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="d1988e82-a079-4fc2-99f7-2bdbc9af0e00",
platforms=["macos"],
endpoint=[{"rule_name": "Potential Persistence via Emond", "rule_id": "1cd247d8-00e8-4c62-b9ee-90cd1811460b"}],
siem=[{"rule_name": "Suspicious Emond Child Process", "rule_id": "3e3d15c6-1509-479a-b125-21718372157e"}],
techniques=["T1546"],
)
@common.requires_os(metadata.platforms)
def main():
# create masquerades
masquerade = "/tmp/emond"
masquerade2 = "/tmp/bash"
common.create_macos_masquerade(masquerade)
common.create_macos_masquerade(masquerade2)
# Execute commands
common.log("Launching fake emond commands to mimic spawning child process.")
common.execute([masquerade, "childprocess", masquerade2], timeout=5, kill=True)
# cleanup
common.remove_file(masquerade)
common.remove_file(masquerade2)
if __name__ == "__main__":
exit(main())
+27
View File
@@ -0,0 +1,27 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="2c186f11-d07c-4df6-8b86-bf9ffd6ca871",
platforms=["macos"],
endpoint=[],
siem=[{"rule_name": "Emond Rules Creation or Modification", "rule_id": "a6bf4dd4-743e-4da8-8c03-3ebd753a6c90"}],
techniques=["T1546"],
)
@common.requires_os(metadata.platforms)
def main():
common.log("Executing file modification on test.plist to mimic emond file modification")
common.temporary_file_helper("testing", file_name="/private/etc/emond.d/rules/test.plist")
if __name__ == "__main__":
exit(main())
+42
View File
@@ -0,0 +1,42 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="4d7ce5b3-f8e4-434c-9caa-c7e133146b27",
platforms=["macos", "linux"],
endpoint=[{"rule_name": "Empire Stager Execution", "rule_id": "b7974ff6-82ff-4743-9e07-1c6901b1f0ea"}],
siem=[],
techniques=["T1132", "T1059"],
)
@common.requires_os(metadata.platforms)
def main():
masquerade = "/tmp/bash"
if common.CURRENT_OS == "linux":
source = common.get_path("bin", "linux.ditto_and_spawn")
common.copy_file(source, masquerade)
else:
common.create_macos_masquerade(masquerade)
# Execute command
common.log("Launching fake bash with base64 decode commands")
common.execute(
[masquerade, "exec(base64.b64decode*aW1wb3J0IHN5cztpbXBvcnQg)"],
timeout=10,
kill=True,
)
# cleanup
common.remove_file(masquerade)
if __name__ == "__main__":
exit(main())
+26 -11
View File
@@ -12,22 +12,31 @@ import argparse
import random
from . import common
from . import RtaMetadata
@common.requires_os(common.WINDOWS)
metadata = RtaMetadata(
uuid="9b19f4a3-7287-45d2-ab0f-9a9c0b1bc8e1",
platforms=["windows"],
endpoint=[],
siem=[
{"rule_id": "7b8bfc26-81d2-435e-965c-d722ee397ef1", "rule_name": "Windows Network Enumeration"},
{"rule_id": "871ea072-1b71-4def-b016-6278b505138d", "rule_name": "Enumeration of Administrator Accounts"},
],
techniques=["T1135", "T1069", "T1087", "T1018"],
)
@common.requires_os(metadata.platforms)
def main(args=None):
slow_commands = [
"gpresult.exe /z",
"systeminfo.exe"
]
slow_commands = ["gpresult.exe /z", "systeminfo.exe"]
commands = [
"ipconfig /all",
"net localgroup administrators",
"net user",
"net user administrator",
"net user /domain"
"tasklist",
"net user /domain" "tasklist",
"net view",
"net view /domain",
"net view \\\\%s" % common.get_ip(),
@@ -43,7 +52,7 @@ def main(args=None):
"net accounts",
"net localgroup",
"net group",
"net group \"Domain Admins\" /domain",
'net group "Domain Admins" /domain',
"net share",
"net config workstation",
]
@@ -51,8 +60,14 @@ def main(args=None):
commands.extend(slow_commands)
parser = argparse.ArgumentParser()
parser.add_argument('-s', '--sample', dest="sample", default=len(commands), type=int,
help="Number of commands to run, chosen at random from the list of enumeration commands")
parser.add_argument(
"-s",
"--sample",
dest="sample",
default=len(commands),
type=int,
help="Number of commands to run, chosen at random from the list of enumeration commands",
)
args = parser.parse_args(args)
sample = min(len(commands), args.sample)
@@ -65,7 +80,7 @@ def main(args=None):
common.log("About to call {}".format(command))
if command in slow_commands:
common.execute(command, kill=True, timeout=15)
common.log("[output suppressed]", log_type='-')
common.log("[output suppressed]", log_type="-")
else:
common.execute(command)
+39
View File
@@ -0,0 +1,39 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="b88c08af-eee5-4683-a56a-36e91e6386d5",
platforms=["macos", "linux"],
endpoint=[
{"rule_name": "Privilege Escalation Enumeration via LinPEAS", "rule_id": "92bb2a27-745b-4291-90a1-b7b654df1379"}
],
siem=[],
techniques=["T1059"],
)
@common.requires_os(metadata.platforms)
def main():
masquerade = "/tmp/sed"
if common.CURRENT_OS == "linux":
source = common.get_path("bin", "linux.ditto_and_spawn")
common.copy_file(source, masquerade)
else:
common.create_macos_masquerade(masquerade)
common.log("Executing fake sed command for LinPEAS behavior.")
common.execute([masquerade, "testImPoSSssSiBlEeetest"], timeout=5, kill=True, shell=True)
# cleanup
common.remove_file(masquerade)
if __name__ == "__main__":
exit(main())
+39
View File
@@ -0,0 +1,39 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="a18454da-5f28-4223-95d6-5dc1f58c861a",
platforms=["macos"],
endpoint=[],
siem=[
{
"rule_name": "Modification of Environment Variable via Launchctl",
"rule_id": "7453e19e-3dbf-4e4e-9ae0-33d6c6ed15e1",
}
],
techniques=["T1574"],
)
@common.requires_os(metadata.platforms)
def main():
masquerade = "/tmp/launchctl"
common.create_macos_masquerade(masquerade)
# Execute command
common.log("Launching fake launchctl command to mimic env variable hijacking")
common.execute([masquerade, "setenv"], timeout=10, kill=True)
# cleanup
common.remove_file(masquerade)
if __name__ == "__main__":
exit(main())
+30
View File
@@ -0,0 +1,30 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="ad9c9b24-cff3-4c4e-9fba-5c51ca9e58ae",
platforms=["windows"],
endpoint=[
{"rule_name": "Control Panel Process with Unusual Arguments", "rule_id": "a4862afb-1292-4f65-a15f-8d6a8019b5e2"}
],
siem=[],
techniques=["T1218"],
)
@common.requires_os(metadata.platforms)
def main():
# Execute command
common.log("Executing control.exe with a non-existing .cpl file")
common.execute(["control.exe", "cpl1.cpl:../a"], timeout=10)
if __name__ == "__main__":
exit(main())
+40
View File
@@ -0,0 +1,40 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="c562a05e-0ac8-46f9-91a2-5e99c8a1117c",
platforms=["windows"],
endpoint=[
{"rule_name": "Execution from Unusual Directory", "rule_id": "16c84e67-e5e7-44ff-aefa-4d771bcafc0c"},
{"rule_name": "Binary Masquerading via Untrusted Path", "rule_id": "35dedf0c-8db6-4d70-b2dc-a133b808211f"},
{
"rule_name": "Suspicious PowerShell Execution via Windows Scripts",
"rule_id": "3899dd3b-f31a-4634-8467-55326cd87597",
},
],
siem=[],
techniques=["T1218", "T1036", "T1059"],
)
EXE_FILE = common.get_path("bin", "renamed_posh.exe")
@common.requires_os(metadata.platforms)
def main():
cscript = "C:\\Users\\Public\\cscript.exe"
common.copy_file(EXE_FILE, cscript)
cmd = "powershell -c echo https://raw.githubusercontent.com/"
# Execute command
common.execute([cscript, "/c", cmd], timeout=10)
common.remove_file(cscript)
if __name__ == "__main__":
exit(main())
+32
View File
@@ -0,0 +1,32 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="f94f70a3-7c63-4f75-b5bc-f2227e284934",
platforms=["windows"],
endpoint=[
{
"rule_name": "Privilege Escalation via Named Pipe Impersonation",
"rule_id": "a0265178-779d-4bc5-b3f1-abb3bcddedab",
}
],
siem=[],
techniques=["T1134"],
)
@common.requires_os(metadata.platforms)
def main():
# Execute command
common.execute(["cmd.exe", "/c", "'echo", "cmd.exe", ">", "\\\\.\\pipe\\named'"], timeout=5)
if __name__ == "__main__":
exit(main())
+45
View File
@@ -0,0 +1,45 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="5e911636-6f68-40d3-b1ef-7a951a397cc9",
platforms=["windows"],
endpoint=[
{
"rule_name": "Execution of Commonly Abused Utilities via Explorer Trampoline",
"rule_id": "5e8498bb-8cc0-412f-9017-793d94ab76a5",
}
],
siem=[],
techniques=["T1218", "T1566", "T1059"],
)
EXE_FILE = common.get_path("bin", "renamed_posh.exe")
@common.requires_os(metadata.platforms)
def main():
explorer = "C:\\Users\\Public\\explorer.exe"
common.copy_file(EXE_FILE, explorer)
common.execute(
[
explorer,
"-c",
"echo",
"/factory,{75dff2b7-6936-4c06-a8bb-676a7b00b24b}",
";mshta",
],
timeout=10,
)
common.remove_files(explorer)
if __name__ == "__main__":
exit(main())
+57
View File
@@ -0,0 +1,57 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="23f0dde3-4803-4976-9a2a-5b5faca50b54",
platforms=["windows"],
endpoint=[
{"rule_name": "Execution from Unusual Directory", "rule_id": "16c84e67-e5e7-44ff-aefa-4d771bcafc0c"},
{"rule_name": "Binary Masquerading via Untrusted Path", "rule_id": "35dedf0c-8db6-4d70-b2dc-a133b808211f"},
{
"rule_name": "Executable File Creation Followed by Immediate Network Connection",
"rule_id": "8d11d741-7a06-41a1-a525-feaaa07ebbae",
},
{
"rule_name": "Execution via Microsoft DotNet ClickOnce Host",
"rule_id": "8606d5fe-5005-4f48-804a-3ad71a22e39d",
},
],
siem=[],
techniques=["T1127", "T1218", "T1036", "T1204", "T1059"],
)
EXE_FILE = common.get_path("bin", "renamed_posh.exe")
@common.requires_os(metadata.platforms)
def main():
rundll32 = "C:\\Users\\Public\\rundll32.exe"
dfsvc = "C:\\Users\\Public\\dfsvc.exe"
common.copy_file(EXE_FILE, dfsvc)
common.copy_file(EXE_FILE, rundll32)
common.log("Loading mstscax.dll into posh")
common.execute([rundll32, "-c", "echo dfshim1ShOpenVerbApplication"], timeout=10)
common.execute(
[
dfsvc,
"-c",
"Test-NetConnection",
"-ComputerName",
"portquiz.net",
"-Port",
"443",
],
timeout=10,
)
common.remove_files(dfsvc, rundll32)
if __name__ == "__main__":
exit(main())
+43
View File
@@ -0,0 +1,43 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="71c81436-242d-4bc8-a195-93d1fdbc774b",
platforms=["windows"],
endpoint=[
{"rule_name": "Binary Masquerading via Untrusted Path", "rule_id": "35dedf0c-8db6-4d70-b2dc-a133b808211f"},
{
"rule_name": "Suspicious Troubleshooting Pack Cabinet Execution",
"rule_id": "d18721f0-dce0-4bbc-a56a-06ea511b025e",
},
],
siem=[],
techniques=["T1218", "T1036"],
)
EXE_FILE = common.get_path("bin", "renamed_posh.exe")
@common.requires_os(metadata.platforms)
def main():
firefox = "C:\\Users\\Public\\firefox.exe"
msdt = "C:\\Users\\Public\\msdt.exe"
common.copy_file(EXE_FILE, firefox)
common.copy_file(EXE_FILE, msdt)
# Creating a high entropy file, and executing the rename operation
common.execute(
[firefox, "/c", "msdt.exe /c", "echo", "/cab", "C:\\Users\\Public\\"],
timeout=10,
)
common.remove_files(firefox, msdt)
if __name__ == "__main__":
exit(main())
@@ -0,0 +1,62 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="537de67d-8ba8-4df8-a965-75ca564d0846",
platforms=["windows"],
endpoint=[
{
"rule_name": "Script Interpreter Process Writing to Commonly Abused Persistence Locations",
"rule_id": "be42f9fc-bdca-41cd-b125-f223d09eef69",
},
{
"rule_name": "Startup Persistence via Windows Script Interpreter",
"rule_id": "a85000c8-3eac-413b-8353-079343c2b6f0",
},
],
siem=[],
techniques=["T1547", "T1059"],
)
@common.requires_os(metadata.platforms)
def main():
powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe"
common.log("Dropping executable to Startup Folder using powershell")
common.execute(
[
powershell,
"-C",
"Copy-Item",
"C:\\Windows\\System32\\cmd.exe",
"'C:\\Documents and Settings\\All Users\\Start Menu\\Programs\\Startup\\'",
]
)
common.log("Dropping executable to Startup Folder using powershell")
common.execute(
[
powershell,
"-C",
"Copy-Item",
"C:\\Windows\\System32\\cmd.exe",
"'C:\\Documents and Settings\\All Users\\Start Menu\\Programs\\Startup\\cmd2.exe'",
]
)
common.remove_files(
"C:\\Documents and Settings\\All Users\\Start Menu\\Programs\\Startup\\cmd2.exe",
"C:\\Documents and Settings\\All Users\\Start Menu\\Programs\\Startup\\cmd.exe",
)
if __name__ == "__main__":
exit(main())
+31
View File
@@ -0,0 +1,31 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="04fa2fff-bbcb-4b13-ad10-33225056e34e",
platforms=["windows"],
endpoint=[
{
"rule_name": "Execution of a Windows Script with Unusual File Extension",
"rule_id": "b76c0a04-b504-4a2f-a0cf-b4175a2f3eea",
}
],
siem=[],
techniques=["T1059"],
)
@common.requires_os(metadata.platforms)
def main():
common.log("Executing cscript against .exe")
common.execute(["cmd.exe", "/c", "cscript.exe", "/e:Vbscript", "cmd.exe"], timeout=5, kill=True)
if __name__ == "__main__":
exit(main())
+42
View File
@@ -0,0 +1,42 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="05f1f2a3-430d-4d20-9c0c-767d3b950cbb",
platforms=["windows"],
endpoint=[
{
"rule_name": "Script Execution via Microsoft HTML Application",
"rule_id": "f0630213-c4c4-4898-9514-746395eb9962",
}
],
siem=[],
techniques=["T1218"],
)
@common.requires_os(metadata.platforms)
def main():
# Execute Command
# Had a hard time trying to escape the quotes that would be needed to execute a real command using
# RunHTMLApplication, this will just fire the rule and result in a Missing entry error
common.log("Running rundll32 RunHTMLApplication")
common.execute(
[
"cmd.exe",
"/c",
"rundll32.exe javascript:\\..\\mshtml.dll,RunHTMLApplication",
],
timeout=5,
kill=True,
)
if __name__ == "__main__":
exit(main())
+35
View File
@@ -0,0 +1,35 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="0885b643-a199-4453-95e0-be0d1f29aafc",
platforms=["windows"],
endpoint=[
{"rule_name": "Suspicious Execution from MSSQL Service", "rule_id": "547636af-cad2-4be0-a74e-613c7bb86664"}
],
siem=[],
techniques=["T1059"],
)
EXE_FILE = common.get_path("bin", "renamed_posh.exe")
@common.requires_os(metadata.platforms)
def main():
powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe"
sqlserver = "C:\\Users\\Public\\sqlserver.exe"
common.copy_file(EXE_FILE, sqlserver)
# Execute command
common.execute([sqlserver, "/c", powershell], timeout=10, kill=True)
common.remove_file(sqlserver)
if __name__ == "__main__":
exit(main())
+28
View File
@@ -0,0 +1,28 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="76050b81-a8da-43d2-8a83-f18b31162b94",
platforms=["windows"],
endpoint=[
{"rule_name": "Suspicious Windows Explorer Execution", "rule_id": "f8ec5b76-53cf-4989-b451-7d16abec7298"}
],
siem=[],
techniques=["T1055", "T1036"],
)
@common.requires_os(metadata.platforms)
def main():
explorer = "C:\\Windows\\explorer.exe"
common.execute([explorer, "easyminerRTA"], timeout=1, kill=True)
if __name__ == "__main__":
exit(main())
+36
View File
@@ -0,0 +1,36 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="c9b68802-7d8b-4806-a817-ad50032efc58",
platforms=["windows"],
endpoint=[
{"rule_name": "Suspicious Execution via MSIEXEC", "rule_id": "9d1d6c77-8acc-478b-8a1f-43da8fa151c7"},
{"rule_name": "Binary Masquerading via Untrusted Path", "rule_id": "35dedf0c-8db6-4d70-b2dc-a133b808211f"},
],
siem=[],
techniques=["T1218", "T1036"],
)
EXE_FILE = common.get_path("bin", "renamed_posh.exe")
@common.requires_os(metadata.platforms)
def main():
powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe"
msiexec = "C:\\Users\\Public\\msiexec.exe"
common.copy_file(EXE_FILE, msiexec)
# Execute command
common.execute([powershell, "/c", msiexec], timeout=10, kill=True)
common.remove_file(msiexec)
if __name__ == "__main__":
exit(main())
+34
View File
@@ -0,0 +1,34 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="b12372b8-0e76-4b3d-9dfc-880664893eb9",
platforms=["windows"],
endpoint=[{"rule_name": "Suspicious Parent-Child Relationship", "rule_id": "18a26e3e-e535-4d23-8ffa-a3cdba56d16e"}],
siem=[],
techniques=["T1055", "T1036"],
)
EXE_FILE = common.get_path("bin", "renamed_posh.exe")
@common.requires_os(metadata.platforms)
def main():
posh = "C:\\Users\\Public\\posh.exe"
tiworker = "C:\\Users\\Public\\TiWorker.exe"
common.copy_file(EXE_FILE, posh)
common.copy_file(EXE_FILE, tiworker)
# Execute command
common.execute([posh, "/c", tiworker], timeout=3, kill=True)
common.remove_files(posh, tiworker)
if __name__ == "__main__":
exit(main())
+35
View File
@@ -0,0 +1,35 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="e9ee4f0c-b8c6-4471-b132-1edf4a7ca441",
platforms=["windows"],
endpoint=[
{"rule_name": "Binary Masquerading via Untrusted Path", "rule_id": "35dedf0c-8db6-4d70-b2dc-a133b808211f"},
{"rule_name": "Potential Masquerading as SVCHOST", "rule_id": "5b00c9ba-9546-47cc-8f9f-1c1a3e95f65c"},
{"rule_name": "Suspicious Windows Schedule Child Process", "rule_id": "eb04896b-935f-4d12-b2ad-579db82e1f42"},
],
siem=[],
techniques=["T1218", "T1036", "T1216", "T1220", "T1053", "T1059"],
)
EXE_FILE = common.get_path("bin", "renamed_posh.exe")
@common.requires_os(metadata.platforms)
def main():
svchost = "C:\\Users\\Public\\svchost.exe"
common.copy_file(EXE_FILE, svchost)
common.execute([svchost, "/c", "echo", "Schedule", "; mshta"], timeout=1, kill=True)
common.remove_file(svchost)
if __name__ == "__main__":
exit(main())
+36
View File
@@ -0,0 +1,36 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="0860c487-e9e0-4f86-9829-5bb98f615046",
platforms=["windows"],
endpoint=[
{"rule_name": "Execution from Unusual Directory", "rule_id": "16c84e67-e5e7-44ff-aefa-4d771bcafc0c"},
{"rule_name": "Binary Masquerading via Untrusted Path", "rule_id": "35dedf0c-8db6-4d70-b2dc-a133b808211f"},
],
siem=[],
techniques=["T1218", "T1036", "T1059"],
)
@common.requires_os(metadata.platforms)
def main():
exe_path = "c:\\windows\\system32\\cscript.exe"
binary = "c:\\Users\\Public\\cscript.exe"
common.copy_file(exe_path, binary)
# Execute command
common.log("Executing cscript from unusual directory")
common.execute([binary], timeout=5, kill=True)
common.remove_files(binary)
if __name__ == "__main__":
exit(main())
+38
View File
@@ -0,0 +1,38 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="65c661e6-7a15-45c0-97ad-0635eda560ba",
platforms=["windows"],
endpoint=[
{
"rule_name": "Suspicious Execution via Microsoft Office Add-Ins",
"rule_id": "9efd977a-6d4a-4cc8-8ab3-355587b0ef69",
}
],
siem=[],
techniques=["T1137", "T1566"],
)
EXE_FILE = common.get_path("bin", "renamed_posh.exe")
@common.requires_os(metadata.platforms)
def main():
powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe"
winword = "C:\\Users\\Public\\winword.exe"
common.copy_file(EXE_FILE, winword)
# Execute command
common.execute([powershell, "/c", winword, "/c", "echo", "doc.wll"], timeout=5, kill=True)
common.remove_file(winword)
if __name__ == "__main__":
exit(main())
+48
View File
@@ -0,0 +1,48 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="20631e46-d3c4-45c0-bfa8-37f6b287db36",
platforms=["macos"],
endpoint=[
{
"rule_name": "Execution via Electron Child Process Node.js Module",
"rule_id": "1d43f87d-2466-4714-8fef-d52816cc25fb",
}
],
siem=[
{
"rule_name": "Execution via Electron Child Process Node.js Module",
"rule_id": "35330ba2-c859-4c98-8b7f-c19159ea0e58",
}
],
techniques=["T1548", "T1059"],
)
@common.requires_os(metadata.platforms)
def main():
masquerade = "/tmp/node"
common.create_macos_masquerade(masquerade)
# Execute command
common.log("Spawning fake node commands to mimic Electon child process.")
common.execute(
[masquerade, "-e", "const { fork } = require('child_process');"],
timeout=10,
kill=True,
)
# cleanup
common.remove_file(masquerade)
if __name__ == "__main__":
exit(main())
+47
View File
@@ -0,0 +1,47 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="8b5119a5-9f78-492a-8448-ff726b0e0b4f",
platforms=["windows"],
endpoint=[
{"rule_name": "Scriptlet Proxy Execution via PubPrn", "rule_id": "0d4454a7-c682-4085-995c-300973c5bdea"},
{"rule_name": "Execution from Unusual Directory", "rule_id": "16c84e67-e5e7-44ff-aefa-4d771bcafc0c"},
{"rule_name": "Binary Masquerading via Untrusted Path", "rule_id": "35dedf0c-8db6-4d70-b2dc-a133b808211f"},
],
siem=[],
techniques=["T1216", "T1218", "T1036", "T1059"],
)
EXE_FILE = common.get_path("bin", "renamed_posh.exe")
RENAMER = common.get_path("bin", "rcedit-x64.exe")
@common.requires_os(metadata.platforms)
def main():
cscript = "C:\\Users\\Public\\cscript.exe"
rcedit = "C:\\Users\\Public\\rcedit.exe"
common.copy_file(RENAMER, rcedit)
common.copy_file(EXE_FILE, cscript)
cmd = "127.0.0.1 script:https://domain.com/folder/file.sct"
# Execute command
common.log("Modifying the OriginalFileName attribute")
common.execute(
[rcedit, cscript, "--set-version-string", "OriginalFileName", "cscript.exe"],
timeout=10,
)
common.execute([cscript, "/c", "echo", cmd], timeout=5, kill=True)
common.remove_files(cscript, rcedit)
if __name__ == "__main__":
exit(main())
+45
View File
@@ -0,0 +1,45 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="bbbfc3e3-e1ba-45ad-9d30-cbbe115a0c6c",
platforms=["windows"],
endpoint=[
{"rule_name": "Execution via Internet Explorer Exporter", "rule_id": "e13a65b7-f46f-4c7f-85cf-7e59170071fa"},
{"rule_name": "Execution via Renamed Signed Binary Proxy", "rule_id": "b0207677-5041-470b-981d-13ab956cf5b4"},
],
siem=[],
techniques=["T1218"],
)
RENAMER = common.get_path("bin", "rcedit-x64.exe")
EXE_FILE = common.get_path("bin", "renamed_posh.exe")
@common.requires_os(metadata.platforms)
def main():
dll = "C:\\Users\\Public\\sqlite3.dll"
posh = "C:\\Users\\Public\\posh.exe"
rcedit = "C:\\Users\\Public\\rcedit.exe"
common.copy_file(RENAMER, dll)
common.copy_file(RENAMER, rcedit)
common.copy_file(EXE_FILE, posh)
# Execute command
common.log("Modifying the OriginalFileName attribute")
common.execute([rcedit, posh, "--set-version-string", "OriginalFilename", "extexport.exe"])
common.log("Executing modified binary with extexport.exe original file name")
common.execute([posh], timeout=10, kill=True)
common.remove_files(dll, posh, rcedit)
if __name__ == "__main__":
exit(main())
+37
View File
@@ -0,0 +1,37 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
from . import common
from . import RtaMetadata
metadata = RtaMetadata(
uuid="5370760b-09ea-4258-bcfa-e426726a4777",
platforms=["windows"],
endpoint=[
{"rule_name": "Execution via Renamed Signed Binary Proxy", "rule_id": "b0207677-5041-470b-981d-13ab956cf5b4"},
{"rule_name": "Executable with Unusual Filename", "rule_id": "d1b6319f-2933-4872-8e67-5728fd09a4a1"},
{
"rule_name": "Process Execution with Unusual File Extension",
"rule_id": "6daf97b0-8e29-476b-998a-c3d168d98506",
},
],
siem=[],
techniques=["T1218", "T1036"],
)
@common.requires_os(metadata.platforms)
def main():
powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe"
unusualext = "C:\\Users\\Public\\powershell.exe.pdf"
common.copy_file(powershell, unusualext)
common.execute([unusualext], timeout=1, kill=True)
common.remove_file(unusualext)
if __name__ == "__main__":
exit(main())

Some files were not shown because too many files have changed in this diff Show More