forked from p15670423/monkey
Agent: Handle interrupts in ransomware
This commit is contained in:
parent
05c5764487
commit
afbc313a7c
|
@ -43,12 +43,8 @@ class Ransomware:
|
|||
file_list = self._find_files()
|
||||
self._encrypt_files(file_list, interrupt)
|
||||
|
||||
if interrupt.is_set():
|
||||
logger.debug("Received a stop signal, skipping remaining tasks of ransomware payload")
|
||||
return
|
||||
|
||||
if self._config.readme_enabled:
|
||||
self._leave_readme_in_target_directory()
|
||||
self._leave_readme_in_target_directory(interrupt)
|
||||
|
||||
def _find_files(self) -> List[Path]:
|
||||
logger.info(f"Collecting files in {self._target_directory}")
|
||||
|
@ -76,8 +72,12 @@ class Ransomware:
|
|||
encryption_attempt = FileEncryptionTelem(str(filepath), success, error)
|
||||
self._telemetry_messenger.send_telemetry(encryption_attempt)
|
||||
|
||||
def _leave_readme_in_target_directory(self):
|
||||
def _leave_readme_in_target_directory(self, interrupt: threading.Event):
|
||||
try:
|
||||
if interrupt.is_set():
|
||||
logger.debug("Received a stop signal, skipping leave readme")
|
||||
return
|
||||
|
||||
self._leave_readme(README_SRC, self._readme_file_path)
|
||||
except Exception as ex:
|
||||
logger.warning(f"An error occurred while attempting to leave a README.txt file: {ex}")
|
||||
|
|
|
@ -5,6 +5,7 @@ from unittest.mock import MagicMock
|
|||
import pytest
|
||||
from tests.unit_tests.infection_monkey.payload.ransomware.ransomware_target_files import (
|
||||
ALL_ZEROS_PDF,
|
||||
HELLO_TXT,
|
||||
TEST_KEYBOARD_TXT,
|
||||
)
|
||||
|
||||
|
@ -69,6 +70,11 @@ def mock_leave_readme():
|
|||
return MagicMock()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def interrupt():
|
||||
return threading.Event()
|
||||
|
||||
|
||||
def test_files_selected_from_target_dir(
|
||||
ransomware,
|
||||
ransomware_options,
|
||||
|
@ -86,6 +92,38 @@ def test_all_selected_files_encrypted(ransomware_test_data, ransomware, mock_fil
|
|||
mock_file_encryptor.assert_any_call(ransomware_test_data / TEST_KEYBOARD_TXT)
|
||||
|
||||
|
||||
def test_interrupt_while_encrypting(
|
||||
ransomware_test_data, interrupt, ransomware_options, build_ransomware
|
||||
):
|
||||
selected_files = [
|
||||
ransomware_test_data / ALL_ZEROS_PDF,
|
||||
ransomware_test_data / HELLO_TXT,
|
||||
ransomware_test_data / TEST_KEYBOARD_TXT,
|
||||
]
|
||||
mfs = MagicMock(return_value=selected_files)
|
||||
|
||||
def _callback(file_path, *_):
|
||||
# Block all threads here until 2 threads reach this barrier, then set stop
|
||||
# and test that neither thread continues to scan.
|
||||
if file_path.name == HELLO_TXT:
|
||||
interrupt.set()
|
||||
|
||||
mfe = MagicMock(side_effect=_callback)
|
||||
|
||||
build_ransomware(ransomware_options, mfe, mfs).run(interrupt)
|
||||
|
||||
assert mfe.call_count == 2
|
||||
mfe.assert_any_call(ransomware_test_data / ALL_ZEROS_PDF)
|
||||
mfe.assert_any_call(ransomware_test_data / HELLO_TXT)
|
||||
|
||||
|
||||
def test_no_readme_after_interrupt(ransomware, interrupt, mock_leave_readme):
|
||||
interrupt.set()
|
||||
ransomware.run(interrupt)
|
||||
|
||||
mock_leave_readme.assert_not_called()
|
||||
|
||||
|
||||
def test_encryption_skipped_if_configured_false(
|
||||
build_ransomware, ransomware_options, mock_file_encryptor
|
||||
):
|
||||
|
|
Loading…
Reference in New Issue