Release ER Production RTAs to DR (#2270)
(cherry picked from commit 0358ec9d9a)
This commit is contained in:
committed by
github-actions[bot]
parent
6c9881027b
commit
1dfc8ca817
@@ -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)
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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")
|
||||
|
||||
@@ -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())
|
||||
@@ -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
@@ -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
@@ -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__":
|
||||
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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.
@@ -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();
|
||||
}
|
||||
@@ -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.
|
||||
|
||||
|
||||
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Binary file not shown.
Executable
BIN
Binary file not shown.
@@ -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
|
||||
Executable
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
@@ -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,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)
|
||||
|
||||
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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
|
||||
|
||||
@@ -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())
|
||||
@@ -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])
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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
@@ -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
@@ -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")
|
||||
|
||||
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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]
|
||||
|
||||
|
||||
@@ -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())
|
||||
@@ -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
@@ -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
@@ -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
@@ -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,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"])
|
||||
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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"
|
||||
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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
@@ -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)
|
||||
|
||||
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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())
|
||||
@@ -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
Reference in New Issue
Block a user