Release 0.7.1

This commit is contained in:
Harsh Raj Singhania
2025-11-14 15:35:17 +05:30
parent 1aa1bb7cdb
commit 2598bd2da2
4 changed files with 182 additions and 4 deletions

View File

@@ -23,7 +23,7 @@ class init:
def init(self):
# Global Variables
version = "0.6.0 Moat"
version = "0.7.1 Moat"
appname = "theZoo"
codename = "Moat"
authors = "Yuval Nativ, Lahad Ludar, 5fingers"
@@ -64,7 +64,7 @@ class Completer:
class vars:
version = "0.6.0 'Moat'"
version = "0.7.1 'Moat'"
appname = "Malware DB"
authors = "Yuval Nativ, Lahad Ludar, 5fingers"
maintainers = [ "Shahak Shalev", "Yuval Nativ" ]

22
setup.cfg Normal file
View File

@@ -0,0 +1,22 @@
[metadata]
name = theZoo
version = 0.7.1
author = theZoo maintainers
license = GPL-3.0-or-later
license_files = LICENSE.md
long_description = file: README.md
long_description_content_type = text/markdown
[options]
packages = find:
include_package_data = True
python_requires = >=3.8
install_requires =
urllib3
pyminizip
pyzipper
[options.entry_points]
console_scripts =
theZoo = theZoo:main
theZoo-gui = theZoo_gui:run

View File

@@ -28,10 +28,10 @@ from imports.globals import vars
from imports.terminal_handler import Controller
from imports import db_handler
__version__ = "0.6.0 Moat"
__version__ = "0.7.1 Moat"
__codename__ = "Moat"
__appname__ = "theZoo"
__authors__ = ["Yuval Nativ", "Shahak Shalev", "Lahad Ludar", "5Fingers"]
__authors__ = ["Yuval Nativ", "Shahak Shalev", "Lahad Ludar", "5Fingers", "Harsh Raj Singhania"]
__licensev__ = "GPL v3.0"
__maintainer = "Yuval Nativ & Shahak Shalev"
__status__ = "Beta"

156
theZoo_gui.py Normal file
View File

@@ -0,0 +1,156 @@
"""Simple Tkinter-based GUI for theZoo malware repository."""
from __future__ import annotations
import tkinter as tk
from tkinter import ttk, messagebox
from typing import List, Tuple
from imports.db_handler import DBHandler
class TheZooGUI:
"""Minimal graphical interface for browsing malware metadata."""
def __init__(self, root: tk.Tk) -> None:
self.root = root
self.root.title("theZoo GUI")
self.root.geometry("900x520")
self.db = DBHandler()
self.malware_rows: List[Tuple] = []
self._build_layout()
self._load_data()
def _build_layout(self) -> None:
main_frame = ttk.Frame(self.root, padding=16)
main_frame.pack(fill=tk.BOTH, expand=True)
search_frame = ttk.Frame(main_frame)
search_frame.pack(fill=tk.X, pady=(0, 12))
ttk.Label(search_frame, text="Filter:").pack(side=tk.LEFT)
self.search_var = tk.StringVar()
search_entry = ttk.Entry(search_frame, textvariable=self.search_var)
search_entry.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=(8, 0))
search_entry.bind("<KeyRelease>", self._filter_rows)
columns = ("ID", "TYPE", "LANGUAGE", "ARCH", "PLATFORM", "NAME")
self.tree = ttk.Treeview(
main_frame,
columns=columns,
show="headings",
height=15,
)
for col in columns:
self.tree.heading(col, text=col.title())
self.tree.column(col, width=120 if col != "NAME" else 220, anchor=tk.W)
self.tree.pack(fill=tk.BOTH, expand=True)
self.tree.bind("<<TreeviewSelect>>", self._on_select)
button_frame = ttk.Frame(main_frame)
button_frame.pack(fill=tk.X, pady=(12, 0))
self.details_button = ttk.Button(
button_frame,
text="Show Details",
command=self._show_selected_details,
state=tk.DISABLED,
)
self.details_button.pack(side=tk.LEFT)
self.status_var = tk.StringVar(value="Loaded 0 entries")
ttk.Label(button_frame, textvariable=self.status_var).pack(side=tk.RIGHT)
def _load_data(self) -> None:
try:
self.malware_rows = self.db.get_partial_details()
except Exception as exc: # pragma: no cover - defensive UI code
messagebox.showerror("Database Error", str(exc))
self.malware_rows = []
finally:
self._refresh_tree(self.malware_rows)
def _refresh_tree(self, rows: List[Tuple]) -> None:
self.tree.delete(*self.tree.get_children())
for row in rows:
self.tree.insert("", tk.END, iid=str(row[0]), values=row)
self.status_var.set(f"Loaded {len(rows)} entries")
self.details_button.configure(state=tk.DISABLED)
def _filter_rows(self, _event: tk.Event) -> None:
text = self.search_var.get().strip().lower()
if not text:
self._refresh_tree(self.malware_rows)
return
filtered = [
row for row in self.malware_rows
if any(text in str(value).lower() for value in row)
]
self._refresh_tree(filtered)
def _on_select(self, _event: tk.Event) -> None:
has_selection = bool(self.tree.selection())
new_state = tk.NORMAL if has_selection else tk.DISABLED
self.details_button.configure(state=new_state)
def _show_selected_details(self) -> None:
selection = self.tree.selection()
if not selection:
return
mal_id = int(selection[0])
try:
result = self.db.get_mal_info(mal_id)
except Exception as exc: # pragma: no cover - defensive UI code
messagebox.showerror("Database Error", str(exc))
return
if not result:
messagebox.showinfo("Malware Info", "No additional metadata available.")
return
(
mal_type,
name,
version,
author,
language,
date,
architecture,
platform,
tags,
) = result[0]
info_lines = [
f"Name: {name or 'N/A'}",
f"Type: {mal_type or 'N/A'}",
f"Version: {version or 'N/A'}",
f"Author: {author or 'N/A'}",
f"Language: {language or 'N/A'}",
f"Date: {date or 'N/A'}",
f"Architecture: {architecture or 'N/A'}",
f"Platform: {platform or 'N/A'}",
f"Tags: {tags or 'N/A'}",
]
messagebox.showinfo("Malware Info", "\n".join(info_lines))
def on_close(self) -> None:
self.db.close_connection()
self.root.destroy()
def run() -> None:
root = tk.Tk()
app = TheZooGUI(root)
root.protocol("WM_DELETE_WINDOW", app.on_close)
root.mainloop()
if __name__ == "__main__":
run()