Skip to content

Conversation

VakarisZ
Copy link
Contributor

@VakarisZ VakarisZ commented Jun 23, 2021

What does this PR do?

Fixes #1238.

Add any further explanations here.

PR Checklist

  • Have you added an explanation of what your changes do and why you'd like to include them?
  • Is the TravisCI build passing?
  • Was the CHANGELOG.md updated to reflect the changes?
  • Was the documentation framework updated to reflect the changes?

Testing Checklist

  • Added relevant unit tests?
  • Have you successfully tested your changes locally? Elaborate:

    Tested by {Running the Monkey locally with relevant config/running Island/...}

  • If applicable, add screenshots or log transcripts of the feature working

Explain Changes

Are the commit messages enough? If not, elaborate.

Comment on lines 23 to 24
LOG.info(f"Windows dir configured for encryption is " f"{config['windows_dir']}")
LOG.info(f"Linux dir configured for encryption is " f"{config['linux_dir']}")
Copy link
Contributor Author

@VakarisZ VakarisZ Jun 23, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should be moved/remove in this PR, because it's where they actually get used.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think logging this information is still valuable.

Comment on lines 26 to 28
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)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be moved to separate class which represents an action?

Comment on lines 27 to 28
self._valid_file_extensions_for_encryption = VALID_FILE_EXTENSIONS_FOR_ENCRYPTION.copy()
self._valid_file_extensions_for_encryption.discard(EXTENSION)
Copy link
Contributor Author

@VakarisZ VakarisZ Jun 23, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just remove EXTENSION from the VALID_FILE_EXTENSIONS_FOR_ENCRYPTION list?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this doing, actually? VALID_FILE_EXTENSIONS_FOR_ENCRYPTION doesn't have m0nk3y in it. Why are you trying to discard it?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a little bit preemptive/defensive. When we implement #1242, we'll want to ensure that the extension isn't in the set of extensions we'll encrypt. I wrote the code this way to avoid introducing bugs later on.


def _encrypt_file(self, filepath):
with open(filepath, "rb+") as f:
data = f.read(CHUNK_SIZE)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we read in chunks?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So that if we're encrypting a 30GB file we don't run out of RAM.

Comment on lines 57 to 58
f.seek(-num_bytes_read, 1)
f.write(encrypted_data)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this be moved into a method with an explanatory name? Like overwrite_bytes_in_file or something?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you think it's still necessary. It now lives inside _encrypt_single_file_in_place(). The "in_place" portion of the name better indicates what's going on. IMHO, this function is short and focused enough that with the new name, I think it's clear what's going in. But I can still change it if you feel strongly about it.

]

all_files = get_all_regular_files_in_directory(self._target_dir)
return filter_files(all_files, file_filters)

def _encrypt_files(self, file_list):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fact that this method and the methods that get called by this method doesn't use self indicates that this shouldn't be in a different class or at least static methods.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed as part of a refactor.


from infection_monkey.ransomware.ransomware_payload import RansomewarePayload

EXTENSION = ".m0nk3y"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we just import the extension from monkey/infection_monkey/ransomware/ransomware_payload.py?

Copy link
Contributor

@shreyamalviya shreyamalviya left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Where are we checking if ransomware is configured or not? If those fields in the config are empty, Path('') will default to the root directory (at least on Linux, it will). All files in the root directory will be encrypted.
  2. Tests fail: TypeError: copytree() got an unexpected keyword argument 'dirs_exist_ok'.

Comment on lines 27 to 28
self._valid_file_extensions_for_encryption = VALID_FILE_EXTENSIONS_FOR_ENCRYPTION.copy()
self._valid_file_extensions_for_encryption.discard(EXTENSION)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this doing, actually? VALID_FILE_EXTENSIONS_FOR_ENCRYPTION doesn't have m0nk3y in it. Why are you trying to discard it?

Comment on lines 8 to 28
self.config = config
LOG.info(f"Windows dir configured for encryption is " f"{config['windows_dir']}")
LOG.info(f"Linux dir configured for encryption is " f"{config['linux_dir']}")

def run_payload(self):
LOG.info(
f"Windows dir configured for encryption is " f"{self.config['windows_dir_ransom']}"
)
LOG.info(f"Linux dir configured for encryption is " f"{self.config['linux_dir_ransom']}")
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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we're not having an if statement in monkey.py, we're running all this code in any case, ransomware configured or not, which doesn't really make sense.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had mistakenly assumed that if the path was empty, no files would be found. In fact, it appears that Path("") evaluates to Path("."). Good catch.

Comment on lines 30 to 32
def run_payload(self):
file_list = self._find_files()
self._encrypt_files(file_list)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function should return the data about the run. List of tuples with each filename and its result.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function should send the appropriate telemetry. For the moment, we're going to avoid having payloads return anything.

@mssalvatore mssalvatore force-pushed the ransomware-bitflip-encryption branch from 4dda012 to 447138c Compare June 23, 2021 10:57
@codecov
Copy link

codecov bot commented Jun 23, 2021

Codecov Report

Merging #1264 (ef209a6) into develop (2b1ba99) will increase coverage by 0.50%.
The diff coverage is 96.59%.

Impacted file tree graph

@@             Coverage Diff             @@
##           develop    #1264      +/-   ##
===========================================
+ Coverage    29.47%   29.97%   +0.50%     
===========================================
  Files          434      441       +7     
  Lines        13184    13283      +99     
===========================================
+ Hits          3886     3982      +96     
- Misses        9298     9301       +3     
Impacted Files Coverage Δ
.../infection_monkey/ransomware/ransomware_payload.py 92.30% <89.65%> (ø)
...y/infection_monkey/ransomware/bitflip_encryptor.py 100.00% <100.00%> (ø)
...nkey/infection_monkey/ransomware/file_selectors.py 100.00% <100.00%> (ø)
monkey/infection_monkey/utils/bit_manipulators.py 100.00% <100.00%> (ø)
...unit_tests/infection_monkey/ransomware/conftest.py 100.00% <100.00%> (ø)
...ction_monkey/ransomware/ransomware_target_files.py 100.00% <100.00%> (ø)
monkey/tests/utils.py 78.57% <100.00%> (+28.57%) ⬆️
...fection_monkey/ransomware/valid_file_extensions.py 100.00% <0.00%> (ø)
... and 4 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 2b1ba99...ef209a6. Read the comment docs.

@mssalvatore mssalvatore marked this pull request as ready for review June 23, 2021 23:16
Copy link
Contributor

@shreyamalviya shreyamalviya left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a few questions

@mssalvatore mssalvatore merged commit 6744ee7 into develop Jun 24, 2021
@mssalvatore mssalvatore deleted the ransomware-bitflip-encryption branch July 29, 2021 14:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Ransomware bitflip encryption
3 participants