From 08f1e3e06324589e1da504b5fbd3aa20cc4b049e Mon Sep 17 00:00:00 2001 From: Hardik Zinzuvadiya <25708027+Z4nzu@users.noreply.github.com> Date: Sun, 15 Mar 2026 13:54:30 +0530 Subject: [PATCH] Phase 3: Installation & path overhaul --- hackingtool.py | 184 +++++++++++------------- install.py | 324 ++++++++++++++++++++++++------------------ tools/tool_manager.py | 145 ++++++++----------- update.sh | 66 ++++----- 4 files changed, 349 insertions(+), 370 deletions(-) diff --git a/hackingtool.py b/hackingtool.py index 9db5a93..9a264f0 100755 --- a/hackingtool.py +++ b/hackingtool.py @@ -1,23 +1,31 @@ #!/usr/bin/env python3 -# Version 1.1.0 (rich UI - purple theme) -import os import sys + +# ── Python version guard (must be before any other local import) ─────────────── +if sys.version_info < (3, 10): + print( + f"[ERROR] Python 3.10 or newer is required.\n" + f"You are running Python {sys.version_info.major}.{sys.version_info.minor}.\n" + f"Upgrade with: sudo apt install python3.10" + ) + sys.exit(1) + +import os import webbrowser from platform import system -from time import sleep from rich.console import Console from rich.panel import Panel from rich.table import Table -from rich.prompt import Prompt, IntPrompt, Confirm +from rich.prompt import IntPrompt, Confirm from rich.align import Align from rich.text import Text from rich import box -from rich.columns import Columns from rich.rule import Rule -from rich.padding import Padding from core import HackingToolsCollection +from constants import VERSION_DISPLAY, REPO_WEB_URL +from config import get_tools_dir from tools.anonsurf import AnonSurfTools from tools.ddos import DDOSTools from tools.exploit_frameworks import ExploitFrameworkTools @@ -40,36 +48,36 @@ from tools.xss_attack import XSSAttackTools console = Console() ASCII_LOGO = r""" - ▄█ █▄ ▄████████ ▄████████ ▄█ ▄█▄ ▄█ ███▄▄▄▄ ▄██████▄ ███ ▄██████▄ ▄██████▄ ▄█ - ███ ███ ███ ███ ███ ███ ███ ▄███▀ ███ ███▀▀▀██▄ ███ ███ ▀█████████▄ ███ ███ ███ ███ ███ - ███ ███ ███ ███ ███ █▀ ███▐██▀ ███▌ ███ ███ ███ █▀ ▀███▀▀██ ███ ███ ███ ███ ███ - ▄███▄▄▄▄███▄▄ ███ ███ ███ ▄█████▀ ███▌ ███ ███ ▄███ ███ ▀ ███ ███ ███ ███ ███ -▀▀███▀▀▀▀███▀ ▀███████████ ███ ▀▀█████▄ ███▌ ███ ███ ▀▀███ ████▄ ███ ███ ███ ███ ███ ███ - ███ ███ ███ ███ ███ █▄ ███▐██▄ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ - ███ ███ ███ ███ ███ ███ ███ ▀███▄ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███▌ ▄ - ███ █▀ ███ █▀ ████████▀ ███ ▀█▀ █▀ ▀█ █▀ ████████▀ ▄████▀ ▀██████▀ ▀██████▀ █████▄▄██ - ▀ ▀ + ▄█ █▄ ▄████████ ▄████████ ▄█ ▄█▄ ▄█ ███▄▄▄▄ ▄██████▄ ███ ▄██████▄ ▄██████▄ ▄█ + ███ ███ ███ ███ ███ ███ ███ ▄███▀ ███ ███▀▀▀██▄ ███ ███ ▀█████████▄ ███ ███ ███ ███ ███ + ███ ███ ███ ███ ███ █▀ ███▐██▀ ███▌ ███ ███ ███ █▀ ▀███▀▀██ ███ ███ ███ ███ ███ + ▄███▄▄▄▄███▄▄ ███ ███ ███ ▄█████▀ ███▌ ███ ███ ▄███ ███ ▀ ███ ███ ███ ███ ███ +▀▀███▀▀▀▀███▀ ▀███████████ ███ ▀▀█████▄ ███▌ ███ ███ ▀▀███ ████▄ ███ ███ ███ ███ ███ ███ + ███ ███ ███ ███ ███ █▄ ███▐██▄ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ + ███ ███ ███ ███ ███ ███ ███ ▀███▄ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███▌ ▄ + ███ █▀ ███ █▀ ████████▀ ███ ▀█▀ █▀ ▀█ █▀ ████████▀ ▄████▀ ▀██████▀ ▀██████▀ █████▄▄██ + ▀ ▀ """ tool_definitions = [ - ("Anonymously Hiding Tools", "🛡️"), - ("Information gathering tools", "🔍"), - ("Wordlist Generator", "📚"), - ("Wireless attack tools", "📶"), - ("SQL Injection Tools", "🧩"), - ("Phishing attack tools", "🎣"), - ("Web Attack tools", "🌐"), - ("Post exploitation tools", "🔧"), - ("Forensic tools", "🕵️"), - ("Payload creation tools", "📦"), - ("Exploit framework", "🧰"), - ("Reverse engineering tools", "🔁"), - ("DDOS Attack Tools", "⚡"), - ("Remote Administrator Tools (RAT)", "🖥️"), - ("XSS Attack Tools", "💥"), - ("Steganograhy tools", "🖼️"), - ("Other tools", "✨"), - ("Update or Uninstall | Hackingtool", "♻️"), + ("Anonymously Hiding Tools", "🛡️"), + ("Information gathering tools", "🔍"), + ("Wordlist Generator", "📚"), + ("Wireless attack tools", "📶"), + ("SQL Injection Tools", "🧩"), + ("Phishing attack tools", "🎣"), + ("Web Attack tools", "🌐"), + ("Post exploitation tools", "🔧"), + ("Forensic tools", "🕵️"), + ("Payload creation tools", "📦"), + ("Exploit framework", "🧰"), + ("Reverse engineering tools", "🔁"), + ("DDOS Attack Tools", "⚡"), + ("Remote Administrator Tools (RAT)", "🖥️"), + ("XSS Attack Tools", "💥"), + ("Steganography tools", "🖼️"), + ("Other tools", "✨"), + ("Update or Uninstall | Hackingtool", "♻️"), ] all_tools = [ @@ -90,7 +98,7 @@ all_tools = [ XSSAttackTools(), SteganographyTools(), OtherTools(), - ToolManager() + ToolManager(), ] @@ -99,20 +107,18 @@ class AllTools(HackingToolsCollection): TOOLS = all_tools def show_info(self): - header = Text() - header.append(ASCII_LOGO, style="bold magenta") - header.append("\n\n",) + header = Text(ASCII_LOGO, style="bold magenta") footer = Text.assemble( - (" https://github.com/Z4nzu/hackingtool ", "bold bright_black"), + (f" {REPO_WEB_URL} ", "bold bright_black"), (" | ",), - ("Version 1.1.0", "bold green"), + (VERSION_DISPLAY, "bold green"), ) - warning = Text(" Please Don't Use For illegal Activity ", style="bold red") + warning = Text(" Please Don't Use For Illegal Activity ", style="bold red") panel = Panel( Align.center(header + Text("\n") + footer + Text("\n") + warning), box=box.DOUBLE, padding=(1, 2), - border_style="magenta" + border_style="magenta", ) console.print(panel) @@ -123,55 +129,32 @@ def build_menu(): table.add_column("name", justify="left") for idx, (title, icon) in enumerate(tool_definitions): - if idx == 17: + if idx == len(tool_definitions) - 1: label = "[bold magenta]99[/bold magenta]" - name = f"[bold magenta]{icon} {title}[/bold magenta]" + name = f"[bold magenta]{icon} {title}[/bold magenta]" else: label = f"[bold magenta]{idx}[/bold magenta]" - name = f"[white]{icon}[/white] [magenta]{title}[/magenta]" + name = f"[white]{icon}[/white] [magenta]{title}[/magenta]" table.add_row(label, name) - top_panel = Panel( + console.print(Panel( Align.center(Text("HackingTool — Main Menu", style="bold white on magenta"), vertical="middle"), - style="magenta", - padding=(0, 1), - box=box.ROUNDED - ) - menu_panel = Panel.fit( + style="magenta", padding=(0, 1), box=box.ROUNDED, + )) + console.print(Panel.fit( table, title="[bold magenta]Select a tool[/bold magenta]", border_style="bright_magenta", - box=box.SQUARE - ) - footer = Align.center(Text("Choose number and press Enter — 99 to exit", style="italic bright_black")) - console.print(top_panel) - console.print(menu_panel) + box=box.SQUARE, + )) console.print(Rule(style="bright_black")) - console.print(footer) + console.print(Align.center(Text( + "Choose number and press Enter — 99 to exit", + style="italic bright_black", + ))) console.print("") -def choose_path(): - fpath = os.path.expanduser("~/hackingtoolpath.txt") - if not os.path.exists(fpath): - os.system("clear" if system() == "Linux" else "cls") - build_menu() - console.print(Panel("Setup path for tool installations", border_style="magenta")) - choice = Prompt.ask("[magenta]Set Path[/magenta]", choices=["1", "2"], default="2") - if choice == "1": - inpath = Prompt.ask("[magenta]Enter Path (with Directory Name)[/magenta]") - with open(fpath, "w") as f: - f.write(inpath) - console.print(f"[green]Successfully Set Path to:[/green] {inpath}") - else: - autopath = "/home/hackingtool/" - with open(fpath, "w") as f: - f.write(autopath) - console.print(f"[green]Your Default Path Is:[/green] {autopath}") - sleep(1) - return fpath - - def interact_menu(): while True: try: @@ -183,13 +166,11 @@ def interact_menu(): if 0 <= choice < len(all_tools): tool = all_tools[choice] name = tool_definitions[choice][0] - console.print(Panel(f"[bold magenta]{tool_definitions[choice][1]} Selected:[/bold magenta] [white]{name}")) + console.print(Panel( + f"[bold magenta]{tool_definitions[choice][1]} Selected:[/bold magenta] [white]{name}[/white]" + )) try: - fn = getattr(tool, "show_options", None) - if callable(fn): - fn() - else: - console.print(f"[yellow]Tool '{name}' has no interactive menu (show_options).[/yellow]") + tool.show_options() except Exception as e: console.print(Panel(f"[red]Error while opening {name}[/red]\n{e}", border_style="red")) if not Confirm.ask("[magenta]Return to main menu?[/magenta]", default=True): @@ -198,29 +179,32 @@ def interact_menu(): else: console.print("[red]Invalid selection. Pick a number from the menu.[/red]") except KeyboardInterrupt: - console.print("\n[bold red]Interrupted by user — exiting[/bold red]") + console.print("\n[bold red]Interrupted — exiting[/bold red]") break + def main(): try: - if system() == "Linux": - fpath = choose_path() - with open(fpath) as f: - archive = f.readline().strip() - os.makedirs(archive, exist_ok=True) - os.chdir(archive) - AllTools().show_info() - interact_menu() - elif system() == "Windows": - console.print(Panel("[bold red]Please run this tool on a Debian/Linux system for best results[/bold red]")) + from os_detect import CURRENT_OS + + if CURRENT_OS.system == "windows": + console.print(Panel("[bold red]Please run this tool on Linux or macOS.[/bold red]")) if Confirm.ask("Open guidance link in your browser?", default=True): - webbrowser.open_new_tab("https://tinyurl.com/y522modc") - sleep(2) - else: - console.print("[yellow]Please Check Your System or Open New Issue ...[/yellow]") + webbrowser.open_new_tab(f"{REPO_WEB_URL}#windows") + return + + if CURRENT_OS.system not in ("linux", "macos"): + console.print(f"[yellow]Unsupported OS: {CURRENT_OS.system}. Proceeding anyway...[/yellow]") + + # Ensure ~/.hackingtool/tools/ exists — no os.chdir(), tools use absolute paths + tools_dir = get_tools_dir() + console.print(f"[dim]Tools directory: {tools_dir}[/dim]") + + AllTools().show_info() + interact_menu() + except KeyboardInterrupt: - console.print("\n[bold red]Exiting ..!!![/bold red]") - sleep(1) + console.print("\n[bold red]Exiting...[/bold red]") if __name__ == "__main__": diff --git a/install.py b/install.py index d7c328f..775063b 100755 --- a/install.py +++ b/install.py @@ -1,207 +1,249 @@ #!/usr/bin/env python3 -# install_hackingtool.py (rich-based installer UI) import os import sys import shutil import subprocess from pathlib import Path +# ── Python version check (must be before any other local import) ────────────── +if sys.version_info < (3, 10): + print( + f"[ERROR] Python 3.10 or newer is required.\n" + f"You are running Python {sys.version_info.major}.{sys.version_info.minor}.\n" + f"Install with: sudo apt install python3.10" + ) + sys.exit(1) + from rich.console import Console from rich.panel import Panel -from rich.prompt import Prompt, Confirm, IntPrompt -from rich.table import Table -from rich.align import Align +from rich.prompt import Confirm from rich.progress import Progress, SpinnerColumn, TextColumn from rich.text import Text from rich import box -from random import choice + +from constants import ( + REPO_URL, APP_INSTALL_DIR, APP_BIN_PATH, + VERSION, VERSION_DISPLAY, + USER_CONFIG_DIR, USER_TOOLS_DIR, USER_CONFIG_FILE, + DEFAULT_CONFIG, +) +from os_detect import CURRENT_OS, REQUIRED_PACKAGES, PACKAGE_UPDATE_CMDS, PACKAGE_INSTALL_CMDS console = Console() -REPO_URL = "https://github.com/Z4nzu/hackingtool.git" -INSTALL_DIR = Path("/usr/share/hackingtool") -BIN_PATH = Path("/usr/bin/hackingtool") VENV_DIR_NAME = "venv" -REQUIREMENTS = "requirements.txt" +REQUIREMENTS = "requirements.txt" +# ── Privilege check ──────────────────────────────────────────────────────────── + def check_root(): if os.geteuid() != 0: - console.print(Panel("[red]This installer must be run as root. Use: sudo python3 install_hackingtool.py[/red]")) + console.print(Panel( + "[error]This installer must be run as root.\n" + "Use: [bold]sudo python3 install.py[/bold][/error]", + border_style="red", + )) sys.exit(1) -def run_cmd(cmd, check=True, capture=False, env=None): - return subprocess.run(cmd, shell=True, check=check, capture_output=capture, text=True, env=env) +# ── OS compatibility check ───────────────────────────────────────────────────── + +def check_os_compatibility(): + """Print detected OS info and exit on unsupported systems.""" + info = CURRENT_OS + console.print( + f"[dim]Detected: OS={info.system} | distro={info.distro_id or 'n/a'} | " + f"pkg_mgr={info.pkg_manager or 'none'} | arch={info.arch}[/dim]" + ) + + if info.system == "windows": + console.print(Panel( + "[error]Windows is not supported natively.[/error]\n" + "Use WSL2 with a Kali or Ubuntu image.", + border_style="red", + )) + sys.exit(1) + + if info.is_wsl: + console.print("[warning]WSL detected. Wireless tools will NOT work in WSL.[/warning]") + + if info.system == "macos": + console.print(Panel( + "[warning]macOS support is partial.[/warning]\n" + "Network/wireless tools require Linux. OSINT and web tools work.", + border_style="yellow", + )) + if not shutil.which("brew"): + console.print("[error]Homebrew not found. Install it first: https://brew.sh[/error]") + sys.exit(1) + + if not info.pkg_manager: + console.print("[warning]No supported package manager found.[/warning]") + console.print("[dim]Supported: apt-get, pacman, dnf, zypper, apk, brew[/dim]") -def colorful_logo(): - logos = ["magenta", "bright_magenta", "cyan", "blue", "green", "yellow"] - style = choice(logos) - logo_lines = r""" - ▄█ █▄ ▄████████ ▄████████ ▄█ ▄█▄ ▄█ ███▄▄▄▄ ▄██████▄ ███ ▄██████▄ ▄██████▄ ▄█ - ███ ███ ███ ███ ███ ███ ███ ▄███▀ ███ ███▀▀▀██▄ ███ ███ ▀█████████▄ ███ ███ ███ ███ ███ - ███ ███ ███ ███ ███ █▀ ███▐██▀ ███▌ ███ ███ ███ █▀ ▀███▀▀██ ███ ███ ███ ███ ███ - ▄███▄▄▄▄███▄▄ ███ ███ ███ ▄█████▀ ███▌ ███ ███ ▄███ ███ ▀ ███ ███ ███ ███ ███ -▀▀███▀▀▀▀███▀ ▀███████████ ███ ▀▀█████▄ ███▌ ███ ███ ▀▀███ ████▄ ███ ███ ███ ███ ███ ███ - ███ ███ ███ ███ ███ █▄ ███▐██▄ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ - ███ ███ ███ ███ ███ ███ ███ ▀███▄ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███▌ ▄ - ███ █▀ ███ █▀ ████████▀ ███ ▀█▀ █▀ ▀█ █▀ ████████▀ ▄████▀ ▀██████▀ ▀██████▀ █████▄▄██ - ▀ ▀ -""" - panel = Panel(Text(logo_lines, style=style), box=box.DOUBLE, border_style=style) - console.print(panel) - console.print(f"[bold {style}]https://github.com/Z4nzu/hackingtool[/bold {style}]\n") +# ── Internet check ───────────────────────────────────────────────────────────── - -def choose_distro(): - console.print(Panel("[bold magenta]Select installation target[/bold magenta]\n\n[1] Kali / Parrot (apt)\n[2] Arch (pacman)\n[0] Exit", border_style="bright_magenta")) - choice = IntPrompt.ask("Choice", choices=["0", "1", "2"], default=1) - return choice - - -def check_internet(): - console.print("[yellow]* Checking internet connectivity...[/yellow]") - try: - run_cmd("curl -sSf --max-time 10 https://www.google.com > /dev/null", check=True) - console.print("[green][✔] Internet connection OK[/green]") - return True - except Exception: - try: - run_cmd("curl -sSf --max-time 10 https://github.com > /dev/null", check=True) - console.print("[green][✔] Internet connection OK[/green]") +def check_internet() -> bool: + console.print("[dim]Checking internet...[/dim]") + for host in ("https://github.com", "https://www.google.com"): + r = subprocess.run( + ["curl", "-sSf", "--max-time", "8", host], + capture_output=True, + ) + if r.returncode == 0: + console.print("[success]✔ Internet connection OK[/success]") return True - except Exception: - console.print("[red][✘] Internet connection not available[/red]") - return False + console.print("[error]✘ No internet connection[/error]") + return False -def system_update_and_install(choice): - if choice == 1: - console.print("[yellow]* Running apt update/upgrade...[/yellow]") - try: - run_cmd("apt update -y && apt upgrade -y") - except subprocess.CalledProcessError as e: - console.print(f"[red][!][/red] apt update/upgrade failed (non-fatal). Continuing installation. Error: {e}") - console.print("[yellow]* Installing required packages (apt)...[/yellow]") - try: - run_cmd("apt-get install -y git python3-pip python3-venv figlet boxes php curl xdotool wget") - except subprocess.CalledProcessError as e: - console.print(f"[red][!][/red] apt-get install failed (non-fatal). You may need to install some packages manually. Error: {e}") - elif choice == 2: - console.print("[yellow]* Running pacman update...[/yellow]") - try: - run_cmd("pacman -Syu --noconfirm") - except subprocess.CalledProcessError as e: - console.print(f"[red][!][/red] pacman update failed (non-fatal). Continuing installation. Error: {e}") - console.print("[yellow]* Installing required packages (pacman)...[/yellow]") - try: - run_cmd("pacman -S --noconfirm git python-pip") - except subprocess.CalledProcessError as e: - console.print(f"[red][!][/red] pacman install failed (non-fatal). You may need to install some packages manually. Error: {e}") - else: - console.print("[red]Invalid package manager choice[/red]") +# ── System packages ──────────────────────────────────────────────────────────── +def install_system_packages(): + mgr = CURRENT_OS.pkg_manager + if not mgr: + console.print("[warning]Skipping system packages — no package manager found.[/warning]") + return + + # Update index first (skip for brew — not needed) + if mgr != "brew": + update_cmd = PACKAGE_UPDATE_CMDS.get(mgr, "") + if update_cmd: + priv = "" if CURRENT_OS.system == "macos" else "sudo " + console.print(f"[dim]Updating package index ({mgr})...[/dim]") + subprocess.run(f"{priv}{update_cmd}", shell=True, check=False) + + packages = REQUIRED_PACKAGES.get(mgr, []) + if not packages: + return + + install_tpl = PACKAGE_INSTALL_CMDS[mgr] + cmd = install_tpl.format(packages=" ".join(packages)) + priv = "" if CURRENT_OS.system == "macos" else "sudo " + console.print(f"[dim]Installing system dependencies ({mgr})...[/dim]") + result = subprocess.run(f"{priv}{cmd}", shell=True, check=False) + if result.returncode != 0: + console.print("[warning]Some packages failed — you may need to install them manually.[/warning]") + + +# ── App directory ────────────────────────────────────────────────────────────── def prepare_install_dir(): - if INSTALL_DIR.exists(): - console.print(f"[red]The directory {INSTALL_DIR} already exists.[/red]") - if Confirm.ask("Replace it? This will remove the existing directory", default=False): - run_cmd(f"rm -rf {str(INSTALL_DIR)}") - else: - console.print("[red]Installation aborted by user.[/red]") + if APP_INSTALL_DIR.exists(): + console.print(f"[warning]{APP_INSTALL_DIR} already exists.[/warning]") + if not Confirm.ask("Replace it? This removes the existing installation.", default=False): + console.print("[error]Installation aborted.[/error]") sys.exit(1) - INSTALL_DIR.mkdir(parents=True, exist_ok=True) + subprocess.run(["rm", "-rf", str(APP_INSTALL_DIR)], check=True) + APP_INSTALL_DIR.mkdir(parents=True, exist_ok=True) -def git_clone(): - console.print("[yellow]* Cloning hackingtool repository...[/yellow]") - try: - run_cmd(f"git clone {REPO_URL} {str(INSTALL_DIR)}") - console.print("[green][✔] Repository cloned[/green]") +def git_clone() -> bool: + console.print(f"[dim]Cloning {REPO_URL}...[/dim]") + r = subprocess.run(["git", "clone", REPO_URL, str(APP_INSTALL_DIR)], check=False) + if r.returncode == 0: + console.print("[success]✔ Repository cloned[/success]") return True - except Exception as e: - console.print(f"[red][✘] Failed to clone repository: {e}[/red]") - return False + console.print("[error]✘ Failed to clone repository[/error]") + return False -def create_venv_and_install(choice): - venv_path = INSTALL_DIR / VENV_DIR_NAME - console.print("[yellow]* Creating virtual environment...[/yellow]") - run_cmd(f"python3 -m venv {str(venv_path)}") - activate = venv_path / "bin" / "activate" +# ── Python venv ──────────────────────────────────────────────────────────────── + +def create_venv_and_install(): + venv_path = APP_INSTALL_DIR / VENV_DIR_NAME + console.print("[dim]Creating virtual environment...[/dim]") + subprocess.run([sys.executable, "-m", "venv", str(venv_path)], check=True) + pip = str(venv_path / "bin" / "pip") - if (INSTALL_DIR / REQUIREMENTS).exists(): - console.print("[yellow]* Installing Python requirements...[/yellow]") - run_cmd(f"{pip} install -r {str(INSTALL_DIR / REQUIREMENTS)}") + req = APP_INSTALL_DIR / REQUIREMENTS + if req.exists(): + console.print("[dim]Installing Python requirements...[/dim]") + subprocess.run([pip, "install", "--quiet", "-r", str(req)], check=False) else: - console.print("[yellow]requirements.txt not found, skipping pip install.[/yellow]") - if choice == 1: - run_cmd("apt install figlet -y") - elif choice == 2: - # try pacman and fallback to AUR instructions - try: - run_cmd("pacman -S --noconfirm figlet") - except Exception: - console.print("[yellow]figlet not available in pacman automatically. Consider installing from AUR.[/yellow]") + console.print("[warning]requirements.txt not found — skipping pip install.[/warning]") +# ── Launcher script ──────────────────────────────────────────────────────────── + def create_launcher(): - console.print("[yellow]* Creating launcher script...[/yellow]") - launcher = INSTALL_DIR / "hackingtool.sh" - with open(launcher, "w") as f: - f.write("#!/bin/bash\n") - f.write(f"source {str(INSTALL_DIR / VENV_DIR_NAME)}/bin/activate\n") - f.write(f"python3 {str(INSTALL_DIR / 'hackingtool.py')} \"$@\"\n") - os.chmod(launcher, 0o755) - # move to /usr/bin/hackingtool - if BIN_PATH.exists(): - BIN_PATH.unlink() - shutil.move(str(launcher), str(BIN_PATH)) - console.print(f"[green][✔] Launcher installed at {str(BIN_PATH)}[/green]") - - -def final_messages(): - panel = Panel( - "[bold magenta]Installation complete[/bold magenta]\n\nType [bold cyan]hackingtool[/bold cyan] in terminal to start.", - border_style="magenta", + launcher = APP_INSTALL_DIR / "hackingtool.sh" + launcher.write_text( + "#!/bin/bash\n" + f'source "{APP_INSTALL_DIR / VENV_DIR_NAME}/bin/activate"\n' + f'python3 "{APP_INSTALL_DIR / "hackingtool.py"}" "$@"\n' ) - console.print(panel) + launcher.chmod(0o755) + if APP_BIN_PATH.exists(): + APP_BIN_PATH.unlink() + shutil.move(str(launcher), str(APP_BIN_PATH)) + console.print(f"[success]✔ Launcher installed at {APP_BIN_PATH}[/success]") + + +# ── User directories ─────────────────────────────────────────────────────────── + +def create_user_directories(): + """ + Create ~/.hackingtool/ and write initial config.json. + Uses Path.home() — always correct regardless of username or OS. + Safe to run as root (creates /root/.hackingtool/) or as a normal user. + """ + import json + USER_CONFIG_DIR.mkdir(parents=True, exist_ok=True) + USER_TOOLS_DIR.mkdir(parents=True, exist_ok=True) + if not USER_CONFIG_FILE.exists(): + USER_CONFIG_FILE.write_text(json.dumps(DEFAULT_CONFIG, indent=2, sort_keys=True)) + console.print(f"[success]✔ Config created at {USER_CONFIG_FILE}[/success]") + console.print(f"[success]✔ Tools directory: {USER_TOOLS_DIR}[/success]") + + +# ── Entry point ──────────────────────────────────────────────────────────────── def main(): check_root() console.clear() - colorful_logo() - choice = choose_distro() - if choice == 0: - console.print("[red]Exiting...[/red]") - sys.exit(0) + + console.print(Panel( + Text(f"HackingTool Installer {VERSION_DISPLAY}", style="bold magenta"), + box=box.DOUBLE, border_style="bright_magenta", + )) + + check_os_compatibility() + if not check_internet(): sys.exit(1) - with Progress(SpinnerColumn(), TextColumn("[progress.description]{task.description}")) as progress: - progress.add_task(description="Preparing system...", total=None) - system_update_and_install(choice) + with Progress(SpinnerColumn(), TextColumn("[progress.description]{task.description}")) as p: + p.add_task("Installing system packages...", total=None) + install_system_packages() prepare_install_dir() - ok = git_clone() - if not ok: + + if not git_clone(): sys.exit(1) - with Progress(SpinnerColumn(), TextColumn("[progress.description]{task.description}")) as progress: - progress.add_task(description="Setting up virtualenv & requirements...", total=None) - create_venv_and_install(choice) + with Progress(SpinnerColumn(), TextColumn("[progress.description]{task.description}")) as p: + p.add_task("Setting up virtualenv & requirements...", total=None) + create_venv_and_install() create_launcher() - final_messages() + create_user_directories() + + console.print(Panel( + "[bold magenta]Installation complete![/bold magenta]\n\n" + "Type [bold cyan]hackingtool[/bold cyan] in a terminal to start.", + border_style="magenta", + )) if __name__ == "__main__": try: main() except KeyboardInterrupt: - console.print("\n[red]Installation interrupted by user[/red]") + console.print("\n[error]Installation interrupted.[/error]") sys.exit(1) except subprocess.CalledProcessError as e: - console.print(f"[red]Command failed: {e}[/red]") + console.print(f"[error]Command failed: {e}[/error]") sys.exit(1) diff --git a/tools/tool_manager.py b/tools/tool_manager.py index 510cc0e..6f5f8c5 100644 --- a/tools/tool_manager.py +++ b/tools/tool_manager.py @@ -1,126 +1,97 @@ -# coding=utf-8 import os import sys +import subprocess from time import sleep -from core import HackingTool -from core import HackingToolsCollection -from rich.console import Console -from rich.theme import Theme -from rich.table import Table -from rich.panel import Panel -from rich.prompt import Prompt +from rich.prompt import Confirm -_theme = Theme({"purple": "#7B61FF"}) -console = Console(theme=_theme) +from core import HackingTool, HackingToolsCollection, console +from constants import APP_INSTALL_DIR, APP_BIN_PATH, USER_CONFIG_DIR, REPO_URL class UpdateTool(HackingTool): TITLE = "Update Tool or System" - DESCRIPTION = "Update Tool or System" + DESCRIPTION = "Update system packages or pull the latest hackingtool code" def __init__(self): - super(UpdateTool, self).__init__([ + super().__init__([ ("Update System", self.update_sys), - ("Update Hackingtool", self.update_ht) + ("Update Hackingtool", self.update_ht), ], installable=False, runnable=False) def update_sys(self): - os.system("sudo apt update && sudo apt full-upgrade -y") - os.system("sudo apt-get install tor openssl curl && sudo apt-get update tor openssl curl") - os.system("sudo apt-get install python3-pip") + from os_detect import CURRENT_OS, PACKAGE_UPDATE_CMDS + mgr = CURRENT_OS.pkg_manager + cmd = PACKAGE_UPDATE_CMDS.get(mgr) + if cmd: + priv = "" if CURRENT_OS.system == "macos" else "sudo " + os.system(f"{priv}{cmd}") + else: + console.print("[warning]Unknown package manager — update manually.[/warning]") def update_ht(self): - os.system("sudo chmod +x /etc/;" - "sudo chmod +x /usr/share/doc;" - "sudo rm -rf /usr/share/doc/hackingtool/;" - "cd /etc/;" - "sudo rm -rf /etc/hackingtool/;" - "mkdir hackingtool;" - "cd hackingtool;" - "git clone https://github.com/Z4nzu/hackingtool.git;" - "cd hackingtool;" - "sudo chmod +x install.sh;" - "./install.sh") + if not APP_INSTALL_DIR.exists(): + console.print(f"[error]Install directory not found: {APP_INSTALL_DIR}[/error]") + console.print("[dim]Run install.py first.[/dim]") + return + console.print(f"[bold cyan]Pulling latest code from {REPO_URL}...[/bold cyan]") + result = subprocess.run( + ["git", "pull", "--rebase"], + cwd=str(APP_INSTALL_DIR), + capture_output=True, text=True, + ) + if result.returncode != 0: + console.print(f"[error]git pull failed:\n{result.stderr}[/error]") + return + pip = str(APP_INSTALL_DIR / "venv" / "bin" / "pip") + if (APP_INSTALL_DIR / "venv" / "bin" / "pip").exists(): + subprocess.run([pip, "install", "-q", "-r", + str(APP_INSTALL_DIR / "requirements.txt")]) + console.print("[success]✔ Hackingtool updated.[/success]") class UninstallTool(HackingTool): TITLE = "Uninstall HackingTool" - DESCRIPTION = "Uninstall HackingTool" + DESCRIPTION = "Remove hackingtool from system" def __init__(self): - super(UninstallTool, self).__init__([ - ('Uninstall', self.uninstall) + super().__init__([ + ("Uninstall", self.uninstall), ], installable=False, runnable=False) def uninstall(self): - console.print("hackingtool started to uninstall..\n") + import shutil + console.print("[warning]This will remove hackingtool from your system.[/warning]") + if not Confirm.ask("Continue?", default=False): + return + + if APP_INSTALL_DIR.exists(): + shutil.rmtree(str(APP_INSTALL_DIR)) + console.print(f"[success]✔ Removed {APP_INSTALL_DIR}[/success]") + else: + console.print(f"[dim]{APP_INSTALL_DIR} not found — already removed?[/dim]") + + if APP_BIN_PATH.exists(): + APP_BIN_PATH.unlink() + console.print(f"[success]✔ Removed launcher {APP_BIN_PATH}[/success]") + + if Confirm.ask(f"Also remove user data at {USER_CONFIG_DIR}?", default=False): + shutil.rmtree(str(USER_CONFIG_DIR), ignore_errors=True) + console.print(f"[success]✔ Removed {USER_CONFIG_DIR}[/success]") + + console.print("[bold green]Hackingtool uninstalled. Goodbye.[/bold green]") sleep(1) - os.system("sudo chmod +x /etc/;" - "sudo chmod +x /usr/share/doc;" - "sudo rm -rf /usr/share/doc/hackingtool/;" - "cd /etc/;" - "sudo rm -rf /etc/hackingtool/;") - console.print("\n[bold green]Hackingtool Successfully Uninstalled... Goodbye.[/bold green]") - sys.exit() + sys.exit(0) class ToolManager(HackingToolsCollection): TITLE = "Update or Uninstall | Hackingtool" TOOLS = [ UpdateTool(), - UninstallTool() + UninstallTool(), ] - def pretty_print(self): - table = Table(title="Tool Manager — Update / Uninstall", show_lines=True, expand=True) - table.add_column("Title", style="purple", no_wrap=True) - table.add_column("Description", style="purple") - - for t in self.TOOLS: - desc = getattr(t, "DESCRIPTION", "") or "" - table.add_row(t.TITLE, desc.strip().replace("\n", " ")) - - panel = Panel(table, title="[purple]Available Manager Tools[/purple]", border_style="purple") - console.print(panel) - - def show_options(self, parent=None): - console.print("\n") - panel = Panel.fit("[bold magenta]Tool Manager[/bold magenta]\nSelect an action to run.", border_style="purple") - console.print(panel) - - table = Table(title="[bold cyan]Available Options[/bold cyan]", show_lines=True, expand=True) - table.add_column("Index", justify="center", style="bold yellow") - table.add_column("Tool Name", justify="left", style="bold green") - table.add_column("Description", justify="left", style="white") - - for i, tool in enumerate(self.TOOLS): - title = getattr(tool, "TITLE", tool.__class__.__name__) - desc = getattr(tool, "DESCRIPTION", "—") - table.add_row(str(i + 1), title, desc) - - table.add_row("[red]99[/red]", "[bold red]Exit[/bold red]", "Return to previous menu") - console.print(table) - - try: - choice = int(Prompt.ask("[bold cyan]Select an option[/bold cyan]", default="99")) - if 1 <= choice <= len(self.TOOLS): - selected = self.TOOLS[choice - 1] - if hasattr(selected, "show_options"): - selected.show_options(parent=self) - elif hasattr(selected, "run"): - selected.run() - else: - console.print("[bold yellow]Selected tool has no runnable interface.[/bold yellow]") - elif choice == 99: - return 99 - except Exception: - console.print("[bold red]Invalid choice. Try again.[/bold red]") - - return self.show_options(parent=parent) - if __name__ == "__main__": manager = ToolManager() - manager.pretty_print() manager.show_options() diff --git a/update.sh b/update.sh index 4f6554b..e18a93d 100644 --- a/update.sh +++ b/update.sh @@ -1,51 +1,33 @@ #!/bin/bash +set -euo pipefail -RED='\e[1;31m' -GREEN='\e[1;32m' -YELLOW='\e[1;33m' -BLUE='\e[1;34m' +INSTALL_DIR="/usr/share/hackingtool" -echo "███████╗██╗ ██╗███╗ ██╗███████╗██╗ ██╗ "; -echo "╚══███╔╝██║ ██║████╗ ██║╚══███╔╝██║ ██║ "; -echo " ███╔╝ ███████║██╔██╗ ██║ ███╔╝ ██║ ██║ "; -echo " ███╔╝ ╚════██║██║╚██╗██║ ███╔╝ ██║ ██║ "; -echo "███████╗ ██║██║ ╚████║███████╗╚██████╔╝ "; -echo "╚══════╝ ╚═╝╚═╝ ╚═══╝╚══════╝ ╚═════╝ "; -echo " "; - -# Check if the script is run as root if [[ $EUID -ne 0 ]]; then - echo -e "${RED}[ERROR]\e[0m This script must be run as root." - exit 1 + echo "[ERROR] Run as root: sudo bash update.sh" + exit 1 fi -install_dir="/usr/share/hackingtool" -# Change to the directory containing the install.sh script -cd $install_dir || { echo -e "${RED}[ERROR]\e[0m Could not change to directory containing install.sh."; exit 1; } -echo -e "${YELLOW}[*] Checking Internet Connection ..${NC}" -echo ""; -if curl -s -m 10 https://www.google.com > /dev/null || curl -s -m 10 https://www.github.com > /dev/null; then - echo -e "${GREEN}[✔] Internet connection is OK [✔]${NC}" - echo "" +if [[ ! -d "$INSTALL_DIR" ]]; then + echo "[ERROR] Installation not found at $INSTALL_DIR. Run install.py first." + exit 1 +fi + +echo "[*] Checking internet connection..." +if ! curl -sSf --max-time 10 https://github.com > /dev/null; then + echo "[ERROR] No internet connection." + exit 1 +fi +echo "[✔] Internet OK" + +echo "[*] Pulling latest changes..." +git -C "$INSTALL_DIR" pull --rebase + +echo "[*] Updating Python dependencies..." +if [[ -f "$INSTALL_DIR/venv/bin/pip" ]]; then + "$INSTALL_DIR/venv/bin/pip" install -q -r "$INSTALL_DIR/requirements.txt" else - echo -e "${RED}[✘] Please check your internet connection[✘]" - echo "" - exit 1 -fi -echo -e "[*]Marking hackingtool directory as safe-directory" -git config --global --add safe.directory $install_dir -# Update the repository and the tool itself -echo -e "${BLUE}[INFO]\e[0m Updating repository and tool..." -if ! sudo git pull; then - echo -e "${RED}[ERROR]\e[0m Failed to update repository or tool." - exit 1 + echo "[WARN] venv not found — skipping pip update. Run install.py to create it." fi -# Re-run the installation script -echo -e "${GREEN}[INFO]\e[0m Running installation script..." -if ! sudo bash install.sh; then - echo -e "${RED}[ERROR]\e[0m Failed to run installation script." - exit 1 -fi - -echo -e "${GREEN}[SUCCESS]\e[0m Tool updated successfully." +echo "[✔] Hackingtool updated. Run 'hackingtool' to start."