2023-03-04 15:02:23 +00:00
|
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
|
import sys
|
2026-03-15 08:24:30 +00:00
|
|
|
|
|
|
|
|
|
|
# ── 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
|
Redesign header: hacker split-layout with ASCII art + live system info
Replace compact text panel with a Metasploit-style split header:
- Left: "HT" block-letter ASCII art in bright green
- Vertical │ separator that runs the full height of the art block
- Right: live system stats — os, kernel, user@host, ip, tool count, session time
- Bottom: random hacker quote (10 options, changes on each launch)
- Bottom: authorized-use warning in dim red
- Panel title: '[ HackingTool v2.0.0 ]' left-aligned (terminal bracket style)
- Panel subtitle: '[ timestamp ]' right-aligned
- Border: bright_magenta HEAVY box
Live info gathered via platform, socket, os.getlogin() with fallbacks:
- OS: platform.freedesktop_os_release() → PRETTY_NAME, else platform.system()
- IP: UDP connect trick (no data sent, gets local outbound IP)
- User: os.getlogin() → USER env → LOGNAME env → 'root'
2026-03-15 11:35:10 +00:00
|
|
|
|
import platform
|
|
|
|
|
|
import socket
|
|
|
|
|
|
import datetime
|
|
|
|
|
|
import random
|
2020-06-27 06:05:51 +00:00
|
|
|
|
import webbrowser
|
2026-03-15 11:27:13 +00:00
|
|
|
|
from itertools import zip_longest
|
2020-07-18 18:28:01 +00:00
|
|
|
|
|
2025-10-14 06:02:18 +00:00
|
|
|
|
from rich.console import Console
|
|
|
|
|
|
from rich.panel import Panel
|
|
|
|
|
|
from rich.table import Table
|
2026-03-15 11:27:13 +00:00
|
|
|
|
from rich.prompt import Prompt, Confirm
|
2025-10-14 06:02:18 +00:00
|
|
|
|
from rich.align import Align
|
|
|
|
|
|
from rich.text import Text
|
|
|
|
|
|
from rich import box
|
|
|
|
|
|
from rich.rule import Rule
|
2026-03-15 11:27:13 +00:00
|
|
|
|
from rich.columns import Columns
|
2025-10-14 06:02:18 +00:00
|
|
|
|
|
2026-03-15 11:27:13 +00:00
|
|
|
|
from core import HackingToolsCollection, clear_screen, console
|
2026-03-15 08:24:30 +00:00
|
|
|
|
from constants import VERSION_DISPLAY, REPO_WEB_URL
|
|
|
|
|
|
from config import get_tools_dir
|
2020-08-14 11:11:59 +00:00
|
|
|
|
from tools.anonsurf import AnonSurfTools
|
|
|
|
|
|
from tools.ddos import DDOSTools
|
|
|
|
|
|
from tools.exploit_frameworks import ExploitFrameworkTools
|
2026-03-15 08:25:05 +00:00
|
|
|
|
from tools.forensics import ForensicTools
|
|
|
|
|
|
from tools.information_gathering import InformationGatheringTools
|
2020-08-14 11:11:59 +00:00
|
|
|
|
from tools.other_tools import OtherTools
|
|
|
|
|
|
from tools.payload_creator import PayloadCreatorTools
|
2026-03-15 08:25:05 +00:00
|
|
|
|
from tools.phishing_attack import PhishingAttackTools
|
2020-08-14 11:11:59 +00:00
|
|
|
|
from tools.post_exploitation import PostExploitationTools
|
|
|
|
|
|
from tools.remote_administration import RemoteAdministrationTools
|
|
|
|
|
|
from tools.reverse_engineering import ReverseEngineeringTools
|
2026-03-15 08:25:05 +00:00
|
|
|
|
from tools.sql_injection import SqlInjectionTools
|
2020-08-14 11:11:59 +00:00
|
|
|
|
from tools.steganography import SteganographyTools
|
|
|
|
|
|
from tools.tool_manager import ToolManager
|
2026-03-15 08:25:05 +00:00
|
|
|
|
from tools.web_attack import WebAttackTools
|
|
|
|
|
|
from tools.wireless_attack import WirelessAttackTools
|
2020-08-14 11:11:59 +00:00
|
|
|
|
from tools.wordlist_generator import WordlistGeneratorTools
|
|
|
|
|
|
from tools.xss_attack import XSSAttackTools
|
Add 35 new tools across 3 new + 6 existing categories
New categories:
- tools/active_directory.py: BloodHound, NetExec (nxc), Impacket,
Responder, Certipy, Kerbrute (6 tools)
- tools/cloud_security.py: Prowler, ScoutSuite, Pacu, Trivy (4 tools)
- tools/mobile_security.py: MobSF, Frida, Objection (3 tools)
Existing categories expanded:
- information_gathering.py: +SpiderFoot, Subfinder, TruffleHog, Gitleaks (4)
- web_attack.py: +Gobuster, Dirsearch, OWASP ZAP, testssl.sh, Arjun,
Caido, mitmproxy (7)
- post_exploitation.py: +Sliver, Havoc, PEASS-ng, Ligolo-ng, Chisel,
Evil-WinRM, Mythic (7)
- reverse_engineering.py: +Ghidra, Radare2 (2)
- forensics.py: +pspy (1)
- wireless_attack.py: +Bettercap (1)
hackingtool.py:
- Import 3 new category modules
- Add 3 new entries to tool_definitions (AD, Cloud, Mobile)
- Add 3 new instances to all_tools list
- Categories: 17 -> 20, total tools: 150+ -> 185+
- Help overlay updated for new range (1-20, 21=Update)
2026-03-15 12:28:45 +00:00
|
|
|
|
from tools.active_directory import ActiveDirectoryTools
|
|
|
|
|
|
from tools.cloud_security import CloudSecurityTools
|
|
|
|
|
|
from tools.mobile_security import MobileSecurityTools
|
2020-07-18 18:28:01 +00:00
|
|
|
|
|
2026-03-15 11:27:13 +00:00
|
|
|
|
# ── Tool registry ──────────────────────────────────────────────────────────────
|
2025-10-14 06:02:18 +00:00
|
|
|
|
|
2026-03-15 11:27:13 +00:00
|
|
|
|
# (full_title, icon, menu_label)
|
|
|
|
|
|
# menu_label is the concise name shown in the 2-column main menu grid.
|
|
|
|
|
|
# full_title is shown when entering the category.
|
2025-10-14 06:02:18 +00:00
|
|
|
|
tool_definitions = [
|
2026-03-15 11:27:13 +00:00
|
|
|
|
("Anonymously Hiding Tools", "🛡 ", "Anonymously Hiding"),
|
|
|
|
|
|
("Information gathering tools", "🔍", "Information Gathering"),
|
|
|
|
|
|
("Wordlist Generator", "📚", "Wordlist Generator"),
|
|
|
|
|
|
("Wireless attack tools", "📶", "Wireless Attack"),
|
|
|
|
|
|
("SQL Injection Tools", "🧩", "SQL Injection"),
|
|
|
|
|
|
("Phishing attack tools", "🎣", "Phishing Attack"),
|
|
|
|
|
|
("Web Attack tools", "🌐", "Web Attack"),
|
|
|
|
|
|
("Post exploitation tools", "🔧", "Post Exploitation"),
|
|
|
|
|
|
("Forensic tools", "🕵 ", "Forensics"),
|
|
|
|
|
|
("Payload creation tools", "📦", "Payload Creation"),
|
|
|
|
|
|
("Exploit framework", "🧰", "Exploit Framework"),
|
|
|
|
|
|
("Reverse engineering tools", "🔁", "Reverse Engineering"),
|
|
|
|
|
|
("DDOS Attack Tools", "⚡", "DDOS Attack"),
|
|
|
|
|
|
("Remote Administrator Tools (RAT)", "🖥 ", "Remote Admin (RAT)"),
|
|
|
|
|
|
("XSS Attack Tools", "💥", "XSS Attack"),
|
|
|
|
|
|
("Steganography tools", "🖼 ", "Steganography"),
|
Add 35 new tools across 3 new + 6 existing categories
New categories:
- tools/active_directory.py: BloodHound, NetExec (nxc), Impacket,
Responder, Certipy, Kerbrute (6 tools)
- tools/cloud_security.py: Prowler, ScoutSuite, Pacu, Trivy (4 tools)
- tools/mobile_security.py: MobSF, Frida, Objection (3 tools)
Existing categories expanded:
- information_gathering.py: +SpiderFoot, Subfinder, TruffleHog, Gitleaks (4)
- web_attack.py: +Gobuster, Dirsearch, OWASP ZAP, testssl.sh, Arjun,
Caido, mitmproxy (7)
- post_exploitation.py: +Sliver, Havoc, PEASS-ng, Ligolo-ng, Chisel,
Evil-WinRM, Mythic (7)
- reverse_engineering.py: +Ghidra, Radare2 (2)
- forensics.py: +pspy (1)
- wireless_attack.py: +Bettercap (1)
hackingtool.py:
- Import 3 new category modules
- Add 3 new entries to tool_definitions (AD, Cloud, Mobile)
- Add 3 new instances to all_tools list
- Categories: 17 -> 20, total tools: 150+ -> 185+
- Help overlay updated for new range (1-20, 21=Update)
2026-03-15 12:28:45 +00:00
|
|
|
|
("Active Directory Tools", "🏢", "Active Directory"),
|
|
|
|
|
|
("Cloud Security Tools", "☁ ", "Cloud Security"),
|
|
|
|
|
|
("Mobile Security Tools", "📱", "Mobile Security"),
|
2026-03-15 11:27:13 +00:00
|
|
|
|
("Other tools", "✨", "Other Tools"),
|
|
|
|
|
|
("Update or Uninstall | Hackingtool", "♻ ", "Update / Uninstall"),
|
2025-10-14 06:02:18 +00:00
|
|
|
|
]
|
2020-07-18 18:28:01 +00:00
|
|
|
|
|
2020-08-14 11:11:59 +00:00
|
|
|
|
all_tools = [
|
|
|
|
|
|
AnonSurfTools(),
|
|
|
|
|
|
InformationGatheringTools(),
|
|
|
|
|
|
WordlistGeneratorTools(),
|
|
|
|
|
|
WirelessAttackTools(),
|
|
|
|
|
|
SqlInjectionTools(),
|
|
|
|
|
|
PhishingAttackTools(),
|
|
|
|
|
|
WebAttackTools(),
|
|
|
|
|
|
PostExploitationTools(),
|
|
|
|
|
|
ForensicTools(),
|
|
|
|
|
|
PayloadCreatorTools(),
|
|
|
|
|
|
ExploitFrameworkTools(),
|
|
|
|
|
|
ReverseEngineeringTools(),
|
|
|
|
|
|
DDOSTools(),
|
|
|
|
|
|
RemoteAdministrationTools(),
|
|
|
|
|
|
XSSAttackTools(),
|
|
|
|
|
|
SteganographyTools(),
|
Add 35 new tools across 3 new + 6 existing categories
New categories:
- tools/active_directory.py: BloodHound, NetExec (nxc), Impacket,
Responder, Certipy, Kerbrute (6 tools)
- tools/cloud_security.py: Prowler, ScoutSuite, Pacu, Trivy (4 tools)
- tools/mobile_security.py: MobSF, Frida, Objection (3 tools)
Existing categories expanded:
- information_gathering.py: +SpiderFoot, Subfinder, TruffleHog, Gitleaks (4)
- web_attack.py: +Gobuster, Dirsearch, OWASP ZAP, testssl.sh, Arjun,
Caido, mitmproxy (7)
- post_exploitation.py: +Sliver, Havoc, PEASS-ng, Ligolo-ng, Chisel,
Evil-WinRM, Mythic (7)
- reverse_engineering.py: +Ghidra, Radare2 (2)
- forensics.py: +pspy (1)
- wireless_attack.py: +Bettercap (1)
hackingtool.py:
- Import 3 new category modules
- Add 3 new entries to tool_definitions (AD, Cloud, Mobile)
- Add 3 new instances to all_tools list
- Categories: 17 -> 20, total tools: 150+ -> 185+
- Help overlay updated for new range (1-20, 21=Update)
2026-03-15 12:28:45 +00:00
|
|
|
|
ActiveDirectoryTools(),
|
|
|
|
|
|
CloudSecurityTools(),
|
|
|
|
|
|
MobileSecurityTools(),
|
2020-08-14 11:11:59 +00:00
|
|
|
|
OtherTools(),
|
2026-03-15 08:24:30 +00:00
|
|
|
|
ToolManager(),
|
2020-08-14 11:11:59 +00:00
|
|
|
|
]
|
|
|
|
|
|
|
2026-03-15 11:27:13 +00:00
|
|
|
|
# Used by generate_readme.py
|
2020-08-14 11:11:59 +00:00
|
|
|
|
class AllTools(HackingToolsCollection):
|
|
|
|
|
|
TITLE = "All tools"
|
|
|
|
|
|
TOOLS = all_tools
|
|
|
|
|
|
|
2020-07-18 18:28:01 +00:00
|
|
|
|
|
2026-03-15 11:27:13 +00:00
|
|
|
|
# ── Help overlay ───────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
|
|
def show_help():
|
|
|
|
|
|
console.print(Panel(
|
|
|
|
|
|
Text.assemble(
|
|
|
|
|
|
(" Main menu\n", "bold white"),
|
|
|
|
|
|
(" ─────────────────────────────────────\n", "dim"),
|
Add 35 new tools across 3 new + 6 existing categories
New categories:
- tools/active_directory.py: BloodHound, NetExec (nxc), Impacket,
Responder, Certipy, Kerbrute (6 tools)
- tools/cloud_security.py: Prowler, ScoutSuite, Pacu, Trivy (4 tools)
- tools/mobile_security.py: MobSF, Frida, Objection (3 tools)
Existing categories expanded:
- information_gathering.py: +SpiderFoot, Subfinder, TruffleHog, Gitleaks (4)
- web_attack.py: +Gobuster, Dirsearch, OWASP ZAP, testssl.sh, Arjun,
Caido, mitmproxy (7)
- post_exploitation.py: +Sliver, Havoc, PEASS-ng, Ligolo-ng, Chisel,
Evil-WinRM, Mythic (7)
- reverse_engineering.py: +Ghidra, Radare2 (2)
- forensics.py: +pspy (1)
- wireless_attack.py: +Bettercap (1)
hackingtool.py:
- Import 3 new category modules
- Add 3 new entries to tool_definitions (AD, Cloud, Mobile)
- Add 3 new instances to all_tools list
- Categories: 17 -> 20, total tools: 150+ -> 185+
- Help overlay updated for new range (1-20, 21=Update)
2026-03-15 12:28:45 +00:00
|
|
|
|
(" 1–20 ", "bold cyan"), ("open a category\n", "white"),
|
|
|
|
|
|
(" 21 ", "bold cyan"), ("Update / Uninstall hackingtool\n", "white"),
|
2026-03-15 12:35:11 +00:00
|
|
|
|
(" / or s ", "bold cyan"), ("search tools by name or keyword\n", "white"),
|
Feature: Tag-based filtering with auto-derived tags (t command)
core.py:
- Add TAGS field to HackingTool class (list[str], default empty)
- Allows manual tag override per tool
hackingtool.py:
- Add _get_all_tags() — builds tag index from 19 regex rules that
auto-derive tags from tool TITLE + DESCRIPTION (osint, scanner, c2,
web, cloud, mobile, wireless, forensics, reversing, etc.)
- Manual TAGS on a tool class take priority over auto-derived
- Add filter_by_tag() — shows all available tags with tool counts,
user picks a tag, results shown with installed status, select to
jump directly into tool.show_options()
- Wire t/tag/tags/filter commands into interact_menu()
- Search also matches against TAGS field
- Updated hint bar: / search · t tags · ? help · q quit
- Updated help overlay with tag filter entry
2026-03-15 12:41:28 +00:00
|
|
|
|
(" t ", "bold cyan"), ("filter tools by tag (osint, web, c2, ...)\n", "white"),
|
2026-03-15 12:45:06 +00:00
|
|
|
|
(" r ", "bold cyan"), ("recommend tools for a task\n", "white"),
|
2026-03-15 11:27:13 +00:00
|
|
|
|
(" ? ", "bold cyan"), ("show this help\n", "white"),
|
|
|
|
|
|
(" q ", "bold cyan"), ("quit hackingtool\n\n", "white"),
|
|
|
|
|
|
(" Inside a category\n", "bold white"),
|
|
|
|
|
|
(" ─────────────────────────────────────\n", "dim"),
|
|
|
|
|
|
(" 1–N ", "bold cyan"), ("select a tool\n", "white"),
|
|
|
|
|
|
(" 99 ", "bold cyan"), ("back to main menu\n", "white"),
|
|
|
|
|
|
(" 98 ", "bold cyan"), ("open project page (if available)\n\n", "white"),
|
|
|
|
|
|
(" Inside a tool\n", "bold white"),
|
|
|
|
|
|
(" ─────────────────────────────────────\n", "dim"),
|
|
|
|
|
|
(" 1 ", "bold cyan"), ("install tool\n", "white"),
|
|
|
|
|
|
(" 2 ", "bold cyan"), ("run tool\n", "white"),
|
|
|
|
|
|
(" 99 ", "bold cyan"), ("back to category\n", "white"),
|
|
|
|
|
|
),
|
|
|
|
|
|
title="[bold magenta] ? Quick Help [/bold magenta]",
|
|
|
|
|
|
border_style="magenta",
|
|
|
|
|
|
box=box.ROUNDED,
|
|
|
|
|
|
padding=(0, 2),
|
|
|
|
|
|
))
|
|
|
|
|
|
Prompt.ask("[dim]Press Enter to return[/dim]", default="")
|
|
|
|
|
|
|
|
|
|
|
|
|
Redesign header: hacker split-layout with ASCII art + live system info
Replace compact text panel with a Metasploit-style split header:
- Left: "HT" block-letter ASCII art in bright green
- Vertical │ separator that runs the full height of the art block
- Right: live system stats — os, kernel, user@host, ip, tool count, session time
- Bottom: random hacker quote (10 options, changes on each launch)
- Bottom: authorized-use warning in dim red
- Panel title: '[ HackingTool v2.0.0 ]' left-aligned (terminal bracket style)
- Panel subtitle: '[ timestamp ]' right-aligned
- Border: bright_magenta HEAVY box
Live info gathered via platform, socket, os.getlogin() with fallbacks:
- OS: platform.freedesktop_os_release() → PRETTY_NAME, else platform.system()
- IP: UDP connect trick (no data sent, gets local outbound IP)
- User: os.getlogin() → USER env → LOGNAME env → 'root'
2026-03-15 11:35:10 +00:00
|
|
|
|
# ── Header: ASCII art + live system info ──────────────────────────────────────
|
|
|
|
|
|
|
2026-03-15 11:58:21 +00:00
|
|
|
|
# Full "HACKING TOOL" block-letter art — 12 lines, split layout with stats
|
|
|
|
|
|
_BANNER_ART = [
|
|
|
|
|
|
" ██╗ ██╗ █████╗ ██████╗██╗ ██╗██╗███╗ ██╗ ██████╗ ",
|
|
|
|
|
|
" ██║ ██║██╔══██╗██╔════╝██║ ██╔╝██║████╗ ██║██╔════╝ ",
|
|
|
|
|
|
" ███████║███████║██║ █████╔╝ ██║██╔██╗ ██║██║ ███╗",
|
|
|
|
|
|
" ██╔══██║██╔══██║██║ ██╔═██╗ ██║██║╚██╗██║██║ ██║",
|
|
|
|
|
|
" ██║ ██║██║ ██║╚██████╗██║ ██╗██║██║ ╚████║╚██████╔╝",
|
|
|
|
|
|
" ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝ ╚═════╝ ",
|
|
|
|
|
|
" ████████╗ ██████╗ ██████╗ ██╗",
|
|
|
|
|
|
" ╚══██╔══╝██╔═══██╗██╔═══██╗██║",
|
|
|
|
|
|
" ██║ ██║ ██║██║ ██║██║",
|
|
|
|
|
|
" ██║ ██║ ██║██║ ██║██║",
|
|
|
|
|
|
" ██║ ╚██████╔╝╚██████╔╝███████╗",
|
|
|
|
|
|
" ╚═╝ ╚═════╝ ╚═════╝ ╚══════╝",
|
|
|
|
|
|
]
|
Redesign header: hacker split-layout with ASCII art + live system info
Replace compact text panel with a Metasploit-style split header:
- Left: "HT" block-letter ASCII art in bright green
- Vertical │ separator that runs the full height of the art block
- Right: live system stats — os, kernel, user@host, ip, tool count, session time
- Bottom: random hacker quote (10 options, changes on each launch)
- Bottom: authorized-use warning in dim red
- Panel title: '[ HackingTool v2.0.0 ]' left-aligned (terminal bracket style)
- Panel subtitle: '[ timestamp ]' right-aligned
- Border: bright_magenta HEAVY box
Live info gathered via platform, socket, os.getlogin() with fallbacks:
- OS: platform.freedesktop_os_release() → PRETTY_NAME, else platform.system()
- IP: UDP connect trick (no data sent, gets local outbound IP)
- User: os.getlogin() → USER env → LOGNAME env → 'root'
2026-03-15 11:35:10 +00:00
|
|
|
|
|
|
|
|
|
|
_QUOTES = [
|
|
|
|
|
|
'"The quieter you become, the more you can hear."',
|
|
|
|
|
|
'"Offense informs defense."',
|
|
|
|
|
|
'"There is no patch for human stupidity."',
|
|
|
|
|
|
'"In God we trust. All others we monitor."',
|
|
|
|
|
|
'"Hackers are the immune system of the internet."',
|
|
|
|
|
|
'"Every system is hackable — know yours before others do."',
|
|
|
|
|
|
'"Enumerate before you exploit."',
|
|
|
|
|
|
'"A scope defines your playground."',
|
|
|
|
|
|
'"The more you sweat in training, the less you bleed in battle."',
|
|
|
|
|
|
'"Security is a process, not a product."',
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _sys_info() -> dict:
|
|
|
|
|
|
"""Collect live system info for the header panel."""
|
|
|
|
|
|
info: dict = {}
|
|
|
|
|
|
|
|
|
|
|
|
# OS pretty name
|
|
|
|
|
|
try:
|
|
|
|
|
|
info["os"] = platform.freedesktop_os_release().get("PRETTY_NAME", "")
|
|
|
|
|
|
except Exception:
|
|
|
|
|
|
info["os"] = ""
|
|
|
|
|
|
if not info["os"]:
|
|
|
|
|
|
info["os"] = f"{platform.system()} {platform.release()}"
|
|
|
|
|
|
|
|
|
|
|
|
info["kernel"] = platform.release()
|
|
|
|
|
|
|
|
|
|
|
|
# Current user
|
|
|
|
|
|
try:
|
|
|
|
|
|
info["user"] = os.getlogin()
|
|
|
|
|
|
except Exception:
|
|
|
|
|
|
info["user"] = os.environ.get("USER", os.environ.get("LOGNAME", "root"))
|
|
|
|
|
|
|
|
|
|
|
|
info["host"] = socket.gethostname()
|
|
|
|
|
|
|
|
|
|
|
|
# Local IP — connect to a routable address without sending data
|
|
|
|
|
|
try:
|
|
|
|
|
|
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
|
|
|
|
s.settimeout(0)
|
|
|
|
|
|
s.connect(("10.254.254.254", 1))
|
|
|
|
|
|
info["ip"] = s.getsockname()[0]
|
|
|
|
|
|
s.close()
|
|
|
|
|
|
except Exception:
|
|
|
|
|
|
info["ip"] = "127.0.0.1"
|
|
|
|
|
|
|
|
|
|
|
|
info["time"] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M")
|
|
|
|
|
|
return info
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _build_header() -> Panel:
|
|
|
|
|
|
info = _sys_info()
|
|
|
|
|
|
|
2026-03-15 11:58:21 +00:00
|
|
|
|
# 12 stat lines paired with the 12 art lines
|
Redesign header: hacker split-layout with ASCII art + live system info
Replace compact text panel with a Metasploit-style split header:
- Left: "HT" block-letter ASCII art in bright green
- Vertical │ separator that runs the full height of the art block
- Right: live system stats — os, kernel, user@host, ip, tool count, session time
- Bottom: random hacker quote (10 options, changes on each launch)
- Bottom: authorized-use warning in dim red
- Panel title: '[ HackingTool v2.0.0 ]' left-aligned (terminal bracket style)
- Panel subtitle: '[ timestamp ]' right-aligned
- Border: bright_magenta HEAVY box
Live info gathered via platform, socket, os.getlogin() with fallbacks:
- OS: platform.freedesktop_os_release() → PRETTY_NAME, else platform.system()
- IP: UDP connect trick (no data sent, gets local outbound IP)
- User: os.getlogin() → USER env → LOGNAME env → 'root'
2026-03-15 11:35:10 +00:00
|
|
|
|
stat_lines = [
|
|
|
|
|
|
(" os › ", info["os"][:34]),
|
|
|
|
|
|
(" kernel › ", info["kernel"][:34]),
|
|
|
|
|
|
(" user › ", f"{info['user']} @ {info['host'][:20]}"),
|
|
|
|
|
|
(" ip › ", info["ip"]),
|
Add 35 new tools across 3 new + 6 existing categories
New categories:
- tools/active_directory.py: BloodHound, NetExec (nxc), Impacket,
Responder, Certipy, Kerbrute (6 tools)
- tools/cloud_security.py: Prowler, ScoutSuite, Pacu, Trivy (4 tools)
- tools/mobile_security.py: MobSF, Frida, Objection (3 tools)
Existing categories expanded:
- information_gathering.py: +SpiderFoot, Subfinder, TruffleHog, Gitleaks (4)
- web_attack.py: +Gobuster, Dirsearch, OWASP ZAP, testssl.sh, Arjun,
Caido, mitmproxy (7)
- post_exploitation.py: +Sliver, Havoc, PEASS-ng, Ligolo-ng, Chisel,
Evil-WinRM, Mythic (7)
- reverse_engineering.py: +Ghidra, Radare2 (2)
- forensics.py: +pspy (1)
- wireless_attack.py: +Bettercap (1)
hackingtool.py:
- Import 3 new category modules
- Add 3 new entries to tool_definitions (AD, Cloud, Mobile)
- Add 3 new instances to all_tools list
- Categories: 17 -> 20, total tools: 150+ -> 185+
- Help overlay updated for new range (1-20, 21=Update)
2026-03-15 12:28:45 +00:00
|
|
|
|
(" tools › ", f"{len(all_tools)} categories · 185+ modules"),
|
Redesign header: hacker split-layout with ASCII art + live system info
Replace compact text panel with a Metasploit-style split header:
- Left: "HT" block-letter ASCII art in bright green
- Vertical │ separator that runs the full height of the art block
- Right: live system stats — os, kernel, user@host, ip, tool count, session time
- Bottom: random hacker quote (10 options, changes on each launch)
- Bottom: authorized-use warning in dim red
- Panel title: '[ HackingTool v2.0.0 ]' left-aligned (terminal bracket style)
- Panel subtitle: '[ timestamp ]' right-aligned
- Border: bright_magenta HEAVY box
Live info gathered via platform, socket, os.getlogin() with fallbacks:
- OS: platform.freedesktop_os_release() → PRETTY_NAME, else platform.system()
- IP: UDP connect trick (no data sent, gets local outbound IP)
- User: os.getlogin() → USER env → LOGNAME env → 'root'
2026-03-15 11:35:10 +00:00
|
|
|
|
(" session › ", info["time"]),
|
2026-03-15 11:58:21 +00:00
|
|
|
|
("", ""),
|
|
|
|
|
|
(" python › ", f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}"),
|
|
|
|
|
|
(" arch › ", platform.machine()),
|
|
|
|
|
|
(" status › ", "✔ READY"),
|
|
|
|
|
|
("", ""),
|
|
|
|
|
|
("", ""),
|
Redesign header: hacker split-layout with ASCII art + live system info
Replace compact text panel with a Metasploit-style split header:
- Left: "HT" block-letter ASCII art in bright green
- Vertical │ separator that runs the full height of the art block
- Right: live system stats — os, kernel, user@host, ip, tool count, session time
- Bottom: random hacker quote (10 options, changes on each launch)
- Bottom: authorized-use warning in dim red
- Panel title: '[ HackingTool v2.0.0 ]' left-aligned (terminal bracket style)
- Panel subtitle: '[ timestamp ]' right-aligned
- Border: bright_magenta HEAVY box
Live info gathered via platform, socket, os.getlogin() with fallbacks:
- OS: platform.freedesktop_os_release() → PRETTY_NAME, else platform.system()
- IP: UDP connect trick (no data sent, gets local outbound IP)
- User: os.getlogin() → USER env → LOGNAME env → 'root'
2026-03-15 11:35:10 +00:00
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
grid = Table.grid(padding=0)
|
|
|
|
|
|
grid.add_column("art", no_wrap=True)
|
|
|
|
|
|
grid.add_column("sep", no_wrap=True)
|
|
|
|
|
|
grid.add_column("lbl", no_wrap=True)
|
|
|
|
|
|
grid.add_column("val", no_wrap=True)
|
|
|
|
|
|
|
2026-03-15 11:58:21 +00:00
|
|
|
|
for art_line, (lbl_text, val_text) in zip(_BANNER_ART, stat_lines):
|
Redesign header: hacker split-layout with ASCII art + live system info
Replace compact text panel with a Metasploit-style split header:
- Left: "HT" block-letter ASCII art in bright green
- Vertical │ separator that runs the full height of the art block
- Right: live system stats — os, kernel, user@host, ip, tool count, session time
- Bottom: random hacker quote (10 options, changes on each launch)
- Bottom: authorized-use warning in dim red
- Panel title: '[ HackingTool v2.0.0 ]' left-aligned (terminal bracket style)
- Panel subtitle: '[ timestamp ]' right-aligned
- Border: bright_magenta HEAVY box
Live info gathered via platform, socket, os.getlogin() with fallbacks:
- OS: platform.freedesktop_os_release() → PRETTY_NAME, else platform.system()
- IP: UDP connect trick (no data sent, gets local outbound IP)
- User: os.getlogin() → USER env → LOGNAME env → 'root'
2026-03-15 11:35:10 +00:00
|
|
|
|
grid.add_row(
|
|
|
|
|
|
Text(art_line, style="bold bright_green"),
|
2026-03-15 11:58:21 +00:00
|
|
|
|
Text(" │ ", style="dim green"),
|
Redesign header: hacker split-layout with ASCII art + live system info
Replace compact text panel with a Metasploit-style split header:
- Left: "HT" block-letter ASCII art in bright green
- Vertical │ separator that runs the full height of the art block
- Right: live system stats — os, kernel, user@host, ip, tool count, session time
- Bottom: random hacker quote (10 options, changes on each launch)
- Bottom: authorized-use warning in dim red
- Panel title: '[ HackingTool v2.0.0 ]' left-aligned (terminal bracket style)
- Panel subtitle: '[ timestamp ]' right-aligned
- Border: bright_magenta HEAVY box
Live info gathered via platform, socket, os.getlogin() with fallbacks:
- OS: platform.freedesktop_os_release() → PRETTY_NAME, else platform.system()
- IP: UDP connect trick (no data sent, gets local outbound IP)
- User: os.getlogin() → USER env → LOGNAME env → 'root'
2026-03-15 11:35:10 +00:00
|
|
|
|
Text(lbl_text, style="dim green"),
|
|
|
|
|
|
Text(val_text, style="bright_green"),
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
# Quote + warning below the split row
|
|
|
|
|
|
quote = random.choice(_QUOTES)
|
|
|
|
|
|
body = Table.grid(padding=(0, 0))
|
|
|
|
|
|
body.add_column()
|
|
|
|
|
|
body.add_row(grid)
|
|
|
|
|
|
body.add_row(Text(""))
|
|
|
|
|
|
body.add_row(Text(f" {quote}", style="italic dim"))
|
|
|
|
|
|
body.add_row(Text(" ⚠ For authorized security testing only",
|
|
|
|
|
|
style="bold dim red"))
|
|
|
|
|
|
|
|
|
|
|
|
return Panel(
|
|
|
|
|
|
body,
|
|
|
|
|
|
title=f"[bold bright_magenta][ HackingTool {VERSION_DISPLAY} ][/bold bright_magenta]",
|
|
|
|
|
|
title_align="left",
|
|
|
|
|
|
subtitle=f"[dim][ {info['time']} ][/dim]",
|
|
|
|
|
|
subtitle_align="right",
|
|
|
|
|
|
border_style="bright_magenta",
|
|
|
|
|
|
box=box.HEAVY,
|
|
|
|
|
|
padding=(0, 1),
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-03-15 11:27:13 +00:00
|
|
|
|
# ── Main menu renderer ─────────────────────────────────────────────────────────
|
2020-06-27 06:05:51 +00:00
|
|
|
|
|
2025-10-14 06:02:18 +00:00
|
|
|
|
def build_menu():
|
2026-03-15 11:27:13 +00:00
|
|
|
|
clear_screen()
|
Redesign header: hacker split-layout with ASCII art + live system info
Replace compact text panel with a Metasploit-style split header:
- Left: "HT" block-letter ASCII art in bright green
- Vertical │ separator that runs the full height of the art block
- Right: live system stats — os, kernel, user@host, ip, tool count, session time
- Bottom: random hacker quote (10 options, changes on each launch)
- Bottom: authorized-use warning in dim red
- Panel title: '[ HackingTool v2.0.0 ]' left-aligned (terminal bracket style)
- Panel subtitle: '[ timestamp ]' right-aligned
- Border: bright_magenta HEAVY box
Live info gathered via platform, socket, os.getlogin() with fallbacks:
- OS: platform.freedesktop_os_release() → PRETTY_NAME, else platform.system()
- IP: UDP connect trick (no data sent, gets local outbound IP)
- User: os.getlogin() → USER env → LOGNAME env → 'root'
2026-03-15 11:35:10 +00:00
|
|
|
|
console.print(_build_header())
|
2026-03-15 11:27:13 +00:00
|
|
|
|
|
|
|
|
|
|
# ── 2-column category grid ──
|
|
|
|
|
|
# Items 1-17 in two columns, item 18 (ToolManager) shown separately
|
|
|
|
|
|
categories = tool_definitions[:-1] # 17 items
|
|
|
|
|
|
update_def = tool_definitions[-1] # ToolManager
|
|
|
|
|
|
|
|
|
|
|
|
mid = (len(categories) + 1) // 2 # 9 (left), 8 (right)
|
|
|
|
|
|
left = list(enumerate(categories[:mid], start=1))
|
|
|
|
|
|
right = list(enumerate(categories[mid:], start=mid + 1))
|
|
|
|
|
|
|
|
|
|
|
|
grid = Table.grid(padding=(0, 1), expand=True)
|
|
|
|
|
|
grid.add_column("ln", justify="right", style="bold magenta", width=5)
|
|
|
|
|
|
grid.add_column("li", width=3)
|
|
|
|
|
|
grid.add_column("lt", style="magenta", ratio=1, no_wrap=True)
|
|
|
|
|
|
grid.add_column("gap", width=3)
|
|
|
|
|
|
grid.add_column("rn", justify="right", style="bold magenta", width=5)
|
|
|
|
|
|
grid.add_column("ri", width=3)
|
|
|
|
|
|
grid.add_column("rt", style="magenta", ratio=1, no_wrap=True)
|
|
|
|
|
|
|
|
|
|
|
|
for (li, (_, lic, ll)), r in zip_longest(left, right, fillvalue=None):
|
|
|
|
|
|
if r:
|
|
|
|
|
|
ri, (_, ric, rl) = r
|
|
|
|
|
|
grid.add_row(str(li), lic, ll, "", str(ri), ric, rl)
|
|
|
|
|
|
else:
|
|
|
|
|
|
grid.add_row(str(li), lic, ll, "", "", "", "")
|
|
|
|
|
|
|
|
|
|
|
|
console.print(Panel(
|
|
|
|
|
|
grid,
|
|
|
|
|
|
title="[bold magenta] Select a Category [/bold magenta]",
|
2025-10-14 06:02:18 +00:00
|
|
|
|
border_style="bright_magenta",
|
2026-03-15 11:27:13 +00:00
|
|
|
|
box=box.ROUNDED,
|
|
|
|
|
|
padding=(0, 1),
|
2026-03-15 08:24:30 +00:00
|
|
|
|
))
|
2025-10-14 06:02:18 +00:00
|
|
|
|
|
2026-03-15 11:27:13 +00:00
|
|
|
|
# ── ToolManager row ──
|
2026-03-15 12:35:11 +00:00
|
|
|
|
tm_num = len(categories) + 1
|
2026-03-15 11:27:13 +00:00
|
|
|
|
console.print(
|
2026-03-15 12:35:11 +00:00
|
|
|
|
f" [bold magenta] {tm_num}[/bold magenta] {update_def[1]} "
|
2026-03-15 11:27:13 +00:00
|
|
|
|
f"[magenta]{update_def[2]}[/magenta]"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2026-03-15 13:07:20 +00:00
|
|
|
|
# ── Claude-style dual-line prompt area ──
|
2026-03-15 11:27:13 +00:00
|
|
|
|
console.print(Rule(style="dim magenta"))
|
|
|
|
|
|
console.print(
|
2026-03-15 14:04:26 +00:00
|
|
|
|
" [dim cyan]/[/dim cyan][dim]search[/dim] "
|
|
|
|
|
|
"[dim cyan]t[/dim cyan] [dim]tags[/dim] "
|
|
|
|
|
|
"[dim cyan]r[/dim cyan] [dim]recommend[/dim] "
|
|
|
|
|
|
"[dim cyan]?[/dim cyan] [dim]help[/dim] "
|
|
|
|
|
|
"[dim cyan]q[/dim cyan] [dim]quit[/dim]"
|
2026-03-15 11:27:13 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-03-15 12:35:11 +00:00
|
|
|
|
# ── Search ─────────────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
|
|
def _collect_all_tools() -> list[tuple]:
|
|
|
|
|
|
"""Walk all collections and return (tool_instance, category_name) pairs."""
|
|
|
|
|
|
from core import HackingTool, HackingToolsCollection
|
|
|
|
|
|
results = []
|
|
|
|
|
|
|
|
|
|
|
|
def _walk(items, parent_title=""):
|
|
|
|
|
|
for item in items:
|
|
|
|
|
|
if isinstance(item, HackingToolsCollection):
|
|
|
|
|
|
_walk(item.TOOLS, item.TITLE)
|
|
|
|
|
|
elif isinstance(item, HackingTool):
|
|
|
|
|
|
results.append((item, parent_title))
|
|
|
|
|
|
|
|
|
|
|
|
_walk(all_tools)
|
|
|
|
|
|
return results
|
|
|
|
|
|
|
|
|
|
|
|
|
Feature: Tag-based filtering with auto-derived tags (t command)
core.py:
- Add TAGS field to HackingTool class (list[str], default empty)
- Allows manual tag override per tool
hackingtool.py:
- Add _get_all_tags() — builds tag index from 19 regex rules that
auto-derive tags from tool TITLE + DESCRIPTION (osint, scanner, c2,
web, cloud, mobile, wireless, forensics, reversing, etc.)
- Manual TAGS on a tool class take priority over auto-derived
- Add filter_by_tag() — shows all available tags with tool counts,
user picks a tag, results shown with installed status, select to
jump directly into tool.show_options()
- Wire t/tag/tags/filter commands into interact_menu()
- Search also matches against TAGS field
- Updated hint bar: / search · t tags · ? help · q quit
- Updated help overlay with tag filter entry
2026-03-15 12:41:28 +00:00
|
|
|
|
def _get_all_tags() -> dict[str, list[tuple]]:
|
|
|
|
|
|
"""Build tag → [(tool, category)] index from all tools."""
|
|
|
|
|
|
import re
|
|
|
|
|
|
_rules = {
|
|
|
|
|
|
r'(osint|harvester|maigret|holehe|spiderfoot|sherlock|recon)': 'osint',
|
|
|
|
|
|
r'(subdomain|subfinder|amass|sublist|subdomainfinder)': 'recon',
|
|
|
|
|
|
r'(scanner|scan|nmap|masscan|rustscan|nikto|nuclei|trivy)': 'scanner',
|
|
|
|
|
|
r'(brute|gobuster|ffuf|dirb|dirsearch|ferox|hashcat|john|kerbrute)': 'bruteforce',
|
|
|
|
|
|
r'(web|http|proxy|zap|xss|sql|wafw00f|arjun|caido|mitmproxy)': 'web',
|
|
|
|
|
|
r'(wireless|wifi|wlan|airgeddon|bettercap|wifite|fluxion|deauth)': 'wireless',
|
|
|
|
|
|
r'(phish|social.media|evilginx|setoolkit|social.fish|social.engineer)': 'social-engineering',
|
|
|
|
|
|
r'(c2|sliver|havoc|mythic|pwncat|reverse.shell|pyshell)': 'c2',
|
|
|
|
|
|
r'(privesc|peass|linpeas|winpeas)': 'privesc',
|
|
|
|
|
|
r'(tunnel|pivot|ligolo|chisel|proxy|anon)': 'network',
|
|
|
|
|
|
r'(password|credential|hash|crack|secret|trufflehog|gitleaks)': 'credentials',
|
|
|
|
|
|
r'(forensic|memory|volatility|binwalk|autopsy|wireshark|pspy)': 'forensics',
|
|
|
|
|
|
r'(reverse.eng|ghidra|radare|jadx|androguard|apk)': 'reversing',
|
|
|
|
|
|
r'(cloud|aws|azure|gcp|kubernetes|prowler|scout|pacu)': 'cloud',
|
|
|
|
|
|
r'(mobile|android|ios|frida|mobsf|objection|droid)': 'mobile',
|
|
|
|
|
|
r'(active.directory|bloodhound|netexec|impacket|responder|certipy|kerberos|winrm|smb|ldap)': 'active-directory',
|
|
|
|
|
|
r'(ddos|dos|slowloris|goldeneye|ufonet)': 'ddos',
|
|
|
|
|
|
r'(payload|msfvenom|fatrat|venom|stitch|enigma)': 'payload',
|
|
|
|
|
|
r'(crawler|spider|katana|gospider)': 'crawler',
|
|
|
|
|
|
}
|
|
|
|
|
|
tag_index: dict[str, list[tuple]] = {}
|
|
|
|
|
|
for tool, cat in _collect_all_tools():
|
|
|
|
|
|
combined = f"{tool.TITLE} {tool.DESCRIPTION}".lower()
|
|
|
|
|
|
# Manual tags first
|
|
|
|
|
|
tool_tags = set(getattr(tool, "TAGS", []) or [])
|
|
|
|
|
|
# Auto-derive tags from title/description
|
|
|
|
|
|
for pattern, tag in _rules.items():
|
|
|
|
|
|
if re.search(pattern, combined, re.IGNORECASE):
|
|
|
|
|
|
tool_tags.add(tag)
|
|
|
|
|
|
for t in tool_tags:
|
|
|
|
|
|
tag_index.setdefault(t, []).append((tool, cat))
|
|
|
|
|
|
return tag_index
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def filter_by_tag():
|
|
|
|
|
|
"""Show available tags, user picks one, show matching tools."""
|
|
|
|
|
|
tag_index = _get_all_tags()
|
|
|
|
|
|
sorted_tags = sorted(tag_index.keys())
|
|
|
|
|
|
|
|
|
|
|
|
# Show tags in a compact grid
|
|
|
|
|
|
console.print(Panel(
|
|
|
|
|
|
" ".join(f"[bold cyan]{t}[/bold cyan]([dim]{len(tag_index[t])}[/dim])" for t in sorted_tags),
|
|
|
|
|
|
title="[bold magenta] Available Tags [/bold magenta]",
|
|
|
|
|
|
border_style="magenta", box=box.ROUNDED, padding=(0, 2),
|
|
|
|
|
|
))
|
|
|
|
|
|
|
|
|
|
|
|
tag = Prompt.ask("[bold cyan]Enter tag[/bold cyan]", default="").strip().lower()
|
|
|
|
|
|
if not tag or tag not in tag_index:
|
|
|
|
|
|
if tag:
|
|
|
|
|
|
console.print(f"[dim]Tag '{tag}' not found.[/dim]")
|
|
|
|
|
|
Prompt.ask("[dim]Press Enter to return[/dim]", default="")
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
matches = tag_index[tag]
|
|
|
|
|
|
table = Table(
|
|
|
|
|
|
title=f"Tools tagged '{tag}'",
|
|
|
|
|
|
box=box.SIMPLE_HEAD, show_lines=True,
|
|
|
|
|
|
)
|
|
|
|
|
|
table.add_column("No.", justify="center", style="bold cyan", width=5)
|
|
|
|
|
|
table.add_column("", width=2)
|
|
|
|
|
|
table.add_column("Tool", style="bold yellow", min_width=20)
|
|
|
|
|
|
table.add_column("Category", style="magenta", min_width=15)
|
|
|
|
|
|
|
|
|
|
|
|
for i, (tool, cat) in enumerate(matches, start=1):
|
|
|
|
|
|
status = "[green]✔[/green]" if tool.is_installed else "[dim]✘[/dim]"
|
|
|
|
|
|
table.add_row(str(i), status, tool.TITLE, cat)
|
|
|
|
|
|
|
|
|
|
|
|
table.add_row("99", "", "Back to main menu", "")
|
|
|
|
|
|
console.print(table)
|
|
|
|
|
|
|
|
|
|
|
|
raw = Prompt.ask("[bold cyan]>[/bold cyan]", default="").strip()
|
|
|
|
|
|
if not raw or raw == "99":
|
|
|
|
|
|
return
|
|
|
|
|
|
try:
|
|
|
|
|
|
idx = int(raw)
|
|
|
|
|
|
except ValueError:
|
|
|
|
|
|
return
|
|
|
|
|
|
if 1 <= idx <= len(matches):
|
|
|
|
|
|
tool, cat = matches[idx - 1]
|
|
|
|
|
|
tool.show_options()
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-03-15 12:45:06 +00:00
|
|
|
|
_RECOMMENDATIONS = {
|
|
|
|
|
|
"scan a network": ["scanner", "port-scanner"],
|
|
|
|
|
|
"find subdomains": ["recon"],
|
|
|
|
|
|
"scan for vulnerabilities": ["scanner", "web"],
|
|
|
|
|
|
"crack passwords": ["bruteforce", "credentials"],
|
|
|
|
|
|
"find leaked secrets": ["credentials"],
|
|
|
|
|
|
"phishing campaign": ["social-engineering"],
|
|
|
|
|
|
"post exploitation": ["c2", "privesc"],
|
|
|
|
|
|
"pivot through network": ["network"],
|
|
|
|
|
|
"pentest active directory": ["active-directory"],
|
|
|
|
|
|
"pentest web application": ["web", "scanner"],
|
|
|
|
|
|
"pentest cloud": ["cloud"],
|
|
|
|
|
|
"pentest mobile app": ["mobile"],
|
|
|
|
|
|
"reverse engineer binary": ["reversing"],
|
|
|
|
|
|
"capture wifi handshake": ["wireless"],
|
|
|
|
|
|
"intercept http traffic": ["web", "network"],
|
|
|
|
|
|
"forensic analysis": ["forensics"],
|
|
|
|
|
|
"ddos testing": ["ddos"],
|
|
|
|
|
|
"create payloads": ["payload"],
|
|
|
|
|
|
"find xss vulnerabilities": ["web"],
|
|
|
|
|
|
"brute force directories": ["bruteforce", "web"],
|
|
|
|
|
|
"osint / recon a target": ["osint", "recon"],
|
|
|
|
|
|
"hide my identity": ["network"],
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def recommend_tools():
|
|
|
|
|
|
"""Show common tasks, user picks one, show matching tools."""
|
|
|
|
|
|
table = Table(
|
|
|
|
|
|
title="What do you want to do?",
|
|
|
|
|
|
box=box.SIMPLE_HEAD,
|
|
|
|
|
|
)
|
|
|
|
|
|
table.add_column("No.", justify="center", style="bold cyan", width=5)
|
|
|
|
|
|
table.add_column("Task", style="bold yellow")
|
|
|
|
|
|
|
|
|
|
|
|
tasks = list(_RECOMMENDATIONS.keys())
|
|
|
|
|
|
for i, task in enumerate(tasks, start=1):
|
|
|
|
|
|
table.add_row(str(i), task.title())
|
|
|
|
|
|
|
|
|
|
|
|
table.add_row("99", "Back to main menu")
|
|
|
|
|
|
console.print(table)
|
|
|
|
|
|
|
|
|
|
|
|
raw = Prompt.ask("[bold cyan]>[/bold cyan]", default="").strip()
|
|
|
|
|
|
if not raw or raw == "99":
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
idx = int(raw)
|
|
|
|
|
|
except ValueError:
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
if 1 <= idx <= len(tasks):
|
|
|
|
|
|
task = tasks[idx - 1]
|
|
|
|
|
|
tag_names = _RECOMMENDATIONS[task]
|
|
|
|
|
|
tag_index = _get_all_tags()
|
|
|
|
|
|
|
|
|
|
|
|
# Collect unique tools across all matching tags
|
|
|
|
|
|
seen = set()
|
|
|
|
|
|
matches = []
|
|
|
|
|
|
for tag in tag_names:
|
|
|
|
|
|
for tool, cat in tag_index.get(tag, []):
|
|
|
|
|
|
if id(tool) not in seen:
|
|
|
|
|
|
seen.add(id(tool))
|
|
|
|
|
|
matches.append((tool, cat))
|
|
|
|
|
|
|
|
|
|
|
|
if not matches:
|
|
|
|
|
|
console.print("[dim]No tools found for this task.[/dim]")
|
|
|
|
|
|
Prompt.ask("[dim]Press Enter to return[/dim]", default="")
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
console.print(Panel(
|
|
|
|
|
|
f"[bold]Recommended tools for: {task.title()}[/bold]",
|
|
|
|
|
|
border_style="green", box=box.ROUNDED,
|
|
|
|
|
|
))
|
|
|
|
|
|
|
|
|
|
|
|
rtable = Table(box=box.SIMPLE_HEAD, show_lines=True)
|
|
|
|
|
|
rtable.add_column("No.", justify="center", style="bold cyan", width=5)
|
|
|
|
|
|
rtable.add_column("", width=2)
|
|
|
|
|
|
rtable.add_column("Tool", style="bold yellow", min_width=20)
|
|
|
|
|
|
rtable.add_column("Category", style="magenta")
|
|
|
|
|
|
|
|
|
|
|
|
for i, (tool, cat) in enumerate(matches, start=1):
|
|
|
|
|
|
status = "[green]✔[/green]" if tool.is_installed else "[dim]✘[/dim]"
|
|
|
|
|
|
rtable.add_row(str(i), status, tool.TITLE, cat)
|
|
|
|
|
|
|
|
|
|
|
|
rtable.add_row("99", "", "Back", "")
|
|
|
|
|
|
console.print(rtable)
|
|
|
|
|
|
|
|
|
|
|
|
raw2 = Prompt.ask("[bold cyan]>[/bold cyan]", default="").strip()
|
|
|
|
|
|
if raw2 and raw2 != "99":
|
|
|
|
|
|
try:
|
|
|
|
|
|
ridx = int(raw2)
|
|
|
|
|
|
if 1 <= ridx <= len(matches):
|
|
|
|
|
|
matches[ridx - 1][0].show_options()
|
|
|
|
|
|
except ValueError:
|
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-03-15 13:07:20 +00:00
|
|
|
|
def search_tools(query: str | None = None):
|
|
|
|
|
|
"""Search tools — accepts inline query or prompts for one."""
|
|
|
|
|
|
if query is None:
|
|
|
|
|
|
query = Prompt.ask("[bold cyan]/ Search[/bold cyan]", default="").strip().lower()
|
|
|
|
|
|
else:
|
|
|
|
|
|
query = query.lower()
|
2026-03-15 12:35:11 +00:00
|
|
|
|
if not query:
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
all_tool_list = _collect_all_tools()
|
|
|
|
|
|
|
Feature: Tag-based filtering with auto-derived tags (t command)
core.py:
- Add TAGS field to HackingTool class (list[str], default empty)
- Allows manual tag override per tool
hackingtool.py:
- Add _get_all_tags() — builds tag index from 19 regex rules that
auto-derive tags from tool TITLE + DESCRIPTION (osint, scanner, c2,
web, cloud, mobile, wireless, forensics, reversing, etc.)
- Manual TAGS on a tool class take priority over auto-derived
- Add filter_by_tag() — shows all available tags with tool counts,
user picks a tag, results shown with installed status, select to
jump directly into tool.show_options()
- Wire t/tag/tags/filter commands into interact_menu()
- Search also matches against TAGS field
- Updated hint bar: / search · t tags · ? help · q quit
- Updated help overlay with tag filter entry
2026-03-15 12:41:28 +00:00
|
|
|
|
# Match against title + description + tags
|
2026-03-15 12:35:11 +00:00
|
|
|
|
matches = []
|
|
|
|
|
|
for tool, category in all_tool_list:
|
|
|
|
|
|
title = (tool.TITLE or "").lower()
|
|
|
|
|
|
desc = (tool.DESCRIPTION or "").lower()
|
Feature: Tag-based filtering with auto-derived tags (t command)
core.py:
- Add TAGS field to HackingTool class (list[str], default empty)
- Allows manual tag override per tool
hackingtool.py:
- Add _get_all_tags() — builds tag index from 19 regex rules that
auto-derive tags from tool TITLE + DESCRIPTION (osint, scanner, c2,
web, cloud, mobile, wireless, forensics, reversing, etc.)
- Manual TAGS on a tool class take priority over auto-derived
- Add filter_by_tag() — shows all available tags with tool counts,
user picks a tag, results shown with installed status, select to
jump directly into tool.show_options()
- Wire t/tag/tags/filter commands into interact_menu()
- Search also matches against TAGS field
- Updated hint bar: / search · t tags · ? help · q quit
- Updated help overlay with tag filter entry
2026-03-15 12:41:28 +00:00
|
|
|
|
tags = " ".join(getattr(tool, "TAGS", []) or []).lower()
|
|
|
|
|
|
if query in title or query in desc or query in tags:
|
2026-03-15 12:35:11 +00:00
|
|
|
|
matches.append((tool, category))
|
|
|
|
|
|
|
|
|
|
|
|
if not matches:
|
|
|
|
|
|
console.print(f"[dim]No tools found matching '{query}'[/dim]")
|
|
|
|
|
|
Prompt.ask("[dim]Press Enter to return[/dim]", default="")
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
# Display results
|
|
|
|
|
|
table = Table(
|
|
|
|
|
|
title=f"Search results for '{query}'",
|
|
|
|
|
|
box=box.SIMPLE_HEAD, show_lines=True,
|
|
|
|
|
|
)
|
|
|
|
|
|
table.add_column("No.", justify="center", style="bold cyan", width=5)
|
|
|
|
|
|
table.add_column("Tool", style="bold yellow", min_width=20)
|
|
|
|
|
|
table.add_column("Category", style="magenta", min_width=15)
|
|
|
|
|
|
table.add_column("Description", style="white", overflow="fold")
|
|
|
|
|
|
|
|
|
|
|
|
for i, (tool, cat) in enumerate(matches, start=1):
|
|
|
|
|
|
desc = (tool.DESCRIPTION or "—").splitlines()[0]
|
|
|
|
|
|
table.add_row(str(i), tool.TITLE, cat, desc)
|
|
|
|
|
|
|
|
|
|
|
|
table.add_row("99", "Back to main menu", "", "")
|
|
|
|
|
|
console.print(table)
|
|
|
|
|
|
|
|
|
|
|
|
raw = Prompt.ask("[bold cyan]>[/bold cyan]", default="").strip().lower()
|
|
|
|
|
|
if not raw or raw == "99":
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
idx = int(raw)
|
|
|
|
|
|
except ValueError:
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
if 1 <= idx <= len(matches):
|
|
|
|
|
|
tool, cat = matches[idx - 1]
|
|
|
|
|
|
console.print(Panel(
|
|
|
|
|
|
f"[bold magenta]{tool.TITLE}[/bold magenta] [dim]({cat})[/dim]",
|
|
|
|
|
|
border_style="magenta", box=box.ROUNDED,
|
|
|
|
|
|
))
|
|
|
|
|
|
tool.show_options()
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-03-15 11:27:13 +00:00
|
|
|
|
# ── Main interaction loop ──────────────────────────────────────────────────────
|
2025-10-14 06:02:18 +00:00
|
|
|
|
|
|
|
|
|
|
def interact_menu():
|
|
|
|
|
|
while True:
|
|
|
|
|
|
try:
|
|
|
|
|
|
build_menu()
|
2026-03-15 13:07:20 +00:00
|
|
|
|
raw = Prompt.ask(
|
|
|
|
|
|
"[bold magenta]╰─>[/bold magenta]", default=""
|
|
|
|
|
|
).strip()
|
2026-03-15 11:27:13 +00:00
|
|
|
|
|
|
|
|
|
|
if not raw:
|
|
|
|
|
|
continue
|
|
|
|
|
|
|
2026-03-15 13:07:20 +00:00
|
|
|
|
raw_lower = raw.lower()
|
|
|
|
|
|
|
|
|
|
|
|
if raw_lower in ("?", "help"):
|
2026-03-15 11:27:13 +00:00
|
|
|
|
show_help()
|
|
|
|
|
|
continue
|
|
|
|
|
|
|
2026-03-15 13:07:20 +00:00
|
|
|
|
if raw.startswith("/"):
|
|
|
|
|
|
# Inline search: /subdomain → search immediately
|
|
|
|
|
|
query = raw[1:].strip()
|
|
|
|
|
|
search_tools(query=query if query else None)
|
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
|
|
if raw_lower in ("s", "search"):
|
2026-03-15 12:35:11 +00:00
|
|
|
|
search_tools()
|
|
|
|
|
|
continue
|
|
|
|
|
|
|
2026-03-15 13:07:20 +00:00
|
|
|
|
if raw_lower in ("t", "tag", "tags", "filter"):
|
Feature: Tag-based filtering with auto-derived tags (t command)
core.py:
- Add TAGS field to HackingTool class (list[str], default empty)
- Allows manual tag override per tool
hackingtool.py:
- Add _get_all_tags() — builds tag index from 19 regex rules that
auto-derive tags from tool TITLE + DESCRIPTION (osint, scanner, c2,
web, cloud, mobile, wireless, forensics, reversing, etc.)
- Manual TAGS on a tool class take priority over auto-derived
- Add filter_by_tag() — shows all available tags with tool counts,
user picks a tag, results shown with installed status, select to
jump directly into tool.show_options()
- Wire t/tag/tags/filter commands into interact_menu()
- Search also matches against TAGS field
- Updated hint bar: / search · t tags · ? help · q quit
- Updated help overlay with tag filter entry
2026-03-15 12:41:28 +00:00
|
|
|
|
filter_by_tag()
|
|
|
|
|
|
continue
|
|
|
|
|
|
|
2026-03-15 13:07:20 +00:00
|
|
|
|
if raw_lower in ("r", "rec", "recommend"):
|
2026-03-15 12:45:06 +00:00
|
|
|
|
recommend_tools()
|
|
|
|
|
|
continue
|
|
|
|
|
|
|
2026-03-15 13:07:20 +00:00
|
|
|
|
if raw_lower in ("q", "quit", "exit"):
|
2026-03-15 11:27:13 +00:00
|
|
|
|
console.print(Panel(
|
|
|
|
|
|
"[bold white on magenta] Goodbye — Come Back Safely [/bold white on magenta]",
|
|
|
|
|
|
box=box.HEAVY, border_style="magenta",
|
|
|
|
|
|
))
|
2025-10-14 06:02:18 +00:00
|
|
|
|
break
|
2026-03-15 11:27:13 +00:00
|
|
|
|
|
|
|
|
|
|
try:
|
2026-03-15 13:07:20 +00:00
|
|
|
|
choice = int(raw_lower)
|
2026-03-15 11:27:13 +00:00
|
|
|
|
except ValueError:
|
2026-03-15 13:07:20 +00:00
|
|
|
|
console.print("[red]⚠ Invalid input — enter a number, /query to search, or q to quit.[/red]")
|
2026-03-15 11:27:13 +00:00
|
|
|
|
Prompt.ask("[dim]Press Enter to continue[/dim]", default="")
|
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
|
|
if 1 <= choice <= len(all_tools):
|
|
|
|
|
|
title, icon, _ = tool_definitions[choice - 1]
|
2026-03-15 08:24:30 +00:00
|
|
|
|
console.print(Panel(
|
2026-03-15 11:27:13 +00:00
|
|
|
|
f"[bold magenta]{icon} {title}[/bold magenta]",
|
|
|
|
|
|
border_style="magenta", box=box.ROUNDED,
|
2026-03-15 08:24:30 +00:00
|
|
|
|
))
|
2025-10-14 06:02:18 +00:00
|
|
|
|
try:
|
2026-03-15 11:27:13 +00:00
|
|
|
|
all_tools[choice - 1].show_options()
|
2025-10-14 06:02:18 +00:00
|
|
|
|
except Exception as e:
|
2026-03-15 11:27:13 +00:00
|
|
|
|
console.print(Panel(
|
|
|
|
|
|
f"[red]Error while opening {title}[/red]\n{e}",
|
|
|
|
|
|
border_style="red",
|
|
|
|
|
|
))
|
|
|
|
|
|
Prompt.ask("[dim]Press Enter to return to main menu[/dim]", default="")
|
2025-10-14 06:02:18 +00:00
|
|
|
|
else:
|
2026-03-15 11:27:13 +00:00
|
|
|
|
console.print(f"[red]⚠ Choose 1–{len(all_tools)}, ? for help, or q to quit.[/red]")
|
|
|
|
|
|
Prompt.ask("[dim]Press Enter to continue[/dim]", default="")
|
|
|
|
|
|
|
2025-10-14 06:02:18 +00:00
|
|
|
|
except KeyboardInterrupt:
|
2026-03-15 08:24:30 +00:00
|
|
|
|
console.print("\n[bold red]Interrupted — exiting[/bold red]")
|
2025-10-14 06:02:18 +00:00
|
|
|
|
break
|
|
|
|
|
|
|
2026-03-15 08:24:30 +00:00
|
|
|
|
|
2026-03-15 11:27:13 +00:00
|
|
|
|
# ── Entry point ────────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
2025-10-14 06:02:18 +00:00
|
|
|
|
def main():
|
|
|
|
|
|
try:
|
2026-03-15 08:24:30 +00:00
|
|
|
|
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]"))
|
2025-10-14 06:02:18 +00:00
|
|
|
|
if Confirm.ask("Open guidance link in your browser?", default=True):
|
2026-03-15 08:24:30 +00:00
|
|
|
|
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]")
|
|
|
|
|
|
|
2026-03-15 11:27:13 +00:00
|
|
|
|
get_tools_dir() # ensures ~/.hackingtool/tools/ exists
|
2026-03-15 08:24:30 +00:00
|
|
|
|
interact_menu()
|
|
|
|
|
|
|
2020-08-14 11:11:59 +00:00
|
|
|
|
except KeyboardInterrupt:
|
2026-03-15 08:24:30 +00:00
|
|
|
|
console.print("\n[bold red]Exiting...[/bold red]")
|
2025-10-14 06:02:18 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
|
main()
|