mirror of
https://github.com/ytisf/theZoo.git
synced 2025-12-05 20:19:57 -08:00
Merge pull request #234 from HarshRajSinghania/master
Release 0.7.1 – GUI & Packaging Enhancements
This commit is contained in:
@@ -23,7 +23,7 @@ class init:
|
|||||||
|
|
||||||
def init(self):
|
def init(self):
|
||||||
# Global Variables
|
# Global Variables
|
||||||
version = "0.6.0 Moat"
|
version = "0.7.1 Moat"
|
||||||
appname = "theZoo"
|
appname = "theZoo"
|
||||||
codename = "Moat"
|
codename = "Moat"
|
||||||
authors = "Yuval Nativ, Lahad Ludar, 5fingers"
|
authors = "Yuval Nativ, Lahad Ludar, 5fingers"
|
||||||
@@ -64,7 +64,7 @@ class Completer:
|
|||||||
|
|
||||||
|
|
||||||
class vars:
|
class vars:
|
||||||
version = "0.6.0 'Moat'"
|
version = "0.7.1 'Moat'"
|
||||||
appname = "Malware DB"
|
appname = "Malware DB"
|
||||||
authors = "Yuval Nativ, Lahad Ludar, 5fingers"
|
authors = "Yuval Nativ, Lahad Ludar, 5fingers"
|
||||||
maintainers = [ "Shahak Shalev", "Yuval Nativ" ]
|
maintainers = [ "Shahak Shalev", "Yuval Nativ" ]
|
||||||
|
|||||||
22
setup.cfg
Normal file
22
setup.cfg
Normal 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
|
||||||
@@ -28,10 +28,10 @@ from imports.globals import vars
|
|||||||
from imports.terminal_handler import Controller
|
from imports.terminal_handler import Controller
|
||||||
from imports import db_handler
|
from imports import db_handler
|
||||||
|
|
||||||
__version__ = "0.6.0 Moat"
|
__version__ = "0.7.1 Moat"
|
||||||
__codename__ = "Moat"
|
__codename__ = "Moat"
|
||||||
__appname__ = "theZoo"
|
__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"
|
__licensev__ = "GPL v3.0"
|
||||||
__maintainer = "Yuval Nativ & Shahak Shalev"
|
__maintainer = "Yuval Nativ & Shahak Shalev"
|
||||||
__status__ = "Beta"
|
__status__ = "Beta"
|
||||||
|
|||||||
156
theZoo_gui.py
Normal file
156
theZoo_gui.py
Normal 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()
|
||||||
Reference in New Issue
Block a user