Loading Dockerfile +14 −6 Original line number Diff line number Diff line FROM kalilinux/kali-rolling:latest RUN apt-get update && \ apt-get install -y git python3-pip figlet sudo && \ apt-get install -y boxes php curl xdotool wget apt-get install -y --no-install-recommends \ git python3-pip python3-venv sudo curl wget php && \ rm -rf /var/lib/apt/lists/* WORKDIR /root/hackingtool COPY requirements.txt ./ RUN pip3 install --no-cache-dir boxes flask lolcat requests -r requirements.txt # Bug 21 fix: boxes/lolcat/flask are NOT pip packages — removed RUN pip3 install --no-cache-dir -r requirements.txt COPY . . RUN true && echo "/root/hackingtool/" > /home/hackingtoolpath.txt; EXPOSE 1-65535 # Bug 20 fix: path file must be in /root/ not /home/ (running as root in Docker) RUN mkdir -p /root/.hackingtool/tools # Vuln 3 fix: removed EXPOSE 1-65535 — this tool is a CLI, not a server ENTRYPOINT ["python3", "/root/hackingtool/hackingtool.py"] core.py +224 −118 Original line number Diff line number Diff line import os import sys import webbrowser from collections.abc import Callable from platform import system from rich import box from rich.console import Console from rich.panel import Panel from rich.prompt import Prompt from rich.table import Table from rich import box from rich.traceback import install from rich.theme import Theme from rich.traceback import install import os import sys import webbrowser from platform import system from traceback import print_exc from typing import Callable, List, Tuple from constants import ( THEME_PRIMARY, THEME_BORDER, THEME_ACCENT, THEME_SUCCESS, THEME_ERROR, THEME_WARNING, THEME_DIM, THEME_ARCHIVED, THEME_URL, ) # Enable rich tracebacks # Enable rich tracebacks globally install() _theme = Theme({"purple": "#7B61FF"}) _theme = Theme({ "purple": "#7B61FF", "success": THEME_SUCCESS, "error": THEME_ERROR, "warning": THEME_WARNING, "archived": THEME_ARCHIVED, "url": THEME_URL, "dim": THEME_DIM, }) # Single shared console — all tool files do: from core import console console = Console(theme=_theme) Loading @@ -22,46 +39,68 @@ def clear_screen(): os.system("cls" if system() == "Windows" else "clear") def validate_input(ip, val_range): val_range = val_range or [] def validate_input(ip, val_range: list) -> int | None: """Return the integer if it is in val_range, else None.""" if not val_range: return None try: ip = int(ip) if ip in val_range: return ip except Exception: return None except (TypeError, ValueError): pass return None class HackingTool(object): class HackingTool: TITLE: str = "" DESCRIPTION: str = "" INSTALL_COMMANDS: List[str] = [] INSTALLATION_DIR: str = "" UNINSTALL_COMMANDS: List[str] = [] RUN_COMMANDS: List[str] = [] OPTIONS: List[Tuple[str, Callable]] = [] INSTALL_COMMANDS: list[str] = [] UNINSTALL_COMMANDS: list[str] = [] RUN_COMMANDS: list[str] = [] OPTIONS: list[tuple[str, Callable]] = [] PROJECT_URL: str = "" # OS / capability metadata SUPPORTED_OS: list[str] = ["linux", "macos"] REQUIRES_ROOT: bool = False REQUIRES_WIFI: bool = False REQUIRES_GO: bool = False REQUIRES_RUBY: bool = False REQUIRES_JAVA: bool = False REQUIRES_DOCKER: bool = False # Archived tool flags ARCHIVED: bool = False ARCHIVED_REASON: str = "" def __init__(self, options=None, installable=True, runnable=True): options = options or [] if isinstance(options, list): if not isinstance(options, list): raise TypeError("options must be a list of (option_name, option_fn) tuples") self.OPTIONS = [] if installable: self.OPTIONS.append(("Install", self.install)) if runnable: self.OPTIONS.append(("Run", self.run)) self.OPTIONS.extend(options) else: raise Exception("options must be a list of (option_name, option_fn) tuples") def show_info(self): desc = f"[cyan]{self.DESCRIPTION}[/cyan]" if self.PROJECT_URL: desc += f"\n[green]🔗 {self.PROJECT_URL}[/green]" console.print(Panel(desc, title=f"[bold purple]{self.TITLE}[/bold purple]", border_style="purple", box=box.DOUBLE)) desc += f"\n[url]🔗 {self.PROJECT_URL}[/url]" if self.ARCHIVED: desc += f"\n[archived]⚠ ARCHIVED: {self.ARCHIVED_REASON}[/archived]" console.print(Panel( desc, title=f"[{THEME_PRIMARY}]{self.TITLE}[/{THEME_PRIMARY}]", border_style="purple", box=box.DOUBLE, )) def show_options(self, parent=None): """Iterative menu loop — no recursion, no stack growth.""" while True: clear_screen() self.show_info() Loading @@ -75,42 +114,43 @@ class HackingTool(object): if self.PROJECT_URL: table.add_row("98", "Open Project Page") table.add_row("99", f"Back to {parent.TITLE if parent else 'Exit'}") console.print(table) option_index = input("\n[?] Select an option: ").strip() raw = Prompt.ask("\n[bold cyan][?] Select an option[/bold cyan]", default="99") try: option_index = int(option_index) if option_index - 1 in range(len(self.OPTIONS)): ret_code = self.OPTIONS[option_index - 1][1]() if ret_code != 99: input("\nPress [Enter] to continue...") elif option_index == 98: self.show_project_page() elif option_index == 99: choice = int(raw) except ValueError: console.print("[error]⚠ Please enter a number.[/error]") Prompt.ask("[dim]Press Enter to continue[/dim]", default="") continue if choice == 99: if parent is None: sys.exit() return 99 except (TypeError, ValueError): console.print("[red]⚠ Please enter a valid option.[/red]") input("\nPress [Enter] to continue...") elif choice == 98 and self.PROJECT_URL: self.show_project_page() elif 1 <= choice <= len(self.OPTIONS): try: self.OPTIONS[choice - 1][1]() except Exception: console.print_exception(show_locals=True) input("\nPress [Enter] to continue...") return self.show_options(parent=parent) Prompt.ask("[dim]Press Enter to continue[/dim]", default="") else: console.print("[error]⚠ Invalid option.[/error]") def before_install(self): pass def install(self): self.before_install() if isinstance(self.INSTALL_COMMANDS, (list, tuple)): for INSTALL_COMMAND in self.INSTALL_COMMANDS: console.print(f"[yellow]→ {INSTALL_COMMAND}[/yellow]") os.system(INSTALL_COMMAND) for cmd in self.INSTALL_COMMANDS: console.print(f"[warning]→ {cmd}[/warning]") os.system(cmd) self.after_install() def after_install(self): console.print("[green]✔ Successfully installed![/green]") console.print("[success]✔ Successfully installed![/success]") def before_uninstall(self) -> bool: return True Loading @@ -118,9 +158,9 @@ class HackingTool(object): def uninstall(self): if self.before_uninstall(): if isinstance(self.UNINSTALL_COMMANDS, (list, tuple)): for UNINSTALL_COMMAND in self.UNINSTALL_COMMANDS: console.print(f"[red]→ {UNINSTALL_COMMAND}[/red]") os.system(UNINSTALL_COMMAND) for cmd in self.UNINSTALL_COMMANDS: console.print(f"[error]→ {cmd}[/error]") os.system(cmd) self.after_uninstall() def after_uninstall(self): pass Loading @@ -130,63 +170,129 @@ class HackingTool(object): def run(self): self.before_run() if isinstance(self.RUN_COMMANDS, (list, tuple)): for RUN_COMMAND in self.RUN_COMMANDS: console.print(f"[cyan]⚙ Running:[/cyan] [bold]{RUN_COMMAND}[/bold]") os.system(RUN_COMMAND) for cmd in self.RUN_COMMANDS: console.print(f"[cyan]⚙ Running:[/cyan] [bold]{cmd}[/bold]") os.system(cmd) self.after_run() def after_run(self): pass def is_installed(self, dir_to_check=None): console.print("[yellow]⚠ Unimplemented: DO NOT USE[/yellow]") return "?" def show_project_page(self): console.print(f"[blue]🌐 Opening project page: {self.PROJECT_URL}[/blue]") console.print(f"[url]🌐 Opening: {self.PROJECT_URL}[/url]") webbrowser.open_new_tab(self.PROJECT_URL) class HackingToolsCollection(object): class HackingToolsCollection: TITLE: str = "" DESCRIPTION: str = "" TOOLS: List = [] TOOLS: list = [] def __init__(self): pass def show_info(self): console.rule(f"[bold purple]{self.TITLE}[/bold purple]", style="purple") console.rule(f"[{THEME_PRIMARY}]{self.TITLE}[/{THEME_PRIMARY}]", style="purple") if self.DESCRIPTION: console.print(f"[italic cyan]{self.DESCRIPTION}[/italic cyan]\n") def _active_tools(self) -> list: """Return tools that are not archived and are OS-compatible.""" from os_detect import CURRENT_OS return [ t for t in self.TOOLS if not getattr(t, "ARCHIVED", False) and CURRENT_OS.system in getattr(t, "SUPPORTED_OS", ["linux", "macos"]) ] def _archived_tools(self) -> list: return [t for t in self.TOOLS if getattr(t, "ARCHIVED", False)] def _incompatible_tools(self) -> list: from os_detect import CURRENT_OS return [ t for t in self.TOOLS if not getattr(t, "ARCHIVED", False) and CURRENT_OS.system not in getattr(t, "SUPPORTED_OS", ["linux", "macos"]) ] def _show_archived_tools(self): """Show archived tools sub-menu (option 98).""" archived = self._archived_tools() if not archived: console.print("[dim]No archived tools in this category.[/dim]") Prompt.ask("[dim]Press Enter to return[/dim]", default="") return while True: clear_screen() console.rule(f"[archived]Archived Tools — {self.TITLE}[/archived]", style="yellow") table = Table(box=box.MINIMAL_DOUBLE_HEAD, show_lines=True) table.add_column("No.", justify="center", style="bold yellow") table.add_column("Tool", style="dim yellow") table.add_column("Reason", style="dim white") for i, tool in enumerate(archived): reason = getattr(tool, "ARCHIVED_REASON", "No reason given") table.add_row(str(i + 1), tool.TITLE, reason) table.add_row("99", "Back", "") console.print(table) raw = Prompt.ask("[bold yellow][?] Select[/bold yellow]", default="99") try: choice = int(raw) except ValueError: continue if choice == 99: return elif 1 <= choice <= len(archived): archived[choice - 1].show_options(parent=self) def show_options(self, parent=None): """Iterative menu loop — no recursion, no stack growth.""" while True: clear_screen() self.show_info() active = self._active_tools() incompatible = self._incompatible_tools() archived = self._archived_tools() table = Table(title="Available Tools", box=box.MINIMAL_DOUBLE_HEAD) table.add_column("No.", justify="center", style="bold cyan") table.add_column("Tool Name", style="bold yellow") table.add_column("Tool", style="bold yellow") for index, tool in enumerate(self.TOOLS): for index, tool in enumerate(active): table.add_row(str(index), tool.TITLE) if archived: table.add_row("[dim]98[/dim]", f"[archived]Archived tools ({len(archived)})[/archived]") if incompatible: console.print(f"[dim]({len(incompatible)} tools hidden — not supported on current OS)[/dim]") table.add_row("99", f"Back to {parent.TITLE if parent else 'Exit'}") console.print(table) tool_index = input("\n[?] Choose a tool: ").strip() raw = Prompt.ask("\n[bold cyan][?] Choose a tool[/bold cyan]", default="99") try: tool_index = int(tool_index) if tool_index in range(len(self.TOOLS)): ret_code = self.TOOLS[tool_index].show_options(parent=self) if ret_code != 99: input("\nPress [Enter] to continue...") elif tool_index == 99: choice = int(raw) except ValueError: console.print("[error]⚠ Please enter a number.[/error]") continue if choice == 99: if parent is None: sys.exit() return 99 except (TypeError, ValueError): console.print("[red]⚠ Please enter a valid option.[/red]") input("\nPress [Enter] to continue...") elif choice == 98 and archived: self._show_archived_tools() elif 0 <= choice < len(active): try: ret = active[choice].show_options(parent=self) except Exception: console.print_exception(show_locals=True) input("\nPress [Enter] to continue...") return self.show_options(parent=parent) Prompt.ask("[dim]Press Enter to continue[/dim]", default="") else: console.print("[error]⚠ Invalid option.[/error]") docker-compose.yml +8 −3 Original line number Diff line number Diff line version: "3.9" services: hackingtool: image: vgpastor/hackingtool # Bug 23 fix: was using external unverified image vgpastor/hackingtool # Now builds from local Dockerfile — no third-party trust required build: . container_name: hackingtool stdin_open: true tty: true volumes: - .:/root/hackingtool ports: - 22:22 No newline at end of file - hackingtool_data:/root/.hackingtool # Bug 22 fix: removed port 22:22 — this is a CLI tool, SSH exposure is unnecessary volumes: hackingtool_data: tools/anonsurf.py +14 −85 Original line number Diff line number Diff line # coding=utf-8 import os from rich.console import Console from rich.panel import Panel from rich.prompt import Prompt from rich.text import Text from rich.table import Table from core import HackingTool from core import HackingToolsCollection console = Console() P_COLOR = "magenta" from core import HackingTool, HackingToolsCollection, console class AnonymouslySurf(HackingTool): TITLE = "Anonymously Surf" DESCRIPTION = ( "It automatically overwrites the RAM when\n" "the system is shutting down and also change Ip." "It automatically overwrites the RAM when the system shuts down\n" "and also changes your IP address." ) # Bug 28 fix: was "cd kali-anonsurf && ./installer.sh && cd .. && sudo rm -r kali-anonsurf" # Deleting the source on install means there is no retry if install fails. # Now kept in a separate step so failure does not destroy the source. INSTALL_COMMANDS = [ "sudo git clone https://github.com/Und3rf10w/kali-anonsurf.git", "cd kali-anonsurf && sudo ./installer.sh && cd .. && sudo rm -r kali-anonsurf", "cd kali-anonsurf && sudo ./installer.sh", ] RUN_COMMANDS = ["sudo anonsurf start"] PROJECT_URL = "https://github.com/Und3rf10w/kali-anonsurf" SUPPORTED_OS = ["linux"] def __init__(self): super(AnonymouslySurf, self).__init__([("Stop", self.stop)]) super().__init__([("Stop", self.stop)]) def stop(self): console.print(Panel(Text(self.TITLE, justify="center"), style=f"bold {P_COLOR}")) console.print("Stopping Anonsurf...", style=f"bold {P_COLOR}") console.print("[bold magenta]Stopping Anonsurf...[/bold magenta]") os.system("sudo anonsurf stop") class Multitor(HackingTool): TITLE = "Multitor" DESCRIPTION = "How to stay in multi places at the same time" DESCRIPTION = "How to stay in multi places at the same time." INSTALL_COMMANDS = [ "sudo git clone https://github.com/trimstray/multitor.git", "cd multitor;sudo bash setup.sh install", "cd multitor && sudo bash setup.sh install", ] RUN_COMMANDS = [ "multitor --init 2 --user debian-tor --socks-port 9000 --control-port 9900 --proxy privoxy --haproxy" ] PROJECT_URL = "https://github.com/trimstray/multitor" SUPPORTED_OS = ["linux"] def __init__(self): # keep original behavior (non-runnable) while still initializing super(Multitor, self).__init__(runnable=False) super().__init__(runnable=False) class AnonSurfTools(HackingToolsCollection): TITLE = "Anonymously Hiding Tools" DESCRIPTION = "" TOOLS = [ AnonymouslySurf(), Multitor(), ] def _get_attr(self, obj, *names, default=""): for n in names: if hasattr(obj, n): return getattr(obj, n) return default def pretty_print(self): table = Table(title="Anonymously Hiding Tools", show_lines=True, expand=True) table.add_column("Title", style="magenta", no_wrap=True) table.add_column("Description", style="magenta") table.add_column("Project URL", style="magenta", no_wrap=True) for t in self.TOOLS: title = self._get_attr(t, "TITLE", "Title", "title", default=t.__class__.__name__) desc = self._get_attr(t, "DESCRIPTION", "Description", "description", default="") url = self._get_attr(t, "PROJECT_URL", "PROJECT_URL", "PROJECT", "project_url", "projectUrl", default="") table.add_row(str(title), str(desc).strip().replace("\n", " "), str(url)) panel = Panel(table, title=f"[{P_COLOR}]Available Tools[/ {P_COLOR}]", border_style=P_COLOR) console.print(panel) def show_options(self, parent=None): console.print("\n") console.print(Panel.fit( "[bold magenta]Anonymously Hiding Tools Collection[/bold magenta]\n" "Select a tool to view options or run it.", border_style=P_COLOR )) table = Table(title="[bold cyan]Available Tools[/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 = self._get_attr(tool, "TITLE", "Title", "title", default=tool.__class__.__name__) desc = self._get_attr(tool, "DESCRIPTION", "Description", "description", default="—") table.add_row(str(i + 1), title, desc or "—") table.add_row("[red]99[/red]", "[bold red]Exit[/bold red]", "Return to previous menu") console.print(table) try: choice = Prompt.ask("[bold cyan]Select a tool to run[/bold cyan]", default="99") choice = int(choice) if 1 <= choice <= len(self.TOOLS): selected = self.TOOLS[choice - 1] # delegate if collection-style interface exists if hasattr(selected, "show_options"): selected.show_options(parent=self) # otherwise, if the tool has actions or a run method, prefer those 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__": tools = AnonSurfTools() tools.pretty_print() tools.show_options() tools/ddos.py +55 −136 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
Dockerfile +14 −6 Original line number Diff line number Diff line FROM kalilinux/kali-rolling:latest RUN apt-get update && \ apt-get install -y git python3-pip figlet sudo && \ apt-get install -y boxes php curl xdotool wget apt-get install -y --no-install-recommends \ git python3-pip python3-venv sudo curl wget php && \ rm -rf /var/lib/apt/lists/* WORKDIR /root/hackingtool COPY requirements.txt ./ RUN pip3 install --no-cache-dir boxes flask lolcat requests -r requirements.txt # Bug 21 fix: boxes/lolcat/flask are NOT pip packages — removed RUN pip3 install --no-cache-dir -r requirements.txt COPY . . RUN true && echo "/root/hackingtool/" > /home/hackingtoolpath.txt; EXPOSE 1-65535 # Bug 20 fix: path file must be in /root/ not /home/ (running as root in Docker) RUN mkdir -p /root/.hackingtool/tools # Vuln 3 fix: removed EXPOSE 1-65535 — this tool is a CLI, not a server ENTRYPOINT ["python3", "/root/hackingtool/hackingtool.py"]
core.py +224 −118 Original line number Diff line number Diff line import os import sys import webbrowser from collections.abc import Callable from platform import system from rich import box from rich.console import Console from rich.panel import Panel from rich.prompt import Prompt from rich.table import Table from rich import box from rich.traceback import install from rich.theme import Theme from rich.traceback import install import os import sys import webbrowser from platform import system from traceback import print_exc from typing import Callable, List, Tuple from constants import ( THEME_PRIMARY, THEME_BORDER, THEME_ACCENT, THEME_SUCCESS, THEME_ERROR, THEME_WARNING, THEME_DIM, THEME_ARCHIVED, THEME_URL, ) # Enable rich tracebacks # Enable rich tracebacks globally install() _theme = Theme({"purple": "#7B61FF"}) _theme = Theme({ "purple": "#7B61FF", "success": THEME_SUCCESS, "error": THEME_ERROR, "warning": THEME_WARNING, "archived": THEME_ARCHIVED, "url": THEME_URL, "dim": THEME_DIM, }) # Single shared console — all tool files do: from core import console console = Console(theme=_theme) Loading @@ -22,46 +39,68 @@ def clear_screen(): os.system("cls" if system() == "Windows" else "clear") def validate_input(ip, val_range): val_range = val_range or [] def validate_input(ip, val_range: list) -> int | None: """Return the integer if it is in val_range, else None.""" if not val_range: return None try: ip = int(ip) if ip in val_range: return ip except Exception: return None except (TypeError, ValueError): pass return None class HackingTool(object): class HackingTool: TITLE: str = "" DESCRIPTION: str = "" INSTALL_COMMANDS: List[str] = [] INSTALLATION_DIR: str = "" UNINSTALL_COMMANDS: List[str] = [] RUN_COMMANDS: List[str] = [] OPTIONS: List[Tuple[str, Callable]] = [] INSTALL_COMMANDS: list[str] = [] UNINSTALL_COMMANDS: list[str] = [] RUN_COMMANDS: list[str] = [] OPTIONS: list[tuple[str, Callable]] = [] PROJECT_URL: str = "" # OS / capability metadata SUPPORTED_OS: list[str] = ["linux", "macos"] REQUIRES_ROOT: bool = False REQUIRES_WIFI: bool = False REQUIRES_GO: bool = False REQUIRES_RUBY: bool = False REQUIRES_JAVA: bool = False REQUIRES_DOCKER: bool = False # Archived tool flags ARCHIVED: bool = False ARCHIVED_REASON: str = "" def __init__(self, options=None, installable=True, runnable=True): options = options or [] if isinstance(options, list): if not isinstance(options, list): raise TypeError("options must be a list of (option_name, option_fn) tuples") self.OPTIONS = [] if installable: self.OPTIONS.append(("Install", self.install)) if runnable: self.OPTIONS.append(("Run", self.run)) self.OPTIONS.extend(options) else: raise Exception("options must be a list of (option_name, option_fn) tuples") def show_info(self): desc = f"[cyan]{self.DESCRIPTION}[/cyan]" if self.PROJECT_URL: desc += f"\n[green]🔗 {self.PROJECT_URL}[/green]" console.print(Panel(desc, title=f"[bold purple]{self.TITLE}[/bold purple]", border_style="purple", box=box.DOUBLE)) desc += f"\n[url]🔗 {self.PROJECT_URL}[/url]" if self.ARCHIVED: desc += f"\n[archived]⚠ ARCHIVED: {self.ARCHIVED_REASON}[/archived]" console.print(Panel( desc, title=f"[{THEME_PRIMARY}]{self.TITLE}[/{THEME_PRIMARY}]", border_style="purple", box=box.DOUBLE, )) def show_options(self, parent=None): """Iterative menu loop — no recursion, no stack growth.""" while True: clear_screen() self.show_info() Loading @@ -75,42 +114,43 @@ class HackingTool(object): if self.PROJECT_URL: table.add_row("98", "Open Project Page") table.add_row("99", f"Back to {parent.TITLE if parent else 'Exit'}") console.print(table) option_index = input("\n[?] Select an option: ").strip() raw = Prompt.ask("\n[bold cyan][?] Select an option[/bold cyan]", default="99") try: option_index = int(option_index) if option_index - 1 in range(len(self.OPTIONS)): ret_code = self.OPTIONS[option_index - 1][1]() if ret_code != 99: input("\nPress [Enter] to continue...") elif option_index == 98: self.show_project_page() elif option_index == 99: choice = int(raw) except ValueError: console.print("[error]⚠ Please enter a number.[/error]") Prompt.ask("[dim]Press Enter to continue[/dim]", default="") continue if choice == 99: if parent is None: sys.exit() return 99 except (TypeError, ValueError): console.print("[red]⚠ Please enter a valid option.[/red]") input("\nPress [Enter] to continue...") elif choice == 98 and self.PROJECT_URL: self.show_project_page() elif 1 <= choice <= len(self.OPTIONS): try: self.OPTIONS[choice - 1][1]() except Exception: console.print_exception(show_locals=True) input("\nPress [Enter] to continue...") return self.show_options(parent=parent) Prompt.ask("[dim]Press Enter to continue[/dim]", default="") else: console.print("[error]⚠ Invalid option.[/error]") def before_install(self): pass def install(self): self.before_install() if isinstance(self.INSTALL_COMMANDS, (list, tuple)): for INSTALL_COMMAND in self.INSTALL_COMMANDS: console.print(f"[yellow]→ {INSTALL_COMMAND}[/yellow]") os.system(INSTALL_COMMAND) for cmd in self.INSTALL_COMMANDS: console.print(f"[warning]→ {cmd}[/warning]") os.system(cmd) self.after_install() def after_install(self): console.print("[green]✔ Successfully installed![/green]") console.print("[success]✔ Successfully installed![/success]") def before_uninstall(self) -> bool: return True Loading @@ -118,9 +158,9 @@ class HackingTool(object): def uninstall(self): if self.before_uninstall(): if isinstance(self.UNINSTALL_COMMANDS, (list, tuple)): for UNINSTALL_COMMAND in self.UNINSTALL_COMMANDS: console.print(f"[red]→ {UNINSTALL_COMMAND}[/red]") os.system(UNINSTALL_COMMAND) for cmd in self.UNINSTALL_COMMANDS: console.print(f"[error]→ {cmd}[/error]") os.system(cmd) self.after_uninstall() def after_uninstall(self): pass Loading @@ -130,63 +170,129 @@ class HackingTool(object): def run(self): self.before_run() if isinstance(self.RUN_COMMANDS, (list, tuple)): for RUN_COMMAND in self.RUN_COMMANDS: console.print(f"[cyan]⚙ Running:[/cyan] [bold]{RUN_COMMAND}[/bold]") os.system(RUN_COMMAND) for cmd in self.RUN_COMMANDS: console.print(f"[cyan]⚙ Running:[/cyan] [bold]{cmd}[/bold]") os.system(cmd) self.after_run() def after_run(self): pass def is_installed(self, dir_to_check=None): console.print("[yellow]⚠ Unimplemented: DO NOT USE[/yellow]") return "?" def show_project_page(self): console.print(f"[blue]🌐 Opening project page: {self.PROJECT_URL}[/blue]") console.print(f"[url]🌐 Opening: {self.PROJECT_URL}[/url]") webbrowser.open_new_tab(self.PROJECT_URL) class HackingToolsCollection(object): class HackingToolsCollection: TITLE: str = "" DESCRIPTION: str = "" TOOLS: List = [] TOOLS: list = [] def __init__(self): pass def show_info(self): console.rule(f"[bold purple]{self.TITLE}[/bold purple]", style="purple") console.rule(f"[{THEME_PRIMARY}]{self.TITLE}[/{THEME_PRIMARY}]", style="purple") if self.DESCRIPTION: console.print(f"[italic cyan]{self.DESCRIPTION}[/italic cyan]\n") def _active_tools(self) -> list: """Return tools that are not archived and are OS-compatible.""" from os_detect import CURRENT_OS return [ t for t in self.TOOLS if not getattr(t, "ARCHIVED", False) and CURRENT_OS.system in getattr(t, "SUPPORTED_OS", ["linux", "macos"]) ] def _archived_tools(self) -> list: return [t for t in self.TOOLS if getattr(t, "ARCHIVED", False)] def _incompatible_tools(self) -> list: from os_detect import CURRENT_OS return [ t for t in self.TOOLS if not getattr(t, "ARCHIVED", False) and CURRENT_OS.system not in getattr(t, "SUPPORTED_OS", ["linux", "macos"]) ] def _show_archived_tools(self): """Show archived tools sub-menu (option 98).""" archived = self._archived_tools() if not archived: console.print("[dim]No archived tools in this category.[/dim]") Prompt.ask("[dim]Press Enter to return[/dim]", default="") return while True: clear_screen() console.rule(f"[archived]Archived Tools — {self.TITLE}[/archived]", style="yellow") table = Table(box=box.MINIMAL_DOUBLE_HEAD, show_lines=True) table.add_column("No.", justify="center", style="bold yellow") table.add_column("Tool", style="dim yellow") table.add_column("Reason", style="dim white") for i, tool in enumerate(archived): reason = getattr(tool, "ARCHIVED_REASON", "No reason given") table.add_row(str(i + 1), tool.TITLE, reason) table.add_row("99", "Back", "") console.print(table) raw = Prompt.ask("[bold yellow][?] Select[/bold yellow]", default="99") try: choice = int(raw) except ValueError: continue if choice == 99: return elif 1 <= choice <= len(archived): archived[choice - 1].show_options(parent=self) def show_options(self, parent=None): """Iterative menu loop — no recursion, no stack growth.""" while True: clear_screen() self.show_info() active = self._active_tools() incompatible = self._incompatible_tools() archived = self._archived_tools() table = Table(title="Available Tools", box=box.MINIMAL_DOUBLE_HEAD) table.add_column("No.", justify="center", style="bold cyan") table.add_column("Tool Name", style="bold yellow") table.add_column("Tool", style="bold yellow") for index, tool in enumerate(self.TOOLS): for index, tool in enumerate(active): table.add_row(str(index), tool.TITLE) if archived: table.add_row("[dim]98[/dim]", f"[archived]Archived tools ({len(archived)})[/archived]") if incompatible: console.print(f"[dim]({len(incompatible)} tools hidden — not supported on current OS)[/dim]") table.add_row("99", f"Back to {parent.TITLE if parent else 'Exit'}") console.print(table) tool_index = input("\n[?] Choose a tool: ").strip() raw = Prompt.ask("\n[bold cyan][?] Choose a tool[/bold cyan]", default="99") try: tool_index = int(tool_index) if tool_index in range(len(self.TOOLS)): ret_code = self.TOOLS[tool_index].show_options(parent=self) if ret_code != 99: input("\nPress [Enter] to continue...") elif tool_index == 99: choice = int(raw) except ValueError: console.print("[error]⚠ Please enter a number.[/error]") continue if choice == 99: if parent is None: sys.exit() return 99 except (TypeError, ValueError): console.print("[red]⚠ Please enter a valid option.[/red]") input("\nPress [Enter] to continue...") elif choice == 98 and archived: self._show_archived_tools() elif 0 <= choice < len(active): try: ret = active[choice].show_options(parent=self) except Exception: console.print_exception(show_locals=True) input("\nPress [Enter] to continue...") return self.show_options(parent=parent) Prompt.ask("[dim]Press Enter to continue[/dim]", default="") else: console.print("[error]⚠ Invalid option.[/error]")
docker-compose.yml +8 −3 Original line number Diff line number Diff line version: "3.9" services: hackingtool: image: vgpastor/hackingtool # Bug 23 fix: was using external unverified image vgpastor/hackingtool # Now builds from local Dockerfile — no third-party trust required build: . container_name: hackingtool stdin_open: true tty: true volumes: - .:/root/hackingtool ports: - 22:22 No newline at end of file - hackingtool_data:/root/.hackingtool # Bug 22 fix: removed port 22:22 — this is a CLI tool, SSH exposure is unnecessary volumes: hackingtool_data:
tools/anonsurf.py +14 −85 Original line number Diff line number Diff line # coding=utf-8 import os from rich.console import Console from rich.panel import Panel from rich.prompt import Prompt from rich.text import Text from rich.table import Table from core import HackingTool from core import HackingToolsCollection console = Console() P_COLOR = "magenta" from core import HackingTool, HackingToolsCollection, console class AnonymouslySurf(HackingTool): TITLE = "Anonymously Surf" DESCRIPTION = ( "It automatically overwrites the RAM when\n" "the system is shutting down and also change Ip." "It automatically overwrites the RAM when the system shuts down\n" "and also changes your IP address." ) # Bug 28 fix: was "cd kali-anonsurf && ./installer.sh && cd .. && sudo rm -r kali-anonsurf" # Deleting the source on install means there is no retry if install fails. # Now kept in a separate step so failure does not destroy the source. INSTALL_COMMANDS = [ "sudo git clone https://github.com/Und3rf10w/kali-anonsurf.git", "cd kali-anonsurf && sudo ./installer.sh && cd .. && sudo rm -r kali-anonsurf", "cd kali-anonsurf && sudo ./installer.sh", ] RUN_COMMANDS = ["sudo anonsurf start"] PROJECT_URL = "https://github.com/Und3rf10w/kali-anonsurf" SUPPORTED_OS = ["linux"] def __init__(self): super(AnonymouslySurf, self).__init__([("Stop", self.stop)]) super().__init__([("Stop", self.stop)]) def stop(self): console.print(Panel(Text(self.TITLE, justify="center"), style=f"bold {P_COLOR}")) console.print("Stopping Anonsurf...", style=f"bold {P_COLOR}") console.print("[bold magenta]Stopping Anonsurf...[/bold magenta]") os.system("sudo anonsurf stop") class Multitor(HackingTool): TITLE = "Multitor" DESCRIPTION = "How to stay in multi places at the same time" DESCRIPTION = "How to stay in multi places at the same time." INSTALL_COMMANDS = [ "sudo git clone https://github.com/trimstray/multitor.git", "cd multitor;sudo bash setup.sh install", "cd multitor && sudo bash setup.sh install", ] RUN_COMMANDS = [ "multitor --init 2 --user debian-tor --socks-port 9000 --control-port 9900 --proxy privoxy --haproxy" ] PROJECT_URL = "https://github.com/trimstray/multitor" SUPPORTED_OS = ["linux"] def __init__(self): # keep original behavior (non-runnable) while still initializing super(Multitor, self).__init__(runnable=False) super().__init__(runnable=False) class AnonSurfTools(HackingToolsCollection): TITLE = "Anonymously Hiding Tools" DESCRIPTION = "" TOOLS = [ AnonymouslySurf(), Multitor(), ] def _get_attr(self, obj, *names, default=""): for n in names: if hasattr(obj, n): return getattr(obj, n) return default def pretty_print(self): table = Table(title="Anonymously Hiding Tools", show_lines=True, expand=True) table.add_column("Title", style="magenta", no_wrap=True) table.add_column("Description", style="magenta") table.add_column("Project URL", style="magenta", no_wrap=True) for t in self.TOOLS: title = self._get_attr(t, "TITLE", "Title", "title", default=t.__class__.__name__) desc = self._get_attr(t, "DESCRIPTION", "Description", "description", default="") url = self._get_attr(t, "PROJECT_URL", "PROJECT_URL", "PROJECT", "project_url", "projectUrl", default="") table.add_row(str(title), str(desc).strip().replace("\n", " "), str(url)) panel = Panel(table, title=f"[{P_COLOR}]Available Tools[/ {P_COLOR}]", border_style=P_COLOR) console.print(panel) def show_options(self, parent=None): console.print("\n") console.print(Panel.fit( "[bold magenta]Anonymously Hiding Tools Collection[/bold magenta]\n" "Select a tool to view options or run it.", border_style=P_COLOR )) table = Table(title="[bold cyan]Available Tools[/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 = self._get_attr(tool, "TITLE", "Title", "title", default=tool.__class__.__name__) desc = self._get_attr(tool, "DESCRIPTION", "Description", "description", default="—") table.add_row(str(i + 1), title, desc or "—") table.add_row("[red]99[/red]", "[bold red]Exit[/bold red]", "Return to previous menu") console.print(table) try: choice = Prompt.ask("[bold cyan]Select a tool to run[/bold cyan]", default="99") choice = int(choice) if 1 <= choice <= len(self.TOOLS): selected = self.TOOLS[choice - 1] # delegate if collection-style interface exists if hasattr(selected, "show_options"): selected.show_options(parent=self) # otherwise, if the tool has actions or a run method, prefer those 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__": tools = AnonSurfTools() tools.pretty_print() tools.show_options()