From 76ff428739d66731124d60aa509e6cb430b69f4f Mon Sep 17 00:00:00 2001 From: 7ka1 <7ka1@noreply.localhost> Date: Thu, 19 Mar 2026 14:18:24 +0000 Subject: [PATCH] Actualiser 7lna.py --- 7lna.py | 187 ++++++++++---------------------------------------------- 1 file changed, 31 insertions(+), 156 deletions(-) diff --git a/7lna.py b/7lna.py index 5e39650..8992d21 100644 --- a/7lna.py +++ b/7lna.py @@ -14,15 +14,9 @@ import secrets import json import platform import shutil -import base64 from watchdog.observers import Observer from watchdog.events import FileSystemEventHandler -# --- Imports pour le chiffrement AES-256 (Vault) --- -from cryptography.fernet import Fernet -from cryptography.hazmat.primitives import hashes -from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC - # ========================================== # CONFIGURATION GLOBALE # ========================================== @@ -30,11 +24,20 @@ UPDATE_URL = "https://git.7ka1.com/7ka1/7LnA_Antivirus_Linux_Free_ClamAV_Based/r QUARANTINE_DIR = os.path.expanduser("~/.7lna_quarantine") WATCH_FOLDER = os.path.expanduser("~/Téléchargements") HISTORY_FILE = os.path.expanduser("~/.7lna_history.json") -VAULT_FILE = os.path.expanduser("~/.7lna_vault.enc") # Fichier chiffré du coffre-fort ctk.set_appearance_mode("dark") ctk.set_default_color_theme("blue") +# ========================================== +# UTILITAIRES SYSTÈME +# ========================================== +def send_desktop_notification(title, message, is_critical=False): + try: + urgency = 'critical' if is_critical else 'normal' + subprocess.Popen(['notify-send', '-u', urgency, '-a', '7LnA Security', title, message]) + except Exception: + pass + class RealTimeShieldHandler(FileSystemEventHandler): def __init__(self, app_instance): self.app = app_instance @@ -49,7 +52,7 @@ class RealTimeShieldHandler(FileSystemEventHandler): class Antivirus7LnA(ctk.CTk): def __init__(self): super().__init__() - self.title("7LnA Security Suite - V10.3 Quantum Edition") + self.title("7LnA Security Suite - V10.1 Quantum Edition") self.geometry("1250x850") self.minsize(1000, 700) @@ -59,26 +62,13 @@ class Antivirus7LnA(ctk.CTk): self.shield_observer = None self.shield_active = False - self.zero_usb_mode = False - self.gaming_mode = False # <--- État du mode Gaming/Discret + self.zero_usb_mode = False # <--- AJOUT : État du mode Zero USB self.check_dependencies() self.setup_ui() threading.Thread(target=self.monitor_usb_drives, daemon=True).start() - # --- UTILITAIRES SYSTÈME (Intégré à la classe pour gérer le Gaming Mode) --- - def send_desktop_notification(self, title, message, is_critical=False): - # Si le mode Gaming est actif et que l'alerte n'est pas critique, on bloque la notification - if self.gaming_mode and not is_critical: - return - - try: - urgency = 'critical' if is_critical else 'normal' - subprocess.Popen(['notify-send', '-u', urgency, '-a', '7LnA Security', title, message]) - except Exception: - pass - def check_dependencies(self): try: subprocess.run(['clamscan', '--version'], capture_output=True, check=True) @@ -93,7 +83,7 @@ class Antivirus7LnA(ctk.CTk): # --- BARRE LATÉRALE --- self.sidebar = ctk.CTkFrame(self, width=260, corner_radius=0, fg_color="#111827") self.sidebar.grid(row=0, column=0, sticky="nsew") - self.sidebar.grid_rowconfigure(11, weight=1) + self.sidebar.grid_rowconfigure(10, weight=1) ctk.CTkLabel(self.sidebar, text="🛡️ 7LnA Sec", font=ctk.CTkFont(size=30, weight="bold"), text_color="#3B82F6").grid(row=0, column=0, padx=20, pady=(30, 20)) @@ -102,14 +92,13 @@ class Antivirus7LnA(ctk.CTk): self.btn_shield = self.create_nav_button("⚡ Bouclier Actif", 3, "shield") self.btn_audit = self.create_nav_button("⚙️ Audit Réseau", 4, "audit") self.btn_tools = self.create_nav_button("🧰 Outils Avancés", 5, "tools") - self.btn_vault = self.create_nav_button("🔐 Coffre-fort (AES)", 6, "vault") # <--- AJOUT BOUTON VAULT - self.btn_quarantine = self.create_nav_button("📦 Quarantaine", 7, "quarantine") - self.btn_schedule = self.create_nav_button("📅 Planification", 8, "schedule") - self.btn_history = self.create_nav_button("📜 Rapports", 9, "history") - self.btn_update = self.create_nav_button("🔄 Mise à jour", 10, "update") + self.btn_quarantine = self.create_nav_button("📦 Quarantaine", 6, "quarantine") + self.btn_schedule = self.create_nav_button("📅 Planification", 7, "schedule") + self.btn_history = self.create_nav_button("📜 Rapports", 8, "history") + self.btn_update = self.create_nav_button("🔄 Mise à jour", 9, "update") - self.version_label = ctk.CTkLabel(self.sidebar, text="v10.3 - Quantum", text_color="#6B7280", font=ctk.CTkFont(weight="bold")) - self.version_label.grid(row=11, column=0, pady=20, sticky="s") + self.version_label = ctk.CTkLabel(self.sidebar, text="v10.1 - Quantum", text_color="#6B7280", font=ctk.CTkFont(weight="bold")) + self.version_label.grid(row=10, column=0, pady=20, sticky="s") self.views = {} self.init_dashboard_view() @@ -117,7 +106,6 @@ class Antivirus7LnA(ctk.CTk): self.init_realtime_view() self.init_audit_view() self.init_tools_view() - self.init_vault_view() # <--- INIT VAULT VIEW self.init_quarantine_view() self.init_schedule_view() self.init_history_view() @@ -170,13 +158,14 @@ class Antivirus7LnA(ctk.CTk): known_mounts = current_mounts except: pass + # <--- MODIFICATION : Logique Zero USB intégrée def prompt_usb_scan(self, path, name): if self.zero_usb_mode: - self.send_desktop_notification("⚡ Zero USB Actif", f"Analyse automatique forcée pour : {name}", is_critical=True) + send_desktop_notification("⚡ Zero USB Actif", f"Analyse automatique forcée pour : {name}", is_critical=True) self.select_view("scanner") threading.Thread(target=self.run_clamav_scan, args=(path, True, self.scan_console), daemon=True).start() else: - self.send_desktop_notification("USB Détectée", f"Disque {name} branché.") + send_desktop_notification("USB Détectée", f"Disque {name} branché.") if messagebox.askyesno("Protection USB", f"Nouveau périphérique USB détecté :\n{name}\n\nVoulez-vous l'analyser ?"): self.select_view("scanner") threading.Thread(target=self.run_clamav_scan, args=(path, True, self.scan_console), daemon=True).start() @@ -197,32 +186,18 @@ class Antivirus7LnA(ctk.CTk): sys_info = f"🖥️ OS : {platform.system()} {platform.release()} | 👤 Compte : {os.getlogin()}" ctk.CTkLabel(sys_frame, text=sys_info, font=ctk.CTkFont(size=16, weight="bold")).pack(padx=20, pady=10, anchor="w") - # Switch Zero USB + # <--- AJOUT : Switch pour activer/désactiver le Mode Zero USB self.zero_usb_switch = ctk.CTkSwitch(frame, text="🛡️ Mode Zero USB (Scan auto des clés USB)", command=self.toggle_zero_usb, font=ctk.CTkFont(size=16, weight="bold"), - progress_color="#DC2626") - self.zero_usb_switch.pack(pady=(20, 10), anchor="w", padx=20) - - # Switch Mode Gaming/Discret - self.gaming_switch = ctk.CTkSwitch(frame, text="🎮 Mode Gaming / Discret (Silencieux & Basse Priorité CPU)", - command=self.toggle_gaming_mode, - font=ctk.CTkFont(size=16, weight="bold"), - progress_color="#8B5CF6") - self.gaming_switch.pack(pady=10, anchor="w", padx=20) + progress_color="#DC2626") # Rouge pour indiquer un mode "agressif" + self.zero_usb_switch.pack(pady=20, anchor="w", padx=20) + # <--- AJOUT : Fonction de bascule pour le Switch def toggle_zero_usb(self): self.zero_usb_mode = self.zero_usb_switch.get() etat = "ACTIVÉ" if self.zero_usb_mode else "DÉSACTIVÉ" - self.send_desktop_notification("Paramètre de Sécurité", f"Mode Zero USB {etat}") - - def toggle_gaming_mode(self): - self.gaming_mode = self.gaming_switch.get() - if self.gaming_mode: - # Envoi d'une dernière notification avant de se taire - self.send_desktop_notification("🎮 Mode Gaming Activé", "Notifications muettes. L'antivirus tourne en basse priorité.", is_critical=True) - else: - self.send_desktop_notification("🎮 Mode Gaming Désactivé", "Les ressources système et notifications sont restaurées.") + send_desktop_notification("Paramètre de Sécurité", f"Mode Zero USB {etat}") # --- FONCTION D'AUTHENTIFICATION GLOBALE --- def get_sudo_password(self, callback_func, title="Sécurité Administrateur", msg="Privilèges requis pour cette action.\nEntrez votre mot de passe session :"): @@ -278,7 +253,7 @@ class Antivirus7LnA(ctk.CTk): self.scan_console = ctk.CTkTextbox(frame, font=ctk.CTkFont(family="Consolas", size=13), fg_color="#111827", corner_radius=10) self.scan_console.grid(row=4, column=0, columnspan=3, pady=20, sticky="nsew") self.setup_console_tags(self.scan_console) - self.scan_console.insert("end", f"{self.get_time_prefix()}[*] Moteur de détection V10.3 prêt...\n", "info") + self.scan_console.insert("end", f"{self.get_time_prefix()}[*] Moteur de détection V10.1 prêt...\n", "info") def run_rootkit_scan(self): self.get_sudo_password(lambda pwd: threading.Thread(target=self._exec_rootkit, args=(pwd,), daemon=True).start()) @@ -386,15 +361,9 @@ class Antivirus7LnA(ctk.CTk): console.insert("end", f"{self.get_time_prefix()}[*] Analyse : {path}\n") if console == self.scan_console: self.scan_progress.start() try: - cmd = [] - # Si le Mode Gaming est actif, on utilise 'nice' pour baisser la priorité CPU du scan (sur Linux, nice 15 est très bas) - if self.gaming_mode: - cmd.extend(['nice', '-n', '15']) - - cmd.extend(['clamscan', '-i', '--no-summary', f'--move={QUARANTINE_DIR}']) + cmd = ['clamscan', '-i', '--no-summary', f'--move={QUARANTINE_DIR}'] if is_dir: cmd.append('-r') cmd.append(path) - process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) infected = 0 for line in process.stdout: @@ -408,7 +377,7 @@ class Antivirus7LnA(ctk.CTk): console.see("end") process.wait() if infected == 0: console.insert("end", f"{self.get_time_prefix()}[+] Fichier propre.\n", "success") - else: self.send_desktop_notification("🚨 VIRUS NEUTRALISÉ", f"{infected} menace(s) trouvée(s).", is_critical=True) + else: send_desktop_notification("🚨 VIRUS NEUTRALISÉ", f"{infected} menace(s) trouvée(s).", is_critical=True) except Exception as e: console.insert("end", f"{self.get_time_prefix()}❌ Erreur : {e}\n", "danger") finally: if console == self.scan_console: self.scan_progress.stop() @@ -491,7 +460,7 @@ class Antivirus7LnA(ctk.CTk): self.audit_console.insert("end", f"\n{self.get_time_prefix()}[+] Scan terminé. {count} appareils détectés sur votre WiFi.\n", "info") if count > 15: - self.send_desktop_notification("WiFi Guard", f"Attention : Beaucoup d'appareils ({count}) sont connectés à votre réseau.", is_critical=True) + send_desktop_notification("WiFi Guard", f"Attention : Beaucoup d'appareils ({count}) sont connectés à votre réseau.", is_critical=True) except Exception as e: self.audit_console.insert("end", f"❌ Erreur : {e}\n", "danger") @@ -596,100 +565,6 @@ class Antivirus7LnA(ctk.CTk): messagebox.showinfo("Succès", "Fichier détruit.") except: pass - # ========================================== - # --- VUE : COFFRE-FORT (NOUVEAU) --- - # ========================================== - def init_vault_view(self): - frame = ctk.CTkFrame(self, fg_color="transparent") - frame.grid_rowconfigure(2, weight=1) - frame.grid_columnconfigure(0, weight=1) - self.views["vault"] = frame - - ctk.CTkLabel(frame, text="🔐 Coffre-fort AES-256", font=ctk.CTkFont(size=34, weight="bold")).grid(row=0, column=0, sticky="w", pady=(0, 20)) - - # Panel de connexion - self.vault_login_frame = ctk.CTkFrame(frame, fg_color="#1F2937", corner_radius=10) - self.vault_login_frame.grid(row=1, column=0, sticky="ew", ipady=20) - - ctk.CTkLabel(self.vault_login_frame, text="Entrez le mot de passe maître :", font=ctk.CTkFont(size=16)).pack(pady=(20, 10)) - self.vault_pwd_entry = ctk.CTkEntry(self.vault_login_frame, show="*", width=300) - self.vault_pwd_entry.pack(pady=10) - - ctk.CTkButton(self.vault_login_frame, text="Déverrouiller / Créer", fg_color="#2563EB", hover_color="#1D4ED8", command=self.unlock_vault).pack(pady=10) - ctk.CTkLabel(self.vault_login_frame, text="Note: Si le coffre n'existe pas, ce mot de passe sera utilisé pour le créer.", text_color="#9CA3AF").pack() - - # Panel de l'éditeur (caché par défaut) - self.vault_editor_frame = ctk.CTkFrame(frame, fg_color="transparent") - - header_editor = ctk.CTkFrame(self.vault_editor_frame, fg_color="transparent") - header_editor.pack(fill="x", pady=(0, 10)) - ctk.CTkLabel(header_editor, text="Vos notes sécurisées :", font=ctk.CTkFont(size=18, weight="bold"), text_color="#10B981").pack(side="left") - ctk.CTkButton(header_editor, text="🔒 Sauvegarder et Verrouiller", fg_color="#059669", hover_color="#047857", command=self.save_vault).pack(side="right") - - self.vault_textbox = ctk.CTkTextbox(self.vault_editor_frame, font=ctk.CTkFont(family="Consolas", size=14), fg_color="#111827", corner_radius=10) - self.vault_textbox.pack(fill="both", expand=True) - - self.current_vault_pwd = None - self.current_vault_salt = None - - def _derive_key(self, password, salt): - kdf = PBKDF2HMAC( - algorithm=hashes.SHA256(), - length=32, - salt=salt, - iterations=480000, - ) - return base64.urlsafe_b64encode(kdf.derive(password.encode())) - - def unlock_vault(self): - pwd = self.vault_pwd_entry.get() - if not pwd: return - - if os.path.exists(VAULT_FILE): - try: - with open(VAULT_FILE, "rb") as f: data = f.read() - salt = data[:16] - encrypted = data[16:] - key = self._derive_key(pwd, salt) - fernet = Fernet(key) - decrypted = fernet.decrypt(encrypted).decode() - - # Succès ! - self.current_vault_pwd = pwd - self.current_vault_salt = salt - self.show_vault_editor(decrypted) - except Exception: - messagebox.showerror("Accès Refusé", "Mot de passe incorrect ou fichier corrompu.") - else: - # Nouveau coffre - self.current_vault_pwd = pwd - self.current_vault_salt = os.urandom(16) - self.show_vault_editor("=== VOTRE COFFRE EST VIDE ===\n\nÉcrivez vos identifiants ou notes secrètes ici...") - - def show_vault_editor(self, content): - self.vault_login_frame.grid_forget() - self.vault_editor_frame.grid(row=2, column=0, sticky="nsew") - self.vault_pwd_entry.delete(0, 'end') - self.vault_textbox.delete("0.0", "end") - self.vault_textbox.insert("end", content) - - def save_vault(self): - data = self.vault_textbox.get("0.0", "end") - key = self._derive_key(self.current_vault_pwd, self.current_vault_salt) - fernet = Fernet(key) - encrypted = fernet.encrypt(data.encode()) - - with open(VAULT_FILE, "wb") as f_out: - f_out.write(self.current_vault_salt + encrypted) - - self.current_vault_pwd = None - self.current_vault_salt = None - self.vault_textbox.delete("0.0", "end") - - self.vault_editor_frame.grid_forget() - self.vault_login_frame.grid(row=1, column=0, sticky="ew", ipady=20) - self.send_desktop_notification("Coffre-fort", "Fichier chiffré avec succès et verrouillé.") - # ----- PLANIFICATION ----- def init_schedule_view(self): frame = ctk.CTkFrame(self, fg_color="transparent")